I'm making bootloader for STM32F103 ARM microprocessor. I already wrote program that is able to execute code stored in RAM memory (16-bit Thumb instructions stored in uint16_t array). Everything runs fine until I set breakpoint at RAM address.
When I start program in debug mode w/o breakpoints in RAM, code runs fine. When I start program in debug mode, then I set breakpoint at the first instruction of my program (jump to main procedure), code also runs fine. Problem happens when I leave that breakpoint set, I stop the execution and then try to run it in debug mode again. Then, instead of first jump instruction (0xe000) I get (probably not) random number (0x6816).
Code:
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);
}
}
When I set breakpoint on each instruction, I get following numbers:
0x6816, 0x2e00, 0xd018, 0xf000, 0x42b5, 0xd0f9. Fourth one doesn't change, probably because it's part of 32-bit instruction (breakpoint was not set on this number's address).
Using SW4STM32 v2.4 with OpenOCD 0.10.0-dev-00007-g58350bc-dirty.
EDIT: I set breakpoint on the beginning of ResetHandler and I noticed that when breakpoint in RAM is set, given memory address is locked for write.
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
That explains why I have garbage in RAM - initial data is not copied to its destination address. So my question is: why debugger locks memory for write and how to prevent it?