feat: ESP32-S3 OTA stack — partitions, Gitea checker, self-update, UART IO, display, Orin serial trigger (6 beads) #731

Merged
sl-jetson merged 6 commits from sl-firmware/ota-esp32 into main 2026-04-17 23:11:05 -04:00
Collaborator

6 OTA beads on esp32s3/ (bd-3gwo, bd-3hte, bd-18nb, bd-21hv, bd-1yr8, bd-1s1s).

  • bd-3gwo: Dual OTA partitions 1.75MB + rollback
  • bd-3hte: WiFi + Gitea version check every 30min
  • bd-18nb: Balance self-OTA with SHA256 verify
  • bd-21hv: UART OTA Balance→IO (1KB chunks, CRC8+ACK)
  • bd-1yr8: GC9A01 badge + progress arc display
  • bd-1s1s: Orin serial CMD_OTA_CHECK/OTA_UPDATE
6 OTA beads on esp32s3/ (bd-3gwo, bd-3hte, bd-18nb, bd-21hv, bd-1yr8, bd-1s1s). - bd-3gwo: Dual OTA partitions 1.75MB + rollback - bd-3hte: WiFi + Gitea version check every 30min - bd-18nb: Balance self-OTA with SHA256 verify - bd-21hv: UART OTA Balance→IO (1KB chunks, CRC8+ACK) - bd-1yr8: GC9A01 badge + progress arc display - bd-1s1s: Orin serial CMD_OTA_CHECK/OTA_UPDATE
sl-jetson added 7 commits 2026-04-17 22:19:51 -04:00
Replaces Orin↔ESP32-S3 BALANCE CAN comms (0x300-0x303 / 0x400-0x401)
with binary serial framing over CH343 USB-CDC at 460800 baud.

Protocol matches bd-wim1 (sl-perception) exactly:
  Frame: [0xAA][LEN][TYPE][PAYLOAD][CRC8-SMBUS]
  CRC covers LEN+TYPE+PAYLOAD, big-endian multi-byte fields.

Commands (Orin→ESP32): HEARTBEAT/DRIVE/ESTOP/ARM/PID
Telemetry (ESP32→Orin): TELEM_STATUS, TELEM_VESC_LEFT (ID 56),
                         TELEM_VESC_RIGHT (ID 68), ACK/NACK

VESC CAN TWAI kept for motor control; drive commands from Orin
forwarded to VESCs via SET_RPM. Hardware note: SN65HVD230
rewired from IO43/44 to IO2/IO1 to free IO43/44 for CH343.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add dual OTA partitions (ota_0/ota_1 × 1.75 MB each) and otadata to
both esp32s3/balance/ and esp32s3/io/ on 4 MB flash layouts.
Enable CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE and OTA HTTP on Balance.
Create esp32s3/io/ project scaffold with config.h pin assignments.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds gitea_ota_check_task on Balance board: fetches Gitea releases API
every 30 min and on boot, filters by esp32-balance/ and esp32-io/ tag
prefixes, compares semver against embedded FW version, stores update info
(version string, download URL, SHA256) in g_balance_update / g_io_update.
WiFi credentials read from NVS namespace "wifi"; falls back to compile-time
DEFAULT_WIFI_SSID/PASS if NVS is empty.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Downloads balance-firmware.bin from Gitea release URL to inactive OTA
partition, streams SHA256 verification via mbedTLS, sets boot partition
and reboots. Auto-rollback via CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE if
ota_self_health_check() not called within 30 s of boot. Progress 0-100%
in g_ota_self_progress for display task.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Balance side (uart_ota.c): downloads io-firmware.bin from Gitea to RAM,
computes SHA256, then streams to IO over UART1 (GPIO17/18, 460800 baud)
as OTA_BEGIN/OTA_DATA/OTA_END frames with CRC8 + per-chunk ACK/retry (×3).
IO side (uart_ota_recv.c): receives frames, writes to inactive OTA partition
via esp_ota_write, verifies SHA256 on OTA_END, sets boot partition, reboots.
IO board main.c + CMakeLists.txt scaffold included.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds ota_display_task (5 Hz) on GC9A01 240×240 round LCD:
- Idle: orange dot badge at top-right when update available, version text
- Progress: arc sweeping 0→360° around display perimeter with phase label
- States: Downloading/Verifying/Applying/Rebooting (Balance) and
  Downloading/Sending/Done (IO via UART)
- Error: red arc + "FAILED RETRY?" prompt
Display primitives (fill_rect, draw_string, draw_arc) are stubs called
from the GC9A01 SPI driver layer (separate driver bead).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extends the bd-66hx serial protocol with two new Orin→ESP32 commands:
  CMD_OTA_CHECK  (0x10): triggers gitea_ota_check_now(), responds with
    TELEM_VERSION_INFO (0x84) for Balance and IO (current + available ver).
  CMD_OTA_UPDATE (0x11): uint8 target (0=balance, 1=io, 2=both) — triggers
    uart_ota_trigger() for IO or ota_self_trigger() for Balance.
    NACK with ERR_OTA_BUSY or ERR_OTA_NO_UPDATE on failure.
New telemetry: TELEM_OTA_STATUS (0x83, target+state+progress+err),
  TELEM_VERSION_INFO (0x84, target+current[16]+available[16]).
Wires OTA stack into app_main: ota_self_health_check on boot,
  gitea_ota_init + ota_display_init after peripherals ready.
CMakeLists updated with all OTA component dependencies.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
sl-jetson force-pushed sl-firmware/ota-esp32 from aec9c472cf to 1ae600ead4 2026-04-17 23:10:56 -04:00 Compare
sl-jetson merged commit 329797d43c into main 2026-04-17 23:11:05 -04:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: seb/saltylab-firmware#731
No description provided.