
本帖最后由 smallcsduck 于 2018-4-12 05:07 编辑 / e9 s# S7 s7 | 使用Arm Compiler 6编译stm32程序(4月12号版) 前面写过一篇把程序迁移到Arm Compiler 6的教程,但是经过实践,发现还有一些错误。而且MDK更新到5.25和Arm Compiler 6.9后,又出现了一些新的特性。所以又重新写了一下,这次都是经过实际程序验证的,应该是没有问题了。Demo工程代码放在http://github.com/babycheng/STM32F767IGDemo.git。Clone下来以后直接编译(我用的板子是apollo的767的开发板,4.12试运行不知道哪里有问题,但是编译是可以通过的,后面再解决)。实际项目结构如下图。 ![]() 下面是使用Arm Compiler 6工具链需要设置的步骤: 首先是STM32的HAL库的迁移。 1.选择Arm Compiler 6.9编译器 ![]() 2.修改C/C++选项卡,改红框里的选项。这个选项是MDK5.25刚加入的,如果你是老版本MDK,在下面的Misc Controls框里加-std=gnu11选项,是一样的效果。 ![]() 3.在Include Paths里添加如下图的头文件目录,具体的目录根据你的MDK安装目录修改,这个目录需要放在最前面,确保这个CMSIS头文件最先被搜索到。 ![]() 完成这三步,HAL库就可以用Arm Compiler 6.9编译了,编译结果没有错误没有警告。 这里要解释一下。其实ARM在推出Arm Compiler 6的时候,已经考虑到了原有代码从Arm Compiler 5编译器迁移到Arm Compiler 6编译器的问题。在CMSIS接口里进行了预处理,原有代码只需要包含最新的CMSIS接口头文件就可以使用Arm Compiler 6了。MDK5.25附带了最新的5.3版的CMSIS接口。如果你是用STM32cubeMX自动创建的工程,那引用的是CubeMX自带的4.3版本CMSIS接口文件,这个版本的CMSIS接口是没有迁移预处理的,你需要自己添加。所以最方便的迁移办法就是添加最新版的CMSIS接口,并且要放在搜索目录最前面,编译器使用第一个被找到的头文件。那怎么看自己的代码在编译的时候是不是使用了最新版的CMSIS接口呢?你查看一下编译文件引用了哪个文件就可以了。 ![]() 如上图,如果是用了cmsis_armclang.h那就是最新版的CMSIS接口。如果是cmsis_armcc_V6.h,那就是用的老版本接口。 然后再是FreeRTOS的迁移。 1.把port.c和portmacro.h这两个文件用GCC编译器的相应版本就可以了。其他的FreeRTOS代码不用改。 .STM32CubeMX创建的工程使用了CMSIS-OS v1的接口,因为ARM现在主推CMSIS-OSv2版接口,v1版的接口不更新了,所以需要做如下图修改。如果你自己使用了最新版的CMSIS-OS v2接口是不需要修改的。 ![]() 其实对于没有为Arm Compiler 6做适配的代码,用Arm Compiler 6编译很多错误的原因都是没有引用正确的cmsis_armclang.h头文件。使用如上图的代码,添加正确的头文件以后,代码不用修改就可以正确通过编译。 这个用GCC代码的方法适用于c代码里面有内链汇编的。Arm Compiler 6要求内链汇编是GNU的格式。所以以前的Arm Compiler 5代码是不能通过编译的。解决办法就是直接用GNU版本的代码。如果你没有GNU版本的代码,那就只能自己改啦。 纯汇编或者纯c语言的代码文件,基本上是不用改的,Arm Compiler 6支持Arm Compiler 5的代码。 最后是STemwin的迁移。 以前写的文章在这个问题上叙述有误。我没有进行验证,想当然的认为是使用GCC版的预编译库就可以了。其实我经过试验后发现,还是得用keil版本的预编译库才行。如下图。 ![]() 上面总结就是如果是使用预编译库,那还是使用keil版本的预编译库,GCC版本的预编译库是不能通过编译的。 最后是前一篇文章里的关于Arm Compiler 6编译器的描述。 ) S7 k9 y( g/ C( \) i3 k, c( X; L 现在主流的Cortex-M开发环境和中间件代码都是基于GNU和Arm Compiler v5工具链的写的。其实Arm Compiler v6工具链已经出来很久了。对比Arm Compiler v5工具链,Arm Compiler v6做了很多改进。为什么要用Arm Compiler v6的工具链呢?Keil网站上有一张图解释了这个问题。 ![]() 毕竟是ARM的官方工具链,对构架理解比较深,优化的好一点吧。 Arm Compiler 6是一个基于LLVM的工具链,那LLVM是什么呢?简单来说LLVM是把工具链的语法分析和机器码生成分开成两个独立部分。这样移植工具链到新构架就很容易了,你只要修改机器码生成部分,语法分析部分不用改。GCC的工具链这两部分是混在一起的,移植起来比较困难。LLVM与GCC比较优点很多,比如错误信息显示详细啊,编译快啊等等。感兴趣的可以百度一下。 一般来讲LLVM的语法分析部分是从GCC继承过来的。所以吗,语法规则和GCC是差不多的。说了这么多其实就想告诉你一件事,Arm Compiler 6的C和汇编的语法和GCC是差不多的。(是不是完全相同?我没看到在文档里有写,也没有验证,脑补算是一样的。) 现有的很多中间件,像HAL库、FREERTOS都没有为Arm Compiler 6做过适配的版本。但是都有GNU工具链的适配代码。那是不是可以直接用Arm Compiler 6编译GNU工具链的代码呢?那肯定是不行的。因为Arm Compiler 6和GNU工具链还是有不同的。 首先是链接器不同,Arm Compiler 6用的是和Arm Compiler 5一样的armlink链接器,和GNU工具链的LD是不一样的,链接脚本也是不一样的。 此外Arm Compiler 6和GNU编工具链用的运行时库是不一样的。Arm Compiler 6的运行时库除了提供标准C库的那些功能,还添加了Semihosting模式,支持Scatter-loading和初始化HEAP、STACK的代码。GNU的运行时库是没有上面三个功能的,需要自己用汇编写(这一点是我脑补的)。 另外,Arm Compiler 6里面有两种汇编语言的编译器,一种是使用GNU汇编格式的armclang,一种是使用ARM汇编格式的armasm。也就是说以前Arm Compiler 5的汇编启动文件还是可以用的。但是C的内联汇编必须使用GNU内联格式。 本人水平有限,以上如有错误之处,敬请指出 ; ]: c: c& Z6 O' w# Q1 l ( P$ A" X0 p3 F$ h" n" R, h! O0 I; l4 i9 j |
https://www.stmcu.org.cn/module/forum/thread-615497-1-1.html
freertos的源码里不是都带了么
各种芯片 各种编译器的
3 Y1 L8 |% b* I/ X( }+ O
经过试验 , 发现还是报了很多错误! U: X% L5 H* X, F/ y: F
没成功
然后没办法 试了下文件比较,发现 同样是 CubeMx 生成,F2的文件和F7的 FreeRTOS的文件很多不一样; F0 ]# D7 v3 u
最后 报错 集中在
- w0 u! w3 B5 S0 P; i- }- M% o, X
../Middlewares/Third_Party/FreeRTOS/Source/portable/RVDS/ARM_CM3\portmacro.h(209): error: unknown type name '__forceinline'
也就是提示 __forceinline 没有定义,这个如何解决?
4 L2 k' E/ k* W( i4 Q Z
2 N& A7 R: D. O: \
+ y' A* ]6 U; d2 ]$ k6 \0 I
我的也是,请问楼主解决了吗?