Custom Bootloader for update the firmware but application don't start.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2023-05-04 3:03 AM
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 */
}
}
Solved! Go to Solution.
- Labels:
-
Bootloader
-
STM32F4 Series
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2023-05-04 4:14 AM
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,
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2023-05-04 3:19 AM
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();
}
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2023-05-04 3:21 AM
My program that I jumped to have properly VTOR tab. I set it during flashing
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2023-05-04 3:34 AM
Hi
Thank for your amswer but not ok.
With debugger i trace and the cpu jump to 0x80029ee also 0x08010004
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2023-05-04 3:48 AM
Ok. About your program that you jump to. Show me linker script for this program
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2023-05-04 3:51 AM
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) }
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2023-05-04 3:55 AM
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.
Step the control transfer, probably gets to app code, and then fails.
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2023-05-04 3:58 AM
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;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2023-05-04 4:04 AM
The linker script that you pasted is for app or bootloader?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2023-05-04 4:07 AM
Yes
