-
优先级表的作用
uCOS III是抢占式内核,默认支持64种不同优先级,优先级数值越小,优先级越高。任务调度时需要知道任务就绪表中的最高优先级, 操作系统管理任务时需要知道哪些优先级被使用了。这些都是通过优先级表来管理的。 -
源码解读
2.1 优先级表初始化
流程十分简单,就是将优先级表全部清0
void OS_PrioInit (void)
{
CPU_DATA i;
for (i = 0u; i < OS_PRIO_TBL_SIZE; i++) {
OSPrioTbl[i] = (CPU_DATA)0;
}
}
2.2 插入优先级
当创建优先级为n的任务时,需要在优先级表相应的位置1,表示任务就绪表中有优先级为n的任务。比如n = 0,把OSPrioTbl0[0]的bit31置1;n = 5, 把OSPrioTbl0[0]的bit26置1; n = 32, 把OSPrioTbl[1]的bit31置1
void OS_PrioInsert (OS_PRIO prio)
{
CPU_DATA bit;
CPU_DATA bit_nbr;
OS_PRIO ix;
ix = prio / DEF_INT_CPU_NBR_BITS;
bit_nbr = (CPU_DATA)prio & (DEF_INT_CPU_NBR_BITS - 1u);
bit = 1u;
bit <<= (DEF_INT_CPU_NBR_BITS - 1u) - bit_nbr;
OSPrioTbl[ix] |= bit;
}
2.3 移除优先级
当从任务就绪表中移除优先级为n的任务时,需要将优先级表相应的位清0。原理同2.2, 这里不再赘述
void OS_PrioRemove (OS_PRIO prio)
{
CPU_DATA bit;
CPU_DATA bit_nbr;
OS_PRIO ix;
ix = prio / DEF_INT_CPU_NBR_BITS;
bit_nbr = (CPU_DATA)prio & (DEF_INT_CPU_NBR_BITS - 1u);
bit = 1u;
bit <<= (DEF_INT_CPU_NBR_BITS - 1u) - bit_nbr;
OSPrioTbl[ix] &= ~bit;
}
2.4 计算任务就绪表中最高的优先级
此函数服务于任务调度,计算任务就绪表中的最高优先级。OSPrioTbl[0]用来标记优先级0~31, OSPrioTbl[1]用来标记优先级32~64, 函数CPU_CntLeadZeros用于计算32位数前导0的个数,cortex-m3的指令’CLZ’, 这里恰好拿来计算优先级。uCOS II中通过查询事先定义的位图表来计算, 不支持’CLZ’指令的MCU可以这样做。为什么不直接计算呢? 答案是效率,此函数的调用频率非常之高
OS_PRIO OS_PrioGetHighest (void)
{
CPU_DATA *p_tbl;
OS_PRIO prio;
prio = (OS_PRIO)0;
p_tbl = &OSPrioTbl[0];
/* 搜索位映像表,找到不为0的一组 */
while (*p_tbl == (CPU_DATA)0) { /* Search the bitmap table for the highest priority */
prio += DEF_INT_CPU_NBR_BITS; /* Compute the step of each CPU_DATA entry */
p_tbl++;
}
/* 从该组中找到第一个bit为1的索引 */
prio += (OS_PRIO)CPU_CntLeadZeros(*p_tbl); /* Find the position of the first bit set at the entry */
return (prio);
}