ucos-ii 信号量实现机制,timer处理

    ucos-ii系统的timer(timer out)机制设计不知道是否合理,与rtk实时操作系统的比较感觉ucos-ii timer处理并不是很合理。

    ucos-ii的timer队列并不是有专门的定时器来递减,而是每个task都有一个timer队列,而每个个task的timer 队列只有当自己所属的task空闲的时候,才会去处理。

ucos-ii 的timer添加,想其它的实时内核一样,要添加一个timer的时候,会先判断当前task的timer队列里是否为空,为空就直接添加,不为空:

    如果要添加的timer比队列里的第一个timer大,就减去第一个后再比较,直到找到自己的位置,这个时候当前添加的timer值,加上队列前面的所有timer值的和,为要添加的timer的初始值。小的过程按同理来处理。

    添加完了timer之后ucos-ii并没有专门的函数来处理这个队列,而是在当前task等待消息(信号量,mailbox之类)的时候,会将timer队列里的成员从前到后,一个一个的timer值,写入到当前task的TCB->OSTCBDly里面,而这个值是直接被system tick终端来递减的。TCB->OSTCBDly值有两个作用,直接delay task,  或者等待事件发生。timer用在后者中。

当task回复运行的时候有两种可能:

    1. task等到evnet了,这个时候timer的时间还没有到,然后就直接用timer值减去等待的时间,再写入timer中。

    2. 时间到了但是没有等到event事件,这个时候timer值为零了,因为当task TCB->OSTCBDly为零时会发生调度。 这个时候timer列表的第一个值到了,然后调用timer回调函数。但是event事件我们还是要等到的,不然就被timer值给扰乱了,所以这个时候又会回去,用timer列表的原来的第二个(原来的第一个已经用掉了),并且继续等待event事件的发生。

ucos-ii这样的timer机制其实会导致误差的,并且一旦task down掉,依赖于task的timer就无法继续了,如果这个timer是定时必须要做的,那么可能整个系统都会挂了。不知道这么理解的对不对?


   ucos-ii系统的信号量机制:

   信号量,event,资源计数其实都是可以用event来实现的:

typedef struct os_event {
    INT8U    OSEventType;                    /* Type of event control block (see OS_EVENT_TYPE_xxxx)    */
    void    *OSEventPtr;                     /* Pointer to message or queue structure                   */
    INT16U   OSEventCnt;                     /* Semaphore Count (not used if other EVENT type)          */
    OS_PRIO  OSEventGrp;                     /* Group corresponding to tasks waiting for event to occur */
    OS_PRIO  OSEventTbl[OS_EVENT_TBL_SIZE];  /* List of tasks waiting for event to occur                */

#if OS_EVENT_NAME_EN > 0u
    INT8U   *OSEventName;
#endif

} OS_EVENT;

    后两个变量就是与对应的任务调度表对应的。

    第一个记录的是这个结构体记录的消息类型,有可能是flag,mailbox,mutex,queue,sem。

    第二个一般为传递的消息。

    第三个,是根据不同的类型的消息设置不同,比如mutex(互斥信号量)设置为1,用的时候+1,不用减1。   记录公共资源的使用数,这个可以为>0的数。  设置为0,一般是表示某个事件放生了。

    最后一个变量记录的是等待当前event事件发生的tasks,当事件发生的时候(OSSemPost()),会先将当前event等待task里找到优先级最高的放入系统的任务就绪表里面,然后从evnet的这个变量中删除等待的task。   其它的等待task 怎么办??????



信号量使用的函数如下:

   分配的时候用OSSemCreate(),

   等待用OSSemPend(), 发生调度。--------将当前task从任务就绪表中取出来,然后将其放入evnet结构体的最后一个变量中,也就是放入等待这个event事件发生的队列当中。

   通知用OSSemPost(),发生调度


你可能感兴趣的:(ucos-II)