Stand-alone boot code Cortex M3

Asked by LiamG

I have a simple Eclipse ARM GNU project LED blinker running on a custom STM32F100C8 board
When I build the project and run on the board via a Segger JLink, the LED blinks fine.
If I then remove the JTAG and power cycle, the code no longer works as stand alone.

I have isolated the issue down to the startup assembly code.
If I "hard wire" the reset vector to point to main:

.syntax unified
.thumb

.section .isr_vector
Vectors:
.word __stack /* stack top address */
.word main /* Reset. First code address after reset */

the linked output is (extract):

Disassembly of section .text:

00000000 <Vectors>:
   0: 20002000 .word 0x20002000
   4: 00000141 .word 0x00000141

00000140 <main>:
 140: b480 push {r7}
 142: b083 sub sp, #12

the code works standalone after power cycle and removal of the JTAG.

However, if I use instead a vector to Reset_Handler, which subsequently BX to main (and does nothing else), the code still works with JTAG, but not standalone after power cycle:

.syntax unified
.thumb

.section .Reset_Handler
.thumb_func
Reset_Handler:
 bl main // Call application entry point

.section .isr_vector
Vectors:
.word __stack /* stack top address */
.word Reset_Handler /* Reset. First code address after reset */

Disassembly of section .text:

00000000 <Vectors>:
   0: 20002000 .word 0x20002000
   4: 00000134 .word 0x00000134

00000134 <Reset_Handler>:
 134: f000 f804 bl 140 <main>
 138: 4770 bx lr

00000140 <main>:
 140: b480 push {r7}
 142: b083 sub sp, #12
etc...

Changing the reset vector in this way is the only difference between the builds.
Link script, main.c, Makefile are all otherwise identical.

Can you suggest what the issue might be?
It seems odd that in the case that works, the linker generates a reset vector that is an odd address (and yet it still works) whereas in the case that doesn't work, the reset vector is even (which I would expect to work).

Thank you.

Question information

Language:
English Edit question
Status:
Solved
For:
GNU Arm Embedded Toolchain Edit question
Assignee:
No assignee Edit question
Solved by:
LiamG
Solved:
Last query:
Last reply:
Revision history for this message
Leo Havmøller (leh-p) said :
#1

Jump to even address means ARM mode, jump to odd address means thumb mode, so for an Cortex-M3 it needs to be an odd address.
Check CPU selection in compiler/assember options.

Revision history for this message
LiamG (cocoasteam) said :
#2

Thank you for your answer.
Not sure how that could be the solution since:

- The code works when the JTAG is plugged in
- and exact same code doesn't then work when the plug is removed and power cycled.

If the core mode was incorrect, then it wouldn't work in either case surely?
Also, Makefile settings are:

$(CC) -v -mcpu=cortex-m3 -mthumb -g -nostartfiles -T $(FOUNDATION)/STM32F100C8.ld main.c StartUp_simple.s -o $(NAME).elf

Revision history for this message
Leo Havmøller (leh-p) said :
#3

The difference between JTAG and self-boot is that with JTAG, the debugger sets MSP from vectors[0], and fetches the entry point from vectors[1]. The debugger knows that the CPU is a Cortex, and as such adjust the entry point address to be odd.

The difference in your source above is that you have told the assembler that Reset_Handler is a .thumb_func, but you havent told the assembler anything about main. So try adding .thumb_func and .globl main.

BTW, none of the code you have shown requires assembler; It can all be done from C, which would also eliminate the problem.

Revision history for this message
LiamG (cocoasteam) said :
#4

Hi Leo.

Thank you very much; that is exactly what I was looking for and explained the symptoms exactly.
I added:

.type Reset_Handler , %function

to the Reset Handler and that fixed everything.
The linker generated the expected odd-addressed branch to handler.

I didn't need to add .globl main.