How do you implement a bootloader on STM32?

 A bootloader allows firmware updates without a hardware programmer (e.g., via UART, USB, or CAN). Here’s how to implement one on STM32:




1. Bootloader Basics

Key Concepts

  • Two Memory Regions:

    • Bootloader (e.g., 0x08000000 to 0x0800FFFF).

    • Application (e.g., 0x08010000 onwards).

  • Vector Table Offset: Application must relocate its interrupt vector table.

  • Communication Protocol: UART, USB DFU, I2C, CAN, etc.


2. Hardware Setup

  • STM32 Board (e.g., STM32F4 Discovery, Blue Pill).

  • Communication Interface (e.g., USB-UART converter for UART bootloader).

  • Boot Pins (Optional): Some STM32s use BOOT0/BOOT1 pins to enter bootloader mode.


3. Step-by-Step Implementation

(1) Partition Flash Memory

Modify the linker script (.ld file) to split Flash into bootloader and application regions.

Example (STM32F103C8 - 64KB Flash):

ld

MEMORY
{
    BOOTLOADER (rx) : ORIGIN = 0x08000000, LENGTH = 16K   /* First 16KB */
    APP_FLASH (rx)  : ORIGIN = 0x08004000, LENGTH = 48K   /* Next 48KB */
    RAM (rwx)       : ORIGIN = 0x20000000, LENGTH = 20K
}

(2) Write the Bootloader Code

The bootloader should:

  1. Check for Firmware Update (e.g., wait for UART command).

  2. Erase Application Sector(s).

  3. Receive New Firmware (via UART/USB/CAN).

  4. Write to Application Flash.

  5. Jump to Application.

Example (UART Bootloader - Pseudocode):

c

#include "stm32f1xx_hal.h"

#define APP_ADDRESS 0x08004000  // Start of application

void JumpToApp(void) {
    void (*app_reset_handler)(void);
    uint32_t *app_stack_ptr = (uint32_t *)APP_ADDRESS;
    
    // Disable interrupts
    __disable_irq();
    
    // Set new stack pointer
    __set_MSP(*app_stack_ptr);
    
    // Set reset handler
    app_reset_handler = (void (*)(void))*(uint32_t *)(APP_ADDRESS + 4);
    
    // Jump to application
    app_reset_handler();
}

int main(void) {
    HAL_Init();
    UART_Init();  // Configure UART
    
    // Check for firmware update (e.g., UART 'U' command)
    if (UART_Receive() == 'U') {
        Flash_Erase(APP_ADDRESS);
        Flash_Write(APP_ADDRESS, new_firmware_data);
    }
    
    // If no update, jump to application
    if (*(uint32_t *)APP_ADDRESS != 0xFFFFFFFF) {
        JumpToApp();
    }
    
    while (1);  // Stay in bootloader if no app
}

(3) Modify the Application

The application firmware must:

  1. Relocate Vector Table (in main.c):

    c

    SCB->VTOR = 0x08004000;  // Set Vector Table Offset
  2. Adjust Linker Script (ensure it starts at 0x08004000).

  3. Compile with Correct Flash Offset.

(4) Flash the Bootloader

  • Use ST-Link (STM32CubeProgrammer or OpenOCD).

  • Flash the bootloader to 0x08000000.

(5) Test Firmware Update

  1. Generate a .bin or .hex file of your application.

  2. Send it via UART (e.g., using pySerial or STM32CubeProgrammer).

  3. Bootloader writes it to 0x08004000.

  4. Reset → Jump to Application.


4. Communication Protocols

MethodProsCons
UARTSimple, widely supportedSlow, requires external tool
USB DFUNo extra hardwareComplex setup
CANRobust (automotive use)Needs CAN transceiver
I2C/SPIGood for multi-device systemsSlower than UART

5. Advanced Features

  • CRC Checksum Verification (ensure firmware integrity).

  • Dual-Bank Flash (STM32F7/H7) for safe updates.

  • Encrypted Firmware (secure boot).

  • Watchdog Timer (recover from failed updates).


6. Debugging Tips

  • Verify Flash writes (read back and compare).

  • Check VTOR (application crashes if vector table is wrong).

  • Use __disable_irq() before jumping to the app.


7. Example Tools

  • STM32CubeProgrammer (USB/UART flashing).

  • OpenOCD (for custom bootloaders).

  • Python Scripts (for UART firmware upload).


Conclusion

basic UART bootloader can be implemented in <100 lines of code. For production use, consider:

  • STM32’s built-in DFU bootloader (via USB).

  • Secure bootloaders (trusted firmware updates).

评论

此博客中的热门博文

Detailed Explanation of STM32 HAL Library Clock System

How to remove write protection of STM32 chip?

The automatic white balance algorithm of Raspberry Pi