1.概述
UCOS的任务切换是当前任务在系统延时函数OSTimeDly()或OSTimeDlyHMSM()中进行的;延时函数调用任务调度函数OSSched(),调度函数通过软件触发RTOSINT中断函数来完成任务切换。
2.任务切换步骤:
①保存当前任务(进程)对应的CPU寄存器值至该任务的栈空间中。
②保存当前任务的SP(栈指针寄存器)值到它的TCB变量中:
OSTCBCurPtr->OSTCBStkPtr = SP;
③调用OSTaskSwHook()钩子函数。
④从就绪列表中得到当前最高优先级的任务:
OSPrioCur = OSPrioHighRdy;
⑤得到当前就绪任务(线程)的TCB:
OSTCBCurPtr = OSTCBHighRdyPtr;
⑥从⑤中的TCB中获得新任务的SP:
SP = OSTCBHighRdyPtr->OSTCBStkPtr;
⑦从新任务的栈中恢复该任务的AR1H,AR0H, XAR2..XAR7, XT, RPC寄存器的值。
⑧用当前的IER值覆盖先前切换任务时保存的IER值;
⑨执行异常返回(中断返回),恢复原任务留下的其他上下文。
3.任务切换的源码
即RTOSINT中断函数的源码,用汇编编写:
.asmfunc
_OS_CPU_RTOSINT_Handler:
OS_CTX_SAVE ; 伪码指示,保存寄存器值。
MOVL XAR0, #_OSTCBCurPtr ; 保存当前任务的栈指针
MOVL XAR1, *XAR0 ; 获得当前任务的栈指针首变量
MOV AL , @SP
MOV *AR1, AL
ASP ; 对齐栈指针—起始为奇地址。
LCR #_OSTaskSwHook ; 调用任务切换钩子函数OSTaskSwHook.
NASP ; 恢复栈指针对齐
; 对应C代码:OSPrioCur = OSPrioHighRdy
MOVL XAR0, #_OSPrioHighRdy
MOVL XAR1, #_OSPrioCur
MOV ACC, *XAR0 ; *XAR0即OSPrioHighRdy首变量
MOV *XAR1, ACC ; *XAR1即OSPrioCur首变量
; 下面对应C代码:OSTCBCurPtr = OSTCBHighRdyPtr
MOVL XAR0, #_OSTCBHighRdyPtr
MOVL XAR1, #_OSTCBCurPtr
MOVL ACC, *XAR0
MOVL *XAR1, ACC
; 从新进程中获得栈指针
MOVL XAR0, *XAR1
MOV AL , *AR0
MOV @SP , AL ; OSTCBCurPtr写入SP寄存器中。
OS_CTX_RESTORE
IRET ;中断返回,恢复自动保存的寄存器值和其余上下文内容.
.endasmfunc
4.小结
任务切换关键步骤是:①进入RTOSINT中断,保存当前任务的栈指针;②获得优先级最高的任务的TCB指针;③获得新任务的栈指针并写入SP寄存器中;④中断返回,恢复其他寄存器值。
由此可见,任务的TCB和栈空间是任务切换的关键:TCB包含了任务的优先级、函数入口;栈空间存储任务的临时变量、切换时存储的上下文。所以要求,各个任务的栈空间要彼此独立,不能覆盖。
本文详细解析了UCOS实时操作系统中任务切换的过程,涉及任务保存、TCB操作、中断处理及中断返回等关键步骤,并展示了RTOSINT中断函数的汇编实现。重点强调了任务TCB和栈空间在切换中的作用。
537

被折叠的 条评论
为什么被折叠?



