2023-05-04 03: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.
2023-05-04 04: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,
2023-05-04 03: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();
}
}
2023-05-04 03:21 AM
My program that I jumped to have properly VTOR tab. I set it during flashing
2023-05-04 03:34 AM
Hi
Thank for your amswer but not ok.
With debugger i trace and the cpu jump to 0x80029ee also 0x08010004
2023-05-04 03:48 AM
Ok. About your program that you jump to. Show me linker script for this program
2023-05-04 03: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) }
}
2023-05-04 03: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.
2023-05-04 03: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;
2023-05-04 04:04 AM
The linker script that you pasted is for app or bootloader?
2023-05-04 04:07 AM
Yes