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

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

3天内不再提示

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

茶话MCU 来源:lq 2019-02-04 15:20 次阅读

曾有STM32用户反馈,他发现同样代码在STM32F1系列芯片上运行好好的,而且代码跟STM32外设关联性也不大。而当代码运行在stm32L071VB单片机时,在做数据的内存拷贝时会进入硬件错误【Hard Fault】,觉得不可理解。

它定义了类似下面的数据结构,并用到预编译命令安排结构体数据成员的存放对齐原则:

#pragma pack‍ (1)

Struct Comm_Frame {

uint8_t Head;

uint16_t Data[3];

uint8_t Class;

uint16_t Tail [2];

} Stream;

#pragma pack ()

他使用到基于上面结构体定义的数据变量进行数据通信,为了让数据成员在内存中紧凑连续存放,将数据结构体的地址对齐规则指定为字节对齐,即使用#pragma pack (1)。数据在内存中像下面样子摆放:

他这样设计的话,数据结构体中的Data[]和Tail[]双字节数据会出现在奇数地址的地方。那么,当将上述Stream.Data[]数据拷贝出去的时候,在基于双字节数据类型的指针寻址访问时,会出现被访问数据的地址不遵循2倍数的原则,即出现访问地址不对齐的问题,可能导致运行出错。一般来讲,对于ARM内核的芯片,基于双字节数据宽度的寻址访问时,被访问数据的地址要求是2的倍数;基于4字节数据宽度的寻址访问时,地址要求是4的倍数。

比如:这里定义了一个数组uint16_t forcomp[3]和下面两个指针:

uint16_t *pointer1 = &forcomp[0];

uint16_t *pointer2 = &Stream.Data[0];

现将上面结构体成员Stream.Data[]的内容通过指针寻址按如下方式拷贝进‍forcomp[]‍。

上面的代码如果运行在基于M0或M0+内核的STM32芯片的话,就会出现Hard Fault错误. 客户使用的芯片stm32L071VBT6正是基于M0+内核的STM32芯片。

为什么会这样呢?这可以从Cortex M0/M0+的内核技术手册上看到相关描述:

显然,基于M0、M0+内核的芯片,它是不支持非对齐寻址访问的。

客户又说过,相同代码在STM32F1芯片上运行又没有问题,那怎么解释呢?

STM32F1系列MCU是基于ARMCortex M3内核的芯片,关于地址对齐方面跟M0/M0+有所不同。M3内核支持部分指令的非对齐地址访问,相关描述如下:

也就是说,基于CortexM3内核的芯片,它支持部分指令的非对齐访问,但非对齐访问要慢于对齐访问。即非对齐访问是需要代价的,访问效率会受到影响。所以,我们在应用中要尽量遵循地址对齐的寻址访问方式。关于地址对齐话题,在各个ARM内核技术参考手册里略有介绍。

结合本案的实际情况,碰巧用户代码先是可以正常运行于基于M3内核的STM32F1芯片,而在基于M0+内核的芯片上出现了异常。导致他觉得不好理解。

这里,指针所指数据类型为双字节类型,为了避免在M0/M0+内核芯片里寻址访问时发生非对齐而导致的异常,可以将结构体变量的内存地址对齐方式改为双字节对齐,即使用#pragma pack (2)。数据在内存中像下面这样摆放。

这样修改后,经过测试的确没有问题。结合到客户的具体情况,客户希望数据连续、紧凑存放,不希望数据间有空隙,即结构体数据成员的内存地址对齐规则不变,仍然采用pack(1)。那么,数据拷贝操作时可以将双字节数据类型的指针强转为单字节数据类型的指针,将双字节数据按字节对齐寻址方式分作两次连续读取完成。此时,用户只需将应用程序稍作调整即可。

