欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

【专题4:平时遇到的问题】 之 【再一次被字节对齐问题折腾到大半夜】

程序员文章站 2022-06-24 18:42:23
读内存字节对齐问题...
希望本是无所谓有,无所谓无的,这正如脚下的路,其实地上本没有路,走的人多了,也便成了路
原创不易,文章会持续更新
文章会同步到作者个人公众号上,感谢扫码关注

【专题4:平时遇到的问题】 之 【再一次被字节对齐问题折腾到大半夜】

所有文章总目录:【嵌入式 无人机 电机控制】
原创视频总目录:【嵌入式 无人机 电机控制】

1.问题由来

还是通信协议的问题。
通信协议定义如下:

    0	0xA5,起始符
    1	发送方设备类型
    2	Main cmd
    3	usParameterLength_low_8bit
    4	usParameterLength_high_8bit
    5	Subcmd_low_8bit
    6	Subcmd_high_8bit
    7   Data[0]
    8   Data[1]
    .
    .
    .
    .

定义了一个结构体:

typedef struct {//这个结构体4字节对齐
    enDeviceType_t	ubDeviceType;//1字节
    uint8_t		 	ubMainCmd;
    uint16_t		usParameterLength;
    uint32_t 		usSubCmd;
    uint8_t*		pParameterBuffer;//4字节
}tagOneFrame_t, *pOneFrame_t;

把从网络得到的数据写到STM32G07平台的flash中。
从网络获得的数据放在数组msgBuffer中。

__attribute__((optimize( 0 ) ))int main(void)
{
	uint8_t msgBuffer[2048];
	tagOneFrame_tframe;
	
	/*对msgBuffer中的数据进行解析*/
	frame.ubDeviceType = msgBuffer[0];
	frame.ubMainCmd = msgBuffer[1];
	frame.usParameterLength = msgBuffer[4] << 8 || msgBuffer[3];
	frame.usSubCmd = msgBuffer[6] << 8 || msgBuffer[5];
	frame.pParameterBuffer = &msgBuffer[7];
	
	uint64_t value = ((uint64_t*)frame.pParameterBuffer)[0];
}

【专题4:平时遇到的问题】 之 【再一次被字节对齐问题折腾到大半夜】
运行到第51行代码时,直接触发HardFault了,也就是CPU挂了。

2.问题复现

将上面的问题简化一下:

__attribute__((optimize( 0 ) ))int main(void)
{
	uint8_t buffer8bit[64];

	uint64_t value = ((uint64_t*)&buffer8bit[9])[0];

	value++;
}

【专题4:平时遇到的问题】 之 【再一次被字节对齐问题折腾到大半夜】
如果把uint64_t改成uint32_t,也会运行出错。

【专题4:平时遇到的问题】 之 【再一次被字节对齐问题折腾到大半夜】

3.结论

(1)读内存:
地址必须对齐,读取uint64_t大小时,地址必须是8字节对齐,读取uint32_t大小时,地址必须是4字节对齐。在定义通信协议时,数据的起始位要注意是否满足字节对齐的要求。否则,处理器会HardFault。

(2)写flash:
STM32G071平台一次性只能写64bit数据,也就是8字节,写的地址必须是8字节对齐。否则,处理器会HardFault。

STM32F103RB平台一次性只能写16bit数据,写的地址必须是2字节对齐。否则,处理器会HardFault。

本文地址:https://blog.csdn.net/qq_29083043/article/details/109634853