UCOS-II之获取最高优先级
作为一个经典的嵌入式实时操作系统,UCOS-II以其独特的任务调度方式在嵌入式开发领域作用突出。其中采用任务就绪表进行时间换空间的方式堪称经典。今天就对UCOS-II的任务调度及查表的操作过程进行讲解。
一、要点简析
1.在UCOS-II操作系统中有0-63共64个优先级,其中数字越小优先级越高。
2.UCOS-II的优先级存放在一个8×8的就绪表OSRdyTbl中,而就绪表中的每一行均对应1×8就绪组OSRdyGrp中的一个单元格,称为一个bit位。如下图所示:
每当有新的优先级进入就绪状态,则将就绪组对应位及就绪表对应位置1。
例如,当前优先级为prior=35的任务进入就绪状态,由于35的二进制编码为0010 0011,则将就绪组的位4置1,就绪表的位[4,5]置1。具体如下:
倘若此时新进入一个优先级prior=23的就绪任务,则将该任务的对应位再置1。如下图:
3.为了实现算法复杂度为O(1)的创建与查找,UCOS-II操作系统定义了两个查找表,分别为OSMapTbl与OSUnMapTbl。
其中OSMapTbl的作用为将下标的序号转化为仅一位数置1的二进制编码,使优先级的对应位置1,使得任务进入就绪状态。
而OSUnMapTbl 的作用为找到二进制数中最低的置1位所在的位置,从而找到最高优先级所在组以及所在位。例如当前二进制数为0000 0111,对应的十进制数为7,则OSUnMapTbl[7]=0,可知7的最低置1位在第0位。又例如当前二进制数为,0001 0010,十进制数为18,则OSUnMapTbl[18]=1,可知18的最低置1位在第1位。
我们现在知道,UCOS-II操作系统的工作进程为:
输入优先级---->将就绪表就绪组对应位置1----->查找最高优先级。
那么我们接下来通过具体实例对该过程进行理解。
二、实例解析
1. 输入优先级
假设当前有优先级大小prior1=23的任务1,优先级大小为prior2=35的任务2进入就绪状态,当前通过查找法查找到最高优先级的优先级大小。
2.将就绪表就绪组对应位置1
当前任务优先级大小为23,35,则应当将就绪表及就绪组的位置置1。如下图所示:
置1方法为:
OSRdyGrp |= OSMapTbl[priority >> 3];
OSRdyTbl[priority >> 3] |= OSMapTbl[priority & 0x07];
例如,当前优先级为23,
priority=0001 0111,
priority >> 3 ==0000 0010,
OSMapTbl[priority >> 3]==OSMapTbl[2]==0000 0100
而此时OSRdyGrp=0000 0000,运算结束后,OSRdyGrp=0000 0100。
OSRdyTbl[priority >> 3] ==OSRdyTbl[2]
OSRdyTbl[2]|= OSMapTbl[0001 0111 & 0000 0111]= OSMapTbl[7]=1000 0000
3.最高优先级查找。
1]变量说明
当前状态下,有以下变量:
OSRdyGrp=0001 0100
OSRdyTbl[2]=1000 0000
OSRdyTbl[4]=0000 1000
2]查OSUnMapTbl得到最高优先级所在组
y=OSUnMapTbl[OSRdyGrp]=OSUnMapTbl[0001 0100]=OSUnMapTbl[20]= 2
3]提取所在组的八位二进制数
W=OSRdyTbl[y]=OSRdyTbl[2]=1000 0000
4]查OSUnMapTbl得到该组中的最高优先级所在位
x=OSUnMapTbl[W]=OSUnMapTbl[128]=7
由此可知,最高优先级处于第二组的位7。
我们知道,每一组对应8个优先级,则当前最高优先级为:
OSPrioHighRdy=(y<<3)+x //组号y×8+组内号x
也就是我们熟悉的公式:
OSPrioHighRdy=(INT 8U)((y<<3)+OSUnMapTbl[OSRdyTbl[y]]);