我正在为STM32F103 ARM微处理器制作引导程序。我已经编写了能够执行存储在RAM存储器中的代码的程序(存储在uint16_t数组中的16位Thumb指令)。一切运行正常,直到我在RAM地址设置断点。
当我在调试模式下启动程序没有RAM中的断点时,代码运行正常。 当我在调试模式下启动程序时,我在程序的第一条指令处设置断点(跳转到主程序),代码运行正常。 当我离开该断点时出现问题,我停止执行,然后尝试再次以调试模式运行它。然后,我得到(可能不是)随机数(0x6816)而不是第一个跳转指令(0xe000)。
代码:
uint16_t program[] = {
// Program code
0xe000, // b.n 0x20000004 <program+4>
0xe7fd, // b.n 0x20000000 <program> -- infinite loop if previous instruction would not work
0xfb00, 0xf000, // mul.w r0, r0, r0
0x4770, // bx lr
0xbf00, // nop
};
int main(void)
{
int (*entry_addr)(int) = (void*)((uint32_t)program | 1); // last bit set for Thumb mode
int ret = entry_addr(7);
if (ret == 49) {
while(1);
} else {
while(1);
}
}
当我在每条指令上设置断点时,我得到以下数字:
0x6816, 0x2e00, 0xd018, 0xf000, 0x42b5, 0xd0f9
。第四个没有改变,可能是因为它是32位指令的一部分(断点没有设置在这个数字的地址上)。
将SW4STM32 v2.4与OpenOCD 0.10.0-dev-00007-g58350bc-dirty一起使用。
编辑:我在ResetHandler的开头设置了断点,我注意到当RAM中的断点被设置时,给定的内存地址被锁定以进行写入。
startup_stm32.s:
Reset_Handler:
/* 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] /* This instruction works only when breakpoint is not set */
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
这解释了为什么我在RAM中有垃圾 - 初始数据不会复制到其目标地址。所以我的问题是:为什么调试器锁定内存以进行写入以及如何防止它?
答案 0 :(得分:-1)
如果“RAM中没有断点”意味着在RAM中定义的地址处中断读取或写入访问,则您观察到的行为是启动时闪存到RAM的复制。
复位时,RAM是随机的,在闪存main()
功能之前,存在从常量到RAM的副本。如果在启动后设置RAM断点,则此过程将被隐藏,如果之前已设置,则RAM在首次中断时为“随机”。如果继续执行,则应该转到main(),然后再在RAM中断开。