/** * @file stk500v1.h * @brief STK500v1 protocol implementation for flashing ATmega328P via optiboot. * * Communicates with Arduino's optiboot bootloader over USB CDC using the * STK500v1 command set (verified against avrdude stk500.c + optiboot.c): * - get_sync (0x30 0x20) -> 0x14 0x10 * - get_signature (0x75 0x20) -> 0x14 1E 95 0F 0x10 * - enter_progmode (0x50 0x20) -> 0x14 0x10 * - load_address (0x55 lo hi 0x20) -> 0x14 0x10 (word address, LE) * - prog_page (0x64 len_hi len_lo 'F' data[] 0x20) -> 0x14 0x10 * - leave_progmode (0x51 0x20) -> 0x14 (optiboot WDT-resets, OK optional) * * Every command is terminated with CRC_EOP=0x20. optiboot replies with * STK_INSYNC=0x14 immediately, then payload, then STK_OK=0x10. */ #pragma once #include #include /* STK500v1 command bytes (from Atmel AVR061 command.h, matches optiboot) */ #define STK_CRC_EOP 0x20 /* End-of-packet sentinel */ #define STK_GET_SYNC 0x30 /* Echos sync, establishes comms */ #define STK_ENTER_PROGMODE 0x50 /* Enter programming mode */ #define STK_LEAVE_PROGMODE 0x51 /* Leave programming mode */ #define STK_LOAD_ADDRESS 0x55 /* Load address (word addr, LE) */ #define STK_PROG_PAGE 0x64 /* Program flash page */ #define STK_READ_PAGE 0x74 /* Read flash page (verify) */ #define STK_READ_SIGN 0x75 /* Read device signature bytes */ /* STK500v1 response bytes */ #define STK_INSYNC 0x14 /* Command accepted */ #define STK_OK 0x10 /* Command completed */ #define STK_NOSYNC 0x15 /* Lost sync */ /* ATmega328P device constants */ #define ATMEGA328P_SIG_0 0x1E #define ATMEGA328P_SIG_1 0x95 #define ATMEGA328P_SIG_2 0x0F #define ATMEGA328P_FLASH_SIZE 32768 /* bytes */ #define ATMEGA328P_PAGE_SIZE 128 /* bytes */ /* Timing / retries */ #define STK_SYNC_RETRIES 20 /* was 10 — give cold-boot optiboot more chances */ #define STK_CMD_TIMEOUT_MS 250 /* was 200 — slightly more per-attempt slack */ #define STK_PAGE_TIMEOUT_MS 500 /* prog_page timeout (page write ~4ms) */ #define STK_LEAVE_TIMEOUT_MS 100 /* leave_progmode (OK may be absent) */ /** * @brief Initialise the STK500v1 layer (no USB work — just logging). * @return true always */ bool stk500v1_init(void); /** * @brief Program a raw binary image into ATmega328P flash via optiboot STK500v1. * * Performs: auto-reset (DTR pulse) -> get_sync -> get_signature -> enter_progmode * -> loop (load_address + prog_page) -> leave_progmode. * Blocks the calling task for the full flash duration (~8s for 32KB). * The caller MUST have claimed USB RX first (usb_host_rx_claim()). * * @param buffer Raw binary flash image (must be <= 32768 bytes) * @param size Size in bytes * @param page_size Page size (typically 128 for ATmega328P) * @return true if all pages written & signature verified */ bool stk500v1_flash_buffer(const uint8_t *buffer, size_t size, uint16_t page_size);