STM32G071字节类型强制转换后进入HardFault_Handler()

在STM32开发过程中,遇到因非字节对齐访问导致的HardFault问题。在STM32F429上,使用类型强制转换进行不同大小变量赋值未出现问题,但在STM32G071(Cortex-M0+内核)上,由于不支持非字节对齐访问,导致程序崩溃。通过内存调试发现,STM32G071对地址对齐有严格要求。为解决此问题,采用了标准库函数memcpy,成功避免了非对齐访问,保证了程序正常运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述

之前的开发一直是基于STM32F429片子进行的,因为我比较懒,秉承着能少写就少些的原则,在对类型不匹配的变量进行赋值的时候,我比较偏向于使用类型强制转换,比如:

uint8_t tmp[2]={0,0};
uint16_t tmp_value=0xABCD;

此时如果要将tmp_value的值赋值给tmp,但是两者的类型又不相同的时候,一般有以下两种方法:

/* 方法1 */
tmp[0] = (uint8_t)tmp_value;
tmp[1] = (uint8_t)(tmp_value>>8);

/* 方法2 */
*uint16_t *)tmp = tmp_value;

由于方法2能少写一句,所以,一直以来我就是按照方法2进行编写的,也没出现过问题,但是最近由于需要开发一个新的项目,功能相对简单一些,不需要很高性能的片子,选择了最近ST比较热门的芯片STM32G071,当程序开发完成以后,发现片子不能够正常运行,进入调试模式发现程序老是在执行下面这句话的时候进入HardFault;

*((uint16_t *)(&(txPacket.payload[2]))) = Data_From;

其中 txPacket.payload 是一个 uint8_t 类型的数组
先开始找不到出问题的原因,因为之前对于F429、F409一直都是采用的这样的写法,后来通过memory调试查看,发现了可能是因为地址问题,这个片子不支持非字节对齐访问,因为 txPacket.payload[2] 的地址为一个奇数,不能够被2整除,为了印证我的猜测,我将上述代码改为:

*((uint16_t *)(&(txPacket.payload[3]))) = Data_From;

结果程序可以正常跳过,为了印证我的猜想,查看了Cortex-M0+手册,发现M0+内核并不支持字节非对其访问(差评)。关于非对其访问的解释:

单片机中,经常使用到的数据类型有:
shortintlongcharfloatdouble
它们的大小分别为:
2 Byte、4 Byte、4 Byte、1 Byte、4 Byte、8 Byte
当定义一个变量的时候,它们在内存中的地址和大小有关系的,也就是地址能够被大小整除。
比如一个char类型的变量,它的大小为 1 Byte,那么它在内存中的地址的最后一位一定是以 0~F中的一个 ;
再比如一个short类型的变量,它的大小为 2 Byte,那么它在内存中的地址的最后一位一定是 02468 、A、 C、E中的一个;
以此类推int类型的变量,它在内存中的地址的最后一位一定是048、c中的一个;
当我们直接强制到一个变量地址中去取一个和该地址不匹配的数据类型,比如 0x20000001 去访问一个short类型的数据,如果能够成功访问,那么就证明能够进行非对其访问,反之,则证明不能进行非对其访问。

解决方法

最终为了秉承能少写一句就少写一句的原则,我想起来可以使用标准库函数里的memcpy(),于是我将代码改为:

memcpy((void *)&txPacket.payload[2], (void *)&Data_Form, 2);

编译下载,no problem!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值