cancel
Showing results for 
Search instead for 
Did you mean: 

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

PZamb.2
Associate III

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 */

     }

 }

1 ACCEPTED SOLUTION

Accepted Solutions
PZamb.2
Associate III

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,

View solution in original post

13 REPLIES 13
Kamil Duljas
Senior III

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();
	}
}

Dudo
Kamil Duljas
Senior III

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

Dudo
PZamb.2
Associate III

Hi

Thank for your amswer but not ok.

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

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

Dudo
PZamb.2
Associate III

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

}

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.

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

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;

Kamil Duljas
Senior III

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

Dudo
PZamb.2
Associate III

Yes