多任务抢占式调度器
什么是抢占式调度?
调度的概念,通俗的说就是系统在多个任务中选择合适的任务执行。系统如何知道
何时该执行哪个任务?可以为每个任务安排一个唯一的优先级别,当同时有多个任务就
绪时,优先运行优先级较高的任务。
同时,任务的优先级也作为任务的唯一标识号。代码中都是对标识号来完成对任务
的操作的。如 OSDelPrioRdy(prio),OSSetPrioRdy(prio)等。
不同的优先级对应就绪表中的每一位。低位对应高优先级。优先级 0 的优先权最高,
优先级 31 的优先权最低。
在程序中要为每一个任务分配一个唯一的优先级。
Main.c
///**************定义任务优先级*************///
#define PrioTask0 0
#define PrioTask1 1
#define PrioTask2 2
#define PrioTask3 3
所谓“抢占式调度”是指:一旦就绪状态中出现优先权更高的任务,便立即剥夺当
前任务的运行权,把 CPU 分配给更高优先级的任务。这样 CPU 总是执行处于就绪条件
下优先级最高的任务。
在程序中查找最高优先级的任务代码如下:
RTOS.h
/* 在就绪表中查找更高级的就绪任务 */
#define OSGetHighRdy() \
{ \
for( OSNextTaskPrio = 0; \
(OSNextTaskPrio < OS_TASKS) && (!(OSRdyTbl & (0x01<
多任务抢占式调度器
多任务系统的时间管理
与人一样,多任务系统也需要一个“心跳”来维持其正常运行,这个心跳叫做时钟
节拍,通常由定时器产生一个固定周期的中断来充当,频率一般为 50-100Hz。在
TargetInit.c 文件中有下面的定时器 0 初始化函数,T0 用作系统心跳计时,产生时钟节拍。
RTOS.h
#define OS_TICKS_PER_SEC 100 /* 设置一秒内的时钟节拍数*/
TargetInit.c
void StartTicker(INT32U TicksPerSec)
{
rTCFG0 = 99; //Prescaler0 = 99
rTCFG1 = 0x03; //Select MUX input for PWM Timer0:divider=16
rTCNTB0 = 31250 / TicksPerSec; //
rTCON |= (1<<1); //Timer 0 manual update
rTCON = 0x09; //Timer 0 auto reload on
//Timer 0 output inverter off
//
//Timer 0 start */
BIT_CLR(rINTMSK, BIT_TIMER0); // Enable WatchDog interrupts
}
清"Timer 0 manual update"
设置中断频率
OSTimeDly 函数就是以时钟节拍为基准来延时的。这个函数完成功能很简单,就是先
挂起当起当前任务,设定其延时节拍数,然后进行任务切换,在指定的时钟节拍数到来之
后,将当前任务恢复为就绪状态。任务必须通过 OSTimeDly 或 OSTaskSuspend 让出 CPU
的使用权,使更低优先级任务有机会运行。
RTOS.c
void OSTimeDly(INT32U ticks)
{
if( ticks > 0 ) /* 当延时有效 */
{
OS_ENTER_CRITICAL();
OSDelPrioRdy(OSPrioCur); /*
TCB[OSPrioCur].OSTCBDly = ticks; /*
OS_EXIT_CRITICAL();
OSSched(); /*
}
}
把任务从就绪表中删去 */
设置任务延时节拍数 */
重新调度 */
7
多任务抢占式调度器
在 T0 的中断服务函数中,依次对各个延时任务的延时节拍数减 1。若发现某个任务
的延时节拍数变为 0,则把它从挂起态置为就绪态。
RTOS.c
void TickInterrupt(void)
{
static INT8U i;
OSTime ++;
//Uart_SendByte('I');
for(i = 0; i < OS_TASKS; i++) /*
{
if(TCB[i].OSTCBDly )
{
TCB[i].OSTCBDly --;
if(TCB[i].OSTCBDly == 0) /*
{
OSSetPrioRdy(i); /*
}
}
}
rSRCPND |= BIT_TIMER0;
rINTPND |= BIT_TIMER0;
}
刷新各任务时钟 */
当任务时钟到时,必须是由定时
器减时的才行*/
使任务可以重新运行 */
系统自身创建了一个空闲任务,并设它为最低优先级,当系统没有任何任务就绪时,
则运行这个任务,让 CPU“有事可干”。用户程序可以在这个任务中加入一些“无关紧要”
的功能,如统计 CPU 使用率等。
RTOS.c
void IdleTask(void)
{
IdleCount = 0;
while(1)
{
IdleCount++;
//Uart_Printf("IdleCount %d\n",IdleCount);
}
}
TIPS:
不要在空闲任务中运行有可能使任务挂起的函数。空闲任务应该一直处于就绪状态。
8