标签 armclang 下的文章
为了描述方便,将ARM Compiler 5简称为AC5,将ARM Compiler 6.12简称AC6.12。目前,我自己的工程已经可以成功的使用AC6.12进行编译和调试了。在适配工程的尾声,也遇到了两个问题,在这里记录下来,以便后面查证。我这里使用的开发环境如下:CPU:LPC55S69Keil:5.27ARM Compiler:AC6.121、Heap 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数据会比实际的长度小一些。由于是我自己在启动代码中初始化data和bss,因此在将flash中的RW data拷贝到RAM中时,RW data的长度我仍然使用的是未压缩的数据长度,该长度大于压缩数据的长度,在将flash中的RW data拷贝到RAM中时,当长度超过压缩数据的长度,flash就会产生保护,从而触发一个总线异常,而且异常的地址存储在BFAR中。解决方法:这里有两种解决方法。方法1:最简单的就是在分散加载文件中RW data相关的加载域和执行域使用NOCOMPRESS标志,当然了这个方法的缺点就是产生的image文件会大一些。方法2:可以在启动代码中配置好sp,然后就不用去对RW data和bss进行处理(屏蔽掉自己写的RW data和bss的处理代码),这些工作ARM官方库会自行处理的(压缩的RW data在拷贝到RAM中时,ARM官方库会进行解压缩的,这些ARM库代码在编译和链接的时候会自动的加入到image中)。如果觉得文章写的不错,对你有帮助,欢迎点赞,关注博主哟!
为了描述方便,将ARM Compiler 5简称为AC5,将ARM Compiler 6.12简称AC6.12。 ARM官方的迁移文档,下载地址:点此下载 ,密钥:0iaf。1、armasm编译汇编代码,链接失败的问题这里新开一篇博文,专门讲讲针对ARM格式的汇编代码,使用AC6.12应该如何处理。下述内容大多来自文档《migration_and_compatibility_guide_100068_0612_00_en.pdf》文档的 3.3 Command-line options for preprocessing assembly source code。我在我自己的工程中遇到过使用AC6.12编译汇编代码成功,但是链接会失败。提示内容大致是:xxx.scf Error: L6236E: No section matches selector - no section to be FIRST/LAST.对于这个问题,我起初以为是分散加载文件(*.scf)有问题,看了半天的分散加载文件内容,也没发现分散加载文件有问题。于是我转换方向,使用命令去手动编译startup_LPC55S69_cm33_core0.s,然后再手动链接,发现还是提示xxx.scf Error: L6236E: No section matches selector - no section to be FIRST/LAST.错误。于是我再次查阅ARM官方的升级与适配手册《migration_and_compatibility_guide_100068_0612_00_en.pdf》,发现armasm使用--cpreproc和--cpreproc_opts选项编译汇编代码时,输入源代码的后缀名是.S(大写)。然而我的工程的ARM格式的汇编代码文件的后缀名均为小写,导致了armasm处理出错。下面是文档中3.3 Command-line options for preprocessing assembly source code对--cpreproc和--cpreproc_opts的描述:If you are using armasm to assemble source code that requires the use of the preprocessor, you must use both the --cpreproc and --cpreproc_opts options together. Also:• As a minimum, you must include the armclang options --target and either -mcpu or -march in --cpreproc_opts.• The input assembly source must have an upper-case extension .S.其中第2点,对汇编源文件后缀名为大写.S作了一个说明吧。为了处理汇编源文件后缀是小写.s的情况,文档的下面也提供了一个操作的说明吧:If you have existing source files, which require preprocessing, and that have the lower-case extension .s, then to avoid having to rename the files:1. Perform the preprocessing step separately using the armclang -x assembler-with-cpp option.2. Assemble the preprocessed file without using the --cpreproc and --cpreproc_opts options.上面这段英文的内容给出了汇编源代码文件后缀是小写.s,但是又不想修改源代码后缀的方法,首先使用armclang (带编译选项-x assembler-with-cpp)去预处理*.s汇编代码,生成一个过程*.s文件,接着再使用armasm(不带编译选项--cpreproc和--cpreproc_opts)去编译这个过程*.s文件。这里提供一个例子如下:(1).armclang --target=arm-arm-none-eabi -mcpu=cortex-m33 -x assembler-with-cpp -E test.s -o test_preproc.s(2).armasm --cpu=Cortex-M33 --fpu=FPv5-SP test_preproc.s2、总结ARM Compiler 6.12对于ARM格式的汇编处理,这里总结下吧,分两种情况:(1).如果ARM格式汇编代码源文件的后缀名是大写的.S,那么直接使用armasm 带编译选项--cpreproc和--cpreproc_opts进行编译即可,例如:armasm --cpu=cortex-m33 --cpreproc --cpreproc_opts=--target=arm-arm-none-eabi,-mcpu=cortex-m33 startup_LPC55S69_cm33_core0.S(2).如果ARM格式汇编代码源文件的后缀名是小写的.s,这里就需要特殊处理了,有两种方法:a.将ARM格式汇编代码源文件的后缀名改为大写.S,然后按照步骤(1)进行处理即可。b.首先使用armclang (带编译选项-x assembler-with-cpp)去预处理*.s汇编代码,生成一个过程*.s文件,接着再使用armasm(不带编译选项--cpreproc和--cpreproc_opts)去编译这个过程*.s文件。这里提供一个例子如下:(1).armclang --target=arm-arm-none-eabi -mcpu=cortex-m33 -x assembler-with-cpp -E test.s -o test_preproc.s(2).armasm --cpu=Cortex-M33 --fpu=FPv5-SP test_preproc.s如果觉得文章写的不错,对你有帮助,欢迎点赞,关注博主哟!
为了描述方便,将ARM Compiler 5简称为AC5,将ARM Compiler 6.12简称AC6.12。 ARM官方的迁移文档,下载地址:点此下载,密钥:0iaf。1、为什么要进行ARM编译器版本的更换目前,AC5基本处于停止更新状态,如果想要使用AC5编译器编译新的ARM架构或者内核的代码,基本是不可能了,因此自然要使用ARM Compiler 6来代替之前的ARM Compiler 5。其实,我自己觉得还有一个比较重要的原因,那就是AC6支持使用armclang编译GNU语法格式的汇编代码,这样在以后的项目开发中,可以只编写GNU语法格式的汇编代码(不必像以前一样还要再写一份符合ARM语法格式的汇编代码),这样既可以使用ARM-GCC编译工具链编译这个项目,也可以使用ARM Compiler编译这个项目,汇编代码维护更加方便了。2、AC6.12的组成(1).armclang:armclang编译器替代了AC5的armcc,并且具有如下优点:基于LLVM和Clang技术;支持编译GNU语法的汇编代码;高度兼容当初为GCC编译的源代码;实现包括ANSI/ISO C和C++,用于Arm架构的ABI,用于64位Arm架构的ABI以及Arm C语言扩展(ACLE)等规范。(2).armlink:功能丰富的专用嵌入式链接器,能够将对象和库组合在一起以生成可执行文件。(3).fromelf:镜像文件转换和反汇编功能。(4).armar:压缩程序。(5).armasm:ARM语法的汇编代码编译器。(6).ARM C和C++库:ARM C库经过ARM公司的优化有很好的的性能和代码密度;ARM C++库基于LLVM libc++项目。下图展示了ARM Compiler 6.12编译工具链的整体结构:3、ARM Compiler 5和ARM Compiler 6编译工具链的差异AC5和AC6的主要差异是AC6使用armclang代替了armcc,因此在AC6中就没有armcc这个编译工具了。并且armclang的编译参数相对于之前的armcc的编译参数也有许多不同。下表列出了ARM Compiler 5和ARM Compiler 6之间各个工具的功能:4、编译工具链升级过程其实将AC5更换为AC6.12编译工具链,无非就是找出这两个工具链的编译参数的差异进行修改即可。当然了,基本上编译参数变化还是挺大的,这里推荐大家参考如下手册进行编译工具链升级。参考手册:《migration_and_compatibility_guide_100068_0612_00_en.pdf》。因为AC5和AC6.12的差异主要体现在ARM Compiler 6使用armclang代替了armcc,因此这篇文章,可以重点关注Chapter 2和Chapter 3,当然了也可以通过搜索一些编译参数来快速定位。5、我在升级过程遇到的问题我在迁移一个项目使用AC6.12的过程中,主要还是参考《migration_and_compatibility_guide_100068_0612_00_en.pdf》文档进行参数修改,起初还算比较顺利,但是涉及到汇编代码的编译过程中死活编译会有问题。这里简单的记录下吧。我这里仍然使用armasm来编译之前的ARM语法格式的汇编代码。修改汇编的编译参数时,一定要注意编译选项--cpreproc,该编译选项在AC5的含义是命令armasm调用armcc预处理输入的汇编源代码;在AC6的含义是命令armasm调用armclang预处理输入的汇编源代码。我的工程,在使用AC5编译工具链时,在汇编过程中,使用的编译参数配置和armcc的编译参数配置是一样的,并且也添加了编译选项--cpreproc。升级到AC6.12之后,因为armclang的编译参数和armcc的差异比较大,自然的就不能够直接用于armasm的配置,因此我按照AC5的armasm配置作为AC6.12armasm的配置,此时能够进行汇编,但是提示:armclang: fatal error: no target architecture given; use --target=arm-arm-none-eabi or --target=aarch64-arm-none-eabi。当时我就在想,为什么我使用armasm编译汇编代码怎么会调用armclang呢,还以为编译工程的脚本有问题,检查了编译脚本也没发现问题,后来还是查看《migration_and_compatibility_guide_100068_0612_00_en.pdf》文档才有所收获。原来在汇编过程中调用armclang是armasm的编译选项--cpreproc在作怪,该编译选项是命令armasm调用armclang预处理输入的汇编源代码。ARM Compile 6中armasm需要另一个编译选项--cpreproc_opts,用于填写armclang预处理汇编代码时的一些配置参数。由于先前没有配置--cpreproc_opts,当然的在使用armclang进行预处理时会提示armclang: fatal error: no target architecture given; use --target=arm-arm-none-eabi or --target=aarch64-arm-none-eabi。问题解决办法:对armasm新增编译选项--cpreproc_opts,并且填写上armclang预处理汇编代码需要用到的一些配置信息。例如:armasm --cpu=cortex-a9 --cpreproc --cpreproc_opts=--target=arm-arm-none-eabi,-mcpu=cortexa9,-D,DEF1,-D,DEF2 -I /path/to/includes1 -I /path/to/includes2 input.S 对于--cpreproc和--cpreproc_opts编译选项,可参考《migration_and_compatibility_guide_100068_0612_00_en.pdf》文档的 3.3 Command-line options for preprocessing assembly source code。6、下面简单列举一些编译参数的差异(1).对于armcc和armclang之间,编译参数存在的差异如下:AC5 OptionAC6 Option描述--cpu=Cortex-M4--target=arm-arm-none-eabi -mcpu=cortex-m4Cortex-M4处理器的修改,其他处理器可能不一样,请参考我这里提供的官方手册.--thumb-mthumb支持thumb指令集--fpu=fpv5_sp_d16-mfloat-abi=hard -mfpu=fpv5_sp_d16支持硬件浮点--fpu=softvfp-mfloat-abi=soft -mfpu=none软件浮点--unaligned_access-munaligned-access设定处理器可以生成地址非对齐的数据--apcs=interwork没有对应的编译选项在AC6中总是允许ARM指令和Thumb指令一起使用,因此没有对应的编译选项.--split_sections-ffunction-sections生成的函数在自己的段中--debug/-g-g生成调试信息--c99 --gnu-xc -std=gnu99允许编译器编译带有GNU扩展的C99代码--cpp --gnu-xc++ -std=gnu++03允许编译器编译带有GNU扩展的C++03代码--no_exceptions-fno-exceptions禁止生成需要支持C++异常的代码--no_rtti-fno-rtti [ALPHA]禁止生成需要支持C++ Run Time Type Information(RTTI)特征的代码-Otime默认支持减少执行时间的优化,代价就是执行文件的大小会增加-O3 -Otime-OmaxHighest optimization for performance-O3 -Ospace-OzHighest optimization for code size(2).对于AC6使用armasm需要注意的事项:使用AC6编译汇编代码时,编译选项和AC5基本差不多,这里再强调一下编译选项:--cpreproc。在AC6中如果使用了编译选项--cpreproc,那么就必须附带的使用编译选项--cpreproc_opts,并且填写上armclang预处理汇编代码需要用到的一些配置信息,例如:armasm --cpu=cortex-a9 --cpreproc --cpreproc_opts=--target=arm-arm-none-eabi,-mcpu=cortexa9,-D,DEF1,-D,DEF2 -I /path/to/includes1 -I /path/to/includes2 input.S好了,我在这里简单的记录了下ARM Compiler 5升级到ARM Compiler 6.12的过程,给以后有需要的朋友留作参考吧。如果觉得文章写的不错,对你有帮助,欢迎点赞,关注博主哟!
- 1
本站信息
目前本站共被浏览 165577 次
目前本站已经运行 3577 天
目前本站共有 165 篇文章
目前本站共有 6 条评论信息
目前本站共有 104 个标签
目前本站共有 0 条留言信息
网站创建时间: 2015年03月01日
最近更新时间: 2023年11月26日
目前本站已经运行 3577 天
目前本站共有 165 篇文章
目前本站共有 6 条评论信息
目前本站共有 104 个标签
目前本站共有 0 条留言信息
网站创建时间: 2015年03月01日
最近更新时间: 2023年11月26日
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