cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_Delay() function is not working after jump from Bootloader

asukarnikhil
Associate

Hello,

I am working on NUCLEO-F070RB board, I have developed the Custom Bootloader Code

to test the Bootloader functionality I am using blinky application with HAL_Delay(1000);

When I run the blinky application independently the application is working fine.

When I remove the HAL_Delay(1000); function and use for(int i = 0; i< 1000000; i++); for the delay, the Bootloader is successfully jumps to application and led starts blinking

from above cases I observed that there is issue with HAL_Delay() function with jump from  bootloader to application

Can you explain what could be the issue and how to resolve it.

following is the function to jump from bootloader to application .

void Bootloader_JumpToApplication(void)
{
#if DEBUG_ENABLED
UART_Debug_Print("Gonna Jump to Application\n");
#endif
void (*app_reset_handler)(void) = (void*)(*((volatile uint32_t*) (APP_START_ADDRESS + 4U)));

__disable_irq();

/* Jump to application */
app_reset_handler();
}

 

5 REPLIES 5
######
Senior II

Hello,

Other users will probably have more experience knowledge, but I believe for the F0 series there is something extra that is required with the Vector Table Offset Register VTOR. I think this needs to be amended to match the new start of code execution.

Because HAL_Delay uses Systick interrupt it may be that your VTOR value is incorrect, hence the Systick version doesnt work.

Apologies in advance if this is misleading / not the case.

 

Check if you disabled MCU interrupts and didn't re-enable

Check code in SystemInit(), or wherever, pointed SCB->VTOR at the location of your new/current vector table basis.

For the Cortex-M0 you'll need to copy the vectors to the base of RAM, and then remap that at zero. Likely via SYSCFG / RMP. Check for IAP code examples within CubeF0

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

Hi All,

 

This post has been escalated to the ST Online Support Team for additional assistance.  We'll contact you directly.

 

Regards,
Jake

ST Support

Following is my bootloader, application and .id file

  • if I use __disable_irq() before jumping to application and when I use __enable_irq() in my application I am getting below error.
  • If I do not use __disable_irq() before jumping to application. then also I am getting same error after HAL_Init();
  • I am using FreeRTOS in my application.

/**

* @brief This is the code that gets called when the processor receives an

* unexpected interrupt. This simply enters an infinite loop, preserving

* the system state for examination by a debugger.

*

* @PAram None

* @retval : None

*/

.section .text.Default_Handler,"ax",%progbits

Default_Handler:

Infinite_Loop:

b Infinite_Loop

.size Default_Handler, .-Default_Handler

Bootloader code:

#define APP_START_ADDRESS 0x08004000
typedef void (*pFunction)(void);
void Bootloader_JumpToApplication(void)
{
static volatile uint32_t JumpAddress;
static volatile pFunction Jump_to_application;
if(((*(uint32_t*) APP_START_ADDRESS) & 0x2FFE0000) == 0x20000000)
 {
 HAL_Delay(100);
 JumpAddress = *(uint32_t *)(APP_START_ADDRESS + 4);
 Jump_to_application = (pFunction)JumpAddress;
 __disable_irq(); // 1. Disable all interrupts
 __set_MSP(*(uint32_t *)APP_START_ADDRESS);
 Jump_to_application();
 }
}

Application code:

#define APPLICATION_ADDRESS     (uint32_t)0x08004000
__IO uint32_t VectorTable[48] __attribute__((section(".my_ram_section")));
void SystemClock_Config(void);
/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  uint32_t i = 0;
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
  /* Configure the system clock */
  SystemClock_Config();

  __enable_irq();

  /* USER CODE BEGIN SysInit */
  for(i = 0; i < 48; i++)
  {
    VectorTable[i] = *(__IO uint32_t*)(APPLICATION_ADDRESS + (i<<2));
  }
  /* Enable the SYSCFG peripheral clock*/
  __HAL_RCC_SYSCFG_CLK_ENABLE();
  /* Remap SRAM at 0x00000000 */
  __HAL_SYSCFG_REMAPMEMORY_SRAM();
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_SPI2_Init();
  MX_ADC_Init();
  user_main();
  while (1)
  {

  }
}

 LinkerScript.ld

