设置断点时,STM32调试器锁定RAM地址以进行写入



我正在为ARM微处理器制作引导加载程序STM32F103。我已经编写了能够执行存储在RAM存储器中的代码的程序(存储在uint16_t数组中的16位Thumb指令)。一切正常,直到我在 RAM 地址设置断点。

当我在 RAM 中没有断点的调试模式下启动程序时,代码运行良好。 当我在调试模式下启动程序时,我在程序的第一条指令(跳转到主过程)设置断点,代码也运行良好。 当我保留该断点集时出现问题,我停止执行,然后再次尝试在调试模式下运行它。然后,我得到的不是第一个跳跃指令(0xe000),而是(可能不是)随机数(0x6816)。

法典:

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 中有垃圾 - 初始数据不会复制到其目标地址。所以我的问题是:为什么调试器会锁定内存进行写入以及如何防止它?

如果"RAM 中没有断点"意味着在 RAM 中定义的地址进行读取或写入访问时中断,那么您观察到的行为是在启动时闪存到 RAM 复制。

重置时,RAM 是随机的,在闪存main()功能之前,有一个从常量复制到 RAM 中的副本。如果在启动后设置了 RAM 断点,则此过程是隐藏的,如果在之前设置,则 RAM 在第一次中断时是"随机的"。如果你继续执行,你应该转到main(),然后在RAM中第二次中断。

最新更新