rustup target add thumbv7em-none-eabihf
sudo apt-get install arm-none-eabi-binutilscd /home/ararext/update_projects/ararext-bootloader
cargo build --release# Convert to binary
arm-none-eabi-objcopy -O binary \
target/thumbv7em-none-eabihf/release/ararext-bootloader \
ararext-bootloader.bin
# Flash to device (using OpenOCD)
openocd -f interface/stlink.cfg -f target/stm32f4x.cfg \
-c "program ararext-bootloader.bin 0x08000000 verify reset exit"ararext-bootloader/
βββ src/
β βββ main.rs # Entry point and bootloader loop
β βββ constants.rs # Definitions and constants
β βββ uart.rs # UART communication
β βββ handlers.rs # Command implementations
β βββ memory.rs # Memory operations
β βββ crc.rs # CRC verification
β βββ flash.rs # Flash management
βββ Cargo.toml # Project manifest
βββ memory.x # Memory layout
βββ README.md # Full documentation
βββ BUILD.md # Build guide
βββ ARCHITECTURE.md # Design documentation
βββ COMPARISON.md # C vs Rust comparison
βββ PROJECT_SUMMARY.md # This summary
| Code | Command | Purpose |
|---|---|---|
| 0x51 | GET_VER | Get bootloader version |
| 0x52 | GET_HELP | List commands |
| 0x53 | GET_CID | Get chip ID |
| 0x54 | GET_RDP_STATUS | Get protection level |
| 0x55 | GO_TO_ADDR | Jump to address |
| 0x56 | FLASH_ERASE | Erase sectors |
| 0x57 | MEM_WRITE | Write memory |
| 0x58 | EN_RW_PROTECT | Enable protection |
| 0x59 | MEM_READ | Read memory |
| 0x5A | READ_SECTOR_P | Query protection |
| 0x5B | OTP_READ | Read OTP |
| 0x5C | DIS_R_W_PROTECT | Disable protection |
cargo buildcargo build --releasecargo checkcargo doc --opencargo testcargo clean- USART2: Command/Control (PA2/PA3) - 115200 bps
- USART3: Debug output (PB10/PB11) - 115200 bps
- PA0: Mode button (LOW=bootloader, HIGH=app)
- PA5: Status LED
- 0x08000000: Bootloader (Sectors 0-1)
- 0x08008000: User application (Sectors 2-7)
- Debug: ~45 KB
- Release: ~25 KB
- With LTO: ~23 KB
- Startup: ~10ms
- Command processing: <1ms
- Sector erase: ~100ms
- Byte write: ~1ms
miniterm /dev/ttyUSB0 115200
# or
screen /dev/ttyUSB0 115200# Terminal 1: Start OpenOCD
openocd -f interface/stlink.cfg -f target/stm32f4x.cfg
# Terminal 2: Debug
arm-none-eabi-gdb target/thumbv7em-none-eabihf/release/ararext-bootloader
(gdb) target remote :3333
(gdb) load
(gdb) break main
(gdb) continueβ CRC-32 verification on incoming protocol frames β Address validation before jumping β Compile-time buffer overflow prevention β Type-safe command parsing β Unsupported operations fail closed with NACK
| Document | Purpose |
|---|---|
| README.md | Overview & features |
| BUILD.md | Build & flashing guide |
| ARCHITECTURE.md | Design details |
| COMPARISON.md | C vs Rust analysis |
| PROJECT_SUMMARY.md | High-level summary |
Edit .cargo/config.toml:
target = "thumbv7em-none-eabihf" # Keep for F407In main.rs:
let clocks = rcc.cfgr
.use_hse(8.mhz())
.sysclk(84.mhz()) // Change here
.freeze();- Add command code to
constants.rs - Create handler in
handlers.rs - Add dispatch case in
main.rsbootloader_loop
| Issue | Solution |
|---|---|
| "linker 'arm-none-eabi-gcc' not found" | sudo apt-get install arm-none-eabi-binutils |
| "failed to find 'rust-lld'" | rustup component add rust-src |
| Flash write fails | Run BL_DIS_R_W_PROTECT (0x5C) first |
| GDB "connection refused" | Check OpenOCD is running |
| Serial port not found | Check device connected with lsusb |
cargo check # Just check syntax, no build
cargo check --all-targets # Include tests/examples# In Cargo.toml [profile.release]
opt-level = "z" # Size optimization
lto = true # Link-time optimization# See binary sections
arm-none-eabi-objdump -h target/thumbv7em-none-eabihf/release/ararext-bootloader
# Analyze size breakdown
cargo bloat --release# Flash multiple devices simultaneously
for device in /dev/ttyUSB*; do
st-link --write ararext-bootloader.bin 0x08000000 &
done| Metric | Value |
|---|---|
| Lines of Code | ~800 |
| Modules | 7 |
| Commands | 12 |
| Binary Size | 25 KB |
| RAM Usage | 3 KB |
| Build Time | 90s |
| Target | STM32F407xx |
| Version | Status | Notes |
|---|---|---|
| 0.1.0 | Core command protocol active; some command handlers still return NACK |
- Build passes without warnings:
cargo build --release - Binary size < 32 KB: ~25 KB
- Device flashed successfully
- Button boot into bootloader works
- Required command subset tested end-to-end (
GET_VER,GET_HELP,GET_CID,GET_RDP_STATUS,GO_TO_ADDR,MEM_READ) - CRC validation verified
- User app jumps successfully
- Serial communication verified at 115200 bps
- Start here: README.md (30 min)
- Understand: ARCHITECTURE.md (45 min)
- Compare: COMPARISON.md (30 min)
- Build: BUILD.md instructions (15 min)
- Code dive: Explore src/ modules (60+ min)
β Memory Safe: Compile-time guarantees, no unsafe surprises β Well Organized: 7 focused modules, not 1 monolithic file β Type Safe: Commands and regions are typed, not raw bytes β Better Errors: Compiler catches bugs before runtime β Documented: Comprehensive guides and inline documentation β Honest Status: Unimplemented features explicitly return NACK
- Try it: Build and flash to your device
- Explore: Review ARCHITECTURE.md
- Customize: Add your own commands
- Extend: Implement OTA updates
- Deploy: Use in your product
For detailed information, see the full documentation in README.md, BUILD.md, and ARCHITECTURE.md
Last Updated: 2026
Status: