[牛人杂谈] ARMCC5到ARMCC6

[复制链接]
2263|12
 楼主| xinpian101 发表于 2023-2-18 17:01 | 显示全部楼层 |阅读模式
ARMCC6和ARMCC5之间有重要的变更,因此无法直接迁移。但是它们保留了互操作性,因此可以将ARMCC5编写的程序迁移到ARMCC6上。

以下是一些ARMCC5程序迁移到ARMCC6的指南:

仔细阅读ARM Compiler 6 Migration and Compatibility Guide,了解编译器之间的重要变更。

使用新的ARMCC6的宏定义(例如: __ARMCC_VERSION)来检测和处理不同编译器之间的不同行为。

根据语言兼容性和编译选项对源文件进行调整。

使用armclang -archv8a+mixed命令将程序构建为ARMv8架构。

希望以上信息能帮助您成功地迁移ARMCC5编写的程序到ARMCC6。

 楼主| xinpian101 发表于 2023-2-18 17:03 | 显示全部楼层
不兼容的语言扩展
主要是代码中的__align(x)、__packed、__weak等编译器扩展语言。解决方法是使用CMSIS定义的相关宏。
1.替换CMSIS头文件,这里使用的是5.6.0版本的CMSIS。
如果安装了较新的Keil,可以在路径.\Keil_v5\ARM\PACK\ARM\CMSIS目录中找到合适的CMSIS版本。
将.\Keil_v5\ARM\PACK\ARM\CMSIS\5.6.0\CMSIS\Core\Include内的文件替换到工程code_cm3.h所在的文件夹。
2.修改lwip协议栈的cc.h文件,因为lwip使用到了编译器的扩展语言,比如取消结构体的对齐优化、指定变量对齐方式等,这些扩展语言 ARM Compiler 5 和 ARM Compiler 6 并不相同。
在cc.h文件中引用CMSIS提供的cmsis_compiler.h文件,然后修改结构体封装与对齐宏代码为:
  1. /* Arm Compiler 4/5 */
  2. #if   defined ( __CC_ARM )
  3.     #define PACK_STRUCT_BEGIN __packed
  4.     #define PACK_STRUCT_STRUCT
  5.     #define PACK_STRUCT_END
  6.     #define PACK_STRUCT_FIELD(fld) fld
  7.     #define ALIGNED(n)  __ALIGNED(n)

  8.   /* Arm Compiler above 6.10.1 (armclang) */
  9. #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6100100)
  10.     #define PACK_STRUCT_BEGIN
  11.     #define PACK_STRUCT_STRUCT __PACKED
  12.     #define PACK_STRUCT_END
  13.     #define PACK_STRUCT_FIELD(fld) fld
  14.     #define ALIGNED(n)  __ALIGNED(n)

  15. /* GNU Compiler */
  16. #elif defined ( __GNUC__ )
  17.     #define PACK_STRUCT_BEGIN
  18.     #define PACK_STRUCT_STRUCT __PACKED
  19.     #define PACK_STRUCT_END
  20.     #define PACK_STRUCT_FIELD(fld) fld
  21.     #define ALIGNED(n)  __ALIGNED(n)
  22.    
  23. #else
  24.     #error "Unsupported compiler"
  25. #endif
3.程序中使用了__packed、__align(n)、__inline、__weak的地方分别用CMSIS提供的宏__PACKED、__ALIGNED(n)、__INLINE、__WEAK代替。
  1. 注意__packed和__attribute__((packed))的使用区别:

  2. ARM Compiler 5 使用__packed:

  3. typedef __packed struct
  4. {
  5.     char x;           
  6.     int y;
  7. } X;

  8. ARM Compiler 6 使用__attribute__((packed)):

  9. typedef struct __attribute__((packed))
  10. {
  11.     char x;                  
  12.     int y;
  13. } X;
4.如果使用ARM Compiler 5 时习惯使用typedef __packed struct {}X;句法,推荐改为CMSIS提供的宏句法:typedef __PACKED_STRUCT {}X;
当使用ARM Compiler 5 时会自动扩展为:typedef __packed struct {}X;
当使用ARM Compiler 6 时会自动扩展为:typedef struct __attribute__((packed)) {}X;
5.如果使用内联函数建议按照以下格式:
  1. __STATIC_INLINE func_name(arg)
  2. {
  3.     //函数体
  4. }
防止ARM Compiler 6在-O0、-O1级别设置下,链接时出现未定义符号的错误。(在这种优化级别下__INLINE可能并不会内联)
不兼容的语言扩展总结如下:
6214763f09430967d5.png
245163f094372df45.png
提示:可以使用uVision IDE的查找功能来查找上述关键字,然后做迁移处理。
内嵌汇编
ARM Compiler 6 完全改变了处理汇编代码的策略。
汇编语法现在兼容GNU风格而不是ARM风格。 汇编也是由C编译器完成, 无需单独的汇编器。
FreeRTOS的移植层由..\FreeRTOS\Source\portable\RVDS\ARM_CM3目录下的port.c和portmacro.h文件改为..\FreeRTOS\Source\portable\GCC\ARM_CM3目录下的port.c和portmacro.h文件。
这是因为这两个文件会涉及内嵌汇编。
自定义的内嵌汇编函数。
ARM Compiler 5:
  1. __asm  uint32_t __get_flash_base(void)
  2. {
  3.    IMPORT |Image$ER_IROM1$RO$Base|;
  4.    
  5.     ldr r0,=|Image$ER_IROM1$RO$Base|;
  6.     bx lr;
  7. }
