STM32H7用链接脚本拆分.bss至不同RAM时符号分配异常排查
STM32H7 GCC链接脚本段迁移异常排查
问题背景
我用STM32H730VBHx芯片搭配GCC工具链开发C++程序,最近代码量上涨导致.bss段塞不下DTCMRAM,打算把CANOpen目录下文件的.bss和.COMMON段迁移到RAM_D1。之前的链接脚本一直正常,改完后却出现异常。
异常现象
- 本该迁移到RAM_D1的CANOpen单例
canOpen仍留在DTCMRAM - 原本该留在DTCMRAM的非CANOpen目录的
ioHandler被移到了RAM_D1
相关代码示例
CANOpen单例定义(canOpen.hpp)
/** * @brief gets the Instance of this singleton class * @return reference to the object * */ static CANopen& getInstance(){ static CANopen canOpen; return canOpen; }
IoHandler单例定义(IoDirect.hpp)
/** * @brief gets the Instance of this singleton class * @return reference to the object */ static IoHandler& getInstance(){ static IoHandler ioHandler; return ioHandler; }
疑问
该异常可能的原因是什么?是否与新增的bss_start = _sbss_heap_D1RAM;语句有关?
可能的原因分析
- 链接脚本匹配顺序或规则错误
若CANOpen文件的段匹配规则位置不当,比如全局的*(.bss)放在CANOpen专属规则前,会优先把所有.bss符号分配到默认的DTCMRAM,后续专属规则直接失效;反之若全局匹配在后面,会覆盖前面的专属规则,把不该迁移的符号也弄到RAM_D1。另外如果匹配规则未精准命中CANOpen目录的目标文件,CANOpen的符号自然不会被分到RAM_D1。 - 静态局部变量的段归属特性
GCC对C++函数内的静态局部变量,默认会放到.bss(未初始化)或.data(有初始化)段,但这类变量的符号名会带有函数前缀,比如_ZN7CANopen11getInstanceEvE9canOpen,若链接脚本只按文件名匹配段,未针对这类符号做处理,就会匹配失败,导致canOpen留在原段。 - 新增语句的干扰
新增的bss_start = _sbss_heap_D1RAM;若打乱了链接脚本中内存区域的地址顺序或段初始化逻辑,比如原本bss_start标记DTCMRAM内.bss段的起始,改成指向RAM_D1起始后,链接器可能会把所有未匹配到专属规则的.bss符号都放到RAM_D1,而canOpen因未被匹配到,就留在了DTCMRAM。 - COMMON段处理不到位
仅处理.bss段迁移但未正确配置.COMMON段规则的话,COMMON段的全局变量会干扰整体段分配逻辑,导致符号归属混乱。
内容的提问来源于stack exchange,提问作者chat_de_schroedinger
相关产品推荐
相关产品推荐

