STM32F103 Cannot jump to bootloader from app

2.8k Views Asked by At

I'd like to do a jump to bootloader from application on STM32 Blue Pill STM32F103C8T6. My approach looks that: - Write to BKP->DR1 any value; - Do a reset (NVIC_SystemReset()); - A the beginning of main, check if BKP->DR1 != 0, than set it to 0 and jump to boot;

Dubugging shows, that core jumps far away (0xfffffffe) and nothing happens. My code:

/*
 * bootloader.c
 *
 *  Created on: 28.03.2020
 *      Author: Admin
 */

#include "stm32f10x.h"
#include "../Logger/logger.h"
#include "core_cm3.h"

#define ADDR 0x1FFFF000

void (*f_boot_jump)();

void boot_jump_to_boot ()
{

    f_boot_jump = (void (*)(void)) (*((uint32_t *)(ADDR + 4)));
    __disable_irq();
    __DSB();
    SCB->VTOR = (uint32_t) ADDR;
    __DSB();
    __ISB();
    __set_MSP(*(__IO uint32_t*) ADDR);
    f_boot_jump();

}

void boot_init()
{
    RCC->APB1ENR |= RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN;
    PWR->CR |= PWR_CR_DBP;

    if (BKP->DR1 != 0) //DR != 0 means, that boot request has been sent
    {
        BKP->DR1 = 0;
        RCC->APB1ENR &= ~RCC_APB1ENR_PWREN;
        RCC->APB1ENR &= ~RCC_APB1ENR_BKPEN;
        PWR->CR &= ~PWR_CR_DBP;
        RCC->CFGR &= ~RCC_CFGR_SW;
        RCC->CR &= ~RCC_CR_PLLON;
        RCC->CR &= ~RCC_CR_HSEON;
        boot_jump_to_boot();
    }

}

void boot_write_boot_request()
{
    BKP->DR1 = 0x1;
    NVIC_SystemReset();
}

SS from IDE: memory registers

I have no idea why it does not work. More over, before jump memory in the area of 0x1FFFF000 looks ok: Before jump

and here is after failing jump to boot: after jump Maybe my chip is fake? ST Utility shows correct values (Device ID, flash size, MediumDensity), but it can means nothing. When I'm using the BOOT pins, the bootloader is loaded properly and STM flashloader recognize it. Even if my chip is a fake, the embedded bootloader works so I can't figure out the reason, why jump from application does not work.

2

There are 2 best solutions below

1
On

I am jumping to bootloader on my stm32l4 chip. I have had success with the following code:

static void JumpToBootloader(void) 
{
  void (*SysMemBootJump)(void);
  volatile uint32_t addr = 0x1FFF0000;
  HAL_RCC_DeInit();

  SysTick->CTRL = 0;
  SysTick->LOAD = 0;
  SysTick->VAL = 0;
  __disable_irq();
  __HAL_RCC_SYSCFG_CLK_ENABLE();           //make sure syscfg clocked
  __DSB();
  __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();  //remap system memory to address 0x0000000
  __DSB();
  __ISB(); 
  SCB->VTOR = 0;                           //set vector table offset to 0
  SysMemBootJump = (void (*)(void)) (*((uint32_t *)(addr + 4)));
  __set_MSP(*(uint32_t *)addr);
    SysMemBootJump();
}

and

int main(void)
{
// Check to see if we need to go to DFU mode (testing only)
  __HAL_RCC_PWR_CLK_ENABLE();
  HAL_PWR_EnableBkUpAccess();  //use SRAM backup to store magic number;

  if (*(__IO uint8_t*)0x20040000 == 212)
  {  //is magic number correct?
    *(__IO uint8_t*)0x20040000 = 0;
    JumpToBootloader();
  }
0
On

The STM32F103 does not support memory remap and __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH is unavailable. Unfortunately STM32F103 also has no Backup SRAM. However you can use Backup registers (BKP) to store flag. Jump to bootloader immediately after CPU restarted without peripheral initialisation. Make sure these registers are 16-bit wide only. So in order to jump in to builtin bootloader you can use this code snippet:

#define BOOTLOADER_MAGIC 0xB01D

/**
 * @brief Reboot to bootloader.
 */
void bootloader_reboot_to(void)
{
  BKP->DR1 = BOOTLOADER_MAGIC;
  HAL_NVIC_SystemReset();
}

/**
 * @brief Bootloader jump.
 */
void bootloader_check_jump(void)
{
  if (BKP->DR1 != BOOTLOADER_MAGIC)
  {
    return;
  }

  BKP->DR1 = 0;
  typedef __attribute((noreturn)) void (*bootloader_caller_t)(void);

  /* Bootloader address. */
#define BOOTLOADER_ADDRESS 0x1FFFF000

  /* Disable all interrupts. */
  __disable_irq();
  __DSB();
  __ISB();

  /* Fetch the bootloader's reset handler. */
  uint32_t bootloader_reset_handler
        = *(__IO uint32_t *)(BOOTLOADER_ADDRESS + 4);
  bootloader_caller_t bootloader_enter
        = (bootloader_caller_t)bootloader_reset_handler;

  /* Update the NVIC's vector. */
  SCB->VTOR = BOOTLOADER_ADDRESS;

  __DSB();
  __ISB();

  /* Initialize the Stack Pointer. */
  __set_MSP(*(__IO uint32_t *)BOOTLOADER_ADDRESS);

  bootloader_enter();
}

// After inside void main(...)
// Do not forget to enable PWR domain CLK.
__HAL_RCC_PWR_CLK_ENABLE();

HAL_PWR_EnableBkUpAccess();

/* Enable BKP CLK enable for backup registers */
__HAL_RCC_BKP_CLK_ENABLE();
bootloader_check_jump();