ARM Compiler 6:(看了下帮助手册,也可以不使用汇编)
  1. uint32_t get_flash_base(void)
  2. {
  3.     extern uint32_t Image$ER_IROM1$RO$Base;
  4.    
  5.     return (uint32_t)&Image$ER_IROM1$RO$Base;
  6. }
语法更严格
比如某个函数之前要对外开放,.c和.h中定义和声明都相同。后来在.c文件中将该函数定义为本地函数,使用static修饰,但.h中忘记删除也没有做相应修改。这种情况下,ARM Compiler 5 不会报错,ARM Compiler 6 会报错:
../file_name.c(10): error: static declaration of 'func_name' follows non-static declaration
2.如下代码:
  1. for(i=0; i<0x7E-0x20; i++)
ARM Compiler 5 不会报错,ARM Compiler 6 会报错:

../file_name.c(332): error: invalid suffix '-0x20' on integer constant

需要将代码改为:
  1. for(i=0; i<0x7E - 0x20; i++)


 楼主| xinpian101 发表于 2023-2-18 17:04 | 显示全部楼层
优化问题
以下代码在 ARM Compiler 5 中,正常执行,但在 ARM Compiler 6 中,只要不是-O0级别,整个函数因为空循环问题,都被优化掉。也就是延时没有起作用。
  1. void delay_us (uint32_t ul_time)
  2. {
  3.     ul_time *= 30;
  4.     while(--ul_time != 0);
  5. }
所以当升级到 ARM Compiler 6 出现使用软延时的外设不工作,比如软件IIC出错、软件SPI出错、LCD黑屏等问题,可以检查是否有类似的代码。
需要改成:
  1. void delay_us (uint32_t ul_time)
  2. {
  3.     ul_time *= 30;
  4.     while(--ul_time != 0)
  5.         __nop();
  6. }
Keil编译器保证__nop()必定会插入一个NOP指令,在这里可以阻止编译器优化。当然,延时的初始值也要做相应的调整。

编译时间和大小
-O0:Program Size: Code=200360 RO-data=20576 RW-data=96 ZI-data=76316
Build Time Elapsed: 00:00:25
-O1:Program Size: Code=119328 RO-data=16824 RW-data=96 ZI-data=76300
Build Time Elapsed: 00:00:25
-O2:Program Size: Code=153340 RO-data=17100 RW-data=96 ZI-data=76300
Build Time Elapsed: 00:00:26
-O3:Program Size: Code=162292 RO-data=17040 RW-data=96 ZI-data=76308
Build Time Elapsed: 00:00:27
-Ofast:Program Size: Code=161896 RO-data=17040 RW-data=96 ZI-data=76308
Build Time Elapsed: 00:00:26
-Os balanced:Program Size: Code=115628 RO-data=17048 RW-data=96 ZI-data=76300
Build Time Elapsed: 00:00:28
-Oz image size:Program Size: Code=103784 RO-data=17020 RW-data=96 ZI-data=76308
Build Time Elapsed: 00:00:25
-Oz image size LTO:Program Size: Code=85888 RO-data=17064 RW-data=40 ZI-data=75960
Build Time Elapsed: 00:00:32
与Compiler 5 对比(我的程序-可能不具有一般性):
-O2:Program Size: Code=94232 RO-data=16736 RW-data=540 ZI-data=75640
Build Time Elapsed: 00:00:16

参考文档
《Arm® Compiler Migration and Compatibility Guide》(内容详细)
《Migrate ARM Compiler 5 to ARM Compiler 6》 (AN298)

小灵通2018 发表于 2023-2-19 13:55 | 显示全部楼层
所以别着急升级。
小明的同学 发表于 2023-2-19 18:13 | 显示全部楼层
主要要知道两个版本差异在哪儿,不然容易搞错。
zhuomuniao110 发表于 2023-2-26 20:49 | 显示全部楼层
兼容性能搞死新手。
小夏天的大西瓜 发表于 2023-2-27 14:46 | 显示全部楼层
现在有时感觉不是新版本就好,太多坑了
星辰大海不退缩 发表于 2023-2-27 15:17 | 显示全部楼层
新版本不兼容那确实太坑
中国龙芯CDX 发表于 2023-2-28 14:49 | 显示全部楼层
楼主这个移植确实很好
LOVEEVER 发表于 2023-2-28 14:56 | 显示全部楼层
看到好几个发这个5和6版本避坑的问题了
AloneKaven 发表于 2023-3-1 19:58 | 显示全部楼层
版本升级搞死我这种新手
 楼主| xinpian101 发表于 2023-3-15 22:18 | 显示全部楼层
AloneKaven 发表于 2023-3-1 19:58
版本升级搞死我这种新手

是的,我也不喜欢用新版的,因为我都是用厂家提供的工程做,那些都是5做的。
AloneKaven 发表于 2023-3-23 22:32 | 显示全部楼层
xinpian101 发表于 2023-3-15 22:18
是的,我也不喜欢用新版的,因为我都是用厂家提供的工程做,那些都是5做的。 ...

是啊,新版也不向下兼容一下
您需要登录后才可以回帖 登录 | 注册

本版积分规则

129

主题

1650

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部