前言:
咳咳,我又来了,这次是软定时器机制,这个更狠一点,网上应该是没有代码的,所以也不用担心,抄代码的现象,不过之所以这么晚才发上来,是因为老师说实验一出现了抄袭现象,只改了名字,其他全部一样。这时,一想到我当初实验一的时候,直接在交作业之前就把所有的东西上传到GitHub是多么愚蠢,后背也突突的直冒冷汗,因为抄袭者和被抄袭者都是零分,所以这次为了防止有人抄我的,我直接就在交作业之后才发上来。所以这篇博客的目的是造福学弟学妹,而不是造福我的同班同学。
一、 实验目的
在了解实时嵌入式操作系统对定时器需求的基础上,练习并掌握为实时应用提供不同类型软定时器的有效方法和管理机制,并构件以消息驱动的有限状态机开发框架打下基础。掌握GPIO的工作原理和控制方式。
二、实验工具及环境
VxSim + TQ2440(ARM920T)
三、 实验内容
- 以替换VxWorks Tick中断服务程序的方式提供实时应用所需要的软定时器服务;
- 支持实时应用常见的两种类型定时功能:单次定时和周期定时;
- 设计方式应体现消息驱动的有限状态机模型的思想,以构建有限状态机开发框架的雏形;
- 定时管理机制包括:
a) 初始化函数;
b) 定时器资源申请,定时器启动,定时器超时激励消息,定时器停止,定时器资源释放;
c) 定时器管理监视机制。 - 创建多Task环境测试定时器以多种方式控制板上所接LED(GPIO)的显示方式,如走马灯,多LED独立周期闪烁等。
四、实验设计
1. 系统结构图
系统结构主要分为四部分,其一是定时器池(Timer Pool)部分,其二是定时器状态转换图,其三是定时器轮子部分(Timer Wheel)部分,其四是消息队列部分。
1)定时器池(Timer Pool)部分
定时器池的系统结构图,如图4.1所示,系统维护一个预先静态分配的定时器池,每次的定时器申请以及释放都是从定时器池中 申请一个定时器,或者向池中释放一个定时器。Y_OS_TMR类型为Timer的结构体,整个定时器池建立的时候以数组的形式进行建立的,每个定时器即数组中的元素,定时器池初始化完成后就变成了一个单向链表,将池中第一个定时器的地址作为头指针 OSTmrFreeList 的值,系统申请和释放定时器都是依靠维护头指针 OSTmrFreeList 指针实现。
系统在定时器部分提供六个接口,为图中右部分,从上到下依次为:创建定时器、启动定时器、暂停定时器、删除定时器、获取定时器剩余Tick数、获取定时器当前状态。
2)定时器状态转换图,如图4.2所示:
3)定时器轮子(Timer Wheel)部分
如图4.3所示,定时器轮子(Timer Wheel)由一个结构体Y_OS_TMR_WHEEL控制,其中的OSTmrFirst指针指向轮子的第一个节点,整个轮子采用双向链表的形式实现,方便于进行插入和删除,定时器轮子主要提供两个功能:插入轮子操作、从轮子中删除操作。轮子中存储的节点均为定时器实体。
4)消息队列部分
消息队列部分的结构如图4.4所示,每个任务都有其私有的消息队列,消息队列的实现基于VxWorks提供的API。其中消息队列中的消息均为图中的Msg格式。
2. 核心常量、结构和变量说明
1)核心常量说明
如图4.5所示,系统配置中主要有四个宏定义常量,分别是:
a) OS_TMR_NUM:定时器池中的定时器数量,定时器数量的范围为 [2,255]。
b) TASK_NUM_MAX:最大任务数,此宏定义决定了系统最大可以创建的Task数量,因为每个任务都有一个私有的消息队列,所以,此常量也代表了消息队列的数量。
c) MSG_Q_SIZE:消息队列中可容纳的消息数量。
d) THIS_IS_TIMER:用在Timer的结构体中,用来标识此结构体是一个Timer。
如图4.6所示,为定时器的类型,定时器可以定义两种类型:单次定时和周期定时。
如图4.7所示,定义了定时器所处的5种状态,分别为:未创建状态(uncreate)、创建了但未使用状态(unused)、暂停状态(stopped)、完成状态(completed)、运行状态(running)。除此5种状态之外,额外定义了再次运行状态(re_running),用来在定时器完成的时候向任务发送消息,使得任务可以鉴别出定时器再次运行的消息。又额外定义了消息来自定时器(msg_from_timer)以及消息内容是指针(content_is_pointer)这两种宏定义,这两种宏定义与定时器状态并不相关,但是这全部8种宏定义恰恰是消息中定义的消息类型,故定义了这8种宏定义分别对应8位比特位中的一位,以达到节省空间的效果。
2)核心结构说明
如图4.8所示,主要有三种核心结构体,分别对应系统结构中的三部分,下对这三种结构作详细解释:
a) Y_OS_TMR:定时器结构体,此结构体定义了定时器的基本类型,主要包括:
OSTmrType:标识此结构体为定时器类型,对应核心常量中的 THIS_IS_TIMER 宏定义;
OSTmrNext:此指针主要有两个作用,其一是在定时器池(Timer Pool)初始化的时候,因为初始化后形成的是单链表,故只需要此 OSTmrNext 指针来指向下一个定时器,其二是在定时器轮子(Timer Wheel)中,定时器轮子是双向链表,此 OSTmrNext 用来指向当前节点的下一个节点;
OSTmrPrev:此指针用来在定时器轮子(Timer Wheel)中,指示当前节点的前一个节点。
OSTmrforWheel:此变量为整个系统的核心变量,根据定时器所处状态不同,主要有两个作用,其一,在定时器处于非运行状态,即定时器并未插入到定时器轮子(Timer Wheel)中时,用来记录当前定时器所剩余的Tick数量。当定时器处于运行状态,即定时器已经插入到定时器轮子中时,用来指示当前定时器节点与上一个正在运行的定时器节点的Tick差值。
OSTmrDly:用来指示定时器的延时时间,对于单次定时器,这个就是定时器的定时时间。对于周期定时器,这个变量的值为周期定时器在开始周期循环之前的延时时间。
OSTmrPeriod:用来指示定时器的周期时间,这个变量只能用来配置周期定时器,用来指示周期定时器每个周期的Tick数量。
OSTmrOpt:用来指示当前定时器的类型,有两种选项:单次定时与周期定时。对应核心常量中的两种宏定义类型。
OSTmrState:用来指示当前定时器所处的状态。对应了核心常量中的5种状态。
TaskID:标识当前定时器从属于那个任务。
b) Y_MSG:消息类型结构体,此结构体定义了消息的基本格式,主要包括:
TimerID:标识此条消息来自于那个定时器。其值为定时器的首地址。
TaskID:标识此条消息发送给那个任务。用来索引消息队列,根据此ID,来找到对应任务的消息队列。其值为任务创建的时候人为规定。
MSGTYPE:这个变量为消息格式中的核心变量,其类型为Y_INT8U类型,意为8个比特位,对应了核心宏定义中的8种消息类型宏定义,根据此变量的不同,来区分各种来源不同的消息。
CONTENT:这个变量为消息中的内容模块。其本身是一个指针,当消息内容小于一个指针的大小时,此字段为消息本身,当消息内容大于一个指针大小的时候,此字段自动转化为指向消息内容的指针。
c) Y_OS_TMR_WHEEL:定时器轮子的结构体,此结构体表示定时器轮子(Timer Wheel)的类型,主要包括:
OSTmrFirst:此指针指向轮子中的第一个节点,维护轮子的正常运行,就是维护这个指针,整个定时器轮子是一个双向链表,有利于定时器的删除操作。
OSTmrEntries:记录当前轮子中的定时器数量。
3)核心变量说明
如图4.9所示,核心变量主要分为6部分,详细说明如下:
a)信号量部分,信号量部分定义了三个信号量:
semForSignal信号量是整个系统的核心信号量,其被定义为计数信号量。当每个中断发生时,此信号量被ISR服务程序Give一次,随之唤醒manage_task,manage_task Take此信号量,并将定时器轮子的首节点的OSTmrforWheel变量减一,从而实现软定时机制。
semForWheel、semForTmrPool这两个信号量是互斥信号量,实现对定时器轮子和定时器池的互斥访问。
b)消息队列部分:msgQue 数组为每个任务都安排了一个私有的消息队列,用来接收消息。
c)定时器池部分,定时器池部分定义了4个变量:
timerEntity数组为定时器池的实体部分,体现了预先静态分配的思想。
OSTmrFreeList指针为指向定时器池中的第一个定时器的指针,此指针为定时器单向链表的头指针,用来维护定时器池。
OSTmrUsed、OSTmrFree两个变量用来记录当前定时器池中定时器的使用情况。
d)定时器轮子部分:timerWheel为全局变量,整个系统只有一个定时器轮子,用来实现软定时机制。
e)管理任务部分:tid_manage_task为管理任务的taskId。
f)LED灯的配置部分,主要由四个变量:LED_1、LED_2、LED_3、LED_4此四个变量分别配置LED灯的状态,每个变量均为Y_INT8U类型,含有8个比特位,对应于LED灯的8次亮灭,故可以为每个LED灯配置以8次亮灭为周期的循环周期显示。
3. 核心思想及其实现函数说明
核心思想主要有四部分,分为:定时器池部分、定时器轮子部分、消息队列部分、管理任务部分。
1)定时器池部分:
定时器池部分的思想,主要为封装、静态预分配。对于定时器池部分,预先从系统中以数组的形式申请好定时器,随后做初始化工作。封装主要体现在,对于从定时器池中取定时器、释放定时器操作都是通过函数封装起来的,不能直接操做OSTmrFreeList指针,规定只能通过相关的函数调用来进行申请以及释放操作。思想类似于第一次的内存实验。
2)定时器轮子部分:
定时器轮子部分的思想,主要为双向链表的使用、定时器轮子的使用方法的巧妙。在定时器轮子的结构上,采用双向链表,这样的话,可以使得其在摘除定时器,即用户暂停定时器时,时间复杂度达到O(1),可以直接根据定时器的指针,从双向链表中摘除指定定时器。轮子使用方法的巧妙主要体现在,其中定时器中的OSTmrforWheel存储的是当前定时器与前一个定时器之间的差值,故在管理任务需要将定时器的Tick数目减一的时候,只需要将轮子的首节点的OSTmrforWheel减一即可,这样由于之后的节点都是存储的与前一个节点的差值,所以只需要操作一步就可以实现所有定时器的Tick数减一。
核心函数实现部分:
a)插入轮子
b)从轮子中摘除指定定时器
3)消息队列部分:
消息队列部分的核心思想,主要是对于消息的操作,包含两个方面,消息类型定义、消息内容的动态确定。消息类型的定义对应于核心常量中的8种状态,因为消息结构体中的MSGTYPE字段是8个比特位,所以可以采用与或的方式获得每个比特位的信息,从而实现8种状态放到一个字节中,这样既方便又节省了空间。消息内容的动态确定,是当消息内容大于一个指针的大小的时候,自动将消息内容变成指针,反之,如果消息内容小于一个指针大小,则直接将消息存入到消息内容这个字段中。
核心函数实现部分,主要是指针的强转:
a)发送消息函数:
4)管理任务部分:
管理任务的核心思想就是信号量的获取,在每一个时钟中断发生的时候,manage_task被唤醒,进行将轮子中的首节点的剩余Tick数减一的操作。
核心函数:
a)管理任务函数代码:
b)中断服务程序
4. 主要过程(API)说明
主要过程包括初始化函数以及一系列接口函数、监管函数说明,位于y_os_interface.h文件中:
如图4.16所示,初始化函数gvInit()用来初始化系统的信号量,消息队列,定时器池,定时器轮子,管理任务等。此函数无参,返回Y_INT8U类型的返回值来表示是否初始化成功。
如图4.17所示,OSTmrCreate()函数接收一系列参数来给从定时器池申请来的定时器赋初值,返回一个Y_OS_TMR类型的指针,指向已经创建好的定时器。
如图4.18所示,OSTmrStart()接收一个定时器指针参数,用来启动指定的定时器。perr参数表示错误状态码,函数返回一个Y_INT8U类型的返回值,来说明程序执行成功与否。
如图4.19所示,OSTmrStop()函数用来暂停一个定时器,函数接收指向定时器的指针,来暂停指定的定时器,接收一个opt、content,用来向任务发送消息,其中opt指示,content是否为空,content为指定字符串,即消息的内容,perr为错误状态码。函数返回值是Y_INT8U类型,指示函数是否执行成功。
如图4.20所示,OSTmrDel()函数,接收一个指向指定定时器的指针,用来删除指定的定时器,perr为错误状态码,函数返回值是Y_INT8U类型,指示函数是否执行成功。
如图4.21所示,OSTmrRemainGet()函数,属于监管机制的部分,可以查看指定定时器当前还剩余多少tick,函数接受一个指向定时器的指针,用来查看指定定时器的剩余tick,perr为错误状态码,函数返回值为Y_INT32U类型,表示当前所生的tick数量。
如图4.22所示,OSTmrStateGet()函数也属于监管机制的一部分,函数接受一个指向定时器的指针,可以查看指定定时器的当前状态,函数返回值为Y_INT8U类型,指示当前定时器所处于的状态。
如图4.23所示,showMsg()接收一个参数,此参数为指定任务的ID,可以获得此任务的消息队列中的消息,并将其展示出来。
如图4.24所示,OS_SetLedMod()接收四个参数,这四个8比特的变量,可以操控每个LED灯的亮灭时刻,一个比特代表一个时刻,故可以设置以8个状态为一个周期的模式。
如图4.25所示,Led_Turn_On()接受一个参数,功能是点亮一个指定的LED小灯。
如图4.26所示,Led_Turn_Down()接受一个参数,功能是熄灭一个指定的LED小灯。
如图4.27所示,Led_Show_Time()按照我们使用OS_SetLedMod()设定的方式来展示小灯的亮灭。
五、 实验测试
1)测试1:多任务环境下测试周期定时器、单次定时器的创建、启动、删除、等待消息、LED小灯按照指定模式点亮过程。
测试代码:
如图5.1,图5.2所示,此测试过程,测试了多任务环境下的周期定时器与单次定时器,对于周期定时器,其tick数为100个tick,因为是周期定时器,所以在showMsg()部分是一个死循环,用来一直接收周期定时器re_running信息。单次定时器,定时是100个tick,因为是单次定时器,所以在最外层套了一个while循环。单次定时器最后会调用删除函数,将定时器释放到定时器池。
测试结果:
如图5.3所示,两个任务task0为单次定时,task1为周期定时,时间都是100个tick,如图所示,task0先创建定时器,然后start定时器,定时器被连接到定时器轮子上,起始状态定时器轮子为空,连接之后,头节点为100个tick,然后task0开始等待定时器的完成消息,进入阻塞状态。task1定义的是周期定时器,首先task1创建一个定时器,然后连接到轮子上,由于轮子上已经有了一个单次定时器为100个tick,所以此周期定时器再插入之后应该与上一个定时器的差值为0。故如图5.3,最终的轮子状态为100、0。即两个定时器分别连接到轮子上成功。
如图5.4所示,task1连接到轮子上之后,也开始等待消息,一段时间后,由于100个tick数已经到达,所以位于轮子的首节点开始从轮子上摘除,图5.4显示了轮子摘除前后的状态。由于task0优先级比task1高,所以task0先运行,task0接收消息,因为task0创建的是单次定时器,故完成的时候timer state为8,意为完成状态,并且随着定时的结束点亮LED1和LED3,最后,task0删除定时器。对于task1状态,因为task1创建的是周期定时器,完成的时候的发送的消息类型为32,意为re_running重新计时,所以会将定时器摘除后再次连接到轮子上,实现周期定时的效果。
Wind View过程分析:
如图5.5所示,体现了manage_task管理任务在每个tick发生的时候被周期唤醒的过程。
如图5.6所示,体现了消息驱动思想,manage_task发送消息到ttest1与ttest2任务的消息队列上,进而唤醒对应的正在等待消息的任务。
如图5.7、图5.8所示,体现了消息发送与接收过程,manage_task发送消息到msgQId为0x57ae088的消息队列上,然后ttest1自消息队列0x57ae088上接收消息。
如图5.9、图5.10所示,体现了消息发送与接收过程,manage_task发送消息到msgQId为0x57adfd0的消息队列上,然后ttest2自消息队列0x57adfd0上接收消息。
2)测试2:测试消息带有内容部分。
测试代码1,测试内容字段为指针:
如图5.11、图5.12所示,创建了一个单任务来进行测试发送内容功能,由于server端输出信息很多,故采用单任务形式来进行测试,这样逻辑更加清晰。如图5.12所示,创建了一个单次定时器,时长为100个tick,由于需要测试发送消息内容“hello,my name is xyy !”,故在设计之初,我就决定将stop操作与发送消息关联起来,即当暂停一个定时器的时候,需要传送消息内容,然后当暂停定时器的时候,会发送一条消息到任务的消息队列,以此来测试消息内容是否为指针的操作。
测试结果:
测试结果如图5.13所示,server端显示content是一个指针,并且指针指向“hello,my name is xyy !”,由于此条消息已经远远超出一个指针的大小,所以消息内容自动转换为指针。
测试代码2,测试内容字段为内容本身:
如图5.14所示,同样是创建了如图5.11的任务,不同的是消息内容换成了一个字符“h”。用来测试当字符长度小于一个指针的时候,内容字段自动转换为内容本身。如图5.15测试结果所示,内容字段本身就是消息内容,并且内容为“h”,故测试成功。由图5.13及5.15所示,消息内容字段自动转换为内容以及指针的操作正常运行。
3)测试3:测试暂停定时器,然后重新启动定时器
如图5.16所示,创建了一个单任务环境,由于测试暂停过程中server输出信息过多,故采用单任务环境,使得实验测试结果更为清晰。
如图5.17所示,首先创建一个周期定时器,周期为100个tick,任务启动定时器,然后任务延时20个tick,此时定时器已经走了20个tick,故应该剩余80个tick,这时暂停定时器,消息内容为空,然后任务再次延时20个tick,最终任务再次启动定时器,定时器从80个tick继续计时。
测试结果:
如图5.18所示,task1首先创建了一个定时器,然后定时器被挂到轮子上,任务延时20个tick后调用stop函数,暂停定时器,可以看到定时器从轮子上摘下,此时的tick数为80,然后任务收到一条消息,定时器状态为4,意为定时器处于暂停状态。task1再次延时20个tick,之后重新启动定时器,定时器再次被挂到轮子上,从80个tick开始计时。由于定时器为周期定时器,故80个tick走完之后开始进入下一个周期,task1再次收到一条消息,此时定时器状态为32,意为周期定时器再次运行。故从图5.18所示结果中,可以明显看到暂停以及再次启动定时器运行正常。
4)测试4:测试监管机制,获取定时器剩余tick数,获取定时器状态
如图5.19、图5.20、图5.21所示,为测试监管机制,获取定时器状态以及剩余tick数量,任务创建了一个单次定时器,定时100个tick。如图5.21所示,可以正确获得定时器的剩余tick数量,以及当前定时器所处状态。故监管机制运行良好。
5)测试5:测试LED显示状态
如图5.22所示,测试LED灯的亮灭采用了周期定时器,周期为50个tick,每次当定时结束的时候,LED显示进入下一个显示状态。对于LED状态显示,由图中的OS_SetLedMod()决定,此函数接收4个参数,用来对每个LED灯进行配置,LED灯的配置如下图5.23所示:
图5.23中每一列分别对应每个时刻,一列中有四个数,分别对应每个LED的亮灭,1为亮,0为灭。在时刻1,灯1灭,灯2、3、4亮。在时刻2,灯2灭,灯1、3、4亮,依次类推。经过连板子实际测试,LED灯显示正常,实际测试结果见附件视频。此视频提供10秒的LED灯显示。下图5.24为测试LED灯亮的结果。
六、 完整源代码
(一)y_os_cfg.h
#define CFGFILE /* define this file for config */
#include "vxWorks.h"
#include "stdio.h"
#include "stdlib.h"
#include "semLib.h"
#include "taskLib.h"
#include "sysLib.h" /* include the header file */
#include "tickLib.h"
#include "msgQLib.h"
#ifdef OS_GLOBALS
#define OS_EXT
#else
#define OS_EXT extern
#endif /* global variable define */
#define Y_OS_TMR_EN 1u /* enable timer */
#define Y_OS_ARG_CHK_EN 1u /* enable arg check */
/*
**********************************************************************************
*
* Timer and msg_queue cfg
*
*Description : The #define here define constants that determine the number of timers,
* the number of tasks, and the length of the message queue in the system
*
*Arguments : none
*
*Returns : none
*
*Notes : The number of timers must be greater than 2, and the number of tasks
* and message queue length must be greater than 0
*
**********************************************************************************
*/
#define OS_TMR_NUM 5u /* the timer num in the timer pool ,at least 2 max Y_INT8U*/
#define TASK_NUM_MAX 10u /* define task max num ,the task created should not over it max Y_INT8U taskID should be [0,TASK_NUM_MAX)*/
#define MSG_Q_SIZE 3u /* define the msg queue size */
#define THIS_IS_TIMER 100u /* this is timer type */
#define OS_TMR_OPT_NONE 0u /* define the timer mode */
#define OS_TMR_OPT_ONE_SHOT 1u /* Timer for one shot */
#define OS_TMR_OPT_PERIODIC 2u /* Timer for periodic */
/* timer state only has 5 */
#define OS_TMR_STATE_UNCREATE 1u /* 0000 0001 */
#define OS_TMR_STATE_UNUSED 2u /* 0000 0010 */
#define OS_TMR_STATE_STOPPED 4u /* 0000 0100 */
#define OS_TMR_STATE_COMPLETED 8u /* 0000 1000 */
#define OS_TMR_STATE_RUNNING 16u /* 0001 0000 */
#define OS_TMR_MSG_RE_RUNNING 32u /* 0010 0000 */
#define MSG_FROM_TIMER 64u /* 0100 0000 */
#define OS_MSG_CONTENT_IS_POINTER 128u /* 1000 0000 */
#define STACK_SIZE 2000 /* each task stack size */
typedef unsigned int Y_INT32U;
typedef unsigned char Y_INT8U;
#define Y_OS_TRUE 0u
#define Y_OS_FALSE 1u
#define Y_OS_TRUE_WITH_MSG 3u
#define CREATE_ERR
#define OS_CREATE_ERR_NONE 0u
#define OS_CREATE_ERR_TMR_INVALID_PERIOD 1u
#define OS_CREATE_ERR_TMR_INVALID_DLY 2u
#define OS_CREATE_ERR_TMR_INVALID_OPT 3u
#define OS_CREATE_ERR_TMR_NON_AVAIL 4u
#define START_ERR
#define OS_START_ERR_NONE 0u
#define OS_START_ERR_TMR_INVALID 1u
#define OS_START_ERR_TMR_INVALID_TYPE 2u
#define OS_START_ERR_TMR_INACTIVE 3u
#define OS_START_ERR_TMR_INVALID_STATE 4u
#define STOP_ERR
#define OS_STOP_ERR_NONE 0u
#define OS_STOP_ERR_TMR_INVALID_TYPE 1u
#define OS_STOP_ERR_TMR_INVALID 2u
#define OS_STOP_ERR_TMR_STOPPED 4u
#define OS_STOP_ERR_TMR_INACTIVE 5u
#define OS_STOP_ERR_TMR_INVALID_STATE 6u
#define SEND_MSG_ERR
#define OS_MSG_NO_ERR 0u
#define OS_MSG_OPT_HAVE_CONTENT 1u
#define OS_MSG_OPT_NO_CONTENT 2u
#define OS_MSG_INVALID_OPT 3u
#define DEL_ERR
#define OS_DEL_ERR_NONE 0u
#define OS_DEL_ERR_TMR_INVALID 1u
#define OS_DEL_ERR_TMR_INVALID_TYPE 2u
#define OS_DEL_ERR_TMR_INACTIVE 3u
#define OS_DEL_ERR_TMR_INVALID_STATE 4u
#define STATE_GET_ERR
#define OS_GET_ERR_NONE 0u
#define OS_GET_ERR_TMR_INVALID 1u
#define OS_GET_ERR_TMR_INVALID_TYPE 2u
#define OS_GET_ERR_TMR_INVALID_STATE 3u
#define REMAIN_ERR
#define OS_REMAIN_ERR_NONE 0u
#define OS_REMAIN_ERR_TMR_INVALID 1u
#define OS_REMAIN_ERR_TMR_INVALID_TYPE 2u
#define OS_REMAIN_ERR_TMR_INACTIVE 3u
#define OS_REMAIN_ERR_TMR_INVALID_STATE 4u
#define LINK_TYPE
#define OS_TMR_LINK_PERIODIC 1u
#define OS_TMR_LINK_DLY 2u
#define OS_TMR_LINK_CONTINUE 3u
#if Y_OS_TMR_EN > 0
typedef struct os_tmr {
Y_INT8U OSTmrType; /* indicate the timer type */
void *OSTmrNext; /* pointer to the next timer struct in the freelist or wheel */
void *OSTmrPrev; /* pointer to the next timer struct in the wheel */
Y_INT32U OSTmrforWheel; /* the tick count remain */
Y_INT32U OSTmrDly; /* the tick count that the timer want to delay ,it has two mode one-shot and periodic*/
Y_INT32U OSTmrPeriod; /* the tick count that the timer want to delay ,it only has one mode periodic */
Y_INT8U OSTmrOpt; /* the mode of the timer one-shot or periodic */
Y_INT8U OSTmrState; /* the timer state */
Y_INT8U TaskID; /* the taskId of task which own the timer for now */
}Y_OS_TMR;
typedef struct msg{
Y_INT32U TimerID; /* the timer id */
Y_INT8U TaskID; /* which task does the msg belong to */
Y_INT8U MSGTYPE; /* the msg type indicate to the state of the timer */
void * CONTENT; /* the msg content */
}Y_MSG;
typedef struct os_tmr_wheel {
Y_OS_TMR *OSTmrFirst; /* the pointer to the first node in the wheel link list */
Y_INT32U OSTmrEntries; /* the timer num in the wheel for now */
}Y_OS_TMR_WHEEL;
#endif
/*************************************** CORE G.V. DEFINE ***********************************************/
/* semphore part */
OS_EXT SEM_ID semForSignal; /* sem for signal task, it is give by ISR, and take by timer manage task */
OS_EXT SEM_ID semForWheel; /* sem for timer wheel */
OS_EXT SEM_ID semForTmrPool; /* sem for timer pool */
/* assume that the map between msg manager and entity is the task id */
OS_EXT MSG_Q_ID msgQue[TASK_NUM_MAX]; /* define msg queue for each task */
/* define the timer pool */
OS_EXT Y_OS_TMR timerEntity[OS_TMR_NUM]; /* define the timer entity */
OS_EXT Y_OS_TMR *OSTmrFreeList; /* Link chain of the timer in the timer pool */
OS_EXT Y_INT8U OSTmrUsed; /* the number timer used */
OS_EXT Y_INT8U OSTmrFree; /* the number timer free*/
/* wheel part */
OS_EXT Y_OS_TMR_WHEEL timerWheel; /* define the only timer pool */
/* manage task cfg*/
int tid_manage_task; /* the task id of management task */
/* LED_DISPLAY_MODE */
OS_EXT Y_INT8U LED_1;
OS_EXT Y_INT8U LED_2;
OS_EXT Y_INT8U LED_3;
OS_EXT Y_INT8U LED_4; /* the variable for each led light */
/*************************************** END ***********************************************/
#include "y_os_interface.h"
/*************************************** Function declaration ***********************************************/
void OS_MemClr (Y_INT8U *pdest,Y_INT32U size);
Y_INT8U memConCpy(Y_INT8U *pdest,Y_INT8U *psrc);
Y_INT8U OS_StrLen (Y_INT8U *psrc);
void manage_task(void);
void isrGive(int arg);
void OSTmr_Init (void);
Y_INT8U sendMsg(Y_INT32U TimerID,Y_INT8U TaskID,Y_INT8U msgtype,Y_INT8U opt,void *content);
void OSTmr_Link(Y_OS_TMR *ptmr,Y_INT8U type);
Y_OS_TMR * OSTmr_Unlink(Y_OS_TMR *ptmr);
Y_INT32U OSTmr_Remain(Y_OS_TMR *ptmr);
void Led_Init(void);
(二)y_os_interface.h
/*************************************** System interface ***********************************************/
/*
**********************************************************************************
*
* gvInit
*
*Description : this function is called to init the g.v. and the timer pool and the
* wheel and connect the func to the ISR
*
*Arguments : none
*
*Returns : Y_INT8U err code
* Y_OS_FALSE : false
* Y_OS_TRUE : true
*
*Notes : none
*
**********************************************************************************
*/
Y_INT8U gvInit();
/*
**********************************************************************************
*
* OSTmrCreate
*
*Description : this function is called to create the timer, and the timer state changed
* OS_TMR_STATE_UNCREATE -> OS_TMR_STATE_UNUSED
*
*Arguments : Y_INT32U dly, the tick we want to delay ,used for the OS_TMR_OPT_ONE_SHOT
* Y_INT32U period, the period tick for the timer ,userd for the OS_TMR_OPT_PERIODIC
* Y_INT8U opt, there are two options :
* OS_TMR_OPT_ONE_SHOT :timer for one time mode
* OS_TMR_OPT_PERIODIC :period timer mode
* Y_INT8U *perr, err code
* Y_INT8U taskId, the id of the task which own the timer
*
*Returns : Y_OS_TMR* the pointer of the timer
*
*Notes : none
*
**********************************************************************************
*/
Y_OS_TMR *OSTmrCreate (Y_INT32U dly, Y_INT32U period, Y_INT8U opt, Y_INT8U *perr, Y_INT8U taskId);
/*
**********************************************************************************
*
* OSTmrStart
*
*Description : this function is called to start the timer
*
*Arguments : Y_OS_TMR *ptmr, the pointer point to the timer
* Y_INT8U *perr, err code
*
*Returns : Y_INT8U err code
* Y_OS_FALSE : false
* Y_OS_TRUE : true
*
*Notes : none
*
**********************************************************************************
*/
Y_INT8U OSTmrStart (Y_OS_TMR *ptmr, Y_INT8U *perr);
/*
**********************************************************************************
*
* OSTmrStop
*
*Description : this function is called to stop the timer,and sent a msg to the task which own the timer
*
*Arguments :Y_OS_TMR *ptmr, the pointer point to the timer
* Y_INT8U opt, the msg which we want to send ,has content?
* OS_STOP_TMR_OPT_HAVE_CONTENT
* OS_STOP_TMR_OPT_NONE
* void *msgContent,msg content, (void *)"hello" or (void *)"a" or (void *)0
* Y_INT8U *perr,err code
*
*Returns : Y_INT8U err code
* Y_OS_FALSE : false
* Y_OS_TRUE : true
*Notes : none
*
**********************************************************************************
*/
Y_INT8U OSTmrStop (Y_OS_TMR *ptmr, Y_INT8U opt, void *msgContent, Y_INT8U *perr);
/*
**********************************************************************************
*
* OSTmrDel
*
*Description : this function is called to delete the timer,unlink the timer from the wheel
* free the timer
*
*Arguments :Y_OS_TMR *ptmr, the pointer point to the timer
* Y_INT8U *perr, err code
*
*Returns : Y_INT8U err code
* Y_OS_FALSE : false
* Y_OS_TRUE : true
*
*Notes : none
*
**********************************************************************************
*/
Y_INT8U OSTmrDel (Y_OS_TMR *ptmr, Y_INT8U *perr);
/*
**********************************************************************************
*
* OSTmrRemainGet
*
*Description : get the tick count of the timer remain
*
*Arguments : Y_OS_TMR *ptmr, the pointer point to the timer
* Y_INT8U *perr, err code
*
*Returns : Y_INT32U the tick count of the timer remain
*
*Notes : none
*
**********************************************************************************
*/
Y_INT32U OSTmrRemainGet (Y_OS_TMR *ptmr, Y_INT8U *perr);
/*
**********************************************************************************
*
* OSTmrStateGet
*
*Description : this function is called to get the state of the timer
*
*Arguments : Y_OS_TMR *ptmr, the pointer point to the timer
* Y_INT8U *perr, err code
*
*Returns : Y_INT8U timer state
*
*Notes : none
*
**********************************************************************************
*/
Y_INT8U OSTmrStateGet (Y_OS_TMR *ptmr, Y_INT8U *perr);
/*
**********************************************************************************
*
* showMsg
*
*Description : this function is called to receive a msg from the msgQ
*
*Arguments : Y_INT8U taskId,the id of the task which associate to the msgQ
*
*Returns : Y_INT8U : Indicates whether the timer has completed successfully
* Y_OS_TRUE
* Y_OS_FALSE
*
*
*Notes : none
*
**********************************************************************************
*/
Y_INT8U showMsg(Y_INT8U taskId);
/*
**********************************************************************************
*
* OS_SetLedMod
*
*Description : this function is called to receive a msg from the msgQ
*
*Arguments : Y_INT8U led1,Y_INT8U led2,Y_INT8U led3,Y_INT8U led4 : each led light
* mode, we set it with 0x??, The light can be turned on in the mode we set
*
*Returns : none
*
*Notes : none
*
**********************************************************************************
*/
void OS_SetLedMod (Y_INT8U led1,Y_INT8U led2,Y_INT8U led3,Y_INT8U led4);
/*
**********************************************************************************
*
* Led_Turn_On
*
*Description : this function is called to Light the specified LED
*
*Arguments : Y_INT8U LedId, the id of led which we want to light
*
*Returns : none
*
*Notes : none
*
**********************************************************************************
*/
void Led_Turn_On(Y_INT8U);
/*
**********************************************************************************
*
* Led_Turn_Down
*
*Description : this function is called to poweroff the specified LED
*
*Arguments : Y_INT8U LedId, the id of led which we want to poweroff
*
*Returns : none
*
*Notes : none
*
**********************************************************************************
*/
void Led_Turn_Down(Y_INT8U);
/*
**********************************************************************************
*
* Led_Show_Time
*
*Description : this function is called to Light the light in the mode we specified
*
*Arguments : none
*
*Returns : none
*
*Notes : none
*
**********************************************************************************
*/
void Led_Show_Time(void);
/*************************************** END ***************************************/
(三)y_tmr_pool.c
#define OS_GLOBALS
#include "y_os_cfg.h" /* declaration for g.v. and #define */
static Y_OS_TMR *OSTmr_Alloc (void);
static void OSTmr_Free (Y_OS_TMR *ptmr); /* static func declaration */
#if Y_OS_TMR_EN >=1u
/*
**********************************************************************************
*
* OS_SetLedMod
*
*Description : this function is called to set the led light mode
*
*Arguments : Y_INT8U led1,
* Y_INT8U led2,
* Y_INT8U led3,
* Y_INT8U led4, each led mode
*
*Returns : none
*
*Notes : none
*
**********************************************************************************
*/
void OS_SetLedMod (Y_INT8U led1,Y_INT8U led2,Y_INT8U led3,Y_INT8U led4)
{
LED_1=led1;
LED_2=led2;
LED_3=led3;
LED_4=led4;
}
/*
**********************************************************************************
*
* OS_MemClr
*
*Description : this function is called to clear the mem by Byte
*
*Arguments : Y_INT8U *pdest, the destination of mem we want to clear
* Y_INT32U size, the range of the mem
*
*Returns : none
*
*Notes : none
*
**********************************************************************************
*/
void OS_MemClr (Y_INT8U *pdest,
Y_INT32U size)
{
while (size > 0u) {
*pdest++ = (Y_INT8U)0; /* clear the mem by Byte */
size--;
}
}
/*
**********************************************************************************
*
* memConCpy
*
*Description : this function is called to copy the content by byte
*
*Arguments : X_INT8U *pdest, the destination of place we want to copy
* Y_INT8U *psrc ,the source of the content
*
*Returns : Y_INT8U true
*
*Notes : none
*
**********************************************************************************
*/
Y_INT8U memConCpy(Y_INT8U *pdest,Y_INT8U *psrc){
while (*psrc != (Y_INT8U)0) {
*pdest = *psrc;
psrc++;
pdest++;
}
*pdest=(Y_INT8U)0;
return (Y_OS_TRUE);
}
/*
**********************************************************************************
*
* OS_StrLen
*
*Description : this function is called to get the length of the source content
*
*Arguments : Y_INT8U *psrc ,the src where we want to measure
*
*Returns : Y_INT8U the length of the src str,
*
*Notes : we assume that the src could only be a str,so the len is greater than
* the true length,for '\0'
*
**********************************************************************************
*/
Y_INT8U OS_StrLen (Y_INT8U *psrc)
{
Y_INT8U len;
len = 0u;
while (*psrc != (Y_INT8U)0) {
psrc++;
len++;
}
len++; /* ensure it has a 0 pos for char */
return (len);
}
/*
**********************************************************************************
*
* OSTmr_Alloc
*
*Description : this function is called to get a timer from the timer pool
*
*Arguments : none
*
*Returns : the pointer to the timer, we just alloc
*
*Notes : none
*
**********************************************************************************
*/
#if Y_OS_TMR_EN > 0u
static Y_OS_TMR *OSTmr_Alloc (void)
{
Y_OS_TMR *ptmr;
if (OSTmrFreeList == (Y_OS_TMR *)0) {
return ((Y_OS_TMR *)0);
}
ptmr = (Y_OS_TMR *)OSTmrFreeList;
OSTmrFreeList = (Y_OS_TMR *)ptmr->OSTmrNext;
ptmr->OSTmrNext = (void *)0;
ptmr->OSTmrPrev = (void *)0;
OSTmrUsed++;
OSTmrFree--;
return (ptmr);
}
#endif
/*
**********************************************************************************
*
* OSTmr_Free
*
*Description : this function is called to free the timer to the timer pool
*
*Arguments : Y_OS_TMR *ptmr ,point to the timer which we want to free
*
*Returns : none
*
*Notes : none
*
**********************************************************************************
*/
#if Y_OS_TMR_EN > 0u
static void OSTmr_Free (Y_OS_TMR *ptmr)
{
ptmr->OSTmrState = OS_TMR_STATE_UNCREATE; /* Clear timer object fields */
ptmr->OSTmrOpt = OS_TMR_OPT_NONE;
ptmr->OSTmrPeriod = 0u;
ptmr->OSTmrforWheel = 0u;
ptmr->OSTmrDly = 0u;
ptmr->OSTmrPrev = (void *)0; /* Chain timer to free list */
ptmr->OSTmrNext = OSTmrFreeList;
OSTmrFreeList = ptmr;
OSTmrUsed--; /* Update timer object statistics */
OSTmrFree++;
}
#endif
/*
**********************************************************************************
*
* manage_task
*
*Description : This function is the entry function for the management task,
* which subtracts the wheel's timing by 1, takes the timer off the wheel
* if the first item of the wheel is 0, determines whether to time it again
* based on the type of timer, and sends a message to the task that
* corresponds to the timer
*
*Arguments : none
*
*Returns : none
*
*Notes : none
*
**********************************************************************************
*/
void manage_task(void)
{
while(1)
{
semTake(semForSignal, WAIT_FOREVER);/* an interupt has happened */
if(timerWheel.OSTmrFirst != (Y_OS_TMR *)0){/* if there are timers in the wheel */
semTake(semForWheel,WAIT_FOREVER);
timerWheel.OSTmrFirst->OSTmrforWheel--;
/* printf("\nthe first timer is %d and it remains -> %d ",timerWheel.OSTmrFirst->TaskID,timerWheel.OSTmrFirst->OSTmrforWheel);*/
while(timerWheel.OSTmrFirst!=(Y_OS_TMR *)0 && timerWheel.OSTmrFirst->OSTmrforWheel == 0){
Y_OS_TMR *del;
del=OSTmr_Unlink(timerWheel.OSTmrFirst);
/*printf("\nbegin to get rid of node");*/
/*if(del!=((Y_OS_TMR *)0))printf("\ndel not null");*/
if(del->OSTmrOpt==OS_TMR_OPT_PERIODIC){
/* printf("begin to link again");*/
OSTmr_Link(del,OS_TMR_LINK_PERIODIC);
/* send msg to the task */
sendMsg((Y_INT32U)del,del->TaskID,OS_TMR_MSG_RE_RUNNING | MSG_FROM_TIMER,OS_MSG_OPT_NO_CONTENT,(void *)0);
}else{
/*printf("\none shot");*/
/* send msg to the task */
sendMsg((Y_INT32U)del,del->TaskID,OS_TMR_STATE_COMPLETED | MSG_FROM_TIMER,OS_MSG_OPT_NO_CONTENT,(void *)0);
}
}
semGive(semForWheel);
}
}
}
/*
**********************************************************************************
*
* isrGive
*
*Description : This function is connected to the Interrupt service routine
*
*Arguments : int arg ,no effect
*
*Returns : none
*
*Notes : none
*
**********************************************************************************
*/
void isrGive(int arg){
arg=arg;
tickAnnounce();
semGive(semForSignal);
}
/*
**********************************************************************************
*
* gvInit
*
*Description : this function is called to init the g.v. and the timer pool and the wheel
* and connect the func to the ISR
*
*Arguments : none
*
*Returns : Y_INT8U err code
* Y_OS_FALSE : false
* Y_OS_TRUE : true
*
*Notes : none
*
**********************************************************************************
*/
Y_INT8U gvInit(){
Y_INT8U i=0u;
OSTmrFreeList = (void *)0;
semForSignal = semBCreate(SEM_Q_FIFO, SEM_EMPTY);
semForWheel = semMCreate(SEM_Q_PRIORITY);
semForTmrPool = semMCreate(SEM_Q_PRIORITY); /* init the sem for g.v. ,the sem is Mutex or Binary*/
LED_1=0u;
LED_2=0u;
LED_3=0u;
LED_4=0u;
Led_Init();
/*printf("\nthe semForSignal id is -> 0x%x",(Y_INT32U)semForSignal);
printf("\nthe semForWheel id is -> 0x%x",(Y_INT32U)semForWheel);
printf("\nthe semForTmrPool id is -> 0x%x",(Y_INT32U)semForTmrPool); */
printf("\ncreate sem succeed");
for(i;i<TASK_NUM_MAX;i++){
msgQue[i] = msgQCreate(MSG_Q_SIZE,sizeof(Y_MSG),MSG_Q_FIFO);
/*printf("\nthe msgQue %d id is -> 0x%x",i+1,(Y_INT32U)msgQue[i]); */
}
printf("\ncreate msgQue succeed\n\n");
timerWheel.OSTmrFirst=(Y_OS_TMR *)0;
timerWheel.OSTmrEntries=0u;
OSTmr_Init(); /* init the timerEntity change it to a linklist , but there is no timer running*/
tid_manage_task = taskSpawn ("manage_task", 10, 0, STACK_SIZE,(FUNCPTR)manage_task,0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
/* create the manage task so it can deal with the wheel */
sysClkConnect((FUNCPTR)isrGive,0); /* connect the tmr isr*/
return Y_OS_TRUE; /* return the err code */
}
/*
**********************************************************************************
*
* OSTmr_Init
*
*Description : this function is called to init the timer pool
*
*Arguments : none
*
*Returns : none
*
*Notes : none
*
**********************************************************************************
*/
#if Y_OS_TMR_EN > 0u
void OSTmr_Init (void)
{
#if OS_TMR_NUM > 1u
Y_INT8U ix;
Y_INT8U ix_next;
Y_OS_TMR *ptmr1;
Y_OS_TMR *ptmr2;
OS_MemClr((Y_INT8U *)&timerEntity[0], sizeof(timerEntity)); /* Clear all the TMRs */
OS_MemClr((Y_INT8U *)&timerWheel, sizeof(timerWheel)); /* Clear the timer wheel */
for (ix = 0u; ix < (OS_TMR_NUM - 1u); ix++) { /* Init. list of free TMRs */
ix_next = ix + 1u;
ptmr1 = &timerEntity[ix];
ptmr2 = &timerEntity[ix_next];
ptmr1->OSTmrType = THIS_IS_TIMER;
ptmr1->OSTmrState = OS_TMR_STATE_UNCREATE; /* Indicate that timer is inactive */
ptmr1->OSTmrNext = (void *)ptmr2; /* Link to next timer */
}
ptmr1 = &timerEntity[ix];
ptmr1->OSTmrType = THIS_IS_TIMER;
ptmr1->OSTmrState = OS_TMR_STATE_UNCREATE; /* Indicate that timer is inactive */
ptmr1->OSTmrNext = (void *)0; /* Last OS_TMR */
OSTmrUsed = 0u;
OSTmrFree = OS_TMR_NUM;
OSTmrFreeList = &timerEntity[0];
#endif
}
#endif
/*
**********************************************************************************
*
* OSTmrCreate
*
*Description : this function is called to create the timer, and the timer state changed
* OS_TMR_STATE_UNCREATE -> OS_TMR_STATE_UNUSED
*
*Arguments : Y_INT32U dly, the tick we want to delay ,used for the OS_TMR_OPT_ONE_SHOT
* Y_INT32U period, the period tick for the timer ,userd for the OS_TMR_OPT_PERIODIC
* Y_INT8U opt, there are two options :
* OS_TMR_OPT_ONE_SHOT :timer for one time mode
* OS_TMR_OPT_PERIODIC :period timer mode
* Y_INT8U *perr, err code
* Y_INT8U taskId, the id of the task which own the timer
*
*Returns : Y_OS_TMR* the pointer of the timer
*
*Notes : none
*
**********************************************************************************
*/
#if Y_OS_TMR_EN > 0u
Y_OS_TMR *OSTmrCreate (Y_INT32U dly,
Y_INT32U period,
Y_INT8U opt,
Y_INT8U *perr,
Y_INT8U taskId)
{
Y_OS_TMR *ptmr;
#if Y_OS_ARG_CHK_EN > 0u
switch (opt) { /* Validate arguments */
case OS_TMR_OPT_PERIODIC:
if (period == 0u) {
*perr = OS_CREATE_ERR_TMR_INVALID_PERIOD;
return ((Y_OS_TMR *)0);
}
break;
case OS_TMR_OPT_ONE_SHOT:
if (dly == 0u) {
*perr = OS_CREATE_ERR_TMR_INVALID_DLY;
return ((Y_OS_TMR *)0);
}
break;
default:
*perr = OS_CREATE_ERR_TMR_INVALID_OPT;
return ((Y_OS_TMR *)0);
}
#endif
semTake(semForTmrPool,WAIT_FOREVER);
ptmr = OSTmr_Alloc(); /* Obtain a timer from the free pool */
if (ptmr == (Y_OS_TMR *)0) {
semGive(semForTmrPool);
*perr = OS_CREATE_ERR_TMR_NON_AVAIL;
return ((Y_OS_TMR *)0);
}
ptmr->OSTmrState = OS_TMR_STATE_UNUSED; /* Indicate that timer is not used yet */
ptmr->OSTmrDly = dly;
ptmr->OSTmrPeriod = period;
ptmr->OSTmrOpt = opt;
ptmr->TaskID = taskId;
semGive(semForTmrPool);
*perr = OS_CREATE_ERR_NONE;
return (ptmr);
}
#endif
/*
**********************************************************************************
*
* OSTmrStart
*
*Description : this function is called to start the timer
*
*Arguments : Y_OS_TMR *ptmr, the pointer point to the timer
* Y_INT8U *perr, err code
*
*Returns : Y_INT8U err code
* Y_OS_FALSE : false
* Y_OS_TRUE : true
*Notes : none
*
**********************************************************************************
*/
#if Y_OS_TMR_EN > 0u
Y_INT8U OSTmrStart (Y_OS_TMR *ptmr,
Y_INT8U *perr)
{
#if Y_OS_ARG_CHK_EN > 0u
if (ptmr == (Y_OS_TMR *)0) {
*perr = OS_START_ERR_TMR_INVALID;
return (Y_OS_FALSE);
}
#endif
if (ptmr->OSTmrType != THIS_IS_TIMER) { /* Validate timer structure */
*perr = OS_START_ERR_TMR_INVALID_TYPE;
return (Y_OS_FALSE);
}
semTake(semForWheel,WAIT_FOREVER);
switch (ptmr->OSTmrState) {
case OS_TMR_STATE_RUNNING: /* Restart the timer */
OSTmr_Unlink(ptmr); /* ... Stop the timer */
OSTmr_Link(ptmr, OS_TMR_LINK_DLY); /* ... Link timer to timer wheel */
semGive(semForWheel);
*perr = OS_START_ERR_NONE;
return (Y_OS_TRUE);
case OS_TMR_STATE_STOPPED: /* if the timer is stopped,continue it */
OSTmr_Link(ptmr, OS_TMR_LINK_CONTINUE); /* ... Link timer to timer wheel */
semGive(semForWheel);
*perr = OS_START_ERR_NONE;
return (Y_OS_TRUE);
case OS_TMR_STATE_UNUSED:
case OS_TMR_STATE_COMPLETED:
OSTmr_Link(ptmr, OS_TMR_LINK_DLY);
/* if the timer is not start ,Link timer to timer wheel start it for the first time */
semGive(semForWheel);
*perr = OS_START_ERR_NONE;
return (Y_OS_TRUE);
case OS_TMR_STATE_UNCREATE: /* Timer not created */
semGive(semForWheel);
*perr = OS_START_ERR_TMR_INACTIVE;
return (Y_OS_FALSE);
default:
semGive(semForWheel);
*perr = OS_START_ERR_TMR_INVALID_STATE;
return (Y_OS_FALSE);
}
}
#endif
/*
**********************************************************************************
*
* OSTmrStop
*
*Description : this function is called to stop the timer,and sent a msg to the task which own the timer
*
*Arguments :Y_OS_TMR *ptmr, the pointer point to the timer
* Y_INT8U opt, the msg which we want to send ,has content?
* void *msgContent,msg content
* Y_INT8U *perr,err code
*
*Returns : Y_INT8U true or false
*
*Notes : none
*
**********************************************************************************
*/
#if Y_OS_TMR_EN > 0u
Y_INT8U OSTmrStop (Y_OS_TMR *ptmr,
Y_INT8U opt,
void *msgContent,
Y_INT8U *perr)
{
Y_MSG msg;
#if Y_OS_ARG_CHK_EN > 0u
if (ptmr == (Y_OS_TMR *)0) {
*perr = OS_STOP_ERR_TMR_INVALID;
return (Y_OS_FALSE);
}
#endif
if (ptmr->OSTmrType != THIS_IS_TIMER) { /* Validate timer structure */
*perr = OS_STOP_ERR_TMR_INVALID_TYPE;
return (Y_OS_FALSE);
}
semTake(semForWheel,WAIT_FOREVER);
switch (ptmr->OSTmrState) {
case OS_TMR_STATE_RUNNING:
OSTmr_Unlink(ptmr); /* Remove from current wheel spoke */
semGive(semForWheel);
*perr = OS_STOP_ERR_NONE;
sendMsg((Y_INT32U)ptmr,ptmr->TaskID,OS_TMR_STATE_STOPPED | MSG_FROM_TIMER,opt,msgContent);
return (Y_OS_TRUE_WITH_MSG);
case OS_TMR_STATE_COMPLETED: /* Timer has already completed the ONE-SHOT or ... */
case OS_TMR_STATE_STOPPED: /* ... timer has STOP yet. */
semGive(semForWheel);
*perr = OS_STOP_ERR_TMR_STOPPED;
return (Y_OS_TRUE);
case OS_TMR_STATE_UNCREATE:
case OS_TMR_STATE_UNUSED: /* Timer was not created or not used */
semGive(semForWheel);
*perr = OS_STOP_ERR_TMR_INACTIVE;
return (Y_OS_FALSE);
default:
semGive(semForWheel);
*perr = OS_STOP_ERR_TMR_INVALID_STATE;
return (Y_OS_FALSE);
}
}
#endif
/*
**********************************************************************************
*
* OSTmrDel
*
*Description : this function is called to delete the timer,unlink the timer from the wheel
* free the timer
*
*Arguments :Y_OS_TMR *ptmr, the pointer point to the timer
* Y_INT8U *perr, err code
*
*Returns : Y_INT8U true or false
*
*Notes : none
*
**********************************************************************************
*/
#if Y_OS_TMR_EN > 0u
Y_INT8U OSTmrDel (Y_OS_TMR *ptmr,
Y_INT8U *perr)
{
#if Y_OS_ARG_CHK_EN > 0u
if (ptmr == (Y_OS_TMR *)0) {
*perr = OS_DEL_ERR_TMR_INVALID;
return (Y_OS_FALSE);
}
#endif
if (ptmr->OSTmrType != THIS_IS_TIMER) { /* Validate timer structure */
*perr = OS_DEL_ERR_TMR_INVALID_TYPE;
return (Y_OS_FALSE);
}
semTake(semForWheel,WAIT_FOREVER);
switch (ptmr->OSTmrState) {
case OS_TMR_STATE_RUNNING:
OSTmr_Unlink(ptmr); /* Remove from current wheel spoke */
OSTmr_Free(ptmr); /* Return timer to free list of timers */
semGive(semForWheel);
*perr = OS_DEL_ERR_NONE;
return (Y_OS_TRUE);
case OS_TMR_STATE_UNUSED:
case OS_TMR_STATE_STOPPED: /* Timer has not started or been stopped. */
case OS_TMR_STATE_COMPLETED: /* ... timer has completed the ONE-SHOT time */
OSTmr_Free(ptmr); /* Return timer to free list of timers */
semGive(semForWheel);
*perr = OS_DEL_ERR_NONE;
return (Y_OS_TRUE);
case OS_TMR_STATE_UNCREATE: /* Already deleted */
semGive(semForWheel);
*perr = OS_DEL_ERR_TMR_INACTIVE;
return (Y_OS_FALSE);
default:
semGive(semForWheel);
*perr = OS_DEL_ERR_TMR_INVALID_STATE;
return (Y_OS_FALSE);
}
}
#endif
/*
**********************************************************************************
*
* OSTmrRemainGet
*
*Description : get the tick count of the timer remain
*
*Arguments : Y_OS_TMR *ptmr, the pointer point to the timer
* Y_INT8U *perr, err code
*
*Returns : Y_INT32U the tick count of the timer remain
*
*Notes : none
*
**********************************************************************************
*/
#if Y_OS_TMR_EN > 0u
Y_INT32U OSTmrRemainGet (Y_OS_TMR *ptmr,
Y_INT8U *perr)
{
Y_INT32U remain;
#if Y_OS_ARG_CHK_EN > 0u
if (ptmr == (Y_OS_TMR *)0) {
*perr = OS_REMAIN_ERR_TMR_INVALID;
return (0u);
}
#endif
if (ptmr->OSTmrType != THIS_IS_TIMER) { /* Validate timer structure */
*perr = OS_REMAIN_ERR_TMR_INVALID_TYPE;
return (0u);
}
semTake(semForWheel,WAIT_FOREVER);
switch (ptmr->OSTmrState) {
case OS_TMR_STATE_RUNNING:
remain = OSTmr_Remain(ptmr); /* Determine how much time is left to timeout */
semGive(semForWheel);
*perr = OS_REMAIN_ERR_NONE;
return (remain);
case OS_TMR_STATE_STOPPED: /* It's assumed that the timer has not started yet */
remain = ptmr->OSTmrforWheel;
semGive(semForWheel);
*perr = OS_REMAIN_ERR_NONE;
return (remain);
case OS_TMR_STATE_COMPLETED: /* Only ONE-SHOT that timed out can be in this state */
semGive(semForWheel);
*perr = OS_REMAIN_ERR_NONE;
return (0u);
case OS_TMR_STATE_UNCREATE:
case OS_TMR_STATE_UNUSED:
semGive(semForWheel);
*perr = OS_REMAIN_ERR_TMR_INACTIVE;
return (0u);
default:
semGive(semForWheel);
*perr = OS_REMAIN_ERR_TMR_INVALID_STATE;
return (0u);
}
}
#endif
/*
**********************************************************************************
*
* OSTmrStateGet
*
*Description : this function is called to get the state of the timer
*
*Arguments : Y_OS_TMR *ptmr, the pointer point to the timer
* Y_INT8U *perr, err code
*
*Returns : Y_INT8U timer state
*
*Notes : none
*
**********************************************************************************
*/
#if Y_OS_TMR_EN > 0u
Y_INT8U OSTmrStateGet (Y_OS_TMR *ptmr,
Y_INT8U *perr)
{
Y_INT8U state;
#if Y_OS_ARG_CHK_EN > 0u
if (ptmr == (Y_OS_TMR *)0) {
*perr = OS_GET_ERR_TMR_INVALID;
return (0u);
}
#endif
if (ptmr->OSTmrType != THIS_IS_TIMER) { /* Validate timer structure */
*perr = OS_GET_ERR_TMR_INVALID_TYPE;
return (0u);
}
state = ptmr->OSTmrState;
switch (state) {
case OS_TMR_STATE_UNCREATE:
case OS_TMR_STATE_UNUSED:
case OS_TMR_STATE_STOPPED:
case OS_TMR_STATE_COMPLETED:
case OS_TMR_STATE_RUNNING:
*perr = OS_GET_ERR_NONE;
break;
default:
*perr = OS_GET_ERR_TMR_INVALID_STATE;
break;
}
return (state);
}
#endif
/*
**********************************************************************************
*
* sendMsg
*
*Description : this function is called to send a msg to the associate task
*
*Arguments : Y_INT32U TimerID,
* Y_INT8U TaskID,
* Y_INT8U msgtype,
* Y_INT8U opt,
* (void *)content
*
*Returns : none
*
*Notes : none
*
**********************************************************************************
*/
Y_INT8U sendMsg(Y_INT32U TimerID,Y_INT8U TaskID,Y_INT8U msgtype,Y_INT8U opt,void *content){
Y_MSG msg;
Y_INT8U perr;
msg.TimerID=TimerID;
msg.TaskID =TaskID;
msg.MSGTYPE=msgtype;
switch (opt) {
case OS_MSG_OPT_HAVE_CONTENT:
if(OS_StrLen(content) >= sizeof((void *)0) ) {
msg.MSGTYPE|=OS_MSG_CONTENT_IS_POINTER;
msg.CONTENT=content;
}else{
memConCpy((Y_INT8U *)&msg.CONTENT,(Y_INT8U *)content);
}
break;
case OS_MSG_OPT_NO_CONTENT:
msg.CONTENT=(void *)0;
break;
default:
perr = OS_MSG_INVALID_OPT;
return perr;
}
msgQSend(msgQue[TaskID],(char *)&msg,sizeof(Y_MSG),WAIT_FOREVER ,MSG_PRI_NORMAL );
return OS_DEL_ERR_NONE;
}
/*
**********************************************************************************
*
* showMsg
*
*Description : this function is called to receive a msg from the msgQ
*
*Arguments : Y_INT8U taskId,the id of the task which associate to the msgQ
*
*Returns : none
*
*Notes : none
*
**********************************************************************************
*/
Y_INT8U showMsg(Y_INT8U taskId){
Y_MSG msg;
printf("\n\ntask %d waiting for msg",taskId);
/* receive msg from queue */
msgQReceive(msgQue[taskId],(char *)&msg,sizeof(Y_MSG),WAIT_FOREVER);
printf("\n\nreceive a msg to task %d",taskId);
if((Y_INT8U)(msg.MSGTYPE & MSG_FROM_TIMER) == (Y_INT8U)MSG_FROM_TIMER ){
printf("\nreceiveMsg from Timer[%d] to Task[%d] ->",msg.TimerID,msg.TaskID);
printf("\nthe timer state is %d :",msg.MSGTYPE & (Y_INT8U)63u);
if(msg.CONTENT != (void *)0){/* if the content is not null */
if((Y_INT8U)(msg.MSGTYPE & OS_MSG_CONTENT_IS_POINTER) == (Y_INT8U)OS_MSG_CONTENT_IS_POINTER){
printf("\nthe msg content is a pointer, and it point to -> %s ",(char *)msg.CONTENT);
}else{
printf("\nthe msg content is a content, and its content is -> %s \n",(char *)&msg.CONTENT);
}/* show the content depent on the msg_type */
}else{
printf("\nthe msg content is null \n");
}
if(((Y_INT8U)(msg.MSGTYPE & OS_TMR_STATE_COMPLETED) == (Y_INT8U)OS_TMR_STATE_COMPLETED) ||(Y_INT8U)(msg.MSGTYPE & OS_TMR_MSG_RE_RUNNING) == (Y_INT8U)OS_TMR_MSG_RE_RUNNING) return Y_OS_TRUE;
}else{
printf("\nthe msg is not from timer");
printf("\n%d %d %d \n",msg.MSGTYPE,MSG_FROM_TIMER,msg.MSGTYPE & MSG_FROM_TIMER);
}
return Y_OS_FALSE;
}
#endif
(四)y_wheel.c
#include "y_os_cfg.h" /* declaration for g.v. and #define */
/*
**********************************************************************************
*
* showWheel
*
*Description : show the timer->OSTmrforWheel in the wheel
*
*Arguments : none
*
*Returns : none
*
*Notes : none
*
**********************************************************************************
*/
void showWheel(){
Y_OS_TMR *pwheel = timerWheel.OSTmrFirst;
printf("\n");
if(pwheel==((Y_OS_TMR *)0)){printf("\nwheel is null");}
while(pwheel != (Y_OS_TMR *)0){
printf("%d ",pwheel->OSTmrforWheel);
pwheel=pwheel->OSTmrNext;
}
printf("\n");
}
/*
**********************************************************************************
*
* OSTmr_Link
*
*Description : this function is called to Link the timer to the wheel
*
*Arguments : Y_OS_TMR *ptmr,the pointer to the timer
* Y_INT8U type, link type :OS_TMR_LINK_PERIODIC OS_TMR_LINK_DLY OS_TMR_LINK_CONTINUE
*
*Returns : none
*
*Notes : none
*
**********************************************************************************
*/
void OSTmr_Link(Y_OS_TMR *ptmr,Y_INT8U type){
Y_OS_TMR *pwheel = timerWheel.OSTmrFirst;
printf("\ntask %d timer begin to link to wheel",ptmr->TaskID);
showWheel();
if(type == OS_TMR_LINK_PERIODIC){
ptmr->OSTmrforWheel = ptmr->OSTmrPeriod;
}
if(type == OS_TMR_LINK_DLY){
if(ptmr->OSTmrDly != 0u) {
ptmr->OSTmrforWheel=ptmr->OSTmrDly;
}else ptmr->OSTmrforWheel = ptmr->OSTmrPeriod;
}
if(type == OS_TMR_LINK_CONTINUE){
if(ptmr->OSTmrforWheel!=0u){
ptmr->OSTmrforWheel=ptmr->OSTmrforWheel;
}else{
if(ptmr->OSTmrDly != 0u) {
ptmr->OSTmrforWheel=ptmr->OSTmrDly;
}else ptmr->OSTmrforWheel = ptmr->OSTmrPeriod;
}
}
ptmr->OSTmrState = OS_TMR_STATE_RUNNING;
if(pwheel ==(Y_OS_TMR *)0){
timerWheel.OSTmrFirst=ptmr;
ptmr->OSTmrNext = (void *)0;
ptmr->OSTmrPrev = (void *)0; /* if pwheel is 0, it indicate that the timer is the first one of the list*/
}else{
while(1){
if(ptmr->OSTmrforWheel<=pwheel->OSTmrforWheel){
/* if the timer's OSTmrforWheel <= pwheel's OSTmrforWheel, so insert the timer before the pwheel */
if(pwheel->OSTmrPrev == (void *)0){
ptmr->OSTmrNext=(void *)pwheel;
ptmr->OSTmrPrev=(void *)0;
pwheel->OSTmrPrev=(void *)ptmr;
timerWheel.OSTmrFirst=ptmr; /* if the pwheel is the first node in the list */
}else{
((Y_OS_TMR *)pwheel->OSTmrPrev)->OSTmrNext=(void *)ptmr;
ptmr->OSTmrPrev=pwheel->OSTmrPrev;
pwheel->OSTmrPrev=(void *)ptmr;
ptmr->OSTmrNext=(void *)pwheel; /* the normal case */
}
break;
}else{ /* if the timer's OSTmrforWheel > pwheel's OSTmrforWheel */
ptmr->OSTmrforWheel-=pwheel->OSTmrforWheel;
if(pwheel->OSTmrNext==(void *)0)
{
pwheel->OSTmrNext=(void *)ptmr;
ptmr->OSTmrPrev=(void *)pwheel;
ptmr->OSTmrNext=(void *)0;
/* if pwheel is the last node in the list, so the timer should be insert after the last node */
break;
}else{
pwheel=(Y_OS_TMR *)pwheel->OSTmrNext;/* pwheel point to the next node */
}
}
}
}
if(ptmr->OSTmrNext!=(void *)0){
((Y_OS_TMR *)ptmr->OSTmrNext)->OSTmrforWheel=((Y_OS_TMR *)ptmr->OSTmrNext)->OSTmrforWheel - ptmr->OSTmrforWheel;
} /* if an insert have occured, the node after the timer which insert just now should change it's OSTmrforWheel */
timerWheel.OSTmrEntries++;
printf("\ntask %d timer after link to wheel",ptmr->TaskID);
showWheel();
}
/*
**********************************************************************************
*
* OSTmr_Unlink
*
*Description : this function is called to unlink the timer from the wheel
*
*Arguments : Y_OS_TMR *ptmr,the pointer to the timer
*
*Returns : Y_OS_TMR * the pointer to the timer ,which is already delete
*
*Notes : none
*
**********************************************************************************
*/
Y_OS_TMR * OSTmr_Unlink(Y_OS_TMR *ptmr){
printf("\ntask %d timer begin to unlink from wheel",ptmr->TaskID);
showWheel();
if(ptmr->OSTmrNext!=(void *)0){
((Y_OS_TMR *)ptmr->OSTmrNext)->OSTmrforWheel+=ptmr->OSTmrforWheel;
}/* if the timer will be unlink, we should change the OSTmrforWheel which after the timer at first */
ptmr->OSTmrforWheel=OSTmr_Remain(ptmr);/* get the ramain tick count */
if(ptmr->OSTmrPrev==(void *)0){
timerWheel.OSTmrFirst=ptmr->OSTmrNext;
if(ptmr->OSTmrNext!=(void *)0){
((Y_OS_TMR *)ptmr->OSTmrNext)->OSTmrPrev=(void *)0;
}/* if the timer is the first timer in the list */
}else{
((Y_OS_TMR *)ptmr->OSTmrPrev)->OSTmrNext=ptmr->OSTmrNext;
if(ptmr->OSTmrNext!=(void *)0){
((Y_OS_TMR *)ptmr->OSTmrNext)->OSTmrPrev=ptmr->OSTmrPrev;
}/* nomal case */
}
ptmr->OSTmrNext=(void *)0;
ptmr->OSTmrPrev=(void *)0;/* init the two pointer */
if(ptmr->OSTmrforWheel == 0u){
ptmr->OSTmrState = OS_TMR_STATE_COMPLETED;
}else{
ptmr->OSTmrState = OS_TMR_STATE_STOPPED;
}/* decide which state the timer should be */
timerWheel.OSTmrEntries--;
printf("\ntask %d timer after unlink from wheel",ptmr->TaskID);
showWheel();
return ptmr;
}
/*
**********************************************************************************
*
* OSTmr_Remain
*
*Description : this function is called to get the tick count of the timer which in the wheel
*
*Arguments : Y_OS_TMR *ptmr,the pointer to the timer
*
*Returns : none
*
*Notes : none
*
**********************************************************************************
*/
Y_INT32U OSTmr_Remain(Y_OS_TMR *ptmr){
Y_INT32U res =0u;
Y_OS_TMR *pwheel=ptmr;
while(pwheel!=(Y_OS_TMR *)0){
res+=pwheel->OSTmrforWheel;
pwheel=(Y_OS_TMR *)pwheel->OSTmrPrev;
}
return res;
}
(五)y_led.c
#include "y_os_cfg.h"
/*#define rGPBCON (*(volatile unsigned *)0x56000010)/* control */
/*#define rGPBDAT (*(volatile unsigned *)0x56000014)/* data */
/*#define rGPBUP (*(volatile unsigned *)0x56000018)/* pull up */
/* For testing purposes, change the #define definition that gets the value from memory to a normal constant definition */
Y_INT32U rGPBCON =1u;/* control */
Y_INT32U rGPBDAT =2u;/* data */
Y_INT32U rGPBUP =3u;/* pull up */
Y_INT8U TIME = 0u;
/*
**********************************************************************************
*
* Led_Init
*
*Description : This function is used to initialize the variable about the light
*
*Arguments : none
*
*Returns : none
*
*Notes : none
*
**********************************************************************************
*/
void Led_Init(void){
rGPBCON = (rGPBCON & (~(0xff<<10))) | 1u<<10 | 1u<<12 | 1u<<14 | 1u<<16 ;
rGPBUP = (rGPBUP & ~ (0xf<<5));
rGPBDAT = (rGPBDAT | (0xf<<5));
/* The light comes on when the level is low, High level initialization, keep the light off*/
}
/*
**********************************************************************************
*
* Led_Turn_On
*
*Description : This function is used to turn on the specified light
*
*Arguments : Y_INT8U led_pos:the id of the light we want to light
*
*Returns : none
*
*Notes : none
*
**********************************************************************************
*/
void Led_Turn_On(Y_INT8U led_pos){
Y_INT8U pos = (led_pos - 1u) % 4u;
rGPBDAT = rGPBDAT & (~(( 1u << pos ) << 5u));
printf("\nled %d is light up",led_pos);
}
/*
**********************************************************************************
*
* Led_Turn_Down
*
*Description : This function is used to turn off the specified light
*
*Arguments : Y_INT8U led_pos:the led id which we want to turn off
*
*Returns : none
*
*Notes : none
*
**********************************************************************************
*/
void Led_Turn_Down(Y_INT8U led_pos){
Y_INT8U pos = (led_pos - 1u) % 4u;
rGPBDAT = rGPBDAT |(( 1u << pos ) << 5u);
/*printf("\nled %d is power off",led_pos);*/
}
/*
**********************************************************************************
*
* Led_Show_Time
*
*Description : Turn on the light in the specified mode
*
*Arguments : none
*
*Returns : none
*
*Notes : none
*
**********************************************************************************
*/
void Led_Show_Time(void){
Y_INT8U i=0u;
printf("\nthis is show time");
for(i=1u;i<=4u;i++){
Led_Turn_Down(i);
}
if((Y_INT8U)(LED_1 & (128u>>TIME)) == (128u>>TIME)) Led_Turn_On(1);
if((Y_INT8U)(LED_2 & (128u>>TIME)) == (128u>>TIME)) Led_Turn_On(2);
if((Y_INT8U)(LED_3 & (128u>>TIME)) == (128u>>TIME)) Led_Turn_On(3);
if((Y_INT8U)(LED_4 & (128u>>TIME)) == (128u>>TIME)) Led_Turn_On(4);
TIME++;
if(TIME >= 8)TIME=0u;
}
(六)test.c
#include "y_os_cfg.h"
int tidTest;
int tidTest2;
void progStart(void);
void taskTestPeriord(int id);
void taskTestOneShot(int id);
void taskTestStop(int id);
void taskTestContent(int id);
void taskTestRemainAndGet(int id);
void progStop(void);
void progStart(void)
{
gvInit();
/* 0xae,0x53,0xe2,0x55 */
/* 0x78,0xb4,0xd2,0xe1 */
/* 0x88,0x44,0x22,0x11 */
/*
0111 1000
1011 0100
1101 0010
1110 0001
*/
/* Set the mode of the light */
OS_SetLedMod(0x78,0xb4,0xd2,0xe1);
/* The multi-task environment has two task */
/* There are five tests in total.
The first is test cycle timing,
the second is test single timing,
the third is test timer suspension operation,
the fourth is test message content automatic conversion format,
the fifth is test monitoring mechanism */
tidTest = taskSpawn ("ttest1", 160, 0, STACK_SIZE,
(FUNCPTR)taskTestOneShot,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
tidTest2 = taskSpawn ("ttest2", 180, 0, STACK_SIZE,
(FUNCPTR)taskTestPeriord,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0);
return;
}
/* Test periodic timer */
void taskTestPeriord(int id)
{
Y_OS_TMR *tmrPointer;
Y_INT8U perr=0u,res=0u,com=Y_OS_FALSE;
printf("\nget in the test task %d",id);
tmrPointer = OSTmrCreate(0,10,OS_TMR_OPT_PERIODIC,&perr,id);
printf("\ntask %d create timer %d -> %d ",id,(Y_INT32U)tmrPointer,perr);
perr=0u;
OSTmrStart(tmrPointer,&perr);
printf("\ntask %d start timer -> %d ",id,perr);
while(1){
com=showMsg(id);
if(com==Y_OS_TRUE)Led_Show_Time();
}
return;
}
/* Test one-shot timer */
void taskTestOneShot(int id)
{
Y_OS_TMR *tmrPointer;
Y_INT8U perr=0u,res=0u,com=Y_OS_FALSE;
printf("\nget in the test task %d",id);
while(1){
tmrPointer = OSTmrCreate(10,0,OS_TMR_OPT_ONE_SHOT,&perr,id);
printf("\ntask %d create timer %d -> %d ",id,(Y_INT32U)tmrPointer,perr);
perr=0u;
OSTmrStart(tmrPointer,&perr);
printf("\ntask %d start timer -> %d ",id,perr);
com=showMsg(id);
if(com==Y_OS_TRUE)Led_Show_Time();
OSTmrDel(tmrPointer,&perr);
printf("\ntask %d delete timer -> %d",id,perr);
}
return;
}
/* Test stop timer */
void taskTestStop(int id)
{
Y_OS_TMR *tmrPointer;
Y_INT8U perr=0u,res=0u;
printf("\nget in the test task");
tmrPointer = OSTmrCreate(0,100,OS_TMR_OPT_PERIODIC,&perr,id);
printf("\ntask %d create timer -> %d ",id,perr);
perr=0u;
OSTmrStart(tmrPointer,&perr);
printf("\ntask %d start timer -> %d ",id,perr);
perr=0u;
taskDelay(20);
printf("\ntask %d begin to delay",id);
res=OSTmrStop(tmrPointer,OS_MSG_OPT_NO_CONTENT,(void *)0,&perr);
if(res==Y_OS_TRUE_WITH_MSG){
showMsg(id);
}
printf("\ntask %d this is in stopping status\n",id);
taskDelay(20);
perr=0u;
OSTmrStart(tmrPointer,&perr);
printf("\ntask %d restart go on",id);
while(1){
showMsg(id);
}
return;
}
/* Test the msg content */
void taskTestContent(int id)
{
Y_OS_TMR *tmrPointer;
Y_INT8U perr=0u,res=0u;
printf("\nget in the test task %d",id);
while(1){
tmrPointer = OSTmrCreate(100,0,OS_TMR_OPT_ONE_SHOT,&perr,id);
printf("\ntask %d create timer %d -> %d ",id,(Y_INT32U)tmrPointer,perr);
perr=0u;
OSTmrStart(tmrPointer,&perr);
printf("\ntask %d start timer -> %d ",id,perr);
perr=0u;
taskDelay(20);
/* the content is "hello,zzz, so the content is a pointer point to the str"*/
/* the content is "a", so the content is the content */
printf("\ntask %d begin to delay",id);
res=OSTmrStop(tmrPointer,OS_MSG_OPT_HAVE_CONTENT,(void *)"h",&perr);
if(res==Y_OS_TRUE_WITH_MSG){
showMsg(id);
}
printf("\ntask %d this is in stopping status\n",id);
taskDelay(20);
perr=0u;
OSTmrStart(tmrPointer,&perr);
printf("\n\ntask %d restart go on",id);
showMsg(id);
OSTmrDel(tmrPointer,&perr);
printf("\ntask %d delete timer -> %d",id,perr);
}
return;
}
/* test monitoring mechanism */
void taskTestRemainAndGet(int id)
{
Y_OS_TMR *tmrPointer;
Y_INT8U perr=0u,res=0u;
printf("\nget in the test task %d",id);
while(1){
perr=0u;
tmrPointer = OSTmrCreate(100,0,OS_TMR_OPT_ONE_SHOT,&perr,id);
printf("\ntask %d create timer -> %d ",id,perr);
perr=0u;
OSTmrStart(tmrPointer,&perr);
printf("\ntask %d start timer -> %d ",id,perr);
taskDelay(20);
perr=0u;
res=OSTmrRemainGet(tmrPointer,&perr);
printf("\ntask %d remain the err code is %d,and the tick remain is %d",id,perr,res);
perr=0u;
res=OSTmrStateGet(tmrPointer,&perr);
printf("\ntask %d state get the err code is %d,and the state of the timer is %d",id,perr,res);
perr=0u;
showMsg(id);
printf("\ntask %d begin to del",id);
OSTmrDel(tmrPointer,&perr);
printf("\ntask %d delete timer -> %d",id,perr);
}
return;
}
void progStop(void)
{
taskDelete(tidTest);
taskDelete(tidTest2);
taskDelete(tid_manage_task);
printf("The End\n");
return;
}