在Keil魔术棒中通过以下方式生成bin文件时,看提示命令执行成功,却生成了一个*.bin文件夹,文件夹内部是两个bin文件,当时感觉很奇怪,第一次遇到这种情况。
使用的命令:fromelf.exe --bin -o ./firmware/@L.bin ./output/@L.axf
刚开始怀疑是Keil配置问题,查了一遍,没发现问题,和以前生成bin文件正常的keil工程做了对比,也没发现有什么问题。排除了这种可能。
没有别的思路,网上搜了一下,找到一篇类似文章,提到是“attribute” 等命令来指定某些变量到指定的ROM地址,而这个地址不是工程程序所在的ROM地址区域导致的。按照这个说法试了一下果然有效。还是网友厉害!给大神点赞!!!
下面是结合实际开发环境和代码,来记录和还原整个结果过程。
环境是:HC32系列单片机,Keil5集成开发环境。
单片机内部Flash为2M,其中bootloader和配置存储占用地址为0~256K,其余是APP。APP起始地址为0x40000。
按照网上说法,在代码里面搜索“attribute”,发现HC库文件hc32_ll_icg.c中有一处使用的变量是指定ROM地址,并且ROM地址不在APP使用的ROM地址中。
代码中ICG_START_ADDR对应的地址0x400,确实不在APP使用的ROM区域中。看了下u32ICGValue的调用关系,发现程序中并没有调用u32ICGValue的地方,所以先不编译这个文件,重新编译工程,果然生成了bin文件,而不是*bin文件夹了。
那么问题来了,这个0x400地址是干什么用的?在HC用户手册中0x400这个地址是初始化配置相关的,描述如下:
根据手册描述来看,这个地址是固定的,按照项目对Flash的分区,这个地址应该在bootloader分区中,那么问题又来了,bootloader分区中这部分内容会不会被bootloader的bin内容覆盖掉从而影响程序的正常工作呢?带着这个疑问,打开bootloader的bin文件来看一看,发现这段区域并没有被bootloader的bin文件覆盖,应该是HC已经做了保护,我们不用担心了。
好了,0x400的ROM地址在bootloader的分区的ROM地址范围内的,生成bin文件是没有问题的了,而bootloader中系统上电复位解除后就自动做了0x400的ROM地址的初始化配置后,APP不再需要重复做了。
再看一下*bin文件夹中其中一个文件名为ER$$.ARM.__AT_0x00000400的内容:
和bootloader中ROM地址0x400~0x45F这段内容是一样的。
最后,再总结一下这个问题的原因和解决方法:
问题原因:程序里使用了 “attribute” 等命令来指定某些变量到指定的ROM地址中, 而这个地址不在工程程序所在的ROM地址区域。例如, 指定一个变量到0x00020000这个地址, 而程序的开始的地址是0x00060000, 此时编译器的编译时会将程序分段, 也就会生成上述的多个文件。
解决方法:将需要设置在ROM中的变量设置在本工程程序的ROM内, 即起始地址之后, 结束地址之前。对于我遇到的问题解决的方法就是在app中直接去掉就可以了,因为0x400的初始化配置是在bootloader的ROM区域内,在上电复位后bootloader中已经做过了。