1》事情缘由:今天遇到一个bug,调试了大半天,最终锁定是字节对齐问题,但具体细节尚不清楚,请路过的大神帮忙指教,谢谢。
2》开发环境:stm32f103vct6 + Keil MDK - 5.23 + 未开启优化。
3》详细细节:本来程序是可以通过运行的,”手抽“将数组调动位置(由于调动位置,导致数组buf[]的起始地址开始满足4字节对齐,后来仅仅满足2字节对齐)。于是开启漫长的debug。。。
4》实际代码:删除部分无关代码,浓缩如下:
5》运行效果:如果注释掉aaa[]数组,程序正常执行;如果不注释掉aaa[]数组(注意:此时buf[]起始地址不满足4字节对齐),程序执行到下述位置,直接进入HardDefualt!!!
- uint8_t aaa[21];
- uint16_t buf[1000];
-
- #define data1 (*((float *)((uint16_t *)(buf + 600))))
- #define data2 (*((float *)((uint16_t *)(buf + 602))))
-
- #define temp1 (*((float *)((uint16_t *)addr + 0)))
- #define temp2 (*((float *)((uint16_t *)addr + 2)))
-
- #define ADDR_BASE ((void *)((uint16_t *)buf + 600))
-
- float func(void *addr)
- {
- volatile float tmp;
- tmp = temp1 + temp2; //程序执行到这里,直接进入HardDefault!!!
- return tmp;
- }
- int main()
- {
- volatile float tmp;
-
- data1 = 1.1;
- data2 = 3.3;
-
- board_init();
-
- tmp = func(ADDR_BASE);
-
- printf("buf = %u, tmp = %f
", (uint32_t)((void *)buf), tmp);
-
- while (1);
- }
复制代码
6》个人理解1:buf[]数组是uint16类型,因此系统默认会让buf[]数组满足2字节对齐,是否满足4字节对齐则是随机的。
7》个人理解2:由于Cortex-M3/M4默认是支持非对齐访问的(无外乎是多浪费几条指令,将非对齐最终转换为对齐访问),所以不明白此段代码为什么会进入HardDefualt,恳请指教,感谢!!!
首先,先感谢2位大神指导,非常感激...
其次,在发表本帖之前,我也翻阅过《Cortex-M3/M4 权威指南》,Page143中列举对齐相关有如下限制:
* 多加载/存储指令不支持非对齐传输。的确如laoshuhunya大神所言。
* 栈操作指令必须对齐。
* 排他操作指令必须对齐。
* 位段操作指令必须对齐。
根据我的实验,本次导致非对齐异常是因为使用LDRD指令(这个《权威指南》没有明确指出该指令会导致对齐异常,但仔细想想,既然是4字节指令,那么4字节对齐或许是默认要求吧),还请大神帮忙证实下,感谢。
最后,给出我实验截图,根据Gorgon_Meducer大神建议,其中第一张图是没有使用__packed关键字,第二张图使用__packed关键字(可见,使用对齐的确可以提升性能)。
001.png (75.09 KB, 下载次数: 0)
下载附件
2018-3-9 10:01 上传
一周热门 更多>