Skip to main content
Visitor II
May 4, 2023
Solved

Custom Bootloader for update the firmware but application don't start.

  • May 4, 2023
  • 11 replies
  • 3801 views

Hi.

I'm writing a bootloader for update a firmware of my project by usb pen drive.

Whe bootloader start verify that in the pen drive there io a .bin file, erase the flash and copy teh bin in the flash defined address.

The flash address is 0x08010000.

This process appare running fine , whith debugger I verified the address and the application is present, but when Jump the cpu don't run.

I tested various jump routines take from examples of bootloader find OnLine , but none work.

I don't. know there is the problem.

I use STM32Cube compiler and the test is applied to Nucleo -F413ZH.

this is the routines code:

/*  Bootloader Test */

#include "bootloader.h"

#include "stm32f4xx_hal.h"

#include "string.h"

extern UART_HandleTypeDef huart3;

extern char USBHPath[4];  /* USBH logical drive path */

extern FATFS USBHFatFS;   /* File system object for USBH logical drive */

extern FIL USBHFile;      /* File object for USBH */

extern char RD_buffer[100];

extern char sw_boot;

FRESULT fresult;

FILINFO USBHfno;

#define UART &huart3

typedef void (*pFunction)(void);

typedef void (application_t)(void);

typedef struct

{

   uint32_t      stack_addr;    // Stack Pointer

   application_t*   func_p;       // Program Counter

} JumpStruct;

/**************************** Various test routine *************************************/

void jumpToApp(const uint32_t address)

{

   const JumpStruct* vector_p = (JumpStruct*)address;

    HAL_SuspendTick();

    HAL_RCC_DeInit();

    HAL_DeInit();

    SysTick->CTRL = 0;

    SysTick->LOAD = 0;

    SysTick->VAL = 0;

    SCB->VTOR = address;

   /* let's do The Jump! */

   /* Jump, used asm to avoid stack optimization */

   asm("msr msp, %0; bx %1;" : : "r"(vector_p->stack_addr), "r"(vector_p->func_p));

}

void BOOT_JumpToApplication(uint32_t ui32StartAddr)

{

   uint32_t* vectorTable = (uint32_t*)ui32StartAddr;

   uint32_t topOfStack = vectorTable[0];

   HAL_RCC_DeInit();

   HAL_DeInit();

   /* disebale systick and its irq */

   HAL_SuspendTick();

   HAL_NVIC_DisableIRQ(CAN1_RX0_IRQn);

   HAL_NVIC_DisableIRQ(TIM2_IRQn);

   HAL_NVIC_DisableIRQ(OTG_FS_IRQn);

   SysTick->CTRL = 0;

   SysTick->LOAD = 0;

   SysTick->VAL = 0;

   /* Jump to user application */

   asm ( "mov sp, %0" : : "r" (topOfStack) );

   uint32_t resetHandlerAddr = vectorTable[1];

   asm ( "bx %0" : : "r" (resetHandlerAddr) );

   ((void (*)())(resetHandlerAddr))();

}

void JumpToApplication(void) // non va

{

   HAL_RCC_DeInit();

   HAL_DeInit();

     SysTick->CTRL = 0;

     SysTick->LOAD = 0;

     SysTick->VAL = 0;

     SCB->VTOR = APP_ADDRESS;

   uint32_t mainStackPointer = *(volatile uint32_t *)(APP_ADDRESS);

       __set_MSP(mainStackPointer);

   uint32_t programResetHandlerAddress = *(volatile uint32_t *) (APP_ADDRESS + 4);

   void (* programResetHandler)(void) = (void (*)(void)) programResetHandlerAddress;

       programResetHandler();

}

 void goto_application(void)

