基于ARM编译器版本5的工程迁移与适配到ARM编译器版本6.12 后续2 - 堆栈初始化以及总线异常问题

By: Ailson Jack
Date: 2019.12.31
个人博客:http://www.only2fire.com/
本文在我博客的地址是:http://www.only2fire.com/archives/111.html,排版更好,便于学习,也可以去我博客逛逛,兴许有你想要的内容呢。

为了描述方便,将ARM Compiler 5简称为AC5,将ARM Compiler 6.12简称AC6.12

       目前,我自己的工程已经可以成功的使用AC6.12进行编译和调试了。在适配工程的尾声,也遇到了两个问题,在这里记录下来,以便后面查证。

我这里使用的开发环境如下:

    CPU:LPC55S69

    Keil:5.27

    ARM Compiler:AC6.12

1Heap region was used, but no heap region was defined

    工程中,我使用的是自己的分散加载文件,并且没有定义ARM_LIB_STACKHEAP,ARM_LIB_STACK,ARM_LIB_HEAP这些符号,因为我自己要重新定义堆栈,就没有使用这些符号,因此在C代码中加入:__asm(".global __use_no_heap"); //不使用ARM提供的堆函数,但是编译的时候还是报错:Error: L6915E: Library reports error: Heap region was used, but no heap region was defined。最初我以为是分散加载文件的问题,后来查看分析,觉得分散加载没问题,于是就换个方向思考。

    因为我在C代码中添加了不使用ARM提供的堆函数的声明,然而ARM_LIB_STACKHEAP,ARM_LIB_STACK,ARM_LIB_HEAP这些符号会在ARM官方代码的堆栈初始化函数中进行使用,那么我只要分析出是谁在调用ARM官方的堆栈初始化函数,就能够解决这个问题了。

    后来发现我的启动代码中少写了一个函数__rt_entry,这个函数的作用就是一些初始化工作,当然也就包括初始化堆栈了。这个函数在ARM官方库中已经实现,由于我没有自定义__rt_entry函数,因此在启动时会调用ARM官方的__rt_entry函数,也就自然会调用ARM库中的堆栈初始化函数,在链接的过程中,当发现分散加载文件没有定义ARM_LIB_STACKHEAP,ARM_LIB_STACK,ARM_LIB_HEAP这些符号就报错:Error: L6915E: Library reports error: Heap region was used, but no heap region was defined

    解决方法:自然是在我的启动文件中自定义一个__rt_entry函数,该函数会调用main()函数。

2、启动过程中出现总线异常

    在解决了上面第1个问题后,工程能够成功的编译和链接,但是程序运行时会出现总线错误,而且有时候代码量减小又不会出现这个问题。最开始分析这个问题,花费了不少时间,也没有摸着门道。后来也是在我组长的指点下才解决的。

    首先分析下为什么这个总线异常问题有时会出现,有时不会出现。这就得说说分散加载文件中加载域和执行域中的一个标志:NOCOMPRESS,AC6.12的armlink文档中有对这个标志的描述:

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.大致意思,默认情况下RW数据会被压缩放置在image中,只有在分散加载文件中相关的加载域与执行域中使用标志NOCOMPRESS时,才不会对RW数据进行压缩。

    因为我没有使用NOCOMPRESS标志,因此会对RW数据进行压缩,因此在image中的RW数据会比实际的长度小一些。由于是我自己在启动代码中初始化databss,因此在将flash中的RW data拷贝到RAM中时,RW data的长度我仍然使用的是未压缩的数据长度,该长度大于压缩数据的长度,在将flash中的RW data拷贝到RAM中时,当长度超过压缩数据的长度,flash就会产生保护,从而触发一个总线异常,而且异常的地址存储在BFAR中。

    解决方法:这里有两种解决方法。

    方法1:最简单的就是在分散加载文件中RW data相关的加载域和执行域使用NOCOMPRESS标志,当然了这个方法的缺点就是产生的image文件会大一些。

    方法2:可以在启动代码中配置好sp,然后就不用去对RW databss进行处理(屏蔽掉自己写的RW databss的处理代码),这些工作ARM官方库会自行处理的(压缩的RW data在拷贝到RAM中时,ARM官方库会进行解压缩的,这些ARM库代码在编译和链接的时候会自动的加入到image中)。

       如果觉得文章写的不错,对你有帮助,欢迎点赞,关注博主哟!

排版更好的内容见我博客的地址:http://www.only2fire.com/archives/111.html
注:转载请注明出处,谢谢!^_^

猜你喜欢

转载自blog.csdn.net/jackailson/article/details/103788243
今日推荐