- 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
- UART binary mode switch mechanism: enter handshake marker '[ota] binary
mode ON', explicit exit via OTA_ABORT (immediate), 10s idle fallback
(was 3s, must exceed the host retry window); host resync by CR probe
- fix: otaIdleMs not re-armed on mode entry - every second 'ota' entry was
kicked out by an instant idle timeout (leftover count from prior session)
- lossy-link tolerance: device drops partial frames after a 100ms byte gap
so host resends re-align; OTA session is now single-owner (second BEGIN
on another channel gets BAD_STATE)
- ble_ota_update.py: wait for the enter marker instead of blind sleeps,
per-frame resend (2s x3), BAD_STATE+expected-offset treated as implicit
ack for duplicate DATA/BEGIN (resync after ack loss), stage-labeled
timeouts with raw-rx dump
- verified on hardware: UART OTA full pass (55.7KB/41s, 4-5 lost frames
auto-recovered) + BLE OTA regression pass; docs: dev log 44,
ble_protocol.md 6.6 rework, AGENTS.md sync
- app_ota.c: after END ok, wait until the RSP is consumed by the host
(BLE e0005 read-out / UART TX done) plus 300ms grace before resetting,
2s timeout fallback; polled from the BLE schedule task (rwip_schedule
must keep running for the ATT read to be processed)
- main.c: app_ota_reset_poll() in the BLE schedule task loop
- docs: ble_protocol.md 6.6 note, dev log section 43, AGENTS.md sync