任务堆栈的创建:
任务堆栈是任务的重要部分,堆栈是RAM中按照“先进先出(FIFO)”的原则组织的一块连续的存储空间。为了满足任务切换和响应中断时保存CPU寄存器中的内容及任务调用其他函数时的需要,每个任务都应该有自己的堆栈。
任务堆栈的创建:
#define START_STK_SIZE 512 //堆栈大小
CPU_STK START_TASK_STK[STArT_STK_SIZE] //定义一个数组来作为任务堆栈
将CPU现在情况导入任务堆栈
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)
{
CPU_STK *p_stk;
(void)opt; /* Prevent compiler warning */
p_stk = &p_stk_base[stk_size]; /* Load stack pointer */
/* Registers stacked as if auto-saved on exception */
*--p_stk = (CPU_STK)0x01000000u; /* xPSR */
*--p_stk = (CPU_STK)p_task; /* Entry Point */
*--p_stk = (CPU_STK)OS_TaskReturn; /* R14 (LR) */
*--p_stk = (CPU_STK)0x12121212u; /* R12 */
*--p_stk = (CPU_STK)0x03030303u; /* R3 */
*--p_stk = (CPU_STK)0x02020202u; /* R2 */
*--p_stk = (CPU_STK)p_stk_limit; /* R1 */
*--p_stk = (CPU_STK)p_arg; /* R0 : argument */
/* Remaining registers saved on process stack */
*--p_stk = (CPU_STK)0x11111111u; /* R11 */
*--p_stk = (CPU_STK)0x10101010u; /* R10 */
*--p_stk = (CPU_STK)0x09090909u; /* R9 */
*--p_stk = (CPU_STK)0x08080808u; /* R8 */
*--p_stk = (CPU_STK)0x07070707u; /* R7 */
*--p_stk = (CPU_STK)0x06060606u; /* R6 */
*--p_stk = (CPU_STK)0x05050505u; /* R5 */
*--p_stk = (CPU_STK)0x04040404u; /* R4 */
return (p_stk);
}
使用创建的任务堆栈
(CPU_STK * )&START_TASK_STK[0], //任务堆栈基地址
(CPU_STK_SIZE)START_STK_SIZE/10, //任务堆栈深度限位
(CPU_STK_SIZE)START_STK_SIZE, //任务堆栈大小
任务堆栈基地址:创建的任务堆栈的头地址
任务堆栈深度限位:当任务堆栈快满时的一个最小提示量,最大极限深度
任务堆栈大小:512*4Bits
任务控制块结构 :
任务控制快是用来记录与任务相关的信息的数据结构,每个任务都要有自己的任务控制块。
OS_TCB StartTaskTCB; //创建一个任务控制块
OS_TCB为一个结构体,描述了任务控制块,任务控制块中的成员变量用户不能直接访问,更不可能改变他们
struct os_tcb
{
CPU_STK *StkPtr;
void *ExtPtr;
CPU_STK *StkLimitPtr
OS_TCB *NextPtr;
OS_TCB *Prev
......
#if OS_CFG_DBG_EN > 0u
OS_TCB *DbgPrevPtr;
OS_TCB *DbgNextPtr;
CPU_CHAR *DbgNamePtr;
#endif
}
任务控制块初始化:同样,函数OSTaskCreate()在创建任务的时候会对任务的任务控制块进行初始化。
优先级:任务执行的一个优先顺序。
UCOSIII中任务优先级数由宏OS_CFG_PRIO_MAX来配置,UCOSIII中数值越小,优先级越高,最低可用优先级就是OS_CFG_PRIO_MAX-1
就绪表:
1.优先级为映射表OSPrioTbl[]:用来记录哪个优先级下有任务就绪
CPU_DATA OSPrioTbl[OS_PRIO_TBL_SIZE];
2.就绪任务列表OSRdyList[]:用来记录每一个优先级下所有就绪的任务
UCOSIII支持时间片轮转调度,同一个优先级下可以有多个任务,因此我们还需要在确定是优先级下的哪个任务就绪了
struct os_rdy_list {
OS_TCB *HeadPtr //用于创建链表,指向链表头
OS_TCB *TailPtr; //用于创建链表,指向链表尾
OS_OBJ_QTY NbrEntries; //此优先级下的任务数量
};
时间轮转调度:执行完一个任务后,这个任务会自动插入到末尾,下一个任务会变成当前执行任务,然后继续轮转。