LAT1420
Local Application Tips
LAT1420 Rev 1.0 Jul. 2024
头文件包含顺序导致 Keil 编译出错的问题分析
关键字:Keil,编译
1. 问题现象
我在移植 USBX 相关工程的时候碰到一个非常有趣的 Keil 编译问题,有意分享给大家。如
下是 Keil 编译的 log 信息:
*** Using Compiler 'V6.16', folder: 'C:\Keil_v5\ARM\ARMCLANG\Bin'
Build target 'Ux_Host_MSC'
../Core/Src/main.c(21): warning: In file included from...
../Core/Inc\app_threadx.h(30): warning: In file included from...
../../../../../../Middlewares/ST/threadx/common/inc\tx_api.h(121): warning: In
file included from...
../../../../../../Middlewares/ST/threadx/ports/cortex_m33/ac6/inc\tx_port.h(111
): warning: In file included from...
C:\Keil_v5\ARM\ARMCLANG\Bin\..\include\arm_compat.h(66): error:
conflicting types for '__disable_irq'
__disable_irq(void) {
^
../../../../../../Drivers/CMSIS/Include/cmsis_armclang.h(750): note: previous
definition is here
__STATIC_FORCEINLINE void __disable_irq(void)
^
../Core/Src/main.c(21): warning: In file included from...
../Core/Inc\app_threadx.h(30): warning: In file included from...
../../../../../../Middlewares/ST/threadx/common/inc\tx_api.h(121): warning: In
file included from...
../../../../../../Middlewares/ST/threadx/ports/cortex_m33/ac6/inc\tx_port.h(111
): warning: In file included from...
C:\Keil_v5\ARM\ARMCLANG\Bin\..\include\arm_compat.h(113): error:
redefinition of '__enable_irq'
__enable_irq(void) {
LAT1420
LAT1420 - Rev 1.0 page 2/9
^
../../../../../../Drivers/CMSIS/Include/cmsis_armclang.h(737): note: previous
definition is here
__STATIC_FORCEINLINE void __enable_irq(void)
^
2 errors generated.
compiling main.c...
"Ux_Host_MSC\Ux_Host_MSC.axf" - 2 Error(s), 0 Warning(s).
从提示信息可以看出,函数__disable__irq(void),__enable_irq(void)复定义了。分别在
头文件 arm_compat.h 和头文件 cmsis_armclang.h 中定义了。
问题是,同样的源码,此问题只在 Keil 编译下报错,在 IAR STM32CubeIDE 工程下均无问
题。
2. 问题分析
首先 arm_compat.h 这个头文件位于
C:\Keil_v5\ARM\ARMCLANG\Bin\..\include\arm_compat.h, 是位于 Keil 安装路径下的,
很明显是编译器 Keil 提供的库文件。而 cmsis_armclang.h 头文件,位
../../../../../../Drivers/CMSIS/Include/cmsis_armclang.h, CMSIS 标准头文件。
另外,arm_compat.h 头文件只在 Keil 编译器下提供,对于 IAR STM32CubeIDE 并没
有此头文件,因此,这就解释了为什么此问题只Keil 有关了。
分别查看这两个头文件,注意到 arm_compat.h 的文件开始处有避免重复定义符号 :
#ifndef __ARM_COMPAT_H
#define __ARM_COMPAT_H
static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
__disable_irq(void) {
//…
}
static __inline__ void __attribute__((__always_inline__, __nodebug__))
__enable_irq(void) {