Keil MDK5中ST32F769 Blinky例程SysTick_Handler多重定义疑问
为什么两个SysTick_Handler强定义能覆盖启动文件的弱定义?
这个问题的核心是链接器对弱定义(weak)和强定义(strong)的优先级处理规则,结合Keil MDK项目的配置逻辑来解释就很清晰了:
1. 弱定义 vs 强定义的基本规则
启动汇编文件里的SysTick_Handler通常是用WEAK关键字标记的弱定义(比如类似WEAK SysTick_Handler的写法)。在ARM编译链接体系中:
- 弱定义的符号优先级极低,只要项目中存在同一个符号的强定义(没有
WEAK/__weak修饰的定义),链接器就会直接忽略弱定义,选择强定义的版本。 - 弱定义的作用是“兜底”:如果项目里完全没有实现
SysTick_Handler,链接器会用这个弱定义(一般是空函数或死循环),避免报未定义符号的错误。
2. 两个强定义的具体场景
你看到的两个SysTick_Handler都是强定义,所以都能覆盖启动文件的弱定义,而且它们对应不同的项目配置场景:
① irq_cm4f.s中的汇编实现
这个版本是为Keil RTX RTOS设计的强定义:
SysTick_Handler PROC EXPORT SysTick_Handler IMPORT osRtxTick_Handler PUSH {R0,LR} ; Save EXC_RETURN BL osRtxTick_Handler ; Call osRtxTick_Handler POP {R0,LR} ; Restore EXC_RETURN MRS R12,PSP B SVC_Context
它的作用是:在SysTick中断触发时,调用RTX的心跳处理函数osRtxTick_Handler,同时处理RTOS的任务上下文切换。只有当项目启用RTX RTOS时,这个汇编文件才会被加入编译列表,链接器会优先选择这个版本。
② EventRecorder.c中的C语言实现
这个版本是为Keil EventRecorder调试工具设计的强定义:
void SysTick_Handler (void) { SysTickOverflowCounter++; SysTickOverflowUpdated = 1U; }
EventRecorder用来记录系统运行中的事件(比如中断触发、函数调用),这个SysTick_Handler负责维护EventRecorder的时间基准。只有当项目启用EventRecorder且未启用RTX时,这个C文件才会被编译链接,此时链接器会选择这个版本。
3. 为什么两个强定义不会冲突?
Keil的Blinky示例项目已经通过配置做了互斥处理:
- 启用RTX的项目会自动排除EventRecorder相关的编译选项;
- 启用EventRecorder的无RTX项目会自动排除RTX的中断汇编文件。
链接器如果遇到同一个符号的多个强定义,会直接报“多重定义”错误,但示例项目的配置确保这两个文件不会同时出现在编译链接流程中,所以不会有冲突。
内容的提问来源于stack exchange,提问作者Djole
相关产品推荐
相关产品推荐

