ARM GCC移植指导

概述

本文主要介绍MDK代码移植到ARM GCC中的注意事项,以及对应的编译器指令

主要包括

  • 启动文件
  • 链接脚本
  • 汇编文件
  • 编译器指令
  • 其它

启动文件

选择适用于gcc as汇编器的启动文件,并注意添加bss的清零和data的复制代码,用于初始化C
runtime,如果使用到了C++,还需要手工复制构造函数表和全局变量表,并调用_start函数来初始化C lib

链接脚本

可以参考ST给的案例或者arm-none-eabi-gcc自带的范例,注意修改FLASH和ROM,stack和heap这些参数来适配到对应的板子

汇编文件

参考gcc as汇编手册,将对应的MDK汇编代码转换成gcc汇编,一般MDK工程中,涉及到汇编的有启动代码和OS移植文件,以及某些lib的汇编级优化代码

编译器指令

主要涉及到packed, align, at绝对定位指令,对应解决方案如下

1
2
3
4
5
6
7
8
9
10
11
12
13
// 移植packed
#if defined ( __CC_ARM )
__packed typedef struct
#elif defined ( __GNUC__ )
typedef struct __attribute__ ((__packed__))
#endif

// 移植align
#if defined ( __CC_ARM )
__align(8) static OS_STK START_TASK_STK[START_STK_SIZE];
#elif defined ( __GNUC__ )
static OS_STK START_TASK_STK[START_STK_SIZE] __attribute__ ((aligned (8)));
#endif

至于mdk中的AT这类绝对定位指令,IAR和MDK均可以用@,
at,location等指令,但gcc中没有这类指令,解决方案是在链接文件中,手工分配段,并指定段的地址,然后在C代码中,显式指定使用的section

其它

1 const常量
MDK中,默认将const常量放在FLASH中,但其它编译器不一定会这么做,也可能放到RAM中,所以默认const不保险,建议显式指定section,如下所示

1
2
3
4
const unsigned char asc2_1608[95][16]
#if defined ( __GNUC__ )
__attribute__ ((section (".text")))
#endif

2 内存映射
通过FSMC的机制,可以映射外部RAM,建议用指针的形式或者在链接脚本中,增加对应的RAM区域,而不是简单的分配大数组

1
2
3
//内存管理表
u16 mem1mapbase[MEM1_ALLOC_TABLE_SIZE]; //内部SRAM内存池MAP
u16 mem2mapbase[MEM2_ALLOC_TABLE_SIZE] __attribute__((at(0X68000000+MEM2_MAX_SIZE))); //外部SRAM内存池MAP

对于gcc来说,由于本身不支持at指令,所以会忽略指令,然后将数组默认分配到RAM中,从而导致overflow或者内存不够等错误