微型抢占式多任务实时内核设计
/*const uint_16 os_maskTable[16] ={ 0x8000,0x4000, .....,0x0008,0x0004,0x0002,0x0001 */
if( msg&0xF0 ) { /*普通级消息*/
pTCB->msg[1] |= os_maskTable[msg&0x0F];
/*普通级消息存在msg[1]中*/
os_rdyState |= os_maskTable[pTCB->priority];
}
else { /*紧急级消息*/
pTCB->msg[0] |= os_maskTable[msg]; ;
/*紧急级消息存在msg[0]中*/
os_rdyhState |= os_maskTable[pTCB->priority];
/*提升动态优先级*/
}
??与先进先出(FIFO)方式的消息队列不同,内核总是取出优先级最高的消息来交给任务处理。消息接收函数os_GetMessage设计思路如下:如果消息接收区中无紧急消息,则降低任务的动态优先级;如果消息接收区中有消息,则取出优先级最高的消息;如果没有消息,则将任务转为等待态。考虑有时候不希望任务进入等待态,MicroStar还提供了非阻塞的os_PeekMessage消息接收函数。
3.2 信 号
??在嵌入式系统编程中,常利用标志位来实现前后台程序或不同的任务间的通信。MicroStar也提供了类似的任务间的通信方式——信号(signal)。它避免了用户程序因不断查询标志位而带来的时间浪费,而且支持信号间的“与”、“或”运算。通俗来说,信号就是标志位,用来标识某个事件的发生。同消息一样,信号也有紧急级与普通级之分。与消息不同的是,信号完全由用户程序创建和维护,内核只是帮助用户程序等待信号,以避免低效率的标志位查询。使用起来不如消息直观,但执行效率较高。实现起来非常简单,请参见源码。
图1
4 定时器
??定时器在嵌入式系统有着大量的用途,如LED的定时刷新、串口通信中的超时检查。对定时器的需求分为两类,一种是周期性重复定时,比如每隔10ms去刷新
LED;另一种是仅需定时一次的一次性定时。定时时长以系统时钟节拍(tick,又译作滴达)作为单位。两次系统定时中断之间的时间间隔为一个节拍。定时器结构体如下:
typedef struct{
uint_16 elapse; /*定时时长的余值*/
uint_16 backTime; /*定时时长的备份值*/
MSG timerId; /*定时器ID号*/
uchar taskId; /*拥有该定时器的任务的ID*/
TIMERPROC lpTimerFunc; /*定时调用的函数指针*/
}TIMER,*PTIMER;
TIMER os_timers[USER_TIMER_NUM]; /*最多为16个*/
《微型抢占式多任务实时内核设计(第4页)》