uCOSIII学习笔记之OSCtrSW( )

来源:互联网 发布:java验证码工具类 编辑:程序博客网 时间:2024/06/06 04:52

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 savedOS_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

这里写图片描述


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