# Bootloader — Design Decisions & TODO ## Open Design Decisions These must be resolved before implementation begins: ### 1. Firmware update interface - [ ] UART only - [ ] USB-CDC only - [ ] Both (selectable via config or auto-detect) - **Notes:** We have MCU_UART and MCU_USB in common/ ready to use via HAL_COM. ### 2. Transfer protocol - [ ] Custom simple protocol (length + CRC32 + raw binary) - [ ] XMODEM / YMODEM (standard, many terminal tools support it) - [ ] Custom framed protocol (start byte, length, payload, CRC, end byte) - **Notes:** Custom is simplest to implement. XMODEM is widely supported by serial tools. ### 3. Flash memory layout - [ ] Define bootloader size (e.g., first 16 KB, 32 KB, or 64 KB of flash) - [ ] Define application start address - [ ] Define metadata region (app version, CRC, valid flag) - **Notes:** RP2040 has 2 MB flash. Pico SDK linker script needs modification to place the bootloader and app at different addresses. ### 4. Bootloader entry trigger - [ ] Always enter bootloader, wait N seconds for firmware, then jump to app - [ ] Check a GPIO pin (button held = stay in bootloader) - [ ] Check a magic value in flash/RAM (set by the application to request update) - [ ] Combination: check button first, then magic value, then jump to app - **Notes:** "Button + timeout" is the most user-friendly approach. ### 5. Application jump mechanism - [ ] Read the app's vector table at the app start address - [ ] Set the MSP (main stack pointer) from the vector table - [ ] Jump to the reset handler from the vector table - **Notes:** Standard Cortex-M0+ boot sequence. Need to disable interrupts and peripherals before jumping. ### 6. Integrity verification - [ ] CRC32 check on the received firmware before writing to flash - [ ] CRC32 check on the stored application before jumping (boot-time validation) - [ ] Signature verification (stretch goal — not needed for initial version) ### 7. Flash write strategy - [ ] Erase + write as chunks arrive (streaming) - [ ] Buffer entire firmware in RAM, then erase + write at once (limited by RAM size) - [ ] Dual-bank: write to alternate region, swap on success (A/B update) - **Notes:** Streaming is most memory-efficient. A/B is safest (rollback on failure) but uses 2x flash. ## Implementation Tasks Once design decisions are made: - [ ] Create linker scripts (bootloader.ld, application.ld) with correct flash regions - [ ] Implement APP_BOOT_enuInit — check entry trigger, decide boot vs update mode - [ ] Implement firmware receive via HAL_COM (protocol parsing, CRC validation) - [ ] Implement flash write using Pico SDK hardware_flash API - [ ] Implement application jump (disable interrupts, set MSP, branch to reset handler) - [ ] Implement boot-time app validation (CRC check before jumping) - [ ] Modify color_switcher's linker script to start at the app address (not 0x10000000) - [ ] Test: flash bootloader, then send color_switcher firmware over UART/USB - [ ] Test: corrupt firmware scenario — bootloader should stay in update mode