KEIL工程调整一下project窗口中加载的文件顺序,编译运行直接进Hardfault

2019-03-23 14:46发布



自己的一个KEIL工程,编译后运行,正常;
调整一下project窗口中加载的文件顺序,编译运行,直接进Hardfault。

按理说文件编译顺序不会影响最终生成的目标文件才对,不应该有不一样的运行结果啊。不明白问题出在哪里。
通过对比发现两种情况编译后生成的map文件是不一样的。别的都一样。

不知道大家有没有遇到过这个问题。求指教。


找到问题原因了,是字节对齐的问题。

工程里定义了两个比较大的数组,如下:__attribute__((aligned(4)))

uint8_t MMU_US_Data_Memory[US_CAPACITY];
uint8_t MMU_SD_Data_Memory[UD_CAPACITY];

对这两个数组的内容进行处理的时候用到了memcpy,调试发现经常在memcpy的地方进入Hardfault。调试看以上两个数组的首地址MMU_US_Data_Memory和MMU_SD_Data_Memory都不是4字节对齐的,所以讲两个数组定义改成:

__attribute__((aligned(4)))  uint8_t US_Data_Memory[US_CAPACITY];
__attribute__((aligned(4)))  uint8_t SD_Data_Memory[UD_CAPACITY];

在memcpy处打断点,两个数组的首地址4字节对齐了,继续运行,没出现Hardfault。

那么基本上就断定是字节对齐的问题导致的Hardfault

有几个不明白的地方请教下:
1、为什么不加__attribute__((aligned(4))) ,申请的数组就不是字节对齐的呢?我申请数组大小是16K,跟我申请空间过大有关系吗?
2、数组字节对齐后,我试着做了这个测试:
    memcpy(US_Data_Memory+1,arrytest,100);
    也就是说在字节对齐的US_Data_Memory数组地址基础上加了偏移量1,那么数据拷入的地址肯定就不是字节对齐了,这个时候代码是不报错的,为什么呢?
3、在调试状态下,看Disassembly窗口的汇编代码,memcpy函数对应的是:__aeabi_memcpy(),在网上查了下,这个意思是不用字节对齐的拷贝函数,如果要4字节对齐,对应的函数是__aeabi_memcpy4(),可是在汇编窗口并没有看到这个函数。不太理解。
4、为什么交换两个文件顺序之后,两个数组的首地址就会被4整除?编译文件顺序会影响数组申请地址吗?

以上四个问题,请大牛们帮忙解释下,谢谢。  

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
18条回答
wsmysyn
2019-03-25 13:54
C++的话,可能涉及到构造函数的执行顺序吧。。构造函数的执行顺序不同,硬件初始化的就有先后了。。

比如全局的对象,初始化对象的时候,调用的构造函数顺序可能会不一样的。。

可以最先初始化一个串口,用来跟踪每个对象的构造函数调用情况,就知道顺序有没有差异了。。

一周热门 更多>