cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7 custom bootloader issue

Kevin Perminjat
Associate II
Posted on May 30, 2018 at 17:21

Hi !

I am working on Nucleo-144 board with the STM32H7 processor using cubeMX and developping on Ac6 System Workbench for STM32 based on Eclipse.

I am currently developping a Bootloader located on the first sector of the flash (0x8000000). The jump to the application is well done, i jump to the right adress and get on the Reset_Handler. I relocate the vector table in the SystemInit() function that is called before getting into the main. And i modified the linker script to have the flash start adress set correctly.

Then I get into  the SystemClock_Config() function and just before getting out, I get a HardFault.

My bootloader is using FreeRtos. First I used the Timer1 as Timebase source and i saw that the bit 0 of BFSR register was set (instruction bus error). Later, i tried to use the Systick as Timebase source and then it was the bit 1 of UFSR register that was set, and not BSFR register anymore.

I am now totally stucked and have no idea how to fix it.

Below, i put the code that is executed just before the jump :

SCB_DisableDCache();

SCB_DisableICache();

HAL_MPU_Disable();

HAL_RCC_DeInit();

HAL_SuspendTick();

__disable_irq();

SysTick->CTRL = 0;

SysTick->VAL = 0;

SysTick->LOAD = 0;

__set_MSP((uint32_t) *((__IO uint32_t*)

APPLICATION_START_ADDR

));

// Use address with 4 bytes offset which specifies jump location where program start(Reset_Handler)

entryPoint = (

pFunction

) *(__IO uint32_t*) (APPLICATION_START_ADDR + 4);

__set_CONTROL(0);

// Launch the SW

entryPoint();

Can anyone tell me where it is wrong?

Thanks !

#bootloader #stm32h7 #hardfault_handler
8 REPLIES 8
Rhodes.Keith
Associate II
Posted on June 01, 2018 at 23:28

I have been using this code to call the application logic for many years and it works well. It counts on you de-initializing all hardware before coming into this routine.

It is all done in assembly because you have to set the stack, NVIC table, VTABLE, etc.

#include 'stm32h7xx_hal.h'

#include 'stm32h7xx_hal_rcc.h'

#include 'stm32h743xx.h'

...

//

// Set the application's vector table start address. Typically this is the

// application start address but in some cases an application may relocate

// this so we can't assume that these two addresses are equal.

//

// The fancy gymnastics about the addresses (e.g. VTABLE_START_ADDRES) is necessary

// because the __asm() function takes a string as an argument and since the string

// contains the assembler and the C preprocessor doesn't change strings, you have

// to externalize the #defines so they can be conditional. Its alot of work to go

// thru so we can have #define variables, but them's the breaks.

//

__asm('movw r0, %0\n' :: 'i' ((unsigned short)VTABLE_START_ADDRESS & 0xffff));

__asm('movt r0, %0\n' :: 'n' (0xffff & (unsigned short)(VTABLE_START_ADDRESS >> 16)));

__asm('movw r1, %0\n' :: 'i' ((unsigned short)NVIC_VTABLE & 0xffff));

__asm('movt r1, %0\n' :: 'n' (0xffff & (unsigned short)(NVIC_VTABLE >> 16)));

__asm('str r0, [r1]\n'

//

// Load the stack pointer from the application's vector table.

//

'ldr sp, [r0]\n'

//

// Load the initial PC from the application's vector table and branch to

// the application's entry point.

//

'ldr r0, [r0, #4]\n'

'bx r0\n');
Posted on June 06, 2018 at 09:48

Thanks for your reply but it didn't solved the problem.

I noticed something about the clocks. On cubeMX, on the Clock Configuration tab, my Bootloader and my application both use PLLCLK on the System Clock Mux. 

But if I use another source for this mux (HSI for example),  for one or both of my softwares, it solved the problem, and I don't get a hardfault.

Posted on June 06, 2018 at 12:28

Unfortunately I had the same problem on the F429.

The application Timer interruped jumped back to the bootloader Interrupt handler.

Somewhere the remapping didnt worked for me like expected.

If FreeRTOS is based on the Systick the application worked fine. Worth a try if this solves the problem too.

Have an eye at the priority of the svc. The wrong priority could lead you to a hardfault too.

What could be helpfull to start the application after a system reset instead of init the bootloader and then de-init again before jumping to application.

Hope this helps a bit.

Posted on June 06, 2018 at 16:05

Have you properly set the VTOR register to point to the new start of your application?

Have you also set the loading point for your application to that new location?

It depends on your toolchain where this is set, but the VTOR typically in the startup assembler code before your main() is called.

The default for VTOR is 0x8000000. In my case, my application starts at 0x8100000 because my bootloader code is smaller than that. I set it in the startup assembler file before main() is called.

The application load address also has to be set to 0x8100000 and that is done in your linker configuration. Some toolchains use a file with .ld extension to set it.

Finally, make sure you disable the RCC in your bootloader code *before* you call the application. This is done with  HAL_RCC_DeInit(); (if you are using the HAL).

...Keith

Posted on June 06, 2018 at 16:17

It depends on your toolchain where this is set, but the VTOR typically in the startup assembler code before your main() is called.

The default for VTOR is 0x8000000. In my case, my application starts at 0x8100000 because my bootloader code is smaller than that. I set it in the startup assembler file before main() is called.

Jumping to the right location is done correctly.

Finally, make sure you disable the RCC in your bootloader code *before* you call the application. This is done with  HAL_RCC_DeInit(); (if you are using the HAL).

Shouldnt be HAL_DeInit() doing all the DeInit-routines?

I will try it.

Thank you for response.

Posted on June 06, 2018 at 16:28

The VTOR is correctly set. It is set in the SystemInit function. 

My linker script is also modified, I change the flash start adresse according to the location of my application. 

I also call the RCC_DeInit() function.

About HAL_DeInit(), I change one line of code. Instead of calling '__HAL_RCC_AHB3_FORCE_RESET();' I write directly into AHB3RSTR register to have the 31st bit set to 0. If not, it causes a CPU reset

Posted on June 24, 2018 at 20:00

Hello

Rhodes.Keith

.,

I am also using the exactly same procedure as

kperminjat

mentioned above .

But the jumping to specified address is not working , I also had look into your reply Can you please give more information on how to use this assembly code to our reuirement . can you please suggest any example code .

If you have done this for STM32H7 MCU, Can you send me a copy of that project , it would be very helpful for me .

Thank you

Posted on June 24, 2018 at 20:56

Not sure who is going to enable the interrupts on the other side.

Can you trace the handover and observe what is happening?

Can you try a simple test of transferring control to the ROM immediately in the Reset_Handler routine?

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..