本帖最后由 香水城 于 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实战经验汇总贴】
|
|