uCOSIII学习笔记之OSCtrSW( )

UCOS-III Users Manual 截图

这里写图片描述

PM0056文档中的4.4.3节,介绍了Interrupt control and state register (SCB_ICSR),即:地址为0xE000ED04的寄存器。
位定义如下图所示:
这里写图片描述
所以:宏OS_TASK_SW() 手工将 NVIC的 PendSV悬起寄存器中写 1。悬起后,在其它的 ISR都完成了处理后,才执行PendSV异常(相关详细内容请看这篇博客)。PendSV异常会自动延迟上下文切换的请求,为实现这个机制,需要把 PendSV设置为最低优先级的异常1

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

    SUBS    R0, R0, #0x20                       ; Save remaining regs r4-11 on process stack
    STM     R0, {R4-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; SP = OSTCBHighRdyPtr->StkPtr;
    LDM     R0, {R4-R11}                        ; Restore r4-11 from new process stack
    ADDS    R0, R0, #0x20
    MSR     PSP, R0                             ; Load PSP with new process SP
    ORR     LR, LR, #0x04                       ; Ensure exception return uses process stack
    CPSIE   I
    BX      LR                                  ; Exception return will restore remaining context

    END

PendSV异常函数在os_cpu_a.s文件中。
这里写图片描述

(1)&(2) The Cortex-M3 auto-saves half of the processor context on any exception, and restores same on return from exception. So only saving of R4-R11 is required and fixing up the stack pointers. When the processor takes an exception, unless the exception is a tail-chained or a late-arriving exception, the processor pushes information onto the current stack. This operation is referred as stacking and the structure of eight data words is referred as stack frame. The stack frame contains the following information:

  • R0-R3, R12
  • Return address (PC+4)
  • PSR
  • LR (R14)

“stack frame”中的内容就是任何异常在执行其异常服务程序之前自动保存到栈(PSP)中的内容。所以在执行PendSV异常服务函数是只用保存寄存器R4-R11,和R13(SP)。其中,R4-R11保存在任务堆栈中(The task being switching out),而R13(SP)保存在任务控制块中(OSTCBCurPtr->OSTCBStkPtr = SP)。任务堆栈指针用的是PSP。

    MRS     R0, PSP                             ; PSP is process stack pointer
    CBZ     R0, OS_CPU_PendSVHandler_nosave     ; Skip register save the first time

    SUBS    R0, R0, #0x20                       ; Save remaining regs r4-11 on process stack
    STM     R0, {R4-R11}

    LDR     R1, =OSTCBCurPtr                    ; OSTCBCurPtr->OSTCBStkPtr = SP;
    LDR     R1, [R1]
    STR     R0, [R1]                            ; R0 is SP of process being switched out

(3) Call OSTaskSwHook()
如果需要的话,可以在执行任务切换的时候执行一些附加的操作,添加在OSTaskSwHook()中。
函数调用时,LR寄存器用于保存函数的额返回地址。但通常函数嵌套不止一层,所以在执行函数调用前需要保存LR中的内容。
但发生异常时,LR寄存器用于保存EXC_RETURN,EXC_RETURN的值是在进入异常服务程序之前,“stacking”过程完成时,加载到LR寄存器中的。
这里写图片描述
这里写图片描述
这里写图片描述
所以在第(7)步时,为了确保PendSV异常使用PSP返回到用户级,执行了ORR LR, LR, #0x04;语句。

    PUSH    {R14}                               ; Save LR exc_return value
    LDR     R0, =OSTaskSwHook                   ; OSTaskSwHook();
    BLX     R0
    POP     {R14}

(4) Get current high priority
任务控制块结构体的第一个成员便是OSTCBStkPtr.

    LDR     R0, =OSPrioCur                      ; OSPrioCur   = OSPrioHighRdy;
    LDR     R1, =OSPrioHighRdy
    LDRB    R2, [R1]
    STRB    R2, [R0]

(5) Get current ready thread TCB

    LDR     R0, =OSTCBCurPtr                    ; OSTCBCurPtr = OSTCBHighRdyPtr;
    LDR     R1, =OSTCBHighRdyPtr
    LDR     R2, [R1]
    STR     R2, [R0]

(6) Get new process SP from TCB

    LDR     R0, [R2]                            ; R0 is new process SP; SP = OSTCBHighRdyPtr->StkPtr

(7) Restore R4-R11 from new process stack

    LDM     R0, {R4-R11}                                        ; Restore r4-11 from new process stack
    ADDS    R0, R0, #0x20
    MSR     PSP, R0                                             ; Load PSP with new process SP

(7) Perform exception return which will restore remaining context

    ORR     LR, LR, #0x04                       ; Ensure exception return uses process stack
    CPSIE   I
    BX      LR                                  ; Exception return will restore remaining context

这里写图片描述

PSP 和 MSP 的使用

任务A切换到任务B的过程总结为:

  1. 处理器硬件自动保存部分寄存器到任务A的栈中;
  2. 在PendSVC的ISR中将剩余没有自动保存的寄存器手动存到任务A的栈中;
  3. 更新任务A的栈指针,并保存到任务A的任务控制块中;
  4. 找到任务B的任务控制块指针,并找到任务B栈指针,从任务B的栈中恢复ISR中手动保存的寄存器;
  5. 更新任务B的栈指针,并赋值到PSP中,从PSP中返回到PendSVC异常。

  1. PendSV异常的优先级设置在函数OSStartHighRdy()中完成,此函数由汇编编写,在os_cpu_a.s文件。博客中所有的代码都来自于micrium官方基于STM32L152移植的UCOSIII代码. ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值