STM32H7 Bootloader jumps as clean as possible to application
Hi,
for this experiment, I use a NUCLEO-H743ZI (with 'Y' version MCU).
I have created two different versions of an application and two versions of a bootloader.
They are just very simple.
One (let's call it version A) is just a blinking a LED and printing on a UART.
The other (version B) is likewise, but also drives an OLED display.
The bootloader prints 'b' to the serial port every 500mS, the app prints 'a' to the serial port every 500mS.
When pressing the user button during reset, the bootloader enters a while loop (printing b's),
and only jumps to the application if the user button is released and pressed again.
If the user button is released during a reset the bootloader jumps to the application directly.
Bootloader A works fine with application A, and B with B.
Somehow I cannot let bootloader A have app B started, or let bootloader B have app A started.
I thought these could be independent programs.
I searched and read a lot about this topic, but I can't seem to find a solution.
What can I check?
My current JumpToApplication program in the bootloader:
void Bootloader_JumpToApplication(uint32_t AppAddress)
{
typedef void (*pFunction)(void);
/* Set the address of the entry point to application */
volatile uint32_t BootAddr = AppAddress;
printmsg("BL_DEBUG_MSG: Bootloader_JumpToApplication\n");
uint32_t MSPValue = *(__IO uint32_t*)BootAddr;
printmsg("BL_DEBUG_MSG: MSP value: 0x%08x\n", MSPValue);
uint32_t JumpAddress = *(__IO uint32_t*)(BootAddr + 4);
pFunction JumpToApplication = (pFunction)JumpAddress;
printmsg("BL_DEBUG_MSG: JumpAddress: 0x%08x\n", JumpAddress);
f_mount(NULL, SDPath, 1);
HAL_SD_MspDeInit(&hsd1);
FATFS_UnLinkDriver(SDPath);
__HAL_RCC_USART1_FORCE_RESET();
__HAL_RCC_USART3_FORCE_RESET();
HAL_Delay(5);
__HAL_RCC_USART1_RELEASE_RESET();
__HAL_RCC_USART3_RELEASE_RESET();
HAL_Delay(5);
HAL_SPI_MspDeInit(&hspi1);
HAL_SPI_MspDeInit(&hspi2);
HAL_SPI_MspDeInit(&hspi4);
HAL_ETH_MspDeInit(&heth);
HAL_UART_MspDeInit(&huart3);
// HAL_SD_MspDeInit(&hsd1);
SCB_DisableDCache();
SCB_DisableICache();
HAL_MPU_Disable();
HAL_SuspendTick();
/* Make sure you disable the RCC in your bootloader code *before* you call the application */
/* Set the clock to the default state */
HAL_RCC_DeInit();
// Modify the HAL_DeInit function:
// HAL_StatusTypeDef HAL_DeInit(void)
// {
// /* Reset of all peripherals */
// // __HAL_RCC_AHB3_FORCE_RESET(); // This causes a CPU reset
// RCC->AHB3RSTR &= 0x7fffffff; // have bit 31 set to 0
// __HAL_RCC_AHB3_RELEASE_RESET();
HAL_DeInit();
// HAL_SuspendTick();
/* Disable all interrupts */
__disable_irq();
// Disable SysTick and clear its exception pending bit, if it is used in the bootloader, e. g. by the RTX.
/* Disable Systick timer */
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
/* Clear Interrupt Enable Register & Interrupt Pending Register */
for (uint8_t i = 0; i < 8; i++)
{
// Disable all enabled interrupts in NVIC
NVIC->ICER[i] = 0xFFFFFFFF;
// Clear all pending interrupt requests in NVIC
NVIC->ICPR[i] = 0xFFFFFFFF;
}
/* Re-enable all interrupts */
__enable_irq();
SCB->ICSR |= SCB_ICSR_PENDSTCLR_Msk;
// Disable individual fault handlers if the bootloader used them.
SCB->SHCSR &= ~(SCB_SHCSR_USGFAULTENA_Msk | \
SCB_SHCSR_BUSFAULTENA_Msk | \
SCB_SHCSR_MEMFAULTENA_Msk);
// Activate the MSP, if the core is found to currently run with the PSP.
if( CONTROL_SPSEL_Msk & __get_CONTROL( ) )
{ /* MSP is not active */
__set_CONTROL( __get_CONTROL( ) & ~CONTROL_SPSEL_Msk ) ;
}
__HAL_RCC_SYSCFG_CLK_ENABLE();
SCB->VTOR = BootAddr;
SystemClock_Config();
__enable_irq();
HAL_ResumeTick();
// Configure the Main Stack Pointer. This function comes from CMSIS.
__set_MSP(*(__IO uint32_t*) BootAddr);
__set_CONTROL(0);
Boot_Delay(200);
JumpToApplication();
}Thanks for helping!