STM32L151无法将数据段从Flash复制到SRAM,陷入启动循环求助
STM32固件启动循环排查求助
我们在某一特定版本固件中遇到异常:设备启动时SRAM未按预期填充数据(该操作应在Reset_Handler入口函数中执行),随后每3.2ms触发一次复位,陷入启动循环。
- 通过编译生成的.map文件确认,SRAM起始地址应存在指定变量,但实际未检测到对应数据;旧版可正常运行的固件则能正常加载该数据。
- 诡异的是,使用STM32CubeIDE加载调试时设备运行正常,但通过ST-Link Utility或串口烧录后,设备自主启动就会出现相同故障,无法获取有效调试信息。
- 使用STM32CubeProgrammer观察发现,程序计数器停留在地址
0x20000000,无法单步调试。
链接脚本片段
/* Entry Point */ ENTRY(Reset_Handler) ... MEMORY { BOT_FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 0x6000 /* 24 kB */ PSB_FLASH (rx) : ORIGIN = 0x08006000, LENGTH = 0x8000 /* 32 kB */ FLASH (rx) : ORIGIN = 0x0800E000, LENGTH = 0x72000 /* 456 kB */ SHARED_DATA (r) : ORIGIN = 0x08080000, LENGTH = 0x200 /* 2 x 256 bytes in EEPROM */ SHARED_DATA_END (r) : ORIGIN = 0x08080200, LENGTH = 0x1 /* end marker */ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x13ED0 RAM_SHARED (rw) : ORIGIN = 0x20013ED0, LENGTH = 0x20 PERSISTENT_RAM(xrw) : ORIGIN = 0x20013EF0, LENGTH = 0x110 MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K } ... SECTIONS { .aBunchOfSectionsInFlash: { ... } >FLASH ... _sidata = .; /* Initialized data sections goes into RAM, load LMA copy after code */ .data : { . = ALIGN(4); _sdata = .; /* create a global symbol at data start */ *(.data) /* .data sections */ *(.data*) /* .data* sections */ *(.RamFunc) /* .RamFunc sections */ . = ALIGN(4); _edata = .; /* define a global symbol at data end */ } >RAM AT>FLASH ... }
.map文件片段
Memory Configuration Name Origin Length Attributes BOT_FLASH 0x08000000 0x00006000 xr PSB_FLASH 0x08006000 0x00008000 xr FLASH 0x0800e000 0x00072000 xr SHARED_DATA 0x08080000 0x00000200 r SHARED_DATA_END 0x08080200 0x00000001 r RAM 0x20000000 0x00013ed0 xrw RAM_SHARED 0x20013ed0 0x00000020 rw PERSISTENT_RAM 0x20013ef0 0x00000110 xrw MEMORY_B1 0x60000000 0x00000000 xr *default* 0x00000000 0xffffffff ... 0x080762e4 _sidata = . .data 0x20000000 0x1380 load address 0x080762e4 0x20000000 . = ALIGN (0x4) 0x20000000 _sdata = . ... 0x20001380 _edata = .
Reset_Handler代码
/** * @brief This is the code that gets called when the processor first * starts execution following a reset event. Only the absolutely * necessary set is performed, after which the application * supplied main() routine is called. * @param None * @retval : None */ .section .text.Reset_Handler .weak Reset_Handler .type Reset_Handler, %function Reset_Handler: /* Setup C - environment, initialise data */ bl SetupCSys /* Low level HW initialization */ bl SystemInit /* Call */ bl main bx lr .size Reset_Handler, .-Reset_Handler /* Provide weak alias for SetupCSys. * This will only be called if another definition is not supplied. */ .weak SetupCSys .thumb_set SetupCSys,Default_SetupCSys .section .text.Default_SetupCSys,"ax",%progbits .type Default_SetupCSys, %function Default_SetupCSys: /* Copy the data segment initializers from flash to SRAM */ movs r1, #0 b LoopCopyDataInit CopyDataInit: ldr r3, =_sidata ldr r3, [r3, r1] str r3, [r0, r1] adds r1, r1, #4 LoopCopyDataInit: ldr r0, =_sdata ldr r3, =_edata adds r2, r0, r1 cmp r2, r3 bcc CopyDataInit ldr r2, =_sbss b LoopFillZerobss FillZerobss: /* Zero fill the bss segment. */ movs r3, #0 str r3, [r2], #4 LoopFillZerobss: ldr r3, = _ebss cmp r2, r3 bcc FillZerobss
排查建议
- 检查烧录完整性:用STM32CubeProgrammer对比烧录后的FLASH内容与编译生成的.bin/.hex文件,确认
_sidata对应的0x080762e4地址开始的.data段数据是否完全一致,排除烧录过程中数据丢失或校验错误。 - 验证时钟配置差异:CubeIDE调试时会自动配置时钟,而自主启动依赖
SystemInit的时钟设置。对比旧版与新版固件的SystemInit代码,重点检查AHB/APB总线时钟、FLASH等待周期(LATENCY)配置,若FLASH访问时钟超过芯片规格,会导致读取_sidata时出错,进而.data段复制失败。 - 检查Reset_Handler执行流程:在
Default_SetupCSys开头添加GPIO翻转操作(用硬件引脚观测),确认自主启动时该函数是否被执行。若未执行,检查向量表是否正确映射——自主启动时向量表默认在FLASH起始地址,若新版固件修改了向量表偏移(如SCB->VTOR)但未在复位后及时设置,会导致Reset_Handler未正确执行。 - 排查RAM访问冲突:检查新版固件中是否有初始化代码在
SetupCSys之前操作RAM(比如某些外设DMA提前启动),覆盖了刚复制的.data段数据;或者PERSISTENT_RAM等区域的配置是否影响了RAM起始地址的访问权限。 - 编译选项对比:对比新旧版固件的编译器优化等级、链接选项,重点检查是否开启了
-fdata-sections/-ffunction-sections等可能影响段分配的选项,确认链接脚本中_sidata、_sdata等符号的定义未被意外修改。 - 硬件复位原因分析:3.2ms的固定复位周期,可能是看门狗触发。检查新版固件中独立看门狗(IWDG)或窗口看门狗(WWDG)的初始化时机,若在.data段未完成复制就开启看门狗,会因变量未初始化导致看门狗喂狗不及时触发复位;同时检查复位状态寄存器(RCC->CSR),确认复位来源是看门狗、硬件复位还是其他原因。
内容的提问来源于stack exchange,提问作者kruml
相关产品推荐
相关产品推荐

