stm32 开发中,经常会出现一些错误,下面总结一些常见错误及可能原因:
1,Default_Handler
出一这个错误 最常见的原因是 开启了中断,但没有对应的中断响应函数
2,HardFault_Handler,这个错出现在原因最多,用mdk工具调试时可以通中Peripherals-->Core Peripherals-->Fault Reports 来查看具体的错误类型:
其中MemManage fault 状态寄存器提供的讯息
位 | 可能的原因 |
MSTKERR | 入栈时发生错误(异常响应序列开始时) 1) 堆栈指针的值被破坏 2) 堆栈容易过大,已经超出 MPU 允许的 region 范围 |
MUNSTKERR | 出栈时发生错误(异常响应序列终止时)。入栈时没有发生错误,出栈时却出 错,总令人有些匪夷所思,可能的原因是 1. 异常服务例程破坏的堆栈指针 2. MPU 配置被异常服务例程更改 |
DACCVIOL | 内存访问保护违例。这是 MPU 发挥作用的体现。常常是用户应用程序企图访 问特权级 region 所致 |
IACCVIOL | 1. 内存访问保护违例。常常是用户应用程序企图访问特权级 region。入栈的 PC 给出的地址,就是产生问题代码之所在 2. 跳转到不可执行指令的 regions 3. 异常返回时,使用了无效的 EXC_RETURN 值 4. 向量表中有无效的向量。例如,异常在向量建立之前就发生了,或者加载 的是用于传统 ARM 内核的可执行映像 5. 在异常处理期间,入栈的 PC 值被破坏了 |
总线 fault 状态寄存器提供的讯息
位 | 可能的原因 |
STKERR | (自动)入栈期间出错 1. 堆栈指针的值被破坏 2. 堆栈容易太大,到达了未定义存储器的区域 3. PSP 未经初始化就使用 |
UNSTKERR | (自动)出栈期间出错。如果没有发生过 STKERR,则最可能的就是在异常处 理期间把 SP 的值破坏了 |
IMPRECISERR | 与设备传送数据的过程中发生总线错误。可能因为设备未经初始化而引起;
如,USB未初始化而进行数据传输,IWDG未初始化确去喂狗等!! |
PRECISERR | 在数据访问期间的总线错误。通过 BFAR 可以获取具体的地址。发生 fault 的 原因同上。 |
IBUSERR | 同 MemManage fault 中的 IACCVIOL |
用法 fault 状态寄存器提供的讯息
位 | 可能的原因 |
DIVBYZERO | 当 DIV_0_TRP 置位时发生除数为零。导致此 fault 的指令可以从入栈的 PC 读 取 |
UNALIGNED | 当 UNALIGN_TRP 置位时发生未对齐访问。导致此 fault 的指令可以从入栈的 PC 读取 |
NOCP | 企图执行一个协处理器指令。导致此 fault 的指令可以从入栈的 PC 读取 |
INVPC | 1. 异常返回时使用了无效的 EXC_RETURN,例如 1) 当 EXC_RETURN=0xFFFF_FFF1 时却要返回线程模式 2) 当 EXC_RETURN=0xFFFF_FFF9 时却要返回 handler 模式 2. 无效的异常活动状态,例如 1) 当前异常的活动状态已经清除了,却在此时执行异常返回。往往是因 为滥用 VECTCLRACTIVE 或清除了 SHCSR 中活动状态所致 2) 在还有其它异常的活动位置位时,却要返回线程模式 3. 由于堆栈指针错误导致了 IPSR 的值不正确。对于 INVPC fault,入栈的 PC 指出了该 fault 服务例程在何处抢占了其它的代码。这个问题往往是比较 隐晦的程序错误造成的,欲详细调查该问题的原因,最好使用 ITM 的跟 踪功能。 4. ICI/IT 位对当前指令无效。当 LDM/STM 指令被异常打断后,在异常服务 例程中又更改了入栈的 PC。结果在中断返回时,非零的 ICI 位段作用到了 不使用 ICI 位段的指令上。如果是其它原因破坏了 PSR 的值,也可能导致 此 fault。 |
INVSTATE | 1. 加载到 PC 中的跳转地址值是偶数(LSB=0)。通过检查入栈 PC 的值,一 下子就可以查出该问题。 2. 向量地址的 LSB=0,诊断方法同上。 3. 入栈的 PSR 在异常处理过程中被破坏,使得在返回时内核尝试进入 ARM 状态。 |
UNDEFINSTR | 1. 使用了 CM3 不支持的指令 -- 如M3内核确下载了M4内核的代码等 2. 代码段中的数据被破坏 3. 连接时加载了 ARM 目标码。请检查编译阶段的设置 4. 指令对齐的问题。例如,在使用 GNU 工具链时,忘记了在.ascii 后使 用.align,就有可能导致下一条指令没有对齐 |
硬 fault 状态寄存器提供的讯息
位 | 可能的原因 |
DEBUGEVF | 因调试事件导致的 fault 1. 断点/观察点事件 2. 如果在硬 fault 服务例程的执行过程中,没有使能监视器异常(MON_EN=0) 也没有使能停机调试(C_DEBUGEN=0),却执行了 BKPT 指令。缺省时,有 些 C 编译器可能会在半主机代码中使用 BKPT 指令。 |
FORCED | 这是 fault“上访”的情况 1. 试图在 SVC/监视器服务例程中执行 SVC/BKPT,或者在其它拥有相同或更高 优先级的服务例程中执行 SVC/BKPT。 2. 发生了 fault,但是它的服务例程被除能 3. 发生了 fault,但是当前处理器在响应同级或更高优先级的异常 4. 发生了 fault,但是它被掩蔽了 |
VECTBL | 取向量失败, 1. 在取向量过程中发生总线 fault 2. 向量表偏移量设置有误 |
调试 fault 状态寄存器提供的讯息
位 | 可能的原因 |
EXTERNAL | EDBGREQ 信号置为有效 |
VCATCH | 发生了向量抓捕事件 |
DWTTRAP | 发生了 DWT 观察点事件 |
BKPT | 1. 执行了 BKPT 指令 2. FPB 单元产生了断点事件 |