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

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

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

复制代码
1
2
3
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个字节空间,但不浪费时间也能避免转换时发生错误。
具体可以看如下代码示例:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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内容请搜索靠谱客的其他文章。

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

评论列表共有 0 条评论

立即
投稿
返回
顶部