OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4275|回复: 2

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

[复制链接]

68

主题

165

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
388
金钱
388
注册时间
2017-3-2
在线时间
156 小时
发表于 2017-6-20 16:23:37 | 显示全部楼层 |阅读模式
1金钱
用ST的HAL库和 CubeMX生成的代码, ST会把所有中断都放在 stm32f4xx_it.c 中 其中有一个是 PendSV_Handler,这个在 uC中是用于任务切换的,但是在 uC中,这个任务切换函数是 OS_CPU_PendSVHandler,为了不修改启动文件以及uC代码,我把OS_CPU_PendSVHandler直接放在了 PendSV_Handler函数中,就是下面这样:

[mw_shl_code=c,true]/**
* @brief This function handles Pendable request for system service.
*/
void PendSV_Handler(void)
{
//调用 uC系统的 PendSV异常处理函数
OS_CPU_PendSVHandler();
}[/mw_shl_code]

结果悲剧了,运行后各种硬件错误,直接进入到 HardFault_Handler,而且每次的错误原因还不固定,这是为什么啊?没想明白原因,uC的这个函数不能被别的函数调用?

最佳答案

查看完整内容[请看2#楼]

最后还是自己搞明白了,说一下吧: 之所以不能采用上述调用的方式是因为链接寄存器 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后程序可能跑飞(取 ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

68

主题

165

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
388
金钱
388
注册时间
2017-3-2
在线时间
156 小时
 楼主| 发表于 2017-6-20 16:23:38 | 显示全部楼层
本帖最后由 kokoromi 于 2017-6-20 20:41 编辑

最后还是自己搞明白了,说一下吧:

之所以不能采用上述调用的方式是因为链接寄存器 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
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2017-6-20 21:26:00 | 显示全部楼层
kokoromi 发表于 2017-6-20 20:39
最后还是自己搞明白了,说一下吧:

之所以不能采用上述调用的方式是因为链接寄存器 LR的问题,进入系统 ...

谢谢分享
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-17 16:03

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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