基于ARM编译器版本5的工程迁移与适配到ARM编译器版本6.12 后续2 - 堆栈初始化以及总线异常问题
<p style="text-indent: 2em;"><span style="color: rgb(255, 0, 0);">为了描述方便,将ARM Compiler 5简称为AC5,将ARM Compiler 6.12简称AC6.12。</span><br/></p><p style="text-indent: 2em;">目前,我自己的工程已经可以成功的使用AC6.12进行编译和调试了。在适配工程的尾声,也遇到了两个问题,在这里记录下来,以便后面查证。<br/></p><p style="text-indent: 2em;">我这里使用的开发环境如下:<br/></p><p style="text-indent: 2em;">CPU:LPC55S69<br/></p><p style="text-indent: 2em;">Keil:5.27<br/></p><p style="text-indent: 2em;">ARM Compiler:AC6.12<br/></p><p class="artical_littlestyle1">1、Heap region was used, but no heap region was defined</p><p style="text-indent: 2em;">工程中,我使用的是自己的分散加载文件,并且没有定义ARM_LIB_STACKHEAP,ARM_LIB_STACK,ARM_LIB_HEAP这些符号,因为我自己要重新定义堆栈,就没有使用这些符号,因此在C代码中加入:<span style="color: rgb(0, 112, 192);">__asm(".global __use_no_heap"); //不使用ARM提供的堆函数</span>,但是编译的时候还是报错:<span style="color: rgb(255, 0, 0);">Error: L6915E: Library reports error: Heap region was used, but no heap region was defined</span>。最初我以为是分散加载文件的问题,后来查看分析,觉得分散加载没问题,于是就换个方向思考。<br/></p><p style="text-indent: 2em;">因为我在C代码中添加了不使用ARM提供的堆函数的声明,然而ARM_LIB_STACKHEAP,ARM_LIB_STACK,ARM_LIB_HEAP这些符号会在ARM官方代码的堆栈初始化函数中进行使用,那么我只要分析出是谁在调用ARM官方的堆栈初始化函数,就能够解决这个问题了。<br/></p><p style="text-indent: 2em;">后来发现我的启动代码中少写了一个函数__rt_entry,这个函数的作用就是一些初始化工作,当然也就包括初始化堆栈了。这个函数在ARM官方库中已经实现,由于我没有自定义__rt_entry函数,因此在启动时会调用ARM官方的__rt_entry函数,也就自然会调用ARM库中的堆栈初始化函数,在链接的过程中,当发现分散加载文件没有定义ARM_LIB_STACKHEAP,ARM_LIB_STACK,ARM_LIB_HEAP这些符号就报错:<span style="color: rgb(255, 0, 0);">Error: L6915E: Library reports error: Heap region was used, but no heap region was defined</span>。<br/></p><p style="text-indent: 2em;">解决方法:自然是在我的启动文件中自定义一个__rt_entry函数,该函数会调用main()函数。<br/></p><p class="artical_littlestyle2">2、启动过程中出现总线异常</p><p style="text-indent: 2em;">在解决了上面第1个问题后,工程能够成功的编译和链接,但是程序运行时会出现总线错误,而且有时候代码量减小又不会出现这个问题。最开始分析这个问题,花费了不少时间,也没有摸着门道。后来也是在我组长的指点下才解决的。<br/></p><p style="text-indent: 2em;">首先分析下为什么这个总线异常问题有时会出现,有时不会出现。这就得说说分散加载文件中加载域和执行域中的一个标志:<span style="color: rgb(255, 0, 0);">NOCOMPRESS</span>,AC6.12的armlink文档中有对这个标志的描述:<br/><span style="color: rgb(0, 112, 192);">RW data compression is enabled by default. The NOCOMPRESS keyword enables you to specify that RW data in an execution region must not be compressed in the final image.</span>大致意思,默认情况下RW数据会被压缩放置在image中,只有在分散加载文件中相关的加载域与执行域中使用标志<span style="color: rgb(255, 0, 0);">NOCOMPRESS</span>时,才不会对RW数据进行压缩。<br/></p><p style="text-indent: 2em;">因为我没有使用<span style="color: rgb(255, 0, 0);">NOCOMPRESS</span>标志,因此会对RW数据进行压缩,因此在image中的RW数据会比实际的长度小一些。由于是我自己在启动代码中初始化data和bss,因此在将flash中的RW data拷贝到RAM中时,RW data的长度我仍然使用的是未压缩的数据长度,该长度大于压缩数据的长度,在将flash中的RW data拷贝到RAM中时,当长度超过压缩数据的长度,flash就会产生保护,从而触发一个总线异常,而且异常的地址存储在BFAR中。<br/></p><p style="text-indent: 2em;">解决方法:这里有两种解决方法。<br/></p><p style="text-indent: 2em;">方法1:最简单的就是在分散加载文件中RW data相关的加载域和执行域使用<span style="color: rgb(255, 0, 0);">NOCOMPRESS</span>标志,当然了这个方法的缺点就是产生的image文件会大一些。<br/></p><p style="text-indent: 2em;">方法2:可以在启动代码中配置好sp,然后就不用去对RW data和bss进行处理(屏蔽掉自己写的RW data和bss的处理代码),这些工作ARM官方库会自行处理的(压缩的RW data在拷贝到RAM中时,ARM官方库会进行解压缩的,这些ARM库代码在编译和链接的时候会自动的加入到image中)。<br/></p><p style="text-indent: 2em;">如果觉得文章写的不错,对你有帮助,欢迎点赞,关注博主哟!<br/></p>
你可能也喜欢:
暂无评论,要不要来个沙发
发表评论
JLink V9掉固件修复(灯不亮) 3Zephyr笔记2 - 在STM32F429上运行HelloWorld 2计算NandFlash要传入的行地址和列地址 1Linux MMC子系统 - 6.eMMC 5.1工作模式-设备识别模式 0Linux MMC子系统 - 5.eMMC 5.1工作模式-引导模式 0Linux MMC子系统 - 4.eMMC 5.1常用命令说明(2) 0
标签云
Linux嵌入式实用技巧ARM内核学习问题集合CC++编程语言阅读笔记汇编Linux内核完全注释Windows驱动开发计算机基础ARM11ARMv7-ASTM32IDESublimeLinux内核学习eMMCMMC子系统Ubuntu操作系统OfficeVMWareAPUEgccRTOS中断漫游世界随笔感悟开发工具软件应用编程VsCodearmccarmclang编译器ZephyrSPIJLink网卡驱动安装各种芯片库函数NFSμCOS内核sambaFlashUnix命令与脚本输入法Linux内核设计与实现gitRIFFWAVJATGFTPar8161安装centos有线上网μCGUI字库工程建立右键菜单网络文件系统Firefox百度NTFS文件系统CodeBlocksCentOS数据结构算法PhotoShop51KeilQTUltraEditscanfglibc宏定义UIDGID优先级娱乐天地SourceInsight磁盘扇区总线I2CPDFBComparePythonI2SFPUMakefileSWDCPUARP软件推荐FileZilla