Keil v.6预处理定义报错求助及v5兼容代码需求
Keil MDK v6 编译兼容问题解答
关于__ARM_COMPILER_V6__宏的疑问
Keil MDK v6默认搭载ARM Compiler 6(基于LLVM/Clang架构),__ARM_COMPILER_V6__是该编译器内置的预定义宏,用来标识当前使用的是ARM Compiler 6版本。
你代码里的#if !defined __ARM_COMPILER_V6__ #error #endif是版本校验逻辑,目的是强制代码必须在ARM Compiler 6环境下编译。现在报错,大概率是项目配置里没选对编译器版本——比如仍在使用Keil v5遗留的ARM Compiler 5,或是v6的编译器路径配置有误,导致编译器未自动定义这个宏。
兼容Keil v5/v6的ITM打印代码
Keil v5里的__CC_ARM是ARM Compiler 5的标识宏,而v6的ARM Compiler 6不再使用该宏,改用__ARM_COMPILER_V6__或数值型的__ARMCC_VERSION(比如v6.19对应6010900)。结合GCC的__GNUC__宏,以下是兼容ARMCC5、ARMCC6、GCC三种环境的ITM打印代码:
#include <stdint.h> #include <stdio.h> // 根据硬件调试需求调整ITM端口号 #define ITM_DEBUG_PORT 0 // 检查ITM端口是否就绪 static inline int itm_is_ready(void) { return ((ITM->TCR & ITM_TCR_ITMENA_Msk) && (ITM->TER & (1UL << ITM_DEBUG_PORT))); } #ifdef __GNUC__ // GCC环境:重定向__io_putchar int __io_putchar(int ch) { if (itm_is_ready()) { while (ITM->PORT[ITM_DEBUG_PORT].u32 == 0); ITM->PORT[ITM_DEBUG_PORT].u8 = (uint8_t)ch; } return ch; } // GCC禁用半主机模式的必要配置 #pragma import(__use_no_semihosting) struct __FILE { int handle; }; FILE __stdout; void _sys_exit(int x) { (void)x; } #elif defined __CC_ARM // ARM Compiler 5环境:重定向fputc int fputc(int ch, FILE *f) { (void)f; if (itm_is_ready()) { while (ITM->PORT[ITM_DEBUG_PORT].u32 == 0); ITM->PORT[ITM_DEBUG_PORT].u8 = (uint8_t)ch; } return ch; } #elif defined __ARM_COMPILER_V6__ // ARM Compiler 6环境:重定向fputc(和ARMCC5逻辑对齐,减少改动) int fputc(int ch, FILE *f) { (void)f; if (itm_is_ready()) { while (ITM->PORT[ITM_DEBUG_PORT].u32 == 0); ITM->PORT[ITM_DEBUG_PORT].u8 = (uint8_t)ch; } return ch; } #endif
说明:
- ARM Compiler 6同时支持
fputc和__io_putchar重定向,这里选fputc是为了和ARMCC5的代码逻辑保持一致,降低迁移成本。 - GCC部分的半主机禁用配置是嵌入式环境下使用
printf的必要操作,避免编译报错。
内容的提问来源于stack exchange,提问作者Submin
相关产品推荐
相关产品推荐