所以,在STM32开发过程中,有些代码或许跟MCU外设没什么关系,但可能跟内核有关。STM32系列众多,涉及多个ARM内核,不同的内核在诸多方面存在些差异,这点需要注意。其实,从MCU软件开发层面来看,地址对齐问题、中断优先级安排问题、堆栈安排问题,都是些比较隐蔽的问题,出错了后果往往也很严重,我们平时可以多留意下。

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

    关注

    2239

    文章

    10671

    浏览量

    348720
  • 代码
    +关注

    关注

    30

    文章

    4555

    浏览量

    66740
  • 数据结构
    +关注

    关注

    3

    文章

    564

    浏览量

    39899

原文标题:一个跟地址对齐有关的应用异常案例

文章出处:【微信号:stmcu832,微信公众号:茶话MCU】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    TC277如何指定该全局数组变量的存储地址对齐方式?

    定义全局数组变量,如何指定该全局数组变量的存储地址对齐方式
    发表于 02-19 07:37

    请问MDK怎么让函数对齐到1K地址边界?

    RT,需要运行时删除部分函数,怎么让它对齐在flash扇区边界上?
    发表于 11-03 07:49

    为何FPU使用float变量地址要4字节对齐

    为何 FPU 使用 float 变量地址要 4 字节对齐
    发表于 10-20 06:53

    为什么ST库函数结构体没加对齐地址是连续的?

    为什么ST库函数结构体没加对齐地址是连续的
    发表于 10-15 08:11

    对flash整块地址数据存储和读取数据为什么要左对齐

    对flash整块地址数据存储和读取数据为什么要左对齐
    发表于 10-13 06:45

    MCU的静态功耗主要是什么因素有关系?

    MCU的静态功耗主要是什么因素有关
    发表于 10-11 08:00

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

    一个地址对齐引起的 HardFault 异常
    的头像 发表于 09-18 10:57 428次阅读
    一个<b class='flag-5'>地址</b>未<b class='flag-5'>对齐</b>引起的HardFault<b class='flag-5'>异常</b>

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

    。 二. 问题 Lwipopts.h中MEM_ALIGNMENT可以配置堆对齐大小,有问题时是配置为1 #define MEM_ALIGNMENT 1U 异常时打印寄存器如下,当然不同平台异常时如何获取上下
    的头像 发表于 09-09 08:44 1213次阅读
    基于DWC_ether_qos的以太网驱动开发-LWIP的堆(内存池)未<b class='flag-5'>对齐</b>导致问题的案例分享

    关于NUC980的网口的发送描述符的缓冲区地址要求4字节对齐的问题

    把数据缓冲区直接发送 另外问题,我看接收缓冲区的地址好像没有要求4字节对齐。 Receive Buffer Starting Address [31..0] Transmit Bu
    发表于 09-04 06:44

    stm32单片机存储擦除方式什么有关

    之前用的stm32f1系列单片机,写数据时是按页擦除的,后来换stm32f407后发现写数据的时候会占用单片机很长时间,后来发现这款单片机是按扇区来擦除的,请问下这个擦除方式什么有关啊,后面设计的时候如何判定
    发表于 08-08 08:17

    NUC980的网口的发送描述符的缓冲区地址要求4字节对齐的问题求解

    NUC980的网口的发送描述符的缓冲区地址要求 4字节对齐的问题,因为我用的协议栈里面要求IP数据段4字节对齐,加上以太网14字节,如果发送缓冲区要求4字节对齐,带来的问题我必须要完成
    发表于 06-27 07:34

    NUC980的网口的发送描述符的缓冲区地址要求4字节对齐的问题求解

    把数据缓冲区直接发送 另外问题,我看接收缓冲区的地址好像没有要求4字节对齐。 Receive Buffer Starting Address [31..0] Transmit Bu
    发表于 06-13 07:01

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

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

    为什么要结构体对齐?为什么结构体对齐那么重要?

    C语言结构体对齐问题,是面试必备问题。我参与招聘技术面试的时候,也喜欢问这个技术点。
    的头像 发表于 05-26 14:10 663次阅读
    为什么要结构体<b class='flag-5'>对齐</b>?为什么结构体<b class='flag-5'>对齐</b>那么重要?

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

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