导读: 本文涉及三部分: 1. 第一部分:任务堆栈的创建和使用 2. 第二部分:任务控制块 3. 第三部分:优先级以及就绪表 希望能通过讲解对UCOSIII的任务管理有进一步的理解. |
一、任务堆栈 |
ucos中的堆栈是遵循“FIFO”原则,也就是先进先出。和一般系统都是一样的。
任务堆栈是用于存放数据,保存现场等等。
任务堆栈的创建 |
define START_STK_SIZE 512 //堆栈大小
CPU_STK START_TASK_STK[START_STK_SIZE]; //定义一个数组来作为任务堆栈
//CPU_STK实际类型为CPU_INT32U,也就是unsigned int类型
//那么实际上堆栈大小即为 512*4byte = 2048字节
任务堆栈初始化:
本质是将初始的值赋值给任务堆栈
CPU_STK *OSTaskStkInit (OS_TASK_PTR p_task,
void *p_arg,
CPU_STK *p_stk_base, //任务堆栈的基址
CPU_STK *p_stk_limit,//任务堆栈的栈深
CPU_STK_SIZE stk_size, //任务堆栈的大小
OS_OPT opt)
//特别说明:任务堆栈的栈深一般为START_STK_SIZE/10,它的作用是当栈仅剩这些容量的时候,就已经到极限了。
一般是在OSTaskCreate直接调用,不需要用户调用。
在移植的时候:需要用户根据CPU修改 OSTaskStkInit 的内容
二、任务控制块 |
每个任务都会有相应的TCB,TCB本质上是一种结构体
一般绝对不要访问OS_TCB中的成员变量
OS_TCB StartTaskTCB; //创建一个任务控制块
TCB结构体(ucosIII) |
成员变量在UCOSIII中远多于UCOSII
struct os_tcb
{
CPU_STK *StkPtr;
void *ExtPtr;
CPU_STK *StkLimitPtr
OS_TCB *NextPtr;
OS_TCB *Prev
…… //此处省略N个成员变量
#if OS_CFG_DBG_EN > 0u
OS_TCB *DbgPrevPtr;
OS_TCB *DbgNextPtr;
CPU_CHAR *DbgNamePtr;
#endif
}
任务控制块的初始化 |
在OSTaskCreate中由系统调用OS_TaskInitPCB(),不需要用户去调用
三、优先级 |
UCOSIII中任务优先级数由宏OS_CFG_PRIO_MAX来配置,UCOSIII中数值越小,优先级越高,最低可用优先级就是OS_CFG_PRIO_MAX-1。
就绪表:优先级位映射表OSPrioTbl[]:用来记录哪个优先级下有任务就绪。 |
OSPrioTbl为32bit
例如:64个优先级则为OSPrioTbl[2]
OS_PRIO OS_PrioGetHighest (void)
{
CPU_DATA *p_tbl;
OS_PRIO prio;
prio = (OS_PRIO)0;
p_tbl = &OSPrioTbl[0];
while (*p_tbl == (CPU_DATA)0) { //先找到OSPrioTbl[i]不为0
prio += DEF_INT_CPU_NBR_BITS;
p_tbl++;
}
prio += (OS_PRIO)CPU_CntLeadZeros(*p_tbl); //得到OSPrioTbl[i]前导0的个数
return (prio);
}
最终找到哪个最高的优先级中有就绪任务
就绪表:就绪任务列表OSRdyList[]:用来记录每一个优先级下所有就绪的任务。 |
* 总是从head’指向的任务开始执行,执行之后就放到尾部