之前一直是用v5编译,编译速度慢,换成V6编译速度至少快3倍以上 ,而且 arm 后期只维护v6编译器,不再更新v5编译器
Keil MDK自 V5.36 版本之后,默认就不带 Arm Compiler V5版本编译器。如果需要使用 V5 版本编译器,就需要自己下载并安装
V5编译通过的工程,V6有可能编译不过去,就算能过,也不知道会不会出莫名其妙的问题,建议从头开始一个项目的时候使用这个方式。
使用v6编译器需要注意以下:
-
配置优化选项
http://t.csdnimg.cn/hqSvT
http://t.csdnimg.cn/Jgs9T
-
使用V6编译器有时候不能跳转到定义
http://t.csdnimg.cn/81A3d
编译器不同,汇编结果不同
问题描述
当数组下标越界时,会触发 HardFault。在不改变代码逻辑,仅将编译器从 Keil ARM 编译器 V5 更换为 Keil ARM 编译器 V6(因为 V6 编译速度快了好几倍)后,代码崩溃并进入了 HardFault。
问题代码
涉及问题的代码如下:
OLED_ShowString(10, 15, g_motor_info_table[(g_menu_device.motor_index - 1) % MOTOR_ID_COUNT].name, OLED_6X8);
其中,g_motor_info_table 是在其他地方定义的全局结构体数组,而 g_menu_device.motor_index 这个变量在初始化时赋值为零。
分析
由于 g_menu_device.motor_index 的初始值为 0,当计算 (g_menu_device.motor_index - 1) 时,结果为 -1,进而作为下标访问 g_motor_info_table 数组时发生了越界访问。
在 STM32 Cortex-M4 微控制器中,RAM(包括 SRAM 及其他类型的 RAM)被映射到内存地址空间中,而 STM32F4 系列微控制器的内部 SRAM 起始地址为 0x20000000。
根据编译后程序内存的分布图(如下所示):
- Keil ARM 编译器 V5:
- Keil ARM 编译器 V6:
在 ARM 编译器 V6 中,变量 g_menu_device.motor_index 的地址为 0x20000004。因此,当数组下标计算溢出导致访问地址低于 0x20000000 时,会访问到无效地址,从而引发 HardFault。