我是靠谱客的博主 疯狂天空,最近开发中收集的这篇文章主要介绍STM32结构体变量保存到FLASH的字节对齐问题解决,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

结构体的首地址不是4的整数倍时,直接用uint32_t强制转换会出现硬件错误导致死机。问题原因是内存访问机制,要求uint32_t 指向的地址最低2bit必须是0,uint16_t* 指向的地址最低1bit必须是0。也就是说32位数存放在RAM里的地址必须是4的倍数,16位数存放在RAM里的地址必须是2的倍数。当这个地址不是4的倍数时,采用强制转成32位数的指针,必然导致问题。
解决方法大致有3种。

1. 在代码里加入字节对齐的宏指令。

static u8 spi1_send_buf[100] __attribute__((aligned(4)));
static u8 spi1_recv_buf[100] __attribute__((aligned(4)));

2. 定义一个缓存数组,将结构体数据转为数组,再进行FLASH读写操作。

3. 把结构体第一个元素改成uint32_t类型,如果不能改,那就增加一个无意义的32位数,作为结构体首个元素。

第一种会浪费大量内存空间,不可取。
第二种办法会浪费一些空间和一些时间,还要保证转换过程别出错,也不是最佳方法。
第三种办法因为32位数在RAM里保存时会自动按4字节对齐,所以可以保证整个结构体首地址最低2位是0,符合内存存取规则。这个才是最巧妙的办法,最多只浪费4个字节空间,但不浪费时间也能避免转换时发生错误。
具体可以看如下代码示例:

struct User_Config//结构体大小12bytes
{
	uint32_t	 u_flag;		//读flash时用此标记判断是否有用户设置参数
	uint8_t	 alert;			//取值范围0-1
	uint16_t report_interval;//取值范围1-300s
	uint16_t undervoltage;	//取值范围0-300V
	uint16_t overvoltage;	//取值范围0-300V
	uint16_t undercurrent;	//取值范围0-200mA
	uint16_t overcurrent;	//取值范围0-9999mA
};

//欠压欠流过压过流报警标志
struct Voltage_Current_Alert
{
	uint8_t uc_flag;	//欠流标志
	uint8_t oc_flag;	//过流标志
	uint8_t uv_flag;	//欠压标志
	uint8_t ov_flag;	//过压标志
};

//单一定时任务结构体
struct Single_Tasks
{
	uint8_t xk;//许可。为0则该闹铃失效
	uint8_t hh;//小时
	uint8_t mm;//分钟
	uint8_t bb;	//亮度值
};


//一天的定时任务结构体
struct Day_Tasks
{
	struct Single_Tasks task_1st;
	struct Single_Tasks task_2nd;
	struct Single_Tasks task_3rd;
	struct Single_Tasks task_4th;
	struct Single_Tasks task_5th;
	struct Single_Tasks task_6th;
};

//一周的定时任务结构体,176bytes
struct Week_Tasks
{
	uint32_t t_flag;		// 	
	uint8_t task_switch;		//任务开关    
	struct Day_Tasks sunday;
	struct Day_Tasks monday;
	struct Day_Tasks tuesday;
	struct Day_Tasks wednesday;
	struct Day_Tasks thursday;
	struct Day_Tasks friday;
	struct Day_Tasks saturday;	
};

最后

以上就是疯狂天空为你收集整理的STM32结构体变量保存到FLASH的字节对齐问题解决的全部内容,希望文章能够帮你解决STM32结构体变量保存到FLASH的字节对齐问题解决所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(54)

评论列表共有 0 条评论

立即
投稿
返回
顶部