cancel
Showing results for 
Search instead for 
Did you mean: 

Bootloader (STM32L496RG) application stuck at first HAL_Delay

GPerk.1
Associate III

I create 2 simple applications on Nucleo-L476RG.

Both application have default settings from STM32CUBEIDE.

1 - bootloader - just jump to 0x08010000

2 - Application - led flashings with HAL_Delay function

Bootloader jumps into application, pplication starts - then stuck into HAL_Delay.

See the modification to both app:

'Bootloader':

/* USER CODE BEGIN 0 */

typedef void (*pFunction)(void); /*!< Function pointer definition */

#define APP_ADDRESS (uint32_t)0x08010000

void jump2APP(){

uint32_t JumpAddress = *(__IO uint32_t*)(APP_ADDRESS + 4);

pFunction Jump  = (pFunction)JumpAddress;

HAL_RCC_DeInit();

HAL_DeInit();

__disable_irq();

SysTick->CTRL = 0;

SysTick->LOAD = 0;

 SysTick->VAL = 0;

SCB->VTOR = APP_ADDRESS;

__set_MSP(*(__IO uint32_t*)APP_ADDRESS);

Jump();

}

/* USER CODE END 0 */

[....]

 uint8_t i=20;

 HAL_GPIO_TogglePin(LD2_GPIO_Port,LD2_Pin);

 while (1)

 {

 /* USER CODE END WHILE */

 /* USER CODE BEGIN 3 */

  HAL_GPIO_TogglePin(LD2_GPIO_Port,LD2_Pin);

HAL_Delay(i*30+1);

if(!i--)

jump2APP();

 }

Application:

* USER CODE BEGIN WHILE */

volatile uint32_t cnt=0;

while(cnt++<500000);

cnt=0;

HAL_GPIO_TogglePin(LD2_GPIO_Port,LD2_Pin);

while(cnt++<5000000);

cnt=0;

HAL_GPIO_TogglePin(LD2_GPIO_Port,LD2_Pin);

while(cnt++<5000000);

cnt=0;

HAL_GPIO_TogglePin(LD2_GPIO_Port,LD2_Pin);

while(cnt++<5000000);

cnt=0;

HAL_GPIO_TogglePin(LD2_GPIO_Port,LD2_Pin);

while(cnt++<5000000);

 while (1)

 {

 /* USER CODE END WHILE */

 /* USER CODE BEGIN 3 */

  HAL_GPIO_TogglePin(LD2_GPIO_Port,LD2_Pin);

  HAL_Delay(100);

 }

 /* USER CODE END 3 */

And in the linker file:

MEMORY

{

 RAM  (xrw)  : ORIGIN = 0x20000000,  LENGTH = 96K

 RAM2  (xrw)  : ORIGIN = 0x10000000,  LENGTH = 32K

 FLASH  (rx)  : ORIGIN = 0x8010000,  LENGTH = 1024K

}

7 REPLIES 7

Hello

>>then stuck into HAL_Delay

HAL_Delay uses SysTick but SysTick was disabled before.

DavidAlfa
Senior II

After __disable_irq(); SysTick will be dead.

You need to enable irq again before the​ delay.

And it will not count the time​ it was disabled, as SysTick was not updated.

GPerk.1
Associate III

Thanks,

I added __enble_irq() in the app at the beginning.

But it is only part of the problem.

I had to add:

SCB->VTOR = APP_ADDRESS;

to the application and all works.

I found nowhere this description, maybe due it works without that in simple cases.

>>I found nowhere this description, maybe due it works without that in simple cases.

Usually done in SystemInit() code, but the way ST implements it's apt to be wrong unless defines are updated. More robust way is to use linker symbols.

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

@Community member​ 

I was looking in system_stm32l4xx.c at SystemInit() and VTOR is not updated there at all(unless some defines are changed)

So it looks like it is changed somewhere after jump from bootloader.

Is there anything wrong in my solution? (except is not elegant)

Can you provide an example of this linker solution?

thanks

CMSIS expect the startup code to call SystemInit() prior to initializing the statics, and before transferring control to main()

system_stm32l4xx.c

/**
  * @brief  Setup the microcontroller system.
  * @param  None
  * @retval None
  */
 
void SystemInit(void)
{
...
  /* Configure the Vector Table location add offset address ------------------*/
#ifdef VECT_TAB_SRAM
  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#else
  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif
}

In Keil,

extern uint32_t * __Vectors;

SCB->VTOR = (uint32_t)(&__Vectors); // Smart Base Location

Make sure it's EXPORTed, and change the name to g_pfnVectors, or whatever your tool chain uses

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

>>Is there anything wrong in my solution? (except is not elegant)

It does seem overly complicated, and tears down clocks and PLLs you'll need to waste time bringing up later.

The compiler is likely to make a mess of things, it's really not going to understand the stack changed mid-function.

Much better that the stack pointer and vector table are changed on the application side.

The real trick to the control transfer is to unwind the interrupts you've actually set up, not just disable the interrupts on the entire MCU, because they'll all come back when you re-enable them, and you might not have your handlers in order.

Got an interrupt on the UART, go turn that OFF, etc. Let the app reconfigure and enable if it wants too.

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