OpenEdv-开源电子网

 找回密码
 立即注册

扫一扫,访问微社区

正点原子全套STM32/FPGA开发资料,上千讲STM32视频教程,RT1052教程免费下载啦...
查看: 702|回复: 0

STM32F0 CM0内核 PendSV中断服务函数 解析分享

[复制链接]

  离线 

16

主题

249

帖子

0

精华

高级会员

Rank: 4

积分
507
金钱
507
注册时间
2013-10-16
在线时间
43 小时
发表于 2018-6-15 16:13:18 | 显示全部楼层 |阅读模式
;********************************************************************************************************
;                                         HANDLE PendSV EXCEPTION
;                                     void OS_CPU_PendSVHandler(void)
;                        ( PendSV 中断服务函数 ==== 太重要了,执行任务切换就在这里 )
; Note(s) : 1) PendSV is used to cause a context switch.  This is a recommended method for performing
;              context switches with Cortex-M0.  This is because the Cortex-M0 auto-saves half of the
;              processor context on any exception, and restores same on return from exception.  So only
;              saving of R4-R7 is required and fixing up the stack pointers.  Using the PendSV exception
;              this way means that context saving and restoring is identical whether it is initiated启动 from
;              a thread or occurs due to an interrupt or exception.
;
;           2) Pseudo-code is:
;              a) Get the process SP, if 0 then skip (goto d) the saving part (first context switch);
;              b) Save remaining剩下的 regs R4-R7 on process stack;
;              c) Save the process SP in its TCB, OSTCBCur->OSTCBStkPtr = SP;
;              d) Call OSTaskSwHook();
;              e) Get current high priority, OSPrioCur = OSPrioHighRdy;
;              f) Get current ready thread TCB, OSTCBCur = OSTCBHighRdy;
;              g) Get new process SP from TCB, SP = OSTCBHighRdy->OSTCBStkPtr;
;              h) Restore R4-R7 from new process stack;
;              i) Perform exception return which will restore remaining context.
;
;           3) On entry into PendSV handler:
;              a) The following have been saved on the process stack (by processor):
;                 xPSR, PC, LR, R12, R0-R3
;              b) Processor mode is switched to Handler mode (from Thread mode)
;              c) Stack is Main stack (switched from Process stack)
;              d) OSTCBCur      points to the OS_TCB of the task to suspend
;                 OSTCBHighRdy  points to the OS_TCB of the task to resume
;
;           4) Since PendSV is set to lowest priority in the system (by OSStartHighRdy() above), we
;              know that it will only be run when no other exception or interrupt is active, and
;              therefore safe to assume that context being switched out was using the process stack (PSP).
;********************************************************************************************************

;OS_CPU_PendSVHandler                       ; 这里搞了这么久,真的什么都有可能的,
PendSV_Handler                                 ; ( PendSV 中断处理函数 )
    CPSID   I                                      ; 失能中断
    MRS     R0, PSP                             ; R0=PSP,

    CMP     R0, #0                             ; if(PSP == 0) 第一次任务切换
    BEQ     OS_CPU_PendSVHandler_nosave            ; (BEQ =相等或为0则跳转 ) saving part (first context switch)

                                                    ; 保存R4,R5,R6,R7到线程堆栈PSP
    SUBS    R0, R0, #0x10                   ; (R0=R0-16(byte)) Adjust stack pointer to where memory needs to be stored to avoid overwriting
    STM     R0!, {R4-R7}                    ; ( store multiple registers(16byte) ),Stores 4 4-byte registers, default increments SP after each storing
    SUBS    R0, R0, #0x10                   ; STM does not automatically call back the SP to initial location so we must do this manually

                                                     ; OSTCBCur->OSTCBStkPtr = SP;
    LDR     R1, =OSTCBCur                   ; R1 = &OSTCBCur,
    LDR     R1, [R1]                          ; R1 = *R1 (R1 = OSTCBCur)
    STR     R0, [R1]                          ; *R1 = R0 (*OSTCBCur = SP)



OS_CPU_PendSVHandler_nosave                 ; At this point, entire context of process has been saved
                                                       ; 调用OSTaskSwHook()
    PUSH   {R14}                                ; 保存R14,因为后面要调用函数
    LDR     R0, =OSTaskSwHook               ; R0 = &OSTaskSwHook
    BLX     R0                                   ; 调用 OSTaskSwHook()
    POP    {R0}                                ; 出栈
    MOV     R14, R0                         ; 恢复R14, LR = R0

                                                    ; OSPrioCur = OSPrioHighRdy;
    LDR     R0, =OSPrioCur                  ; R0 = &OSPrioCur
    LDR     R1, =OSPrioHighRdy              ; R1 = &OSPrioHighRdy
    LDRB    R2, [R1]                        ; R2 = *R1 (R2 = OSPrioHighRdy)
    STRB    R2, [R0]                        ; *R0 = R2 (OSPrioCur = OSPrioHighRdy)

                                                  ; OSTCBCur  = OSTCBHighRdy;
    LDR     R0, =OSTCBCur                   ; R0 = &OSTCBCur
    LDR     R1, =OSTCBHighRdy               ; R1 = &OSTCBHighRdy
    LDR     R2, [R1]                        ; R2 = *R1 (R2 = OSTCBHighRdy)
    STR     R2, [R0]                        ; *R0 = R2 (OSTCBCur = OSTCBHighRdy)

    LDR     R0, [R2]                        ; R0 = *R2 (R0 = OSTCBHighRdy), R0 is new process SP; ((SP = OSTCBHighRdy->OSTCBStkPtr;))

    LDM     R0!, {R4-R7}                    ; Restore R4-R7 from new process stack

    MSR     PSP, R0                         ; Load PSP with new process SP

                                                  ; 确认使用进程堆栈
    MOV     R0,  R14                        ; R0=LR,
    MOVS    R1,  #0x04                      ; Immediate move to register
    ORRS    R0,  R1                         ; Ensure exception return uses process stack
    MOV     R14, R0                         ; 确认LR位2为1,返回后使用进程堆栈
    CPSIE   I                               ; 使能中断
    BX      LR                              ; Exception return will restore remaining context

    ALIGN                                   ; Ensures that ARM instructions start on four-byte boundary

    END

代码分析分享
2, PendSV中断服务函数,
21,关闭中断
22,判断PSP==0(如果第一次任务切换就跳过)
23,保存R4/5/6/7到线程堆栈PSP
24,保存现场,OSTCBCur->OSTCBStrPtr=PSP
25,OS_CPU_PendSVHandler_nosave
26,调用OSTaskSwHook()
27,OSPrioCur = OSPrioHighRdy;
28,OSTCBCur  = OSTCBHighRdy;
29,SP = OSTCBHighRdy->OSTCBStkPtr;
30,恢复R4-R7,
31,PSP = OSTCBHighRdy->OSTCBStkPtr;恢复PSP
32,确认使用进程堆栈
33,根据LR程序执行跳转



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则




关闭

正点原子双11大促销上一条 /1 下一条

正点原子公众号

QQ|联系我们|手机版|官方淘宝店|微信公众平台|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2018-11-16 20:25

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表
/* */