微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > μC/OS-II的内核结构

μC/OS-II的内核结构

时间:10-08 来源:互联网 点击:

第0位bit0。类似地,

如果OSRdyTbl[3]的值是二进制11100100,则OSUnMapTbl[OSRdyTbc[3]]的值是2,即第2

位。于是任务的优先级Prio就等于26(3*8+2)。利用这个优先级的值。查任务控制块优

先级表OSTCBPrioTbl[],得到指向相应任务的任务控制块OS_TCB的工作就完成了。

3.5 任务调度(TaskScheduling)

μC/OS-Ⅱ总是运行进入就绪态任务中优先级最高的那一个。确定哪个任务优先级最

高,下面该哪个任务运行了的工作是由调度器(Scheduler)完成的。任务级的调度是由函

数OSSched()完成的。中断级的调度是由另一个函数OSIntExt()完成的,这个函数将在以

后描述。OSSched()的代码如程序清单L3.8所示。

程序清单L3.8任务调度器(theTaskScheduler)

voidOSSched(void)

{

INT8Uy;

OS_ENTER_CRITICAL();

if((OSLockNesting|OSIntNesting)==0){(1)

y=OSUnMapTbl[OSRdyGrp];(2)

OSPrioHighRdy=(INT8U)((y3)+OSUnMapTbl[OSRdyTbl[y]]);(2)

if(OSPrioHighRdy!=OSPrioCur){(3)

OSTCBHighRdy=OSTCBPrioTbl[OSPrioHighRdy];(4)

OSCtxSwCtr++;(5)

OS_TASK_SW();(6)

}

}

OS_EXIT_CRITICAL();

}

μC/OS-Ⅱ任务调度所花的时间是常数,与应用程序中建立的任务数无关。如程序清单

中[L3.8(1)]条件语句的条件不满足,任务调度函数OSSched()将退出,不做任务调度。这

个条件是:如果在中断服务子程序中调用OSSched(),此时中断嵌套层数

OSIntNesting>0,或者由于用户至少调用了一次给任务调度上锁函数OSSchedLock(),使

OSLockNesting>0。如果不是在中断服务子程序调用OSSched(),并且任务调度是允许的,

即没有上锁,则任务调度函数将找出那个进入就绪态且优先级最高的任务[L3.8(2)],进入

就绪态的任务在就绪任务表中有相应的位置位。一旦找到那个优先级最高的任务,

OSSched()检验这个优先级最高的任务是不是当前正在运行的任务,以此来避免不必要的任

务调度[L3.8(3)]。注意,在μC/OS中曾经是先得到OSTCBHighRdy然后和OSTCBCur做比

较。因为这个比较是两个指针型变量的比较,在8位和一些16位微处理器中这种比较相对

较慢。而在μC/OS-Ⅱ中是两个整数的比较。并且,除非用户实际需要做任务切换,在查任

务控制块优先级表OSTCBPrioTbl[]时,不需要用指针变量来查OSTCBHighRdy。综合这两项

改进,即用整数比较代替指针的比较和当需要任务切换时再查表,使得μC/OS-Ⅱ比μC/OS

在8位和一些16位微处理器上要更快一些。

为实现任务切换,OSTCBHighRdy必须指向优先级最高的那个任务控制块OS_TCB,这是

通过将以OSPrioHighRdy为下标的OSTCBPrioTbl[]数组中的那个元素赋给OSTCBHighRdy来

实现的[L3.8(4)]。接着,统计计数器OSCtxSwCtr加1,以跟踪任务切换次数[L3.8(5)]。

最后宏调用OS_TASK_SW()来完成实际上的任务切换[L3.8(6)]。

任务切换很简单,由以下两步完成,将被挂起任务的微处理器寄存器推入堆栈,然后

将较高优先级的任务的寄存器值从栈中恢复到寄存器中。在μC/OS-Ⅱ中,就绪任务的栈结

构总是看起来跟刚刚发生过中断一样,所有微处理器的寄存器都保存在栈中。换句话说,

μC/OS-Ⅱ运行就绪态的任务所要做的一切,只是恢复所有的CPU寄存器并运行中断返回指

令。为了做任务切换,运行OS_TASK_SW(),人为模仿了一次中断。多数微处理器有软中断

指令或者陷阱指令TRAP来实现上述操作。中断服务子程序或陷阱处理(Traphardler),

也称作事故处理(exceptionhandler),必须提供中断向量给汇编语言函数OSCtxSw()。

OSCtxSw()除了需要OS_TCBHighRdy指向即将被挂起的任务,还需要让当前任务控制块

OSTCBCur指向即将被挂起的任务,参见第8章,移植μC/OS-Ⅱ,有关于OSCtxSw()的更详

尽的解释。

OSSched()的所有代码都属临界段代码。在寻找进入就绪态的优先级最高的任务过程

中,为防止中断服务子程序把一个或几个任务的就绪位置位,中断是被关掉的。为缩短切

换时间,OSSched()全部代码都可以用汇编语言写。为增加可读性,可移植性和将汇编语言

代码最少化,OSSched()是用C写的。

3.6 给调度器上锁和开锁(LockingandUnLockingtheScheduler)

给调度器上锁函数OSSchedlock()(程序清单L3.9)用于禁止任务调度,直到任务完

成后调用给调度器开锁函数OSSchedUnlock()为止,(程序清单L3.10)。调用

OSSchedlock()的任务保持对CPU的控制权,尽管有个优先级更高的任务进入了就绪态。然

而,此时中断是可以被识别的,中断服务也能得到(假设中断是开着的)。OSSchedlock()

和OSSchedUnlock()必须成对使用。变量OSLockNesting跟踪OSSched

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top