Skip to main content
Visitor II
November 21, 2021
Question

STM32F072CBT6 - Entering bootloader from application

  • November 21, 2021
  • 5 replies
  • 1950 views

I need to enter into the bootloader from my application during runtime.

I found an example code to achieve this for another family series and followed the instructions to determine the specific memory region I should jump to based on my particular MCU.

Below is the resulting code.

typedef void jumpFunc(void);
 
void Bootloader_Start(uint32_t run)
{
 /* Set the address of the entry point to bootloader */
 volatile uint32_t BootAddr = 0x1FFFC800;
 
 /* Set up the jump to booloader address + 4 */
 jumpFunc* SysMemBoot = (jumpFunc*)0x1FFFC804;
 
 if (run == 1)
 {
 // Shut down any task running
 HAL_RCC_DeInit();
 SysTick->CTRL = 0; // reset the SysTick Timer
 SysTick->LOAD = 0;
 SysTick->VAL = 0;
 
 __disable_irq(); // Disable interrupts
 
 /* Set the main stack pointer to the bootloader stack */
 __set_MSP(*(uint32_t *)BootAddr);
 
 SysMemBoot();
 
 while (1);
 }
}

However, this code is not working for me. Executing it always results in a Hard fault interrupt.

What am I missing?

Thanks

    This topic has been closed for replies.

    5 replies

    ERODR.1Author
    Visitor II
    November 21, 2021

    Thank you very much. Very helpful. It looks like I was missing this:

    SYSCFG->CFGR1 = 0x01;

    So now it doesn't end up in a Hard Fault interrupt. However, I haven't been able to connect using the Flash Loader Demonstrator. I have tried all 3 options for Echo without luck.

    0693W00000GYKviQAH.png0693W00000GYKwIQAX.png0693W00000GYKvYQAX.pngUsing the STM32CubeProgrammer UART, I get it to connect, but haven't been able to flash anything. It stays with the loading bar ping-ponging without ever increasing from 0%.

    0693W00000GYKwWQAX.png 

    What am I missing here?

    Graduate II
    November 21, 2021

    Try ommit the call to __disable_irq();

    ERODR.1Author
    Visitor II
    November 21, 2021

    Thanks for the follow up. I tried, but if the interrupts are not disabled, for some reason it resets after calling the SysMemBootJump.

    Graduate II
    November 21, 2021

    You need disable interrupts one by one before call Bootloader start.

    ERODR.1Author
    Visitor II
    November 21, 2021

    Thanks for your assistance. Based on your input I decided to call the DeInit functions for each and every peripheral currently used by my application as well as disabling all interrupts enabled by my application. I followed the reverse Initialization order while doing it.

    Here's the final code tested to work using the Flash Demonstrator app:

    void Bootloader_Start(uint32_t run) {
     void (*SysMemBootJump)(void);
     
     /**
     * Set system memory address.
     *
     * For STM32F072, system memory is on 0x1FFF C800
     * For other families, check AN2606 document table 155 with descriptions of memory addresses
     */
     volatile uint32_t addr = 0x1FFFC800;
     
     if (run == 1)
     {
     // De-initialize all peripherals configured for this Application
     HAL_TIM_Base_DeInit(&htim1);
     HAL_TIM_Base_DeInit(&htim6);
     HAL_TIM_Base_DeInit(&htim7);
     HAL_TIM_Base_DeInit(&htim14);
     
     HAL_TIM_PWM_DeInit(&htim15);
     HAL_TIM_Base_DeInit(&htim15);
     
     HAL_CRC_DeInit(&hcrc);
     
     HAL_NVIC_DisableIRQ(DMA1_Channel1_IRQn);
     HAL_NVIC_DisableIRQ(DMA1_Channel2_3_IRQn);
     HAL_NVIC_DisableIRQ(DMA1_Channel4_5_6_7_IRQn);
     HAL_DMA_DeInit(&hdma_memtomem_dma1_channel2);
     
     HAL_PCD_DeInit(&hpcd_USB_FS);
     HAL_UART_DeInit(&huart2);
     HAL_UART_DeInit(&huart1);
     
     HAL_ADC_DeInit(&hadc);
     
     // Disable GPIO interrupts
     HAL_NVIC_DisableIRQ(EXTI0_1_IRQn);
     HAL_NVIC_DisableIRQ(EXTI2_3_IRQn);
     HAL_NVIC_DisableIRQ(EXTI4_15_IRQn);
     
     // Disable RCC, set it to default (after reset) settings
     // Internal clock, no PLL, etc.
     HAL_RCC_DeInit();
     
     // Disable systick timer and reset it to default values
     SysTick->CTRL = 0;
     SysTick->LOAD = 0;
     SysTick->VAL = 0;
     
     // Disable all interrupts
     __disable_irq();
     
     /**
     * Remap system memory to address 0x0000 0000 in address space
     * For each family registers may be different.
     * Check reference manual for each family.
     *
     * For STM32F4xx, MEMRMP register in SYSCFG is used (bits[1:0])
     * For STM32F0xx, CFGR1 register in SYSCFG is used (bits[1:0])
     * For others, check family reference manual
     */
     //Remap by hand... {
     #if defined(STM32F4)
     SYSCFG->MEMRMP = 0x01;
     #endif
     #if defined(STM32F0)
     SYSCFG->CFGR1 = 0x01;
     #endif
     //} ...or if you use HAL drivers
     //__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH(); //Call HAL macro to do this for you
     
     // Set jump memory location for system memory
     // Use address with 4 bytes offset which specifies jump location where program starts
     SysMemBootJump = (void (*)(void)) (*((uint32_t *)(addr + 4)));
     
     /**
     * 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(*(uint32_t *)addr);
     
     /**
     * Call our function to jump to set location
     * This will start system memory execution
     */
     SysMemBootJump();
     }
    }