当设置断点时,STM32调试器锁定用于写入的RAM地址

时间:2018-04-18 23:36:32

标签: debugging gdb embedded stm32 openocd

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

1 个答案:

答案 0 :(得分:-1)

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

复位时,RAM是随机的,在闪存main()功能之前,存在从常量到RAM的副本。如果在启动后设置RAM断点,则此过程将被隐藏,如果之前已设置,则RAM在首次中断时为“随机”。如果继续执行,则应该转到main(),然后再在RAM中断开。