You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32中断处理器未声明时链接器 fallback 至Default_Handler原因问询

中断处理器已实现却跳转至Default_Handler的原因

问题背景

近期排查了一个UART1中断相关的问题,场景如下:

  1. MCU启动文件中定义的中断向量表及弱符号:
g_pfnVectors:
[...some lines removed]
  .word USART1_IRQHandler
[...more lines removed]
.weak   USART1_IRQHandler
.thumb_set USART1_IRQHandler,Default_Handler
  1. 在stm32wlxx_it.cpp中实现了中断处理器,但未在对应头文件中添加声明:
void USART1_IRQHandler(void) {
     uint32_t isrflags = USART1->ISR;
    if (isrflags & uart1::rdrNotEmpty) {
        uart1::rxNotEmpty();
    }
    if (isrflags & uart1::tdrEmpty) {
        uart1::txEmpty();
    }
}
  1. 项目编译链接无错误,但中断触发时,代码跳转至启动文件中的Default_Handler死循环:
.section .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
  b Infinite_Loop
.size Default_Handler, .-Default_Handler

疑问:为何已实现中断处理器但未加声明时,链接器会 fallback 至Default_Handler?

原因解析

核心是C++名字修饰机制与汇编弱符号规则共同作用的结果:

  • 启动文件里用汇编定义的.weak USART1_IRQHandler是C风格的未修饰符号,链接器会按这个原始名字去查找对应的函数实现。
  • 你在.cpp文件里写的USART1_IRQHandler是C++函数,编译器会对其进行名字修饰(比如生成类似_Z16USART1_IRQHandlerv的符号名),这个修饰后的名字和汇编里的弱符号完全不匹配。
  • 链接器找不到与USART1_IRQHandler匹配的强符号,就会启用启动文件中定义的弱符号版本——也就是绑定到Default_Handler的默认实现。
  • 编译链接无报错的原因:.cpp文件内的函数是内部实现,编译器不会报错;弱符号的存在让链接器认为符号已定义,只是使用了默认的弱实现,因此也不会抛出错误。

修复方案

有两种常用解决方式:

  • 直接在C++文件中用extern "C"包裹中断函数,强制编译器按C风格生成未修饰的符号:
extern "C" {
void USART1_IRQHandler(void) {
     uint32_t isrflags = USART1->ISR;
    if (isrflags & uart1::rdrNotEmpty) {
        uart1::rxNotEmpty();
    }
    if (isrflags & uart1::tdrEmpty) {
        uart1::txEmpty();
    }
}
}
  • 在头文件中用extern "C"声明该函数,然后在.cpp文件中实现,确保跨文件引用时符号一致:
// stm32wlxx_it.h
extern "C" void USART1_IRQHandler(void);

内容的提问来源于stack exchange,提问作者Strooom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 23:28:21