1

I've programmed my STM32F401 in C and Rust but am having a problem with assembly.

  • When I initially load the code with a Black Magic Probe, it runs fine
  • When my board powers up or is reset, the code doesn't run.
  • After reset, in GDB, if I try to Continue it, it throws an exception.
  • After reset, in GDB, if I try to Run it, it runs fine

The actual code in the reset handler is the perennial "blinky". I'm sure there's no problem with the code, this "smells" of some kind of "initialisation issue"?

  • I'm a massive GDB noob, but if I do info registers, PC is always the value I'd expect - 0x8000198
Disassembly of section .text:

08000000 <vector_table>:
 8000000:   20010000    .word   0x20010000
 8000004:   08000198    .word   0x08000198
 8000008:   08000194    .word   0x08000194
 -- redacted a load from brevity... they're all 0x0800194 
 8000188:   08000194    .word   0x08000194
 800018c:   08000194    .word   0x08000194
 8000190:   08000194    .word   0x08000194

08000194 <Default_handler>:
 8000194:   f7ff bffe   b.w 8000194 <Default_handler>

08000198 <Reset_handler>:

            ; RCC_AHB1ENR := RCC_AHB1ENR OR RCC_AHB1Periph_GPIOC

 8000198:   f643 0030   movw    r0, #14384  ; 0x3830
 800019c:   f2c4 0002   movt    r0, #16386  ; 0x4002
 80001a0:   6802        ldr r2, [r0, #0]
 80001a2:   f042 0204   orr.w   r2, r2, #4
 80001a6:   6002        str r2, [r0, #0]

            ; GPIOC_MODER := GPIO_MODER_13_OUTPUT

 80001a8:   f640 0000   movw    r0, #2048   ; 0x800
 80001ac:   f2c4 0002   movt    r0, #16386  ; 0x4002
 80001b0:   f240 0200   movw    r2, #0
 80001b4:   f2c0 4200   movt    r2, #1024   ; 0x400
 80001b8:   6002        str r2, [r0, #0]

 80001ba:   f240 0220   movw    r2, #32     ;          0b00100000
 80001be:   f2c0 0200   movt    r2, #0

 80001c2:   f640 0019   movw    r0, #2073   ; 0x819    GPIOC_BSRR8
 80001c6:   f2c4 0002   movt    r0, #16386  ; 0x4002
 80001ca:   f640 011b   movw    r1, #2075   ; 0x81b    GPIOC_BSRR24
 80001ce:   f2c4 0102   movt    r1, #16386  ; 0x4002

080001d2 <.loop>:
 80001d2:   7002        strb    r2, [r0, #0] ; set bit

 80001d4:   f240 0300   movw    r3, #0
 80001d8:   f2c0 030d   movt    r3, #13
080001dc <.delay0>:
 80001dc:   3b01        subs    r3, #1
 80001de:   bf18        it  ne
 80001e0:   e7fc        bne.n   80001dc <.delay0>

 80001e2:   700a        strb    r2, [r1, #0] ; reset bit

 80001e4:   f240 0300   movw    r3, #0
 80001e8:   f2c0 030d   movt    r3, #13
080001ec <.delay1>:
 80001ec:   3b01        subs    r3, #1
 80001ee:   bf18        it  ne
 80001f0:   e7fc        bne.n   80001ec <.delay1>

 80001f2:   e7ee        b.n 80001d2 <.loop>
Andy Preston
  • 779
  • 4
  • 9
  • 23

1 Answers1

2
 8000004:   08000198    .word   0x08000198

that needs to be an odd number to boot

you need to use .thumb_func or .type (if using gnu assembler, if using another assembly language then you need to sort it out for that langauge)

.cpu cortex-m4
.thumb

vector_table:
.word 0x20001000
.word ResetVector

.thumb_func
.globl ResetVector
ResetVector:
   b .

Disassembly of section .text:

08000000 <vector_table>:
 8000000:   20001000    .word   0x20001000
 8000004:   08000009    .word   0x08000009

08000008 <ResetVector>:
 8000008:   e7fe        b.n 8000008 <ResetVector>

and this will boot (or at least will try to run the reset handler)

without:

.cpu cortex-m4
.thumb

vector_table:
.word 0x20001000
.word ResetVector

.globl ResetVector
ResetVector:
   b .

Disassembly of section .text:

08000000 <vector_table>:
 8000000:   20001000    .word   0x20001000
 8000004:   08000008    .word   0x08000008

08000008 <ResetVector>:
 8000008:   e7fe        b.n 8000008 <ResetVector>

this will not boot

you can use .type as well, .type works for both arm and thumb (if doing ARM instructions which this cannot be because it is a cortex-m).

.cpu cortex-m4
.thumb

vector_table:
.word 0x20001000
.word ResetVector

.type ResetVector, %function
.globl ResetVector
ResetVector:
   b .

Disassembly of section .text:

08000000 <vector_table>:
 8000000:   20001000    .word   0x20001000
 8000004:   08000009    .word   0x08000009

08000008 <ResetVector>:
 8000008:   e7fe        b.n 8000008 <ResetVector>

all of the vectors other (not the sp init value) must be odd. Use the tools do not do some plus one thing.

Your debugger was probably launching the program directly and not resetting the part.

old_timer
  • 69,149
  • 8
  • 89
  • 168
  • 1
    Note that the lsbit being set is in the ARM documentation for the core. – old_timer Feb 10 '21 at 12:04
  • 1
    All other entries must have bit[0] set to 1, because this bit defines the EPSR.T bit on exception entry. – old_timer Feb 10 '21 at 12:07
  • I had wrongly assumed that `thumb_func` was used for mixing ARM and Thumb functions (on cores where that may be possible) and had also forgotten about "the +1 thing"... Back to the docs I go. – Andy Preston Feb 10 '21 at 12:09
  • Ah yes, `EPSR.T` sounds like "the magic invokation" I am needing to look up. Thanks. – Andy Preston Feb 10 '21 at 12:10
  • Think ORRed with one not ADDed with one, if you orr with one it is always right if you ADD one and the tools worked then addition may make it wrong. – old_timer Feb 10 '21 at 12:10
  • it is just the T thumb mode bit in the PSR, goes back to the ARMv4T days (The beginning of the post-acorn ARM). for the full sized armv4 to armv7 cores you can go between arm and thumb mode and the T bit in the PSR is a reflection of the mode. The lsbit is used by specific instructions (varies by architecture and version) to switch modes so ldr r0,=0x1000; bx r0 switches or keeps you in arm mode and branches to 0x1000. ldr r0,=0x1001; bx r0 switches or keeps you in thumb mode. the cortex-ms are thumb mode only so you have to stay in thumb mode – old_timer Feb 10 '21 at 12:13
  • Yes searching EPSR or EPSR.T in the armv7 ARM ARM will basically say the same thing. thumb mode and you have to stay in thumb mode. – old_timer Feb 10 '21 at 12:14
  • I dont remember how I learned about thumb func, but .type I figured out from examining the output of gcc and why gcc created functions would make interworking work with the linker and my asm functions not. Interestingly last time I looked gcc puts both .thumb_func and .type in there, a bit of overkill but likewise one or the other may also set other internal flags so there may be value in both. But in this case .thumb_func is the minimum needed to get the tool to do the ORRed with one work for you (as well as indicate to the linker you need it to interwork for non cortex-ms) – old_timer Feb 10 '21 at 12:17