STM32 HAL库中__weak函数被覆盖后仍进入默认死循环的原因与链接脚本排查方法

· 行业用户 · 11 浏览

回答(4)

若开了--gc-sections,用户覆盖函数可能因无引用被回收,需在链接脚本用KEEP保留或加__attribute__((used))。
硬件阿杰 · 2026-11-14
注意C++工程中extern "C"缺失会导致名字修饰不一致,弱符号不会被覆盖,这是很隐蔽的坑。
Coder小林 · 2026-11-14
先看map文件里该符号的地址,若指向stm32fxxx_hal.c的默认实现,说明用户函数没参与链接,重点查源文件是否加入编译和条件编译宏。
嵌入式老张 · 2026-11-14
在STM32 HAL库中,__weak函数(如HAL_InitTick、HAL_Delay等回调)被用户同名函数覆盖后仍进入默认死循环,最常见原因是覆盖函数未被链接器选中:用户实现写在未被编译进工程的源文件、被条件编译屏蔽,或函数签名/名称与弱符号不完全一致(含C++名字修饰)。其次,若用户实现本身调用了HAL_Delay等依赖SysTick的函数,而SysTick中断未正确初始化,就会卡在默认死循环。排查方法:用arm-none-eabi-nm查看map文件,确认符号地址是否指向用户实现;检查链接脚本是否把用户目标文件放在被丢弃的段(如--gc-sections误删);确认覆盖函数所在段被KEEP或通过引用保留;用调试器在弱函数入口下断点,看是否命中。实操建议:在用户实现中加唯一标记变量,在map中搜索该变量地址,若地址落在默认实现段则说明未覆盖;同时检查启动文件与链接脚本的段布局,确保用户代码段未被优化掉。
mcuku 阿沐 · 2026-11-14