在 uC/OS-III 中,任务被创建后,任务的 TCB 会被放入就绪列表中,表示任务在就绪,随时可能被运行。就绪列表包含一个表示任务优先级的优先级表,一个存储任务 TCB 的 TCB 双向链表。
1.优先级表
1.1优先级表介绍
优先级表实质上是一个数组。在os_prio.c中定义。
CPU_DATA OSPrioTbl[OS_PRIO_TBL_SIZE];
- 数组类型为 CPU_DATA, 在 Cortex-M 内 核 芯 片 的 MCU 中 CPU_DATA 为 32 位 整 型。
- OS_PRIO_TBL_SIZE 的具体取值与 uC/OS-III 支持多少个优先级有关,支持的优先级越多,优先级表也就越大,需要的 RAM 空间也就越多。理论上无限的。
图中就是优先级表了,优先级表的成员是 32 位的,每个成员可以表示 32 个优先级。如果优先级超过 32 个,那么优先级表的成员就要相应的增加。
例如,CPU 的类型为 32 位,支持最大的优先级为 32 个,优先级表只需要一个成员即可,即只有 OSPrioTbl[0]。
假如创建一个优先级为 Prio 的任务,那么就在OSPrioTbl[0]的位[31-prio]置 1 即可。如果 Prio 等于3,那么就将位 28 置 1。OSPrioTbl[0]的位 31 表示的是优先级最高的任务。
1.2优先级表的操作
优先级表操作函数实现在os_prio.c文件中。一共四个函数。
1.2.1 OS_PrioInit()
OS_PrioInit()函数用于初始化优先级表,在OSInit()中被调用。
void OS_PrioInit(void)
{
CPU_DATA i;
//默认全部初始化为0
for(i = 0u; i < OS_PRIO_TBL_SIZE; i++)
{
OSPrioTbl[i] = (CPU_DATA)0;
}
}
初始化完之后的优先级表
1.2.2 OS_PrioInsert()
该函数是用来置位优先级表中相应的位,被OSTaskCreate()函数调用。
void OS_PrioInsert(OS_PRIO prio)
{
CPU_DATA bit;
CPU_DATA bit_nbr;
OS_PRIO ix;
//求模操作,获取优先级表数组下标索引
ix = prio/DEF_INT_CPU_NBR_BITS;
//求余操作,将优先级限制在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;
//将优先级在优先级表相应位置置为1
OSPrioTbl[ix] |= bit;
}
若分别创建了优先级为3,5,8,11四个任务,创建完之后
在系统中,最高优先级和最低优先级是留给系统任务使用,用户任务不能使用。
1.2.3 OS_PrioRemove()
OS_PrioRemove()函数用于清除优先级表中相应的位,与上面Insert函数作用相反。
void OS_PrioRemove(OS_PRIO prio)
{
CPU_DATA bit;
CPU_DATA bit_nbr;
OS_PRIO ix;
//求模操作,获取优先级表数组下标索引
ix = prio/DEF_INT_CPU_NBR_BITS;
//求余操作,将优先级限制在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;
//将优先级在优先级表相应位置置为0
OSPrioTbl[ix] &= ~bit;
}
1.2.4 OS_PrioGetHighest()
OS_PrioGetHighest()用于从优先