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 22, 2017 at 03:42

I am using stm32f746g EVAL board/STLink. Basically started with demo project, modified startup to include initial SP and defined DATA_IN_ExtSRAM inside of system_stm32f7xx.c Also added BSP_SRAM_Init()

You mean 

__main does not go straight to main() but does whole lot of other stuff before that?

Posted on November 22, 2017 at 04:00

>>You mean 

__main does not go straight to main() but does whole lot of other stuff before that?

Yes, I think I've been saying that since the outset this morning..

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 22, 2017 at 04:43

There is SystemInit() and the entire call-tree underneath that, the code is executed so as to set up the system so the memories can be filled with the data that is packed into the FLASH/ROM image by the linker. The code in __main does the unpacking and sets up the C run-time environment, and finally transfers control to your main() entry point.

The exact code built to perform __main depends on the linker, which builds structures describing the load regions, and depending on if the data is compressible, using a couple of algorithms/settings to find the most efficient, the appropriate code to decompress the data into RAM.

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 22, 2017 at 04:55

Ok, I see, you meant the 

SystemInit below, And __main unpacks constant data and loads it into internal or external memories. that makes much more sense now.

I also noticed that my code has much better chance of starting up if board power is cycled vs using reset button.

void SystemInit(void)

{

/* FPU settings ------------------------------------------------------------*/

♯ if (__FPU_PRESENT == 1) && (__FPU_USED == 1)

SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */

♯ endif

/* Reset the RCC clock configuration to the default reset state ------------*/

/* Set HSION bit */

RCC->CR |= (uint32_t)0x00000001;

/* Reset CFGR register */

RCC->CFGR = 0x00000000;

/* Reset HSEON, CSSON and PLLON bits */

RCC->CR &= (uint32_t)0xFEF6FFFF;

/* Reset PLLCFGR register */

RCC->PLLCFGR = 0x24003010;

/* Reset HSEBYP bit */

RCC->CR &= (uint32_t)0xFFFBFFFF;

/* Disable all interrupts */

RCC->CIR = 0x00000000;

♯ if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)

SystemInit_ExtMemCtl();

♯ endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */

/* Configure the Vector Table location add offset address ------------------*/

♯ ifdef VECT_TAB_SRAM

SCB->VTOR = SRAM1_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */

♯ else

SCB->VTOR = FLASH_BASE; /* Vector Table Relocation in Internal FLASH */

♯ endif

}
Sergio Petrovko
Associate II
Posted on November 22, 2017 at 16:24

If I put all of my RW&ZI data into external SRAM, it works every time on power up and about 4 out of 5 times after pressing reset button. It is only that stable with the following MPU settings for SRAM region :TEX0S0B1C1. However if at least one array is forced into internal SRAM, it hardly ever works. 

Other way around, no issues running from internal SRAM whats so ever, again, until at least 1 of the arrays is placed into external SRAM

Makes me think that issue must be with the external SRAM initialization.

Sergio Petrovko
Associate II
Posted on November 23, 2017 at 00:01

Just wanted to add that I partially replicated the problem with GNU/GCC. After relocating all of the data sections to external SRAM, stm32f746G EVAL demo project fails to respond to reset button once in a while.  After locating 1 data array into separate SRAM - same thing.

It does seem that GNU/GCC is much more stable as reset failed a lot less often and I was always able to start the board after power cycling, even for cases when Keil loader never worked at all (for example with all data in Internal SRAM except for 1 array which was placed into External SRAM section)

Posted on November 23, 2017 at 01:07

I'd probably step back at this point and do some saturation testing of the external memory to validate it's functionality. Keil doesn't need any structures placed in the memory, you just need to initialize it and use pointers.

SDRAM has sequence and timing requirements during initialization, and refresh during normal use.

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 23, 2017 at 03:14

I tried running at lower HSI clock by disabling HSE and PLL inside of SystemInit() as you suggested, makes no difference. Section which causes hard fault is Keil's loader which does zero init on external SRAM. If I add UNINIT to external SRAM section inside of my .sct, everything works just like GNU/GCC. So the code

AVI_crak.videocrak

posted above apparently works a lot better than whatever Keil's linker adds to the code behind the scene.

P.S.:

External SRAM is perfectly accessible, writable and readable if I just set a pointer manually to the area starting 0x68000000.

Sergio Petrovko
Associate II
Posted on November 25, 2017 at 06:43

SOLVED!!!

The problem originated from my scatter file. I had ext SRAM Section declared under its own load region:

LR_SRM 0x68000000 0x00200000 {

RW_SRM 0x68000000 0x00200000 {

*.o (.ExtSramSection)}}

While correct way to do it is most likely like this:

LR_IROM1 0x08000000 0x00100000 { 

ER_IROM1 0x08000000 0x00100000 {

*.o (RESET, +First)

*(InRoot$$Sections)

.ANY (+RO)

}

RW_IRAM1 0x20000000 0x00050000 { a

.ANY (+RW +ZI)

}

RW_ESRM 0x68000000 0x00200000 {

*.o (.ExtSramSection)

}}