STMCU小助手
发布时间:2023-2-19 17:00
|
1. 概述* `: `6 \9 \& Q0 z+ _! M! e- j. o% }# e % p- O2 \- ~. m+ T 客户在使用 STM32G070 的时候,KEIL MDK 为编译工具,当编译优化选项设置为Level0 的时候,程序会出现 Hard Fault 异常,而当编译优化选项设置为 Level1 的时候,则程序运行正常。表面上看,这似乎是 KEIL MDK 的问题,通过分析,导致这个问题的本质原因是内存地址没有对齐引起的,下面章节将详细分析该问题的来龙去脉以及解决方法。% s5 Z, \" r8 r) Y 4 b8 B3 S( B* q* W 2. 问题描述与分析" N( y" e1 m8 S$ \& g$ k8 ~ 根据客户的反馈,引起问题的代码很简单,客户定义了几个全局数组,在主程序中访问这几个数组就会出现 Hard Fault 异常,参考代码如下。; R, g( ~# Y$ K2 C1 K" V6 g* ^! \ & E+ o9 d8 y2 W4 A7 | ; E2 k& L' o( `- C+ m! k& d
|- T2 g: [$ m0 }- o1 \ 把客户提供的代码片段移植到 NUCLEO-G070RB 开发板上,问题很容易就复现了,代码本身功能简单,写法上也没有错误,所以从代码片段本身上看,无法确定问题出在哪里,通过 KEIL 调试器,在汇编窗口单步调试下,最终发现导致 HardFault 异常的语句为下图所示语句。9 T/ A+ ^- \% X ) ]' [9 |$ x D, U 9 ~" Y! ^" j, P! P
. L1 A5 V! l( q 根据单步调试得知出现问题的语句为 LDR 指令,参考 Cortex M0 编程手册 PM0223 得知 LDR 指令的作用是从内存地址中加载一个 WORD 数据到目的寄存器 Rt 中,其中内存地址根据 Rn 或者 SP 寄存器的值以及立即数 imm 得到。- ?* r, c, T% Y4 t4 k; { / Y1 O* d$ Y' P1 Z
, I+ [: y8 [1 u! T$ s# } 根据指令的描述,使用 LDR 指令的时候,通过 Rn 和 imm 计算得到的内存地址必须是读取字节数的倍数,LDR 每次读取一个 WORD,所以使用 LDR 指令时,内存地址必须 4字节对齐。如果地址没有对齐,则会导致 HardFault 异常。 结合 LDR 指令的描述,在调试状态下,通过查看寄存器值,图 2 出错语句中根据 Rn和 imm 计算得到的内存地址为 R0=0x2000000B,imm=4 所以内存地址为 0x2000000F,很显然这个地址不是 4 字节对齐的。 $ X& b5 \ w( F3 d6 q/ t6 Q u% d) {6 g& v0 p 8 f o$ q; M4 I6 o6 p % _7 S, E& M/ l! J 完整版请查看:附件
一个地址未对齐引起的 HardFault 异常.pdf
(673.92 KB, 下载次数: 9)
|
【STM32H735G-DK 测评】STM32H735G-DK External Loder 编译和测试
Keil-MDK 在线调试设置断点的高级用法
请教下STM32N6570 怎么把分辨率改成320x240并可以全屏显示
【福利三:逢7发帖赢大礼】想要充分利用STM32H743VI片内的RAM空间(但并不顺利)
基于stm32平台上的IC-MU磁绝对值编码器SPI通讯和码盘数据处理
使用STM32 MCU和MPU连接PDM数字麦克风
分享STM32资料-采用 STM32U031R8 MCU 的 STM32 Nucleo-64 开发板,官方资料,数据手册等资料
HRTIM 指南
使用 STM32 的 DWT 单元监控内存
DAC,COMP,HRTIM Fault 功能的使用
微信公众号
手机版