libopencm3/libopencm3 — pull request #69 by nfbraun (2012-11-28 14:39:34+00:00)
Title: Add __attribute__ ((naked)) to reset_handler()

See discussion on mailing list: http://sourceforge.net/mailarchive/forum.php?thread_name=216B56E4-9F61-4D83-A8F9-41347DDCDE7D%40gmail.com&forum_name=libopencm3-devel

In the current versions of libopencm3 and the SAT toolchain, this bug can be triggered by choosing optimization level -O2 (in lib/stm32/f4/Makefile). A disassembly of reset_handler then looks like

Dump of assembler code for function reset_handler:

0x08000224 <+0>: push {r4}
0x08000226 <+2>: ldr r3, [pc, #80] ; (0x8000278 )
0x08000228 <+4>: msr MSP, r3
[...]

As you can see, gcc generates code to push r4 to the stack, *before* the stack pointer is set up. This behavior actually makes sense, as, per the ARM ABI, registers r0 - r3 are caller-saved, whereas r4-... are callee-saved.

While I had to use -O2 to trigger this, there is obviously nothing to prevent other versions of gcc to exhibit the same behavior on -Os, or -O0, as nothing tells the compiler that it must not use the stack (yet).

A fix that worked for me was to add \_\_attribute\_\_((naked)) to reset_handler (in lib/cm3/vector.c):

void WEAK \_\_attribute\_\_ ((naked)) reset_handler(void)

As reset_handler is only called once, and should never return, this is probably OK. However, I am not really sure if \_\_attribute\_\_((naked)) is the right solution here.