打印
[信息]

【实战经验】STM32缓存的对齐问题

[复制链接]
3670|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 香水城 于 2017-8-14 14:09 编辑

STM32缓存的对齐问题

前言

在我们对STM32进行编程的时候,都会用到变量,因为我们的MCU是32位的,所以在申请变量的时候,就会存在变量长度不一致,需要对齐的问题.这个变量长度对齐的问题,小则可以只是影响代码执行的效率,大则会出现系统hard-fault的问题.下面我们将详细的解说这个问题.

不对齐的后果

效率
需要对变量进行对齐的一个重要原因是因为MCU访问数据的效率问题.例如,如果一个变量的地址没有对齐,比如在0x00000002,则MCU如果需要读取它的值,则需要进行两次访问.如果在0x00000003的话,则需要三次访问,然后整合读取的数据.而如果数据是对齐的话,例如0x00000004,那么只需要一次访问就可以了.但是现在的IDE都比较智能,就算你强制让一个变量放到基数或者其他非对齐的地址上时,他是会报错的.


空间
变量地址对齐了,就会带来空间的浪费,但这个一般体现在结构体上.由下面的例子我们可以看出,就算一样的结构体,不同的顺序,会带来不一样的总长度.在Struce B中,char虽然物理上是2个byte,但是由于对齐的原因,加上他紧随的变量和他的变量不一致,所以他需要额外的2个byte来使结构体内部对齐.所以在定义结构体的变量时,我们一般最好做到同样的顺序,即使类型从小到大排序,或着从大到小来排序.这样可以带来空间上的节省.最直接的方式就是你可以用SIZEOF()这个函数来查看结构体的大小



综合
通过上述,一般以为只要按照最好的排序方式,结构体就会对齐了.其实并不是这样的,他只会对不同类型的变量之间做对齐,如果如下面的结构体.

因为第一个和第一个变量的类型是一致的,所以系统会合并,所以a1+a2的大小才是8byte.如果如下,就会对齐了,但是长度就会编程16byte.

在第一个例子里面会存在效率的问题,如果在一些低功耗上,或者对算法实时性要求较高的地方,就会是个不小的问题.为什么?因为a2没有对齐.这会带来效率上的问题,下面我们通过实际代码来测试这个效率差.

案例与总结

案例1 :

通过一个for循环来检测他的运行时间.


这串代码所需的tick
运行之前:0x3D3F

可以看出这段代码所需时间为: 0x3D3F - 0x31EC = 0x0B53


案例2 :

有下图我们可以看到a1和a2之间并不像案例1之间有填补.

这串代码所需的tick
运行之前:0x3D3F

运行之后:

可以看出这段代码所需时间为: 0x3D3F - 0x2DF1 = 0x0F4E

总结 :

可以看出,简单的三行代码,在是否对齐下,增加35.1%的时间,如果在一些复杂度要求较高的应用,低功耗的应用中,这将会是一个很大的问题.

建议 :
所以如果在一些比较大或者运用的比较多的结构体,我们可以人为的错开不同的类型变量,因为就算你外部添加了强制的对齐命令,在现有的IDE里面(KEIl 5.20),暂时还没有对同种类型的变量进行对齐.如果基本都是同种类型的变量,建议可以嵌套结构体来避开.这样错开了,剩下的就有系统帮你完成对齐动作.


对应的PDF:stm32缓存对齐的问题
更多实战经验请看: 【ST MCU实战经验汇总贴】

沙发
mmuuss586| | 2016-8-9 10:00 | 只看该作者
谢谢分享,以前还没注意过这个问题;

使用特权

评论回复
板凳
idqiye| | 2016-11-8 13:45 | 只看该作者
这个PDF为什么下载不了

使用特权

评论回复
地板
idqiye| | 2016-11-8 15:06 | 只看该作者
系统hard-fault的问题,并没有提到额,还有针对STM32来说,如果用keil编译器的话,是不是你在定义变量时就自动给你按照对齐方式分配地址了,所有的变量都是按照对齐方式来的,这样的结果只会造成系统内存空间,可能会有点浪费,不存在效率问题额,所以对于STM32直接按照4字节对齐来就行了,你说的hard-fault怎样才能出现?

使用特权

评论回复
5
icecut| | 2016-11-8 16:19 | 只看该作者
idqiye 发表于 2016-11-8 15:06
系统hard-fault的问题,并没有提到额,还有针对STM32来说,如果用keil编译器的话,是不是你在定义变量时就 ...

你可以构造一个特殊的语法绕过 编译器检查,进行读取不对齐数据,就会报错了

使用特权

评论回复
6
idqiye| | 2016-11-9 09:47 | 只看该作者
icecut 发表于 2016-11-8 16:19
你可以构造一个特殊的语法绕过 编译器检查,进行读取不对齐数据,就会报错了 ...

有一点疑惑,stm32应该是默认4字节对齐的,为什么MDK编译器下默认是8字节呐
“Default The default is #pragma pack(8).”????

使用特权

评论回复
7
icecut| | 2016-11-9 12:54 | 只看该作者
idqiye 发表于 2016-11-9 09:47
有一点疑惑,stm32应该是默认4字节对齐的,为什么MDK编译器下默认是8字节呐
“Default The default is #p ...

不知道

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:意法半导体(中国)投资有限公司
简介:STM32技术专家

596

主题

17099

帖子

287

粉丝