基于ARM编译器版本5的工程迁移与适配到ARM编译器版本6.12 后续2 - 堆栈初始化以及总线异常问题
 2019.12.31    |      嵌入式学习    |     AilsonJack    |     暂无评论    |     1019 views
By: Ailson Jack
Date: 2019-12-31
个人博客: http://www.only2fire.com/
<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(&quot;.global __use_no_heap&quot;); //不使用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>
欢迎关注博主的公众号呀,精彩内容随时掌握:
热情邀请仔细浏览下博客中的广告,万一有对自己有用或感兴趣的呢。◕ᴗ◕。。
如果这篇文章对你有帮助,记得点赞和关注博主就行了^_^,当然了能够赞赏博主,那就非常感谢啦!
注: 转载请注明出处,谢谢!^_^
暂无评论,要不要来个沙发
发表评论

 
Copyright © 2015~2023  说好一起走   保留所有权利   |  百度统计  蜀ICP备15004292号