/*
******************************************************************************
**
** @file        : LinkerScript.ld
**
** @author      : Auto-generated by STM32CubeIDE
**
** @brief       : Linker script for STM32F070CBTx Device from STM32F0 series
**                      128KBytes FLASH
**                      16KBytes RAM
**
**                Set heap size, stack size and stack location according
**                to application requirements.
**
**                Set memory bank area and size if external memory is used
**
**  Target      : STMicroelectronics STM32
**
**  Distribution: The file is distributed as is, without any warranty
**                of any kind.
**
******************************************************************************
** @attention
**
** Copyright (c) 2024 STMicroelectronics.
** All rights reserved.
**
** This software is licensed under terms that can be found in the LICENSE file
** in the root directory of this software component.
** If no LICENSE file comes with this software, it is provided AS-IS.
**
******************************************************************************
*/

/* Entry Point */
ENTRY(Reset_Handler)

/* Highest address of the user mode stack */
_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */

_Min_Heap_Size = 0x200; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */

/* Memories definition */
MEMORY
{
  RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 16K
  FLASH    (rx)    : ORIGIN = 0x8004000,   LENGTH = 112K
}

/* Sections */
SECTIONS
{
  /* The startup code into "FLASH" Rom type memory */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >FLASH

  .my_ram_section (NOLOAD) : 
  {
    . = ALIGN(4);
    *(.my_ram_section)
  } >RAM AT >FLASH
  
  /* The program code and other data into "FLASH" Rom type memory */
  .text :
  {
    . = ALIGN(4);
    *(.text)           /* .text sections (code) */
    *(.text*)          /* .text* sections (code) */
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */
    *(.eh_frame)

    KEEP (*(.init))
    KEEP (*(.fini))

    . = ALIGN(4);
    _etext = .;        /* define a global symbols at end of code */
  } >FLASH

  /* Constant data into "FLASH" Rom type memory */
  .rodata :
  {
    . = ALIGN(4);
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
    . = ALIGN(4);
  } >FLASH

  .ARM.extab (READONLY) : /* The "READONLY" keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
  {
    . = ALIGN(4);
    *(.ARM.extab* .gnu.linkonce.armextab.*)
    . = ALIGN(4);
  } >FLASH

  .ARM (READONLY) : /* The "READONLY" keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
  {
    . = ALIGN(4);
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
    . = ALIGN(4);
  } >FLASH

  .preinit_array (READONLY) : /* The "READONLY" keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
    . = ALIGN(4);
  } >FLASH

  .init_array (READONLY) : /* The "READONLY" keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
    . = ALIGN(4);
  } >FLASH

  .fini_array (READONLY) : /* The "READONLY" keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
    . = ALIGN(4);
  } >FLASH

  /* Used by the startup to initialize data */
  _sidata = LOADADDR(.data);

  /* Initialized data sections into "RAM" Ram type memory */
  .data :
  {
    . = ALIGN(4);
    _sdata = .;        /* create a global symbol at data start */
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */
    *(.RamFunc)        /* .RamFunc sections */
    *(.RamFunc*)       /* .RamFunc* sections */

    . = ALIGN(4);
    _edata = .;        /* define a global symbol at data end */

  } >RAM AT> FLASH

  /* Uninitialized data section into "RAM" Ram type memory */
  . = ALIGN(4);
  .bss :
  {
    /* This is used by the startup in order to initialize the .bss section */
    _sbss = .;         /* define a global symbol at bss start */
    __bss_start__ = _sbss;
    *(.bss)
    *(.bss*)
    *(COMMON)

    . = ALIGN(4);
    _ebss = .;         /* define a global symbol at bss end */
    __bss_end__ = _ebss;
  } >RAM

  /* User_heap_stack section, used to check that there is enough "RAM" Ram  type memory left */
  ._user_heap_stack :
  {
    . = ALIGN(8);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(8);
  } >RAM

  /* Remove information from the compiler libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }

  .ARM.attributes 0 : { *(.ARM.attributes) }
}

 

Guillaume K
ST Employee

By default the HAL uses SYSTICK interrupt to increment the uwTick tick counter used by HAL_Delay().

If you are using FreeRTOS, it takes the Systick for its own purpose.

In that case you should configure the application to use another interrupt (e.g. TIM interrupt) than Systick to increment the HAL tick.

See example in STM32CubeF0 : STM32CubeF0/Projects/STM32072B_EVAL/Applications/FreeRTOS/FreeRTOS_ThreadCreation at master · STMicroelectronics/STM32CubeF0 · GitHub

in particular, see file stm32f0xx_hal_timebase_tim.c

with function HAL_InitTick() that configures TIM6 instead of Systick used in default implementation of HAL_InitTick() in stm32f0xx_hal.c (weak function).