You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32F103C8T6的Cortex-M3内核异常返回问题求助

Cortex-M3内核模式切换至用户模式(PSP)触发Usage Fault问题排查

问题场景

基于STM32开发简易RTOS,通过SVC中断实现内核到用户模式的上下文切换,中断处理函数__int_SVC汇编代码如下:

__int_SVC:
@ __user_mode:
    @ save kernel context
    ldr r2, =kernel_save
    stmia r2!, {r4-r11}
    mov r1, pc
    str r1, [r2], 4
    mov r1, lr
    str r1, [r2], 4

    @ set up return frame for task
    mov r1, 8
loop1:
    ldr r2, [r0], 4
    str r2, [sp], 4
    add r1, -1
    cmp r1, 0
    bgt loop1
    add sp, -4 * 8

    @ restore other regs
    ldmia r0!, {r4-r11}
    ldr r1, [r0]
    msr psp, r1

    @ enable interrupt tim2
    @ ldr r0, nvic_base
    @ ldr r1, [r0]
    @ orr r1, r1, 0x10000000
    @ str r1, [r0]

    @ go thread mode, using psp
    mov lr, 0xfffffffd
    bx lr

.align 2
nvic_base:
    .word 0xE000E100

.section .bss
.align 2
kernel_save:
    .rept 10
    .word 0x00000000
    .endr

执行bx lr时,若lr设为0xFFFFFFFD(返回线程模式并使用PSP作为栈指针),会触发Usage Fault,且Usage Fault状态寄存器的INVPC位置位,提示「尝试使用无效EXC_RETURN值执行异常操作」;但将lr设为0xFFFFFFF9(返回线程模式并使用MSP)时,能正常切换到用户代码,仅栈指针不符合预期。

已执行的调试操作

  • 确认异常返回的返回栈配置正确
  • 尝试通过POP、LDR等方式将EXC_RETURN值加载至PC,均无效
  • 验证后续用户代码使用的PSP值有效
  • 触发SVC时无其他活跃中断,无需设置Configuration Control Register的NONBASETHRDENA位
  • 确认未修改xPSR中的异常编号

官方文档关键规则(翻译自Cortex-M3异常返回文档)

  1. EXC_RETURN值编码规则:
    • 最低三位用于指定返回模式与栈指针:
      • 位0:必须为1(标识这是异常返回,而非普通分支跳转)
      • 位1:0=返回后使用MSP,1=返回后使用PSP
      • 位2:0=返回线程模式,1=返回处理模式
    • 合法的EXC_RETURN值包括:
      • 0xFFFFFFF9:线程模式 + MSP
      • 0xFFFFFFFD:线程模式 + PSP
      • 0xFFFFFFF1:处理模式 + MSP
      • 0xFFFFFFF5:处理模式 + PSP
  2. 异常返回失败触发条件:
    若EXC_RETURN值不符合编码规则、栈指针未对齐、栈帧不完整或内存权限不足,会触发Usage Fault,其中INVPC位置位表示EXC_RETURN值无效。

排查方向

  1. 检查PSP对齐性:Cortex-M3要求栈指针必须8字节对齐,若msr psp, r1设置的PSP值未满足双字对齐,使用0xFFFFFFFD返回时会触发错误
  2. 验证任务栈帧完整性:使用PSP返回时,栈帧必须包含完整的8个寄存器值(xPSR、PC、LR、R12、R0-R3),且顺序与异常入栈的顺序一致
  3. 检查CONTROL寄存器配置:返回用户模式时,CONTROL寄存器的位0(nPRIV)需为1;同时确认栈帧中xPSR的T位是否为1(Cortex-M3仅支持Thumb模式)
  4. 栈内存权限检查:用户模式下访问的PSP栈内存区域,需配置为用户可访问的权限,不能是内核专属的内存块
  5. 实时调试PSP值:在执行msr psp, r1后,查看PSP的实际值是否指向合法的栈空间起始位置,是否超出内存范围

内容的提问来源于stack exchange,提问作者AO7

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 05:05:02