- boot_usart: bare-metal USART1 460800, polled TX, 3KB DMA ring RX, SysTick millis
- boot_cli: polled line editor + mini printf + command subset; wire-compatible
with the app UART CLI (prompt/devinfo cur bank/ota marker) so
ble_ota_update.py --uart works unchanged against the bootloader
- share app_ota.c/app_bootset.c into the Boot build via BOOT_FIRMWARE ifdef
(single OTA engine source); frame constants moved to shared Boot/src/ota_wire.h
- entry: 2s Enter window after the boot banner, or forced when no jumpable
image (invalid bootsetting + APP1 vector sanity fail) - brick recovery path
- OTA target in boot = inactive bank per bootsetting (APP1 when invalid)
- merge_image.py: hard-fail when boot bin exceeds the 16KB region
- APP V1.00.28 (shared-source touch only, behavior unchanged)
- tested: normal boot / download CLI / OTA APP1<->APP2 round trip / bricked
recovery (bootsetting+APP1 sector erased -> forced download -> OTA restore)
- docs: dev log sec.52, ble_protocol sec.6.8, AGENTS.md
- firmware BSP_USART_BAUDRATE 460800 (divider error +0.03%); uartrst/
uartinfo follow the macro
- RX DMA ring 2KB -> 3KB: at 460800 2KB only covers 44ms, less than the
~45ms flash-erase interrupt-off window; stack top now 0x2000BDE8
(guard warns <1KB from the 0x2000C000 cliff, by design)
- tools: ble_ota_update.py UartTransport and uart_cap.py default baud
- Verified: stream OTA 55832B in 2.6s @23kB/s (one lost frame recovered
by go-back-N), PASS after reboot; text CLI fine at 460800
- docs: ble_protocol.md, design spec, AGENTS.md, dev log section 48
Firmware:
- bsp_usart: RX moved from RXDNE byte-queue IRQ to DMA CH2 circular ring
(2KB) + IDLE-irq wakeup; bytes keep landing during flash-erase
interrupt-off windows (the reason lockstep was needed before)
- app_ota: stream mode (ble_protocol.md section 6.7) - 16B BEGIN with
flags bit0=STREAM (UART channel only), DATA acked on 4KB sector
crossings (original chunk length; two ack-gating bugs fixed during
field test), throttled BAD_STATE for go-back-N
- FreeRTOS heap 20KB->18KB: the 2KB ring pushed the stack top past the
0x2000C000 SRAM cliff (probed via SWD: accesses above fault on this
silicon, usable app SRAM is 32KB) which locked the board at boot;
merge_image.py now hard-fails the package when the image initial SP
leaves (0x20004000, 0x2000C000]
Tools:
- ble_ota_update.py: UART stream sender (8KB window, stall watchdog
rewind, auto-fallback to lockstep on pre-V1.00.24 firmware,
--lockstep to force); case-insensitive option parsing
- flash_package.py/bat: stream NSpyocd output live (chunked reads keep
the \r progress bar), vendor banner rebranded to CAIIC NSLINK UMP
- merge_image.py: initial-SP cliff guard
Verified: UART stream OTA both directions, 55.8KB in ~5.9s @9.5kB/s
0 rewinds (lockstep was 39s), PASS after reboot; board boot fixed and
verified via SWD.
Docs: ble_protocol.md section 6.7, dev log section 47 (+ SRAM cliff
post-mortem), AGENTS.md RAM rule rewritten (both cliffs) + V1.00.25
- firmware version bump V1.00.22 -> V1.00.23 (0x00010017), no code change;
user-verified BLE OTA (APP1->APP2) and UART OTA both PASS
- ble_ota_update.py: frame-level live progress bar on tty (bar/pct/bytes/
rate/per-frame ack RTT, ~10fps throttled), 5%-step lines when redirected;
resend/resync notices no longer mix into the bar line; END summary now
reports resent/resynced counters; BEGIN/END stage banners
- docs: dev log 46, AGENTS.md sync
- firmware: version bump to V1.00.22 (0x00010016), no code change
- ble_ota_update.py: cur-bank detection now reads the full devinfo output
and parses strictly (early break at the 'cur bank:' prefix could miss
'APP2' and silently default to APP1 -> wrong payload selection, caught
by the device bank_mismatch guard on hardware)
- new pre-flight check_blob_bank(): payload vector reset PC must land in
the target bank before transferring (BLE and UART paths)
- UART path: post-reboot verification over the text CLI (bank+version),
deterministic PASS/FAIL like the BLE path
- verified: UART OTA APP2->APP1 V1.00.22 full pass with auto-verify
- docs: dev log 45, AGENTS.md sync