{

 //void (*app_reset_handler)(void) = (void*)(*((volatile uint32_t*) (APP_ADDRESS + 4U)));

   void (*app_reset_handler)(void) = ((volatile uint32_t*) (APP_ADDRESS + 4U));

   HAL_RCC_DeInit();

   HAL_DeInit();

   HAL_SuspendTick();

   HAL_NVIC_DisableIRQ(CAN1_RX0_IRQn);

   HAL_NVIC_DisableIRQ(TIM2_IRQn);

   HAL_NVIC_DisableIRQ(OTG_FS_IRQn);

   HAL_NVIC_DisableIRQ(OTG_FS_WKUP_IRQn);

   __disable_irq();

   SysTick->CTRL = 0;

   SysTick->LOAD = 0;

   SysTick->VAL = 0;

   SCB->VTOR = APP_ADDRESS;

   __set_MSP(*(volatile uint32_t*) APP_ADDRESS);

 app_reset_handler();   //call the app reset handler

}

 void JumpToBootloader2(void)

 {

  uint32_t i=0;

  void (*SysMemBootJump)(void);

  /* Set the address of the entry point to bootloader */

     volatile uint32_t BootAddr = APP_ADDRESS;

  /* Disable all interrupts */

     __disable_irq();

  /* Disable Systick timer */

     SysTick->CTRL = 0;

  /* Set the clock to the default state */

     HAL_RCC_DeInit();

  /* Clear Interrupt Enable Register & Interrupt Pending Register */

     for (i=0;i<5;i++)

     {

     NVIC->ICER[i]=0xFFFFFFFF;

     NVIC->ICPR[i]=0xFFFFFFFF;

     }

  /* Re-enable all interrupts */

     __enable_irq();

  /* Set up the jump to booloader address + 4 */

     SysMemBootJump = (void (*)(void)) (*((uint32_t *) ((BootAddr + 4))));

  /* Set the main stack pointer to the bootloader stack */

     __set_MSP(*(uint32_t *)BootAddr);

  /* Call the function to jump to bootloader location */

     SysMemBootJump();

  /* Jump is done successfully */

     while (1)

     {

      /* Code should never reach this loop */

     }

 }

    This topic has been closed for replies.
    Best answer by PZamb.2

    Ok Thanks I found the problem

    In the application connection script I do not change ten Flash Addresses, default 0x800000; But must be 0x8010000.

    Now Run.

    Thank for your inspiration,

    11 replies

    Graduate
    May 4, 2023

    I use this solution:

    void jump_to_application(uint32_t const application_address) {
    	typedef void (*jumpFunction)(void);
     
     
    	/**
    	 * Step: Disable RCC and other peripherals
    	 */
    	HAL_NVIC_DisableIRQ(EXTI15_10_IRQn);
    	HAL_NVIC_DisableIRQ(USART1_IRQn);
    	HAL_NVIC_DisableIRQ(USART2_IRQn);
    	HAL_GPIO_DeInit(LD2_GPIO_Port, LD2_Pin);
    	HAL_GPIO_DeInit(USER_BUTTON_GPIO_Port, USER_BUTTON_Pin);
    	uint8_t isDeInitOk = 0;
    	if ((HAL_RCC_DeInit() || HAL_UART_DeInit(&huart1)
    			|| HAL_UART_DeInit(&huart2) || HAL_DeInit()) == HAL_OK) {
    		isDeInitOk = 1;
    	}
     
     
    	/**
    	 * Step: Disable systick timer and reset it to default values
    	 */
    	SysTick->CTRL = 0;
    	SysTick->LOAD = 0;
    	SysTick->VAL = 0;
     
     
    	/**
    	 * Step: Set jump memory location to application address
    	 */
    	uint32_t jumpAddress = *(__IO uint32_t*) (application_address + 4);
    	jumpFunction jumpToProgram = (jumpFunction) jumpAddress;
     
     
    	/**
    	 * Step: Set main stack pointer.
    	 * This step must be done last otherwise local variables in this function
    	 * don't have proper value since stack pointer is located on different position
    	 *
    	 * Set direct address location which specifies stack pointer in SRAM location
    	 */
    	__set_MSP(*(__IO uint32_t*) application_address);
     
     
    	/**
    	 * Step: Actually call our function to jump to set location. This will start application execution.
    	 * If isDeinitOk flag is not set, then call system reset.
    	 */
    	if (isDeInitOk) {
    		jumpToProgram();
    	} else {
    		HAL_NVIC_SystemReset();
    	}
    }

    Graduate
    May 4, 2023

    My program that I jumped to have properly VTOR tab. I set it during flashing

    PZamb.2Author
    Visitor II
    May 4, 2023

    Hi

    Thank for your amswer but not ok.

    With debugger i trace and the cpu jump to 0x80029ee also 0x08010004

    Graduate
    May 4, 2023

    Ok. About your program that you jump to. Show me linker script for this program ​

    PZamb.2Author
    Visitor II
    May 4, 2023

    Is the default of Nucleo conf:

    /*

    ******************************************************************************

    **

    ** @file       : LinkerScript.ld

    **

    ** @author     : Auto-generated by STM32CubeIDE

    **

    ** Abstract   : Linker script for NUCLEO-F413ZH Board embedding STM32F413ZHTx Device from stm32f4 series

    **                     1536Kbytes FLASH

    **                     320Kbytes 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) 2023 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 = 320K

     FLASH   (rx)   : ORIGIN = 0x8000000,  LENGTH = 1536K

    }

    /* Sections */

    SECTIONS

    {

     /* The startup code into "FLASH" Rom type memory */

     .isr_vector :

     {

       . = ALIGN(4);

       KEEP(*(.isr_vector)) /* Startup code */

       . = ALIGN(4);

     } >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  : {

       . = ALIGN(4);

       *(.ARM.extab* .gnu.linkonce.armextab.*)

       . = ALIGN(4);

     } >FLASH

     .ARM : {

       . = ALIGN(4);

       __exidx_start = .;

       *(.ARM.exidx*)

       __exidx_end = .;

       . = ALIGN(4);

     } >FLASH

     .preinit_array    :

     {

       . = ALIGN(4);

       PROVIDE_HIDDEN (__preinit_array_start = .);

       KEEP (*(.preinit_array*))

       PROVIDE_HIDDEN (__preinit_array_end = .);

       . = ALIGN(4);

     } >FLASH

     .init_array :

     {

       . = ALIGN(4);

       PROVIDE_HIDDEN (__init_array_start = .);

       KEEP (*(SORT(.init_array.*)))

       KEEP (*(.init_array*))

       PROVIDE_HIDDEN (__init_array_end = .);

       . = ALIGN(4);

     } >FLASH

     .fini_array :

     {

       . = 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) }

    }

    Graduate II
    May 4, 2023

    Make sure the code in the apps SystemInit() sets the right address in SCB​->VTOR that the define changes or you use the vector table symbol.

    S​tep the control transfer, probably gets to app code, and then fails.

    PZamb.2Author
    Visitor II
    May 4, 2023

    I add the step:

    void jump_to_application(uint32_t const application_address) {

        typedef void (*jumpFunction)(void);

        /**

        * Step: Disable RCC and other peripherals

        */

        HAL_NVIC_DisableIRQ(EXTI15_10_IRQn);

        HAL_NVIC_DisableIRQ(USART1_IRQn);

        HAL_NVIC_DisableIRQ(USART2_IRQn);

        //HAL_GPIO_DeInit(LD2_GPIO_Port, LD2_Pin);

        //HAL_GPIO_DeInit(USER_BUTTON_GPIO_Port, USER_BUTTON_Pin);

        uint8_t isDeInitOk = 0;

        if ((HAL_RCC_DeInit() || HAL_UART_DeInit(&huart3))

              == HAL_OK) {

           isDeInitOk = 1;

        }

        HAL_DeInit();

        SCB->VTOR = application_address;

        /**

        * Step: Disable systick timer and reset it to default values

        */

        SysTick->CTRL = 0;

        SysTick->LOAD = 0;

        SysTick->VAL = 0;

    Graduate
    May 4, 2023

    The linker script that you pasted is for app or bootloader?

    PZamb.2Author
    Visitor II
    May 4, 2023

    Yes

    PZamb.2Author
    Visitor II
    May 4, 2023

    for boot loader

    Graduate
    May 4, 2023

    Ok, could you show code that set application address?