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).

评论

此博客中的热门博文

How To Connect Stm32 To PC?

What are the common HDL languages used in FPGA design?

How do you set up ADC (Analog-to-Digital Converter) in STM32?