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.