In main function after nexti
instruction on bl
, gdb debugger continues instead of stopping. The issue does not occur in functions called by main (e.g. I can step over functions called in init_pin_output
). What am I missing in setup?
start.s:
@ ...
@ vector_table
@ ...
.thumb_func
.global reset
.align 4
reset:
ldr r2, PPB_BASE
ldr r1, VTOR_OFFSET
add r1, r1, r2
ldr r0, =vector_table
str r0, [r1]
ldr r1, SRAM_STRIPED_END
mov sp, r1
platform_entry:
ldr r1, =main
blx r1
mov r0, r0
bkpt #0 @ should not return
main.s:
.thumb_func
.global main
.align 4
main:
push {lr}
@ ...
.init_led:
movs r0, #25
bl init_pin_output
.init_lcd:
bl init_screen
@ ...
@ delay loop
@ ...
pop {pc}
.thumb_func
.global init_pin_output
.align 4
init_pin_output:
push {lr}
ldr r1, =out_pin
str r0, [r1]
ldr r0, out_pin
movs r1, #5 @ 5 - SIO
bl GPIO_function_select
ldr r0, out_pin
bl output_enable_pin
pop {pc}
.align 4
out_pin: .word 0
Tried calling main from wrapper function with the same result.
On backtrace
gdb outputs: „Backtrace stopped: previous frame identical to this frame (corrupt stack?)”.
After inspecting disassembly of sdk generated .elf files I did not encounter frame pointer modification (as it is not effective in thumb mode).
Found the problem in my code. It turns out that naming sections (for readability reasons) breaks the GDB's temporary breakpoint, as it expects execution to return to the very same section (as stated in this answer). My code in main.s looked more like:
thumb_func
.global main
.align 4
main:
push {lr}
.clk:
bl setup_internal_clk
.init_gpio:
bl init_gpio
.init_ps2:
movs r0, #13
bl init_keyboard
@ ...
The problem was that when returning from function, the code did not return to the same section - it jumped directly to the next one. The solution is either to avoid making function calls at the end of a section or to add nop
instructions after the function call.