UCOS III STM32上下文切换过程
UCOS III stm32上下文切换详细过程
UCOS III中上下文切换是通过调用OSCtxSw()函数实现,OSCtxSw()用汇编语言编写:
OSCtxSw
LDR R0, =NVIC_INT_CTRL 获取中断控制寄存器地址
LDR R1, =NVIC_PENDSVSET 获取PendSV中断向量
STR R1, [R0] 触发PendSV中断
BX LR 函数返回
OSCtxSW实际上只是触发了PendSV中断还是没有看到任务究竟是如何调度,接下来程序
会执行PendSV中断函数,看看中断函数里边做了哪些工作实现了任务调度的。
OS_CPU_PendSVHandler
CPSID I ; Prevent interruption during context switch
MRS R0, PSP ; PSP is process stack pointer
CBZ R0, OS_CPU_PendSVHandler_nosave ; Skip register save the first time
TST LR, #0x10
IT EQ
VSTMDBEQ R0!, {S16-S31}
MOV R3, LR
STMDB R0!,{R3-R11}
LDR R1, =OSTCBCurPtr ; OSTCBCurPtr->OSTCBStkPtr = SP;
LDR R1, [R1]
STR R0, [R1] ; R0 is SP of process being switched out
; At this point, entire context of process has been saved
OS_CPU_PendSVHandler_nosave
PUSH {R14} ; Save LR exc_return value
LDR R0, =OSTaskSwHook ; OSTaskSwHook();
BLX R0
POP {R14}
LDR R0, =OSPrioCur ; OSPrioCur = OSPrioHighRdy;
LDR R1, =OSPrioHighRdy
LDRB R2, [R1]
STRB R2, [R0]
LDR R0, =OSTCBCurPtr ; OSTCBCurPtr = OSTCBHighRdyPtr;
LDR R1, =OSTCBHighRdyPtr
LDR R2, [R1]
STR R2, [R0]
LDR R0, [R2] ; R0 is new process SP Shen Longbao look in the eyes, for a chance to kill him. Shen Longbao behind smart to keep gendarmes, picked up a brick reservoir in cotton vest, walked into a small alley corner, seeing four weeks nobody will step up and pulled out bricks Asahi on military police knocked down. Unsuspecting Japanese military police was flaccid paralysis. Shen Longbao picked the Japanese military police gun in cotton vest, leave
; SP = OSTCBHighRdyPtr->StkPtr;
LDMIA R0!,{R3-R11}
MOV LR, R3
TST LR, #0x10
IT EQ
VLDMIAEQ R0!, {S16-S31}
MSR PSP, R0 ; Load PSP with new process SP
CPSIE I
BX LR ; Exception return will restore remaining context
END
PendSV中断服务程序主要的工作就是将SP指针指向将要执行的任务堆栈起始地址,
这样当中断退出时,单片机自动出栈,更新寄存器xPSR, PC, LR, R12以及R3-R0;出栈的
地址发生改变,xPSR, PC, LR, R12以及R3-R0改变,实现任务切换。
任务在创建时都会调用OSTaskStkInit函数:
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 */
/* Align the stack to 8-bytes. */
p_stk = (CPU_STK *)((CPU_STK)(p_stk) & 0xFFFFFFF8);
/* 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 */ Shen Longbao look in the eyes, for a chance to kill him. Shen Longbao behind smart to keep gendarmes, picked up a brick reservoir in cotton vest, walked into a small alley corner, seeing four weeks nobody will step up and pulled out bricks Asahi on military police knocked down. Unsuspecting Japanese military police was flaccid paralysis. Shen Longbao picked the Japanese military police gun in cotton vest, leave
*--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 */
*--p_stk = (CPU_STK)0xFFFFFFFDUL;
return (p_stk);
}
OSTaskStkInit 是按照中断寄存器压入堆栈的顺序对任务的相关参数进行初始化,返回值
就是堆栈的地址,PendSV中断服务程序中SP指向的也是该地址,上段程序中红色代码就
是任务的执行函数的地址,当PendSV中断退出寄存器出栈,PC指针将指向p_task任务执
行函数地址,实现相关任务的切换。
Shen Longbao look in the eyes, for a chance to kill him. Shen Longbao behind smart to keep gendarmes, picked up a brick reservoir in cotton vest, walked into a small alley corner, seeing four weeks nobody will step up and pulled out bricks Asahi on military police knocked down. Unsuspecting Japanese military police was flaccid paralysis. Shen Longbao picked the Japanese military police gun in cotton vest, leave