cancel
Showing results for 
Search instead for 
Did you mean: 

Failure to start main on STM32F7

Sergio Petrovko
Associate II
Posted on November 21, 2017 at 17:11

I am having an issue where STM32F7 fails to start on reset. Here is a section of a startup code which fails:

IMPORT SystemInit

IMPORT __main

LDR R0, =SystemInit

BLX R0

LDR R0, =__initial_sp ; restore original stack pointer

MSR MSP, R0

LDR R0, =__main

BX R0

ENDP

It gets stuck on the line 

BX R0 and never goes to main. Did anyone ever had similar issues? It only happens if I am trying to put something into external SRAM, though the SystemInit code stays the same regardless, and all registers before BX R0 look identical in both cases.

Any ideas? I am really stuck here

18 REPLIES 18
Posted on November 21, 2017 at 17:55

This isn't your main() function, but rather the Keil code to initialize the statics, ie copy initial content to RAM, and zero other areas. Once the __main function completes it calls your main function.

Your code in SystemInit() needs to completely initialize the external bus and memories so that data you have directed to external memory via the linker can be placed there. This means clocks, pins, peripheral, all the things need to bring up the interface and devices attached to it.

You should 'STOP' the debugger once your code crashes and see where it is, most likely in the while(1) loop of you Hard Fault Handler.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on November 21, 2017 at 18:10

SystemInit() is not an issue as I can run with RW and ZI section located in external SRAM and it works. In this case I am trying to put just 1 array into external SRAM, and it is not used util way further in the code. The problem is it never gets past BX R0  as it does go to Hard Fault on this line.

Posted on November 21, 2017 at 18:14

So dump out the registers, look at the exception registers, and the context that has been stacked.

Is R0 an ODD or EVEN number? Does the stack look to be viable? Is the stack on the external memory? Going to be slower

Hard to debug through a key-hole

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on November 21, 2017 at 19:00

right before the call:

R0       0x080001C9

R1

       

0xE000ED08

R13 

 0x20023C48

R14 

 0x08013D95

R15 

 0x080002A4

MSP    0x20023C48

xPSR    0xA1000000

after the fault:

R0    0x2005000

R1   0x6804F1D5

R3    0xFFFB0E2A

R4   0x68025800

R6   0x0000009C

R13 

 0x20023C18

R14 

 0xFFFFFFF9

R15 

 0x0800F36E

MSP 

 0x20023C18

xPSR

  0xA1000003

In this example everything is on the internal memory except for 1 array which is not used until way further in the code. stack size is 0x4000

AVI-crak
Senior
Posted on November 21, 2017 at 21:22

How do you expect to execute the function without initializing variables? By the way, you have a piece of code from the M0 device. This code is not optimal for M7, it should not work at all.

Use the code below - as a template.

.section .text.Reset_Handler

.weak Reset_Handler

.type Reset_Handler, %function

Reset_Handler:

ldr sp, =_estack /* set stack pointer */

/* Copy the data segment initializers from flash to SRAM */

__LOADdata:

ldr r0, =_sidata

ldr r1, =_sdata

ldr r2, =_edata

__LOADdatax:

cmp r1, r2

ittt ne

ldrne r3, [r0], #4

strne r3, [r1], #4

bne __LOADdatax

__bss_zero:

mov r0, #0

ldr r1, =_sbss

ldr r2, =_ebss

__bss_zerox:

cmp r1, r2

itt ne

strne r0, [r1], #4

bne __bss_zerox

/* Call the clock system initialization function.*/

bl SystemInit

/* Call static constructors */

__LOADSDRAM:

ldr r0, =_sisdramdata

ldr r1, =_sqsdramload

ldr r2, =_eqsdramload

__LOADSDRAMx:

cmp r1, r2

ittt ne

ldrne r3, [r0], #4

strne r3, [r1], #4

bne __LOADSDRAMx

/* Call the application's entry point.*/

bl main

bx lr

.size Reset_Handler, .-Reset_Handler
Posted on November 21, 2017 at 21:28

The OP is using Keil not GNU/GCC, and setting the SP is not that problematic, it allows you to move the SP to external memory(s) after reset where you put some arbitrary internal SRAM address in the vector table

The '__main' function is Keil's run time to initialize the statics, does the equivalent to all the code you have in your GNU startup.s

SystemInit() must run first to initialize the hardware the external memories rely upon.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Sergio Petrovko
Associate II
Posted on November 22, 2017 at 02:35

What bothers me is that the issue is not consistent. Exactly the same initialization code works in some cases and not the others. How is that code change way farther down the line can cause a fault so early on? 

Even more weird, it would sometimes run and sometimes fail without changing anything in the code at all!

Almost seems like some random stuff inside of a CPU like branch prediction or something. Any idea how to trouble shoot this further?

Posted on November 22, 2017 at 03:17

__main unpacks structures created by the linker, this can include compressed data. Sensitive to data and ordering.

Truly squirrely behaviour can be had if the cache or flash subsystem is misconfigured. Make sure you have sufficient wait states.

Is this your own hardware? Can odd behaviour be replicated on DISCO, NUCLEO or EVAL boards? Check voltages and capacitors on VCAP pins.

Things to try, remove all HSE/PLL code from SystemInit() paths. Let the part run off HSI as it currently does, check for stability.

Using ST-LINK, J-Link or U-Link debug pod?

I'd disassemble and sanity check the failing image, add code to output internal state via USART, and without debugger. Doing a CRC of the image prior to calling SystemInit() to confirm integrity of image in FLASH, and as read by CPU. Repeat after SystemInit() to confirm higher speeds/settings don't break things.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Sergio Petrovko
Associate II
Posted on November 22, 2017 at 04:33

If I understood correctly, you mean that compiler will look ahead, for example  if it finds a call to SystemClock_Config()  where HSE/PLL are set it will execute that section before main()?