A professional UART-based bootloader for STM32F407VGT6 microcontroller with full flash management, memory operations, and protection features. Includes a Python host application for easy firmware updates and system control.
- STM32F407xx Custom Bootloader
- π Table of Contents
- β¨ Features
- π§ Hardware Requirements
- π Project Structure
- π Getting Started
- π¨ Building the Project
- π₯ Flashing the Bootloader
- π Bootloader Commands
- π Protocol Specification
- π₯οΈ Using the Python Host
- πΎ Memory Layout
- π Additional Resources
- π§ Contact
- π Future Enhancements & Roadmap
- UART Communication: 115200 baud, 8-N-1 format
- CRC-32 Protection: Hardware CRC-32/MPEG-2 for data integrity
- 13 Bootloader Commands: Complete flash management and system control
- Flash Operations: Erase, write, read with sector-level control
- Memory Protection: Read/Write protection configuration
- Address Validation: Safe memory access with bounds checking
- Version Management: Bootloader version tracking
- Jump to Application: Seamless transition to user firmware
- Cross-Platform: Python 3.8+ (Windows, Linux, macOS)
- Interactive CLI: Easy-to-use command-line interface
- Automatic Timeout: Dynamic timeout calculation for flash operations
- Binary Upload: Flash firmware directly from .bin files
- Memory Operations: Read/Write/Verify memory regions
- Protection Management: Configure sector write protection
- Debug Output: Comprehensive logging for troubleshooting
- MCU: STM32F407VGT6 (Cortex-M4, 1MB Flash, 192KB RAM)
- Board: STM32F407 Discovery or compatible
- Debugger: ST-LINK/V2 or compatible (for initial bootloader flash)
- UART Interface: USB-to-Serial adapter (FTDI, CP2102, etc.)
- Connections:
- USART2_TX β PA2
- USART2_RX β PA3
- GND β Common ground
- User Button (B1) β PA0 (bootloader entry)
bootloader_stm32f407xx/
βββ Core/
β βββ Inc/
β β βββ bootloader_comm.h # UART & CRC communication
β β βββ bootloader_core.h # Command processing
β β βββ bootloader_flash.h # Flash operations
β β βββ bootloader_utils.h # Utilities & debug
β β βββ system_init.h # System initialization
β β βββ main.h # Main header
β β βββ stm32f4xx_hal_conf.h # HAL configuration
β β βββ stm32f4xx_it.h # Interrupt handlers
β βββ Src/
β β βββ bootloader_comm.c # Communication implementation
β β βββ bootloader_core.c # Command handlers (641 lines)
β β βββ bootloader_flash.c # Flash operations (485 lines)
β β βββ bootloader_utils.c # Utility functions
β β βββ system_init.c # Peripheral initialization
β β βββ main.c # Application entry point
β β βββ stm32f4xx_hal_msp.c # HAL MSP initialization
β β βββ stm32f4xx_it.c # Interrupt service routines
β β βββ system_stm32f4xx.c # System clock configuration
β βββ Startup/
β βββ startup_stm32f407vgtx.s # Startup code
βββ Drivers/
β βββ STM32F4xx_HAL_Driver/ # STM32 HAL library
β βββ CMSIS/ # ARM CMSIS headers
βββ Host/
β βββ bootloader_stm32f407xx_host.py # Python host application
β βββ README.md # Host usage guide
β βββ testfile/
β βββ file2write.txt # Test data
βββ Debug/ # Build output directory
βββ PROTOCOL.md # Detailed protocol documentation
βββ STM32F407VGTX_FLASH.ld # Flash linker script
βββ STM32F407VGTX_RAM.ld # RAM linker script
βββ bootloader_stm32f407xx.ioc # STM32CubeMX project
βββ README.md # This file
For Firmware Development:
- STM32CubeIDE Version: 1.17.0
- GNU ARM Embedded Toolchain
- STM32CubeMX (optional, for hardware configuration)
- STM32CubeProgrammer (for flashing)
For Host Application:
- Python 3.8 or later
- PySerial library
- Clone the repository:
git clone https://github.com/dchithinh/stm32f407xx_bootloader.git
cd stm32f407xx_bootloader- Install Python dependencies:
python -m pip install --upgrade pip
python -m pip install pyserial- Open project in STM32CubeIDE:
- File β Open Projects from File System
- Select
bootloader_stm32f407xxfolder - Build the project (Ctrl+B)
-
Open the project:
- File β Open Projects from File System
- Select
bootloader_stm32f407xxfolder
-
Build:
- Right-click project β Build Project
- Or press Ctrl+B
- Binary output:
Debug/bootloader_stm32f407xx.elf
-
Clean build (recommended after changes):
- Right-click project β Clean Project
- Then build again
- Connect ST-LINK debugger to board
- Right-click project β Debug As β STM32 C/C++ Application
- Or use Run β Run/Debug configurations
- Reset the board
- Press and hold User Button (B1)
- Connect UART adapter to PA2/PA3
- Open serial terminal (115200 8-N-1)
- Release button - should see bootloader messages in debug logs
The bootloader supports 13 commands for comprehensive system control:
| Command Code | Name | Description |
|---|---|---|
| 0x51 | GET_VER | Get bootloader version |
| 0x52 | GET_HELP | Get list of supported commands |
| 0x53 | GET_CID | Get chip identification number |
| 0x54 | GET_RDP_STATUS | Get Read Protection level |
| 0x55 | GO_TO_ADDR | Jump to specified address |
| 0x56 | FLASH_ERASE | Erase flash sectors |
| 0x57 | MEM_WRITE | Write to memory (Flash/SRAM) |
| 0x58 | EN_RW_PROTECT | Enable read/write protection |
| 0x59 | MEM_READ | Read from memory |
| 0x5A | READ_SECTOR_STATUS | Get sector protection status |
| 0x5B | OTP_READ | Read OTP memory (not implemented) |
For detailed packet formats and protocol specifications, see PROTOCOL.md.
For complete protocol details, see PROTOCOL.md.
python .\bootloader_stm32f407xx_host.py --help
usage: bootloader_stm32f407xx_host.py [-h] [--port PORT] [--baud BAUD] [--timeout TIMEOUT] [--quiet]
{ports,get-ver,get-help,get-cid,get-rdp,go,erase,write,mem-read,prot-enable,prot-status,prot-disable,otp-read,send-unsupported} ...
STM32F4 Bootloader Host (Python 3)
positional arguments:
{ports,get-ver,get-help,get-cid,get-rdp,go,erase,write,mem-read,prot-enable,prot-status,prot-disable,otp-read,send-unsupported}
ports List available serial ports
get-ver Get bootloader version
get-help Get supported commands
get-cid Get chip ID
get-rdp Get RDP status
go Jump to address
erase Erase flash sector(s) or mass erase
write Write binary to memory
mem-read Read memory region
prot-enable Enable write protection
prot-status Read sector protection status
prot-disable Disable write protection (if supported)
otp-read Read OTP (likely unsupported)
send-unsupported Send an intentionally unsupported command
options:
-h, --help show this help message and exit
--port PORT Serial port (e.g., COM3)
--baud BAUD Baud rate
--timeout TIMEOUT Serial timeout seconds
--quiet Reduce logging
python Host/bootloader_stm32f407xx_host.py portspython Host/bootloader_stm32f407xx_host.py --port COM3 get-verpython Host/bootloader_stm32f407xx_host.py --port COM3 get-cid# Erase sectors 2-6 (user application area)
python Host/bootloader_stm32f407xx_host.py --port COM3 flash-erase 2 5# Write user application starting at sector 2 (0x08008000)
python Host/bootloader_stm32f407xx_host.py --port COM3 mem-write 0x08008000 Host/testfile/user_app_stm32f407xx.bin# Read 256 bytes from address 0x08008000
python Host/bootloader_stm32f407xx_host.py --port COM3 mem-read 0x08008000 256python Host/bootloader_stm32f407xx_host.py --port COM3 prot-statuspython Host/bootloader_stm32f407xx_host.py --port COM3 go 0x08008000For complete host documentation, see Host/README.md.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 0x08000000 - 0x08003FFF Sector 0 (16 KB) Bootloader β
β 0x08004000 - 0x08007FFF Sector 1 (16 KB) Bootloader β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 0x08008000 - 0x0800BFFF Sector 2 (16 KB) User App β
β 0x0800C000 - 0x0800FFFF Sector 3 (16 KB) User App β
β 0x08010000 - 0x0801FFFF Sector 4 (64 KB) User App β
β 0x08020000 - 0x0803FFFF Sector 5 (128 KB) User App β
β 0x08040000 - 0x0805FFFF Sector 6 (128 KB) User App β
β 0x08060000 - 0x0807FFFF Sector 7 (128 KB) User App β
β 0x08080000 - 0x0809FFFF Sector 8 (128 KB) User App β
β 0x080A0000 - 0x080BFFFF Sector 9 (128 KB) User App β
β 0x080C0000 - 0x080DFFFF Sector 10 (128 KB) User App β
β 0x080E0000 - 0x080FFFFF Sector 11 (128 KB) User App β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- SRAM1: 0x20000000 - 0x2001BFFF (112 KB)
- SRAM2: 0x2001C000 - 0x2001FFFF (16 KB)
- CCM RAM: 0x10000000 - 0x1000FFFF (64 KB) - Core-coupled memory
- Bootloader Start: 0x08000000
- User App Start: 0x08008000 (Sector 2)
- User App Vector Table: Must be at 0x08008000
- Bootloader occupies: Sectors 0-1 (32 KB)
- User App available: Sectors 2-11 (992 KB)
The bootloader uses a function pointer table for command dispatch, making it easy to add new commands without modifying the switch statement or exposing handler prototypes.
Simple 3-step process:
-
Define command code in
Core/Inc/bootloader_core.h:#define BL_CMD_NEW_FEATURE 0x5C
-
Implement handler function in
Core/Src/bootloader_core.c:/** * @brief Handle NEW_FEATURE command * @param buffer Pointer to received packet buffer * @retval None */ static void BL_HandleNewFeatureCmd(uint8_t *buffer) { uint32_t packet_len = PACKET_LENGTH(buffer); uint32_t crc_host = CRC_FROM_PACKET(buffer); BL_PrintMessage("BL_CMD_NEW_FEATURE command\n"); if (BL_VerifyCRC(&buffer[0], packet_len - 4, crc_host) == VERIFY_CRC_SUCCESS) { BL_PrintMessage("CRC: PASS\n"); BL_UART_SendAck(buffer[1], 1); // Your command implementation here uint8_t result = 0x00; // success BL_UART_WriteData(&result, 1); } else { BL_PrintMessage("CRC: FAIL\n"); BL_UART_SendNack(); } }
-
Add entry to command table in
Core/Src/bootloader_core.c:/* Command table - maps command codes to handler functions */ static const BL_CommandEntry_t bl_command_table[] = { { BL_CMD_GET_VER, BL_HandleGetVersionCmd, "GET_VER" }, { BL_CMD_GET_HELP, BL_HandleGetHelpCmd, "GET_HELP" }, // ... existing commands ... { BL_CMD_OTP_READ, BL_HandleOTPReadCmd, "OTP_READ" }, { BL_CMD_NEW_FEATURE, BL_HandleNewFeatureCmd, "NEW_FEATURE" } // β Add here };
That's it! The command is automatically:
- Added to the supported commands list (GET_HELP response)
- Registered in the dispatch system
- Logged with its name when executed
Update host bootloader to support new CMD:
- Update Python host in
Host/bootloader_stm32f407xx_host.pyto add client support - Document the protocol in
PROTOCOL.md
Enable Debug Messages:
Set in bootloader_utils.h:
#define BL_DEBUG_MSG_EN 1View Debug Output:
- Uses SWO (Serial Wire Output) via ITM (default in this project)
- Configure in debug configuration: 16 MHz SYSCLK
- View in STM32CubeIDE: Window β Show View β SWV β ITM Data Console
Quick: see BL_PrintMessage logs
- Ensure
BL_DEBUG_MSG_ENis set to1inCore/Inc/bootloader_utils.h(default). - Debug the board with STβLINK and SWO connected.
- In SWV ITM Data Console: set Core Clock to your SYSCLK (default 16 MHz HSI), tick "Stimulus Port 0", click "Start Trace".
- All
BL_PrintMessage("...")output will appear in the ITM console.
Also available: UART debug mirroring (optional)
BL_PrintMessagealso mirrors the same text over UART3 usingHAL_UART_Transmit()if UART3 is initialized.- To use it, ensure
MX_USART3_UART_Init()is implemented and called during startup, and wire UART3 TX/RX to your USBβUART adaptor. - Typical STM32F407 ALT mappings for USART3 are PB10/PB11 or PC10/PC11 (AF7) β check your board/ioc for the exact pins.
- Caution: Do NOT reuse USART2 for debug β it is used by the bootloader protocol and mixing logs with protocol bytes will break communication.
Repository: github.com/dchithinh/stm32f407xx_bootloader
This section outlines potential features and improvements for production deployment and enhanced functionality.
- Cross-platform desktop GUI (PyQt5/PyQt6 or Tkinter)
- Visual COM port selection with auto-detection
- Drag-and-drop firmware file upload
- Real-time progress bars for flash operations
- Memory map visualization (bootloader/application regions)
- Flash sector status display with visual indicators
- Read/Write protection configuration interface
- Device information panel (version, chip ID, RDP status)
- Color-coded log console with filtering
- Firmware verification post-upload
- Smartphone-based firmware updates (Flutter/React Native)
- Bluetooth Low Energy (BLE) connectivity
- QR code scanning for device pairing
- OTA update management
- Update history and rollback options
- Push notifications for update availability
- Browser-based interface (Web Serial API)
- No installation required
- Multi-device management
- Cloud-based firmware repository
- Analytics and telemetry visualization
- Digital signature verification (ECDSA/RSA)
- Cryptographic verification before flashing
- Public key stored in bootloader OTP
- Prevents unauthorized firmware uploads
- Integration with mbedTLS or WolfSSL
- AES-256 encrypted firmware images
- Host encrypts
.binfiles before transmission - Bootloader decrypts on-the-fly during flashing
- Protects intellectual property during transit
- Host encrypts
- Hash-based firmware integrity
- SHA-256 hash verification of entire firmware
- Hash stored in firmware header
- Validation before jumping to application
- Version monotonicity enforcement
- Firmware version tracking in flash
- Prevent downgrade to vulnerable versions
- Anti-rollback counter in OTP memory
- Password-protected bootloader access
- Authentication required for sensitive commands
- Brute-force protection with lockout
- Audit logging of access attempts
- Failsafe firmware updates
- Two independent application partitions (Bank A & B)
- Update inactive bank while running from active
- Atomic bank swap on successful update
- Automatic rollback on boot failure or CRC mismatch
- Critical for remote/inaccessible devices
- Continuous runtime validation
- Periodic CRC checks of application flash
- Detection of flash corruption or bit flips
- Automatic recovery from backup partition
- Automatic fault recovery
- Independent watchdog during updates
- Auto-reboot to bootloader if application hangs
- Configurable retry limits before failsafe mode
- Safe flash operations during brownout
- Transaction-based flash writes
- State machine for resumable operations
- Battery backup or supercapacitor monitoring
-
Bluetooth Low Energy (BLE)
- Nordic UART Service (NUS) or custom GATT
- Chunk-based transfer with acknowledgments
- Mobile app integration (iOS/Android)
-
WiFi (ESP8266/ESP32 co-processor)
- HTTP/HTTPS firmware download
- MQTT-based update notifications
- Web-based configuration portal
-
LoRa/LoRaWAN
- Long-range updates for IoT deployments
- Low-power wide-area network (LPWAN)
- Firmware delta updates to reduce bandwidth
-
Cellular (4G/5G LTE modules)
- Cloud-connected update server
- Remote device management
- Scheduled update campaigns
-
USB DFU (Device Firmware Update)
- Standard USB class for firmware updates
- Tool-less updates on USB connection
- Compatible with dfu-util and STM32CubeProgrammer
-
CAN Bus
- Automotive and industrial applications
- ISO-TP protocol for large data transfer
- Multi-node bootloader network
-
Ethernet
- TFTP or HTTP-based updates
- Industrial automation integration
- PXE-style network boot
-
SPI/I2C
- MCU-to-MCU firmware updates
- Master device programs slave MCUs
- Daisy-chain update propagation
- LZ4/LZMA decompression
- 30-50% smaller transfer sizes
- Host compresses
.binbefore sending - Bootloader decompresses to flash
- Reduces update time and bandwidth costs
- Binary diff patching (bsdiff/courgette)
- Transfer only changed bytes
- 70-90% size reduction for minor updates
- Faster updates over slow networks
- Multi-sector erase/write
- Leverage STM32 dual-bank architecture
- Background flash operations
- Interrupt-driven DMA transfers
- Multiple user applications in flash
- Application selection menu in bootloader
- Factory reset partition (golden image)
- A/B testing of firmware versions
- SPI/QSPI flash integration (W25Q128, etc.)
- Overflow storage for large applications
- Staging area for firmware downloads
- Extended logging and configuration storage
- Persistent device configuration
- Backup/restore settings to OTP or dedicated flash sector
- Factory default restoration
- Configuration migration across firmware versions
- Erase cycle tracking per sector
- Predictive maintenance alerts
- Wear leveling recommendations
- Bad block marking and remapping
- Telemetry and health monitoring
- Boot reason detection (power-on, watchdog, brownout)
- Flash operation metrics (time, success rate)
- Error logging in circular buffer
- Remote debug log retrieval
- One-click production flashing
- Combined bootloader + firmware + configuration
- Serial number injection
- Calibration data programming
- Manufacturing test automation
- Metadata bundling
- Version information
- Build timestamp and Git commit hash
- Digital signature generation
- Release notes embedding
- CI/CD integration
- GitHub Actions for build automation
- Pytest-based command testing
- Hardware-in-the-loop (HIL) testing
- Regression test suite for all commands
- QEMU-based bootloader testing
- Test protocol without hardware
- Fuzzing for robustness testing
- Performance profiling
- Fleet-wide firmware deployment
- Staged rollout (5% β 25% β 100%)
- Rollback on failure threshold
- Update success rate tracking
- Usage statistics collection
- Firmware version distribution
- Update failure root cause analysis
- Device health scoring