STM32 boot

For the bluepill, I wanted to be able to write a standard C++ program with a main function and whatnot, and not have to deal with the weird vector struct mapping; I pulled up the datasheet and found the table with the listing of the vector table. I put this into an assembly file and when I got home, tried to use this to run a basic blink demo. However, the LED didn't blink. I fired up OpenOCD and went to debug it; stepping through it seemed to be working until two steps later:

$ step
target halted due to single-step, current mode: Handler HardFault
xPSR: 0x00000003 pc: 00000000 msp: 0x000000e0
halted: PC: 0x00000000

I spent a while trying to get figure out what was going on; my startup.s file looked pretty much like everyone else's, but no luck. It took a while for me to realise that I was double mapping addresses. That is, the linker script I had was defining the flash start at an offset, then uploading to another offset. The fix was straightforward:

-    rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
-    ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
+    flash (rx) : ORIGIN = 0x00000000, LENGTH = 128K
+    sram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K

The renaming is incidental.

Now I have the following linker script:

    flash (rx) : ORIGIN = 0x00000000, LENGTH = 128K
    sram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K

   .text : { *(.text*) } > flash
   .bss  : { *(.bss*) } > sram

and the following startup code:

 * Startup code for the STM32F103-based blue pill board.
 * The stack pointer is initialised to the top of the stack (which
 * grows downward), so I pointed it to the end of the SRAM (where the
 * stack should be).

.cpu cortex-m3

.globl  vectors
.align  2
.long   0x20005000      /* stack pointer points to top of SRAM */
.long   reset_handler       /* reset handler */
.long   0           /* NMI handler */
.long   0           /* hard_fault_handler */
.long   0           /* memory management handler */
.long   0           /* bus fault handler */
.long   0           /* usage fault handler */
.skip   0x20            /* reserved */
.long   0           /* svcall handler */
.long   0           /* debug handler */
.skip   4           /* reserved */
.long   0           /* pendsv handler */
.long   0           /* systick handler */
.skip   0x100           /* remaining / IRQ vectors */

    bl  main

This appears to work, but occasionally gets weird and I have to re-flash the blink demo from the previous post.

I'll do some more investigating.

Tags: , ,