0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

一个地址未对齐引起的HardFault异常

jf_pJlTbmA9 来源:STM32单片机 作者:STM32单片机 2023-09-18 10:57 次阅读

1.概述

客户在使用 STM32G070 的时候,KEIL MDK 为编译工具,当编译优化选项设置为Level0 的时候,程序会出现 Hard Fault 异常,而当编译优化选项设置为 Level1 的时候,则程序运行正常。

表面上看,这似乎是 KEIL MDK 的问题,通过分析,导致这个问题的本质原因是内存地址没有对齐引起的,下面章节将详细分析该问题的来龙去脉以及解决方法。

2.问题描述与分析

根据客户的反馈,引起问题的代码很简单,客户定义了几个全局数组,在主程序中访问这几个数组就会出现 Hard Fault 异常,参考代码如下。

wKgaomUDzW-ASSFXAAKMO7qO1zU016.png

把客户提供的代码片段移植到 NUCLEO-G070RB 开发板上,问题很容易就复现了,代码本身功能简单,写法上也没有错误,所以从代码片段本身上看,无法确定问题出在哪里,通过 KEIL 调试器,在汇编窗口单步调试下,最终发现导致 HardFault 异常的语句为下图所示语句。

wKgaomUDzXSAKy7hAAIJqOIWXwQ854.png

根据单步调试得知出现问题的语句为 LDR 指令,参考 Cortex M0 编程手册 PM0223 得知 LDR 指令的作用是从内存地址中加载一个 WORD 数据到目的寄存器 Rt 中,其中内存地址根据 Rn 或者 SP 寄存器的值以及立即数 imm 得到。

wKgZomUDzXaAfhbqAAFcPh7FuT4672.png

根据指令的描述,使用 LDR 指令的时候,通过 Rn 和 imm 计算得到的内存地址必须是读取字节数的倍数,LDR 每次读取一个 WORD,所以使用 LDR 指令时,内存地址必须 4字节对齐。如果地址没有对齐,则会导致 HardFault 异常。

结合 LDR 指令的描述,在调试状态下,通过查看寄存器值,图 2 出错语句中根据 Rn和 imm 计算得到的内存地址为 R0=0x2000000B,imm=4 所以内存地址为 0x2000000F,很显然这个地址不是 4 字节对齐的。

wKgaomUDzXiAXrhKAAHpxnz5tEs892.png

而当我们改变编译优化选项为 Level1 时,得到的内存地址为R0=0x20000000,imm=0x04 显然这个地址是按照 4 字节对齐的,所以这种情况下是不会出现 HardFault 异常的,印证了客户的问题现象。

wKgZomUDzXyAA6YsAAH2kOHpX_o908.png

3.问题解决

通过上一节的分析,明确了导致该问题的本质原因是内存地址没有对齐,这个内存地址实际上是代码中定义的全局变量 g_curPlaySound_app 指向的地址,也就是全局数组变量 SoundFile 的地址,在编译器不同的优化选项下,分配给 SoundFile 变量的地址是不一样的,在本案例中,编译优化选项 Level0 条件下,SoundFile 分配的地址没有按照WORD 对齐,而在优化选项 Level1 条件下,SoundFile 分配的地址是 WORD 对齐,所以在两种优化选项下,出现了不一样的运行结果。

所以要保证程序不出错,当通过指针访问变量的时候,要确保指针指向的地址是 4 字节对齐的,在 Keil 环境下,可以通过__attribute__((aligned (4))) 关键字实现,如下图所示,通过该关键字,对齐了地址,也就不会出现 HardFault 异常了。

图6 确保地址对齐

wKgaomUDzX6AMKw_AALxznUvPqE621.png

4.总结

地址未对齐是嵌入式系统中容易忽视的一个细节,忽视这点往往会导致一些奇怪的问题,所以在开发过程中,注意这些细节还是很有必要的。

来源:STM32单片机

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 单片机
    +关注

    关注

    6032

    文章

    44513

    浏览量

    632734
  • 嵌入式系统
    +关注

    关注

    41

    文章

    3563

    浏览量

    129207
  • STM32
    +关注

    关注

    2265

    文章

    10870

    浏览量

    354716
  • MDK
    MDK
    +关注

    关注

    4

    文章

    209

    浏览量

    32032
