μC/OSⅡ中的任务调度 Group01小组 柴永锋 李逢春 苗 冬
相关介绍 C/OS是占先式实时多任务内核,优先级最高的任 务一旦准备就绪,则拥有CPU的所有权开始投入运 行。 C/OS –II 2.51版本支持64个任务,每个任务一 个特定的优先级。优先级越高,数字越小。 C/OS任务调度所花的时间为常数,与应用程序中 建立的任务数无关
任务状态 3
任务控制块(TCB) 任务控制块 OS_TCB是一个数据结构,保存 该任务的相关参数,包括任务堆栈指针, 状态,优先级,任务表位置,任务链表指 针等。 所有的任务控制块分为两条链表,空闲链 表和使用链表。 4
µC/OS-II任务控制块.ucos-ii.h typedef struct os_tcb { OS_STK *OSTCBStkPtr; 指向当前任务栈顶的指针 #if OS_TASK_CREATE_EXT_EN>0 void *OSTCBExtPtr; 指向用户定义的任务控制 块扩展 OS_STK *OSTCBStkBottom; 指向任务栈底的指针 INT32U OSTCBStkSize; 栈中可容纳的指针元数 INT16U OSTCBOpt; 把“选择项”传给 OSTaskCreateExt() INT16U OSTCBId; 任务的识别码 #endif struct os_tcb *OSTCBNext; 任务控制块OS_TCBs的双重 链接 struct os_tcb *OSTCBPrev; #if OS_EVENT_EN OS_EVENT *OSTCBEventPtr; /* 指向事件控制 块*/ 5
µC/OS-II任务控制块.ucos-ii.h #if ((OS_Q_EN>0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN >0) void *OSTCBMsg; 指向传给任务的消息的指 针 #endif INT16U OSTCBDly; 任务延时若干时钟节拍 INT8U OSTCBStat; 任务的状态字 0,就绪 INT8U OSTCBPrio; 任务优先级 INT8U OSTCBX; INT8U OSTCBY; 用于加速任务进入就绪态的过 程 INT8U OSTCBBitX; 或进入等待事件发生状态的过 程 INT8U OSTCBBitY; #if OS_TASK_DEL_EN BOOLEAN OSTCBDelReq; 表示该任务是否需要删除 自身 } OS_TCB; 6
与TCB相关的结构 7
两个关键: 优先级数分解为高三位和低三位分别确定; 高优先级有着小的优先级号 ; 8
优先级和就绪任务表的位置关系 每个就绪的任务都放入就绪表中(ready list) 中,就绪表有两个变量:OSRdyGrp、OSRdyTbl[] 9
优先根据优先级确定就绪表(1) 假设优先级为12的任务进入就绪状态,12=1100b,则 OSRdyTbl[1]的第4位置1,且OSRdyGrp的第1位置1,相应 的数学表达式为: OSRdyGrp |=0x02; OSMapTbl[1]=(0000 0010) OSRdyTbl[1] |=0x10; OSMapTbl[4]=(0001 0000) 而优先级为21的任务就绪21=10 101b,则OSRdyTbl[2]的 第5位置1,且OSRdyGrp的第2位置1,相应的数学表达式为 : OSRdyGrp |=0x04; OSMapTbl[2]=(0000 0100) OSRdyTbl[2] |=0x20; OSMapTbl[5]=(0010 0000) 10
根据优先级确定就绪表(2) 从上面的计算我们可以得到:若OSRdyGrp及OSRdyTbl[]的第n位置1, 则应该把OSRdyGrp及OSRdyTbl[]的值与2n 相或。uC/OS中,把2n的 n=0-7的8个值先计算好存在数组OSMapTbl[7]中,也就是: OSMapTbl[0] =20=0x01(0000 0001) OSMapTbl[1] =21=0x02(0000 0010) …… Index Bit Mask (Binary) 00000001 1 00000010 2 00000100 3 00001000 4 00010000 5 00100000 6 01000000 7 10000000 11
使任务进入就绪态 如果prio是任务是优先级,也是任务的识别号, 则将任务放入就绪表,即使任务进入就绪态的方 法是: OSRdyGrp |=OSMapTbl[prio>>3]; OSRdyTbl[prio>>3] |=OSMapTbl[prio & 0x07]; 假设优先级为12——1100b OSMapTbl[1]=00000010 OSMapTbl[4]=00010000 OSRdyGrp |=0x02; OSRdyTbl[1] |=0x10; 12
根据就绪表确定最高优先级 通过OSRdyGrp值确定高3位,假设为0x24=100 100b, --- 〉 对应OSRdyTbl[2] 和OSRdyTbl[5],高优先级为2 通过OSRdyTbl[2]的值来确定低3位, 假设为0x12=010 010b ,---〉第2个和第5个任务,取高 优先级为2,则最高优先级的任务号为17 13
源代码中使用了查表法 查表法具有确定的时间,增加了系统的可预测性, uC/OS中所有的系统调用时间都是确定的 High3 =OSUnMapTbl[OSRdyGrp]; Low3 =OSUnMapTbl[OSRdyTbl[High3]]; Prio =(High3<<3)+Low3; 14
优先级判定表OSUnMapTbl[256] (os_core.c) 举例: 如OSRdyGrp的值为00101000B,即0X28,则查得OSUnMapTbl[OSRdyGrp]的值是3,它相应于OSRdyGrp中的第3位置1; 如OSRdyTbl[3]的值是11100100B,即0XE4,则查OSUnMapTbl[OSRdyTbl[3]]的值是2,则进入就绪态的最高任务优先级 Prio=3*8+2=26 INT8U const OSUnMapTbl[] = { 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 }; 15
Task scheduler void OS_Sched (void) /*os_core.c中*/ { INT8U y; OS_ENTER_CRITICAL(); if ((OSLockNesting =0)&&(OSIntNesting= 0)) { y = OSUnMapTbl[OSRdyGrp]; OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]) if (OSPrioHighRdy != OSPrioCur) { OSTCBHighRdy=OSTCBPrioTbl[OSPrioHighRdy]; OSCtxSwCtr++; OS_TASK_SW(); } OS_EXIT_CRITICAL(); 16
谢谢!