ExplicitBootloaderJump

From Stm32World Wiki
Jump to navigation Jump to search

Work in progress, STM32H562 being tested on.

#include "stm32h5xx_hal.h"
#include "jump-bootloader.h"

#define SYSMEM_BOOT_ADDRESS ((uint32_t)0x0BF97000)  // Not certain, but 

/**
 * @brief  Jumps to the system memory bootloader.
 */
void JumpToBootloader(void) {

    // --- Step 1: De-initialize the system ---
    // Disable all interrupts
    __disable_irq();

    // De-initialize all HAL-configured peripherals
    HAL_DeInit();

    // De-initialize the RCC (clock system) to its reset state
    // This is important for the bootloader to configure the clocks correctly.
    HAL_RCC_DeInit();

    // Clear any pending interrupts from the NVIC
    for (IRQn_Type i = 0; i < 240; i++) { // STM32H5 has up to 240 interrupts
        NVIC_DisableIRQ(i);
        NVIC_ClearPendingIRQ(i);
    }

    // Disable SysTick timer and clear its exception pending bit
    SysTick->CTRL = 0;
    SysTick->LOAD = 0;
    SysTick->VAL = 0;
    SCB->ICSR |= SCB_ICSR_PENDSTCLR_Msk;

    // --- Step 2: Prepare for the jump ---

    // Get the bootloader's entry address (Reset_Handler)
    // The second word (at address + 4) of the bootloader's vector table
    // contains the entry point.
    uint32_t bootloader_entry = *(volatile uint32_t*) (SYSMEM_BOOT_ADDRESS + 4);


    // Function pointer for the bootloader entry
    void (*SysMemBootJump)(void);

    // Create a function pointer to the bootloader's entry address
    SysMemBootJump = (void (*)(void)) bootloader_entry;

    // --- Step 3: Set the stack pointer and jump ---

    // Set the main stack pointer (MSP) to the bootloader's initial stack value.
    // The first word (at the base address) of the bootloader's vector table
    // contains the initial MSP value.
    __set_MSP(*(volatile uint32_t*) SYSMEM_BOOT_ADDRESS);

    // Execute the jump to the bootloader
    SysMemBootJump();

    // The program should never reach this point
    while (1)
        ;
}