收藏 人收藏

    评论

    相关推荐

    RISC-V对齐导致问题案例

    本文介绍对齐导致问题案例
    的头像 发表于 06-08 10:04 1581次阅读
    RISC-V<b class='flag-5'>未</b><b class='flag-5'>对齐</b>导致问题案例

    基于DWC_ether_qos的以太网驱动开发-LWIP的堆(内存池)对齐导致问题的案例分享

    本文转自公众号欢迎关注 https://mp.weixin.qq.com/s/ErIa2ss2YZLGYbSwoJEzog . 前言 内存对齐访问问题这个已经是老生常谈的问题了, 由于LWIP
    的头像 发表于 09-09 08:44 1658次阅读
    基于DWC_ether_qos的以太网驱动开发-LWIP的堆(内存池)<b class='flag-5'>未</b><b class='flag-5'>对齐</b>导致问题的案例分享

    HardFault_Handler异常

    请教各位,最近用MDK5.11编写STM32F103RC的程序,但是却莫名其妙进入HardFault_Handler异常中断,现在本人完全头雾水,还请大神指点迷津!
    发表于 11-07 17:51

    灵动微课堂 (第173讲) | HardFault定位方法和步骤

    复位之外的任何异常抢占。 HardFault HardFault 是由于在正常操作过程中或在异常处理过程中出现错误而出现的
    发表于 07-02 15:20

    为什么要进行内存对齐操作呢

    地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问
    发表于 12-17 06:34

    导致STM32进入HardFault异常的原因

    图所示程序进入HardFault异常。如下所示我们找到SP寄存器,0x200045B8即为栈地址,栈里面的值依次为R0~R3、R12、PC(Return address)、xPSR(CPS...
    发表于 01-07 06:52

    ARM处理器是否曾经为指令或数据访问生成对齐的突发

    节)数据包与32位边界对齐。然后显示了对齐的第一个字节的突发示例。我还看到了有关在突发写
    发表于 08-19 15:43

    iMXRT1170的cortex M7上的HardFault异常是怎么回事?

    HardFault 异常)。下面是来自 IAR EW 的错误图像。代码行仅执行从结构到另一个结构变量的赋值操作。 谁能告诉我们为什么会
    发表于 04-04 07:42

    RISC-V对齐访问导致问题案例

    转自公众号,欢迎关注 参考https://mp.weixin.qq.com/s/8wfRFg1XcBsXw5gMq-cKaQ前言 本文以实例,讲解RISC-V对齐访问导致的问题.
    发表于 05-06 19:14

    MRS_关于HardFault问题查找思路

    ,MTVAL=20000ca1。由表可知该案例的报错原因为Load指令访存地址对齐,结合MTVAL的情况1可知异常时存储器访问的地址为0
    发表于 08-24 10:57

    异常向量表重映射

    异常向量表重映射 向量表是异常产生时内核获取异常处理函数入口地址块连续内存,每一个
    发表于 03-26 09:34 20次下载

    地址对齐有关的应用异常案例

    也就是说,基于CortexM3内核的芯片,它支持部分指令的非对齐访问,但非对齐访问要慢于对齐访问。即非对齐访问是需要代价的,访问效率会受到影响。所以,我们在应用中要尽量遵循
    的头像 发表于 02-04 15:20 2536次阅读
    <b class='flag-5'>一</b><b class='flag-5'>个</b>跟<b class='flag-5'>地址</b><b class='flag-5'>对齐</b>有关的应用<b class='flag-5'>异常</b>案例

    解决STM32因字节对齐问题导致读写Flash失败进入HardFault的问题

    ,获取升级包的文件所有结构体采用字节对齐,解析升级包采用指针偏移的方式。进入Flash未进行擦除操作前的参数如下:要写入的长度和地址都是没问题的,但是buf指针的在RAM中的地址为0
    发表于 12-02 09:06 15次下载
    解决STM32因字节<b class='flag-5'>对齐</b>问题导致读写Flash失败进入<b class='flag-5'>HardFault</b>的问题

    工程师笔记|地址对齐引起的 HardFault 异常

    关键词:地址对齐Hardfault,STM32G0 目录预览 1. 概述 2. 问题描述与分析 3. 问题解决 4. 总结 1.概述 客户在使用 STM32G070 的时候,KEIL MDK 为
    的头像 发表于 02-10 11:05 2085次阅读

    ES32F36xx芯片发生HardFault异常时的函数调用关系及问题定位

    ES32F36xx芯片发生HardFault异常时的函数调用关系及问题定位
    的头像 发表于 11-06 17:13 721次阅读
    ES32F36xx芯片发生<b class='flag-5'>HardFault</b><b class='flag-5'>异常</b>时的函数调用关系及问题定位