uC/OS-II任务栈处理的一种改进方法
……
以上各任务堆栈数组变量在初始化函数OSTCBInit()中被会给了任务控制块OS_TCB的OSTCBStkPtr变量。在任务切换时,μC/OS-II调用OSCtxSw汇编过程(OS_CPU_A.ASM文件),将CPU的SP指针指向该变量,从而使每个任务使用独立的任务堆栈。
LES BX,DWORD PTR DS:_OSTCBCur
;保存挂起任务的堆栈指针SP
MOV ES:[BX+2],SS
MOV ES:[BX+0],SP
……
LESB X,DWORD PTR DS:_OSTCBHighRdy ;切换SP到要运行任务的堆栈空间
MOV SS,ES:[BX+2]
MOV SP,ES:[BX]
……
在代码中,变量OSTCBHighRdy(OSTCBCur)和堆栈指针变量OSTCBStkPtr的数值是同同的,因为OSTCBStkPtr是结构OSTCBHighRdy的第一个变量。
这种任务栈处理方法的缺点是可能造成空间的浪费。因为一个任务如果堆栈满了,该任务也就无法运行,即使其它任务的堆栈还有空间可用。当然,这种方法的好处是任务栈切换的时间非常短,只需要几条指令。
4 共用空间的堆栈处理方法
(1)栈共用连续存储空间
如果多个任务使用同一段连续空间作为堆栈,这样各个堆栈之间就可以互补使用。在前面说过,共用空间的问题在于一个任务运行时不能破坏其它任务的堆栈数据。为简单起见,先看图3所示两个任务的情况。
假定任务1首次运行时任务栈为空。运行一段时间后任务2运行,堆栈空间继续往上生长。这次任务切换不需要修改CPU的SP数值,但需要记下任务1的栈顶位置SP1(图3中)。
在任务2运行一段时间后,RTOS又切换到任务1运行。在切换时,不能简单地将SP指针修改回SP1的数值,因为这样堆栈向上生长时会破坏任务2堆栈中的数据。办法是将原来任1务堆栈保存的数据移动到靠栈顶的位置,而将任务2堆栈数据下移到靠栈底的位置,堆栈指针SP实际上不需要修改(图3右)。
考虑到更为一般的情况,有N个任务,当前运行的任务为k,下一个运行的任务为j,在共用任务堆栈时必须做的工作有:
*为每个任务定义栈顶和栈底2个堆栈指针;
*在任务切换时,将待运行任务j的堆栈内容移动到靠栈顶位置,同时将其堆栈上方的任务堆栈下移,修改被移动推栈的任务堆栈指针。
假设我们定义的任务栈空间和任务的栈指针变量为:
void TaskSTK[MAX_STK_LEN];/*任务堆栈空间*/
typedef struct TaskSTKPoint{
int TaskID;
int pTopSTK;
int pBottomSTK;
《uC/OS-II任务栈处理的一种改进方法(第2页)》