STM32+Keil环境下外部SDRAM中初始化数组出现随机值问题
STM32 Keil uVision下SDRAM中const数组初始化失败的解决方案
问题根源
你遇到的核心问题是:const修饰的全局数组被指定到外部SDRAM段后,Keil默认启动流程不会自动将Flash中的初始化数据复制到SDRAM。启动代码仅处理内部RAM的段初始化,外部SDRAM的初始化逻辑需要手动添加。
具体解决步骤
1. 调整分散加载文件,指定初始化数据的Flash存储地址
修改你的分散加载脚本,明确将数组的初始化数据存放在Flash,运行时地址放在SDRAM:
; 定义SDRAM运行时区域,指定起始地址和大小 SDRAM_ACQ_HARDCODED_AV 0xD0643000 0x141000 { ; 指定该段的初始化数据存储在Flash的空闲区域(替换0x080XXXXX为实际可用的Flash地址) LOAD_FLASH 0x080XXXXX { *(.sdram_acq_hardcoded_av) } }
注意:Flash地址需选择未被代码占用的区域,大小需大于等于数组字节数(14592×2=29184字节)。
2. 添加手动复制初始化数据的代码
在SDRAM初始化完成后(比如main()函数开头,或SDRAM初始化函数末尾),添加代码将Flash中的初始化数据复制到SDRAM对应段:
// 声明分散加载生成的段地址符号 extern uint32_t Image$$SDRAM_ACQ_HARDCODED_AV$$Base; // SDRAM段起始地址 extern uint32_t Image$$SDRAM_ACQ_HARDCODED_AV$$Limit; // SDRAM段结束地址 extern uint32_t Image$$SDRAM_ACQ_HARDCODED_AV$$RO$$Base;// Flash中初始化数据起始地址 void copy_sdram_const_data(void) { uint8_t* src = (uint8_t*)&Image$$SDRAM_ACQ_HARDCODED_AV$$RO$$Base; uint8_t* dest = (uint8_t*)&Image$$SDRAM_ACQ_HARDCODED_AV$$Base; uint32_t size = (uint32_t)&Image$$SDRAM_ACQ_HARDCODED_AV$$Limit - (uint32_t)&Image$$SDRAM_ACQ_HARDCODED_AV$$Base; // 逐字节复制初始化数据 while (size--) { *dest++ = *src++; } }
在SDRAM初始化完成后调用copy_sdram_const_data()即可完成数组初始化。
3. 额外排查点
- 确认SDRAM初始化逻辑正确:可在复制前向SDRAM写入测试值并读取验证,排除硬件或初始化配置错误。
- 确认Keil工程已启用分散加载文件:在
Options for Target -> Linker中勾选Use scatter file并指定你的脚本路径。
内容的提问来源于stack exchange,提问作者igtu
相关产品推荐
相关产品推荐

