打印
[STM32F4]

将 OS_CPU_PendSVHandler 嵌套 PendSV_Handler 里出错,为什么?

[复制链接]
2793|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
kokoromi|  楼主 | 2017-6-20 16:28 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
用 ST的 HAL库和 CubeMX生成的代码, ST会把所有中断都放在 stm32f4xx_it.c 中 其中有一个是 PendSV_Handler,这个在 uC中是用于任务切换的,但是在 uC中,这个任务切换函数是 OS_CPU_PendSVHandler,为了不修改启动文件以及uC代码,我把OS_CPU_PendSVHandler直接放在了 PendSV_Handler函数中,就是下面这样:
/**
* [url=home.php?mod=space&uid=247401]@brief[/url] This function handles Pendable request for system service.
*/
void PendSV_Handler(void)
{
//调用 uC系统的 PendSV异常处理函数
OS_CPU_PendSVHandler();
}
结果悲剧了,运行后各种硬件错误,直接进入到 HardFault_Handler,而且每次的错误原因还不固定,这是为什么啊?没想明白原因,uC的这个函数不能被别的函数调用?

沙发
kokoromi|  楼主 | 2017-6-20 20:37 | 只看该作者
最后还是自己搞明白了,说一下吧:

之所以不能采用上述调用的方式是因为链接寄存器 LR的问题,进入系统异常 PendSV_Handler后,LR的值为 EXC_RETURN,但在调用 OS_CPU_PendSVHandler后,LR的值变为这个函数的返回地址,即进入OS_CPU_PendSVHandler后的 LR的值已经不是 EXC_RETURN,而是 OS_CPU_PendSVHandler的返回地址,所以在 OS_CPU_PendSVHandler中对 LR的操作(ORR LR, R4, #0xF4)会导致最后执行 BX LR后程序可能跑飞(取决于 ORR操作是否修改了返回地址 LR的值),综上,中断处理函数 OS_CPU_PendSVHandler必须直接放到中断向量表中,不能被其他函数调用。



OS_CPU_PendSVHandler
    CPSID   I                                                   ; Prevent interruption during context switch
    MRS     R0, PSP                                         ; PSP is process stack pointer
    STMFD   R0!, {R4-R11}                             ; Save remaining regs r4-11 on process stack

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

                                                                      ; At this point, entire context of process has been saved
    MOV     R4, LR                                            ; Save LR exc_return value (此处保存的已经不是 exc_return了,而是这个函数的返回地址)
    BL      OSTaskSwHook                                 ; OSTaskSwHook();

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

    MOV32   R1, OSTCBHighRdyPtr                   ; OSTCBCurPtr = OSTCBHighRdyPtr;
    LDR     R2, [R1]
    STR     R2, [R5]

    ORR     LR, R4, #0xF4                                ; Ensure exception return uses process stack
    LDR     R0, [R2]                                            ; R0 is new process SP; SP = OSTCBHighRdyPtr->StkPtr;
    LDMFD   R0!, {R4-R11}                                ; Restore r4-11 from new process stack
    MSR     PSP, R0                                             ; Load PSP with new process SP
    CPSIE   I
    BX      LR                                                      ; Exception return will restore remaining context

    END





使用特权

评论回复
板凳
yjmwxwx| | 2017-6-20 22:31 | 只看该作者
胡乱说个我没实验哦
开头加PUSH {R0-R12,LR}
结尾BX LR改成POP {R0-R12,PC}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

111

主题

344

帖子

3

粉丝