核心原因是__weak符号在链接阶段被“强符号”覆盖的规则未按预期生效,常见于:1) 用户重定义函数与HAL库默认实现不在同一编译单元/库中,且用户实现被编进了静态库(.a)而非直接参与链接的目标文件,链接器先解析到库内弱符号后不再拉取用户库成员;2) 用户函数名拼写、参数或C++名字修饰不一致,实际是另一个符号;3) 重定义写在被条件编译屏蔽的代码里,或链接脚本/--gc-sections把用户段回收;4) 使用了LTO或不同优化等级导致符号可见性变化。排查:用arm-none-eabi-nm -A 工程所有.o/.a | grep 函数名,确认存在T(强)与W(弱)两个符号;用arm-none-eabi-objdump -t 或链接map文件看最终选用哪个;检查链接命令行中用户目标文件是否在库之前、是否被--start-group/--whole-archive影响。实操建议:把用户重定义函数放到直接参与链接的.c(非库)中,确保与HAL库同链接;必要时用__attribute__((used))防回收,并在map文件确认符号来源;避免在头文件里定义。
mcuku 阿沐 · 2026-10-18