This Rust CLI tool flashes the Francor Frankly-Bootloader to blank microcontrollers, enabling them to receive firmware updates via the Frankly update tool.
- ELF Processing: Parses bootloader ELF files and modifies device identification data
- Hardware Programming: Uses probe-rs for reliable STM32 chip programming
- Safe Operations: Detects existing device data on-chip and in ELF files, with interactive prompts for overwrite confirmation
- Smart Device Management: Option to preserve existing device identification or flash with current data
- Automatic Production Mode: Continuous monitoring and auto-flashing for production environments
- Testing Support: Comprehensive dry-run mode for testing without hardware
- Production Ready: Automatic production date calculation and validation
cargo build --releasePrograms a bootloader ELF file to a target microcontroller:
frankly-bootflash flash --chip <CHIP> --elf-file <FILE> --vendor-id <ID> --product-id <ID> [OPTIONS]Required Arguments:
--chip <CHIP>: Target chip name for probe-rs (e.g., STM32F103C8)--elf-file <FILE>: ELF file containing the bootloader--vendor-id <ID>: 32-bit unsigned vendor identifier (decimal or hex with 0x prefix)--product-id <ID>: 32-bit unsigned product identifier (decimal or hex with 0x prefix)
Optional Arguments:
--device-ident-variable <VAR>: Device identification variable name (default:__DEVICE_IDENT__)--dry-run: Simulate all operations without actual flashing--verbose/-v: Enable detailed progress information and step-by-step output--overwrite-identification: Automatically overwrite existing device identification without prompting--keep-identification: Keep existing device identification and flash bootloader unchanged without prompting
Note: The --overwrite-identification and --keep-identification flags are mutually exclusive.
Example:
# Flash to real hardware (using hex values)
frankly-bootflash flash --chip STM32F103C8 --elf-file bootloader.elf --vendor-id 0x12345678 --product-id 0x87654321
# Flash to real hardware (using decimal values)
frankly-bootflash flash --chip STM32F103C8 --elf-file bootloader.elf --vendor-id 305419896 --product-id 2271560481
# Test without hardware (dry-run with hex values)
frankly-bootflash flash --chip STM32F103C8 --elf-file bootloader.elf --vendor-id 0x12345678 --product-id 0x87654321 --dry-run
# Verbose output for detailed information and step-by-step progress
frankly-bootflash flash --chip STM32F103C8 --elf-file bootloader.elf --vendor-id 0x12345678 --product-id 0x87654321 --verbose
# Real hardware example with STM32G431RB (tested configuration)
frankly-bootflash flash --chip STM32G431RB --elf-file data/franklyboot_nucleo_g431rb.elf --vendor-id 0x11111111 --product-id 0x22222222 --verbose
# Automatically overwrite existing device identification without prompting
frankly-bootflash flash --chip STM32G431RB --elf-file bootloader.elf --vendor-id 0x12345678 --product-id 0x87654321 --overwrite-identification
# Keep existing device identification and flash bootloader without prompting
frankly-bootflash flash --chip STM32G431RB --elf-file bootloader.elf --vendor-id 0x12345678 --product-id 0x87654321 --keep-identificationCreates a sample ELF file for testing purposes:
frankly-bootflash create-sample-elf --output <FILE>Example:
frankly-bootflash create-sample-elf --output test_bootloader.elfContinuously monitors for new hardware connections and automatically flashes them:
frankly-bootflash auto --chip <CHIP> --elf-file <FILE> --vendor-id <ID> --product-id <ID> [OPTIONS]Required Arguments:
--chip <CHIP>: Target chip name for probe-rs--elf-file <FILE>: ELF file containing the bootloader--vendor-id <ID>: 32-bit vendor identifier (supports hex with 0x prefix or decimal)--product-id <ID>: 32-bit product identifier (supports hex with 0x prefix or decimal)
Optional Arguments:
--device-ident-variable <VAR>: Device identification variable name (default:__DEVICE_IDENT__)--verbose/-v: Enable detailed progress output--poll-interval <SECONDS>: Poll interval for checking new hardware (default: 2 seconds)
Features:
- ✅ Automatic device detection and flashing
- ✅ Skips devices already programmed with matching vendor/product IDs
- ✅ Updates production date for each device automatically
- ✅ Continuous monitoring with configurable poll interval
- ✅ Production-ready with minimal console output
Examples:
# Production mode with minimal output
frankly-bootflash auto --chip STM32G431RB --elf-file bootloader.elf --vendor-id 0x12345678 --product-id 0x87654321
# Verbose monitoring with custom poll interval
frankly-bootflash auto --chip STM32F103C8 --elf-file bootloader.elf --vendor-id 305419896 --product-id 2271560481 --verbose --poll-interval 5
# Stop with Ctrl+CProvides selective or complete flash memory erase capabilities:
frankly-bootflash erase --chip <CHIP> [--elf-file <FILE> | --all] [OPTIONS]Required Arguments:
--chip <CHIP>: Target chip name for probe-rs- One of the following:
--elf-file <FILE>: ELF file to determine bootloader sections to erase (selective erase)--all: Erase all flash memory on the chip (complete erase)
Optional Arguments:
--verbose/-v: Enable detailed progress output--dry-run: Show what would be erased without actually erasing
Erase Modes:
-
Selective Erase (
--elf-file): Erases only the sections defined in the ELF file- Preserves application areas not covered by the bootloader
- Device identification may be preserved if not in bootloader sections
- Safer for partial updates
-
Complete Erase (
--all): Erases all flash memory on the chip- Completely blanks the entire flash memory
- Removes all data including device identification
- Prepares chip for fresh programming
Examples:
# Selective erase - only bootloader sections
frankly-bootflash erase --chip STM32G431RB --elf-file bootloader.elf --verbose
# Complete chip erase
frankly-bootflash erase --chip STM32G431RB --all --verbose
# Test selective erase without actually erasing
frankly-bootflash erase --chip STM32G431RB --elf-file bootloader.elf --dry-run --verbose
# Test complete erase without actually erasing
frankly-bootflash erase --chip STM32F103C8 --all --dry-run
# Simple complete erase with minimal output
frankly-bootflash erase --chip STM32F103C8 --all- Selective Erase: Only erases bootloader sections, application areas remain intact
- Complete Erase: Permanently erases ALL data on the chip including device identification, application code, and configuration data
Use selective erase for bootloader updates and complete erase to prepare chips for fresh programming or recover from corrupted flash states.
The tool includes comprehensive testing capabilities that don't require physical hardware:
-
Create a test ELF file:
frankly-bootflash create-sample-elf --output test.elf
-
Run in dry-run mode:
frankly-bootflash flash --chip STM32F103C8 --elf-file test.elf --vendor-id 0x12345678 --product-id 0x87654321 --dry-run
The dry-run mode validates:
- ELF file parsing and section identification
- Device identification data modification
- Production date calculation
- All error handling and user interactions
The tool manages device identification through a comprehensive multi-step process:
Parses the bootloader ELF file and locates the ._dev_ident section containing the device identification array.
Connects to the target microcontroller and reads existing device identification data from flash memory.
If device identification already exists on the chip, the tool provides three modes of operation:
- First Prompt: "Device identification already exists on chip. Overwrite? (y/N)"
- Yes: Proceeds to overwrite with new vendor/product IDs
- No: Presents second option
- Second Prompt: "Flash bootloader with existing device identification? (y/N)"
- Yes: Flashes bootloader while preserving existing device data
- No: Cancels operation safely
--overwrite-identification: Automatically overwrites existing device identification without prompting--keep-identification: Automatically preserves existing device identification without prompting
These automated modes enable unattended operation in production environments.
The device identification array contains:
- Vendor ID: 32-bit identifier provided via command line
- Product ID: 32-bit identifier provided via command line
- Production Date: Automatically calculated as seconds since January 1, 2020
- Unused: Reserved field (set to 0xFFFFFFFF)
Programs the modified bootloader to the target microcontroller and resets the device.
The bootloader must contain an uninitialized device identification array:
Requirement for the bootloader-application, how the device identification has to look like:
/**
* Device identification index
*/
enum DeviceIdentIdx {
DEV_IDENT_VENDOR_ID = 0U,
DEV_IDENT_PRODUCT_ID = 1U,
DEV_IDENT_PRODUCTION_DATE = 2U,
};
/*
* This array contains the device identification information, which is stored in a extra section in the flash
* memory. The default value is 0xFFFFFFFFU for uninitialized flash.
* The data is written during the flash process.
*/
#pragma pack(push, 1)
volatile uint32_t __DEVICE_IDENT__[4U]
__attribute__((section("._dev_ident"))) = {0xFFFFFFFFU, 0xFFFFFFFFU, 0xFFFFFFFFU, 0xFFFFFFFFU};
#pragma pack(pop)# Build for development
cargo build
# Build for release
cargo build --release
# Run tests
cargo test
# Check code without building
cargo check
# Format code
cargo fmt
# Lint code
cargo clippyThe tool is built with a modular Rust architecture:
- CLI Module: Command-line argument parsing with
clap - ELF Processor: ELF file parsing and modification using
goblin - Device Identification: Data structures and production date calculation
- Flasher: probe-rs integration for hardware programming
- Test Utils: Sample ELF generation for testing
clapv4.4 - CLI argument parsinggoblinv0.10 - ELF file manipulationprobe-rsv0.25 - Microcontroller programminganyhowv1.0 - Error handlingchronov0.4 - Date/time calculationstempfilev3.0 - Temporary file handling
- Primary Target: STM32 microcontrollers
- Debug Probes: All probe-rs supported debuggers (ST-Link, J-Link, DAPLink, etc.)
- Programming Interface: SWD/JTAG via probe-rs