Question

I wrote (IMO) almost simpliest ARM application and it didn't work :) What could be wrong? What is missed?

After flash write and CPU reset there are garbage in registers.

Please, be kind and if U know, tell me what has to be done to run simplest application on STM32F1.

May be someone coud enumerate what has to be done before application starts, ie.

  1. Initialize stack (it is necessary?)
  2. Set something.
  3. Set something else.

The application:

@Directives
    .thumb                  @.code 16
    .syntax unified

.section .text
    .org 0                  @ Alters location of pointer - in this case set to zero

vectors:                    @ Define basic vectors for specific capabilities
    .word _start + 1        @ Set - start address and increment pointer
    .word _nmi_handler + 1  @ Below all other vectors will be declared:
    .word _hard_fault + 1
    .word _memory_fault + 1
    .word _bus_fault + 1
    .word _usage_fault + 1

_start:
    mov r0, #5
    mov r1, #4
    add r2, r0, r1

_nmi_handler:
_hard_fault:
_memory_fault:
_bus_fault:
_usage_fault:

Maybe someone know any tutorials or books, about linker scripts, cpu initialisation etc.?

The processor is: STM32F103VBT6

Programmed by: OpenOCD.

Thanks in advance.

Was it helpful?

Solution

I have many thumb and cortex-m based examples http://github.com/dwelch67

As Joachim pointed out you are missing the first entry in the vector table, the stack pointer. the cortex-m does not have the same vector table as an arm, meaning one that boots up in arm mode with arm instructions.

To complete the answer though, for the cortex-m you can setup the stack by putting the starting value for the stack pointer in that first word location

.cpu cortex-m3
.thumb

.word   0x10008000  /* stack top address */
.word   _start      /* 1 Reset */
.word   hang        /* 2 NMI */
.word   hang        /* 3 HardFault */
.word   hang        /* 4 MemManage */

you can certainly once running set the stack pointer manually as you would with an arm in arm mode or most other processors.

I would have your code fall into an infinite loop so that, as written, you dont fall into undefined instructions, etc. (should be 0xFFs, which on the cortex-m0 I think is an undefined, on a -m3 or -m4 with armv7 thumb2 support it might be a real instruction).

Notice that I didnt use the +1 on my vectors. You need to know your tools. You need that lsbit set to indicate a thumb address/thumb mode on the branch. Although I learned a lesson on that (will have to find the so question)

Arm/Thumb: using BX in Thumb code, to call a Thumb function, or to jump to a Thumb instruction in another function

With the gnu assembler if you put a directive .thumb_func before a label, that label is marked to be a thumb label and the gnu tools will then use the address|1.

.thumb_func
.globl _start
_start:

You need to build and disassemble every now and again to make sure your table is being built correctly and branches and such are using the proper address.

   0:   10008000    andne   r8, r0, r0
   4:   0000005b    andeq   r0, r0, fp, asr r0
   8:   00000050    andeq   r0, r0, r0, asr r0
   c:   00000050    andeq   r0, r0, r0, asr r0
  10:   00000050    andeq   r0, r0, r0, asr r0

see, apparently I have a bug in one of my examples...it never does anything but reset (no interrupts used in the example, so that is how I got away with not knowing). forgot the .thumb_func

hang:   b .

produced

00000050 <hang>:
  50:   e7fe        b.n 50 <hang>

change to

.thumb_func
hang:   b .

and the vector table goes to

00000000 <hang-0x50>:
   0:   10008000    andne   r8, r0, r0
   4:   0000005b    andeq   r0, r0, fp, asr r0
   8:   00000051    andeq   r0, r0, r1, asr r0
   c:   00000051    andeq   r0, r0, r1, asr r0
  10:   00000051    andeq   r0, r0, r1, asr r0
  14:   00000051    andeq   r0, r0, r1, asr r0

this is interesting, change the code to

.cpu cortex-m3
.thumb

.word   0x10008000  /* stack top address */
.word   _start+1      /* 1 Reset */
.word   hang+1        /* 2 NMI */
.word   hang+1        /* 3 HardFault */
.word   hang        /* 4 MemManage */
.word   hang        /* 5 BusFault */

and it doesnt really do a plus one but instead an or one.

00000000 <hang-0x50>:
   0:   10008000    andne   r8, r0, r0
   4:   0000005b    andeq   r0, r0, fp, asr r0
   8:   00000051    andeq   r0, r0, r1, asr r0
   c:   00000051    andeq   r0, r0, r1, asr r0
  10:   00000051    andeq   r0, r0, r1, asr r0

That is a bit disturbing. The bottom line though, two things, with a cortex-m you can setup the stack pointer in the vector table, second, when starting a new project disassemble and examine the vector table to make sure it is what you are expecting. Esp if it isnt doing what you think it should.

OTHER TIPS

From the M3 documentation;

The vector table at location 0 is only required to have four values:

Stack top address
Reset routine location
NMI ISR location
Hard Fault ISR location.

The stack top address should be at address 0, seems you're missing it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top