uC/OS ii 系统时钟

系统时钟

  系统时钟节拍

  时钟节拍是特定的周期性中断(时钟中断),这个中断可以看作是系统心脏的脉动。操作系统通过时钟中断来确定时间间隔,实现时间的延时及确定任务超时。中断之间的时间间隔取决于不同的应用,一般在10~200 ms之间。时钟的节拍式中断使得内核可以将任务延时若干个整数时钟节拍,以及当任务等待事件发生时提供等待超时的依据。时钟节拍频率越快,系统的额外开销就越大。系统定义了32位无符号整数OSTime来记录系统启动后时钟滴答的数目。用户必须在多任务系统启动以后再开启时钟节拍器,也就是在调用 OSStart()之后。μC/OSII中的时钟节拍服务是通过在中断服务子程序中调用OSTimeTick()实现的。时钟节拍中断服务子程序的示意代码如下:

void OSTickISR(void) {

  保存处理器寄存器的值;

  调用OSIntEnter ()或是将OSIntNesting加1;

  调用OSTimeTick ();

  调用OSIntExit ();

  恢复处理器寄存器的值;

  执行中断返回指令;

}

 

2 时钟管理系统

2.1 ucos ii时钟管理系统

  ucos ii原有的时钟管理系统类似于Linux,但是比Linux简单得多。它仅向用户提供一个周期性的信号OSTime,时钟频率可以设置在 10~100 Hz,时钟硬件周期性地向CPU发出时钟中断,系统周期性响应时钟中断,每次时钟中断到来时,中断处理程序更新一个全局变量OSTime。ucos ii时钟中断服务程序的核心是调用OSTimeTick ()函数。OSTimeTick ()函数用来判断延时任务是否延时结束从而将其置于就绪态。其程序伪代码如下:

void OSTimeTick(void)

{

 OSTimeTickHook();// 调用用户定义的时钟节拍外连函数

 while { (除空闲任务外的所有任务)

  OS_ENTER_CRITICAL();//关中断

  对所有任务的延时时间递减;

  扫描时间到期的任务,并且唤醒该任务;

  OS_EXIT_CRITICAL();//开中断

  指针指向下一个任务;

  }

  OSTime++;//累计从开机以来的时间

}

  在ucos ii的时钟节拍函数中,需要执行用户定义的时钟节拍外连函数OSTimeTickHook (),以及对任务链表进行扫描并且递减任务的延时。这样就造成了时钟节拍函数OSTimeTick ()有两点不足:

  ① 在时钟中断中处理额外的任务OSTimeIickHook (),这样增加了中断处理的负担,影响了定时服务的准确性; ② 在关中断情况下扫描任务链表,任务越多所需要时间越长,而长时间关中断对中断响应有不利影响,是中断处理应当避免的。

2.2 改进的时钟管理系统

  针对上述OSTimeTick ()的不足之处,需加以改进来优化时钟节拍函数。在Linux中一般对中断的响应分为两部分:立即中断服务和底半中断处理(bottom half)。立即中断服务仅仅做重要的并且能快速完成的工作,而把不太重要的需要较长时间完成的工作放在底半处理部分来完成,这样就可以提高中断响应速度。

  ucos ii不支持底半处理,为了减轻时钟中断处理程序的工作量来提高ucos ii的时钟精确度,可以将一部分在每次时钟中断需处理的工作内容放在任务级来完成。这样就可以减少每次时钟中断处理的CPU消耗,从而提高中断响应速度和ucos ii的时钟精确度。为此,定义任务OSTimeTask (),由它来处理原来在OSTimeTick()中需要处理的操作。因为μC/OSII采用基于优先级的抢占式调度策略,而每次时钟中断处理程序结束后需要首先调度该任务执行,因此让任务OSTimeTask()具有系统内最高优先级。由它执行用户定义的时钟节拍外连函数OSTimeTickHook (),以及对所有任务的延时时间进行递减,并把到期的任务链入到链表OSTCBRList中,OSTCBRList管理所有到期任务。 OSTimeTask()函数伪代码如下:

void OSTimeTask() {

 OSTimeTickHook()//用户定义的时间处理函数

 while { (除空闲任务外的所有任务)

  对所有任务的延时时间进行递减;

  把所有要到期的任务链入到OSTCBRList链表中;

}

  任务状态改为睡眠,调用OSSched ()进行任务调度;

}

   在任务OSTimeTask()中,执行原来在时钟中断处理的用户函数OSTimeIickHook (),并实现将延时到期的任务链入到OSTCBRList链表中,这样在时钟中断程序中就只需要扫描任务到期的链表而不需要扫描整个链表,减少了关中断的时间。OSTCBRList为新建链表,它管理所有到期的任务。

  同时,需要减少OSTimeTick ()的执行工作量,只对OSTCBRList链表扫描,这样也减少了关中断时间。OSTimeTick ()伪代码如下:

void OSTimeTick(void) {

OSTime++;

OS_TCB* ptcb=OSTCBList;// OSTCBRList指向所有到期任务的链表

while(ptchb!=null){

  关中断;

  唤醒任务;

  开中断;

  指针指向下一个任务;

  }

}

posted @ 2013-05-30 11:42  cronus象牙塔  阅读(461)  评论(0编辑  收藏  举报