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

ARM Cortex-M3无法触发Bus Fault、Usage Fault等异常的问题排查

问题分析与解决方案

咱们一步步拆解你代码里的问题,以及为什么触发异常后没进入预期的handler:

1. 错误配置了SCB->CFSR寄存器

SCB->CFSR是可配置故障状态寄存器,它本质是个**只读(仅支持写1清零错误位)**的状态记录寄存器,用来标记已发生的错误类型,而非配置异常开启的控制寄存器。你直接给它赋值0x0367E7C3完全不合理——这些位要么是只读的状态位,要么只能通过写1来清除错误标记,初始化时应该清零(写对应位为1完成清除)或者保持上电默认值(0)。这个错误的写操作可能干扰了故障检测的正常逻辑。

正确的处理方式:

// 写1清除所有可配置故障状态位
SCB->CFSR = 0xFFFFFFFF;

2. 除零异常未触发:你用的是浮点数除法(软件模拟)

你提到除零后变量显示为"Infinity",这说明你执行的是浮点数除法。而Cortex-M3的DIV_0_TRP位(SCB->CCR的bit4)只对**硬件整数除法指令(SDIV/UDIV)**生效。

如果是C语言中的浮点数除法,编译器会调用软件库处理,除零会返回IEEE标准的Infinity值,不会触发硬件UsageFault。要触发除零异常,你需要用整数除法,比如:

int a = 1;
int b = 0;
int c = a / b; // 这会触发硬件除零异常,进入UsageFault_Handler

另外要确保编译器没有把整数除法优化成软件模拟,比如ARM GCC的-mthumb -mcpu=cortex-m3默认会启用硬件除法支持,不用额外配置。

3. Bus Fault未触发的可能原因

首先要确认你触发Bus Fault的方式是否正确,常见的有效触发场景:

  • 访问不存在的内存地址(比如超出芯片地址空间的0xFFFFFFF0)
  • 开启对齐检查(SCB->CCR的UNALIGN_TRP位,bit3)后,执行非对齐的内存访问(比如用32位指针访问奇数地址的内存)
  • 访问未就绪或地址错误的外设

另外,检查你的Bus Fault handler是否被编译器优化掉了——如果handler是空的,编译器可能会把它优化成空函数甚至直接忽略,导致调试时无法命中断点。你可以在handler里加死循环防止优化:

void BusFault_Handler(void){
    while(1){
        volatile int dummy = 0; // 用volatile变量阻止编译器优化
        dummy++;
    }
}

4. 其他注意事项

  • 调试器配置:有些调试器会在故障发生时自动暂停,而非进入自定义handler,你可以关闭调试器里类似"Auto halt on fault"的选项,让程序进入你自己的handler。
  • SCB->SHCSR的设置是对的:0x00070000对应开启MemManage(bit16)、BusFault(bit17)、UsageFault(bit18),这部分没问题。
  • NVIC优先级:你把三个故障的优先级设为0x01是可行的,但要注意Cortex-M3的优先级分组(SCB->AIRCR的PRIGROUP字段),确保优先级值在有效范围内。

最后,修正后的EnableExceptions函数参考:

void EnableExceptions(void) {
    UINT32 uReg = SCB->SHCSR;
    // 开启MemManage、BusFault、UsageFault(用宏定义更易读)
    uReg |= (SCB_SHCSR_MEMFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk | SCB_SHCSR_USGFAULTENA_Msk);
    SCB->SHCSR = uReg;

    // 清除所有可配置故障状态位
    SCB->CFSR = 0xFFFFFFFF;

    // 开启除零触发UsageFault
    SCB->CCR |= SCB_CCR_DIV_0_TRP_Msk;

    // 设置故障handler优先级
    NVIC_SetPriority(MemoryManagement_IRQn, 0x01);
    NVIC_SetPriority(BusFault_IRQn, 0x01);
    NVIC_SetPriority(UsageFault_IRQn, 0x01);
}

这样修改后,用整数除零或正确的Bus Fault触发方式,应该就能进入对应的handler了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 13:32:52