Flashing notes: first flash of the signed firmware, and the way back
FLASHING.md still described flashing as for the previous firmware. The port
changed the partition table (NVS 24 KB -> 80 KB, app 0x10000 -> 0x20000), so a
board coming from the previous firmware needs its NVS range erased once and a
full flash, not app-flash; without the erase the BLE bond cannot be stored and
the phone pairs on every connection. Documented that, what the boot log and
the app show afterwards (credentials provisioned on first Connect, stale phone
pairings to forget), both ways back to the previous firmware (the backup image,
or commit 7285fa1 built with IDF 6.1), the production board's port (COM3,
UART bridge), the station-link names in the phone and bring-up sections, and
that the build is self-contained with obu-firmware/external/vanetza-idf.
This commit is contained in:
+75
-27
@@ -13,11 +13,17 @@ inherits the first's `IDF_PYTHON_ENV_PATH` and reports every Python dependency
|
|||||||
as unmet. Don't run `install.bat` to "fix" that - open a fresh terminal, or
|
as unmet. Don't run `install.bat` to "fix" that - open a fresh terminal, or
|
||||||
clear the state with `$env:IDF_PYTHON_ENV_PATH = $null; $env:IDF_PATH = $null`.
|
clear the state with `$env:IDF_PYTHON_ENV_PATH = $null; $env:IDF_PATH = $null`.
|
||||||
|
|
||||||
The build also needs the colleague's `microbu-esp32c5` checkout beside this
|
The build is self-contained: the C-ITS library comes from
|
||||||
repository (gitignored here): vanetza-idf is taken from its
|
`obu-firmware/external/vanetza-idf`, a copy of `external/vanetza-idf` from the
|
||||||
`external/vanetza-idf`. Pass `-DVANETZA_IDF_DIR=<path>` to `idf.py` if it lives
|
colleague's microbu-esp32c5 repository (their commit cf4b99f, unchanged). Pass
|
||||||
elsewhere. The first build downloads `espressif/esp-boost` into
|
`-DVANETZA_IDF_DIR=<path>` to `idf.py` to build against another checkout. The
|
||||||
`managed_components/`.
|
first build downloads `espressif/esp-boost` into `managed_components/`.
|
||||||
|
|
||||||
|
Nothing is fetched from or pushed to the colleague's repository (HAW GitLab,
|
||||||
|
urban-mobility-lab/microbu/microbu-esp32c5). To take a newer vanetza-idf from
|
||||||
|
it, copy their `external/vanetza-idf` over this folder, rebuild and test, and
|
||||||
|
commit it here. The rest of their tree (their own VAM firmware, PKI tooling,
|
||||||
|
station-link Python tools, the V2X2MAP bridge) is not part of this repository.
|
||||||
|
|
||||||
## Every new PowerShell session
|
## Every new PowerShell session
|
||||||
|
|
||||||
@@ -28,23 +34,61 @@ C:\Espressif\frameworks\esp-idf-v6.0.2\export.ps1
|
|||||||
idf.py --version # v6.0.2
|
idf.py --version # v6.0.2
|
||||||
```
|
```
|
||||||
|
|
||||||
## Going back to the previous firmware
|
|
||||||
|
|
||||||
`firmware-backups/` in the repository root (gitignored) holds a full-flash image
|
|
||||||
of the COM3 board as it was before the port, with the esptool command to write
|
|
||||||
it back in its README.txt.
|
|
||||||
|
|
||||||
## Build & flash
|
## Build & flash
|
||||||
|
|
||||||
|
Flash over the board's **UART-bridge port** (CH343; COM3 for the production OBU
|
||||||
|
on the bench), not the native port the phone uses.
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
cd C:\Users\Ashin\AndroidStudioProjects\MicrOBU\obu-firmware
|
cd C:\Users\Ashin\AndroidStudioProjects\MicrOBU\obu-firmware
|
||||||
idf.py set-target esp32c5 # only needed once per clean build folder
|
idf.py set-target esp32c5 # only needed once per clean build folder
|
||||||
idf.py build
|
idf.py build
|
||||||
idf.py -p COM5 -b 921600 flash monitor
|
idf.py -p COM3 -b 921600 flash monitor
|
||||||
```
|
```
|
||||||
|
|
||||||
Swap `COM5` for whatever port the ESP32-C5 enumerates as (Device Manager →
|
Swap `COM3` for whatever port the ESP32-C5's bridge enumerates as (Device Manager →
|
||||||
Ports). `monitor` opens the serial console after flashing — `Ctrl+]` to exit.
|
Ports). `monitor` opens the serial console after flashing — `Ctrl+]` to exit.
|
||||||
|
Use `flash` (bootloader + partition table + app), not `app-flash`, whenever the
|
||||||
|
partition table may differ from what the board has.
|
||||||
|
|
||||||
|
### First flash onto a board with the previous firmware
|
||||||
|
|
||||||
|
The partition table changed with the port (NVS 24 KB → 80 KB, app 0x10000 →
|
||||||
|
0x20000), and the old NVS is full of Wi-Fi settings the previous firmware left
|
||||||
|
behind. Erase the whole new NVS range once, then do a full flash:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
python -m esptool --chip esp32c5 -p COM3 -b 921600 erase-region 0x9000 0x15000
|
||||||
|
idf.py -p COM3 -b 921600 flash
|
||||||
|
```
|
||||||
|
|
||||||
|
Without the erase, the board cannot store the BLE bond and the phone has to pair
|
||||||
|
on every connection (2026-09-23). After it:
|
||||||
|
|
||||||
|
- the boot log shows `0 bonded phone(s) in NVS`, `BLE advertising started as
|
||||||
|
'micrOBU-XXXX'` and `station task ready`; the radio stays off until the app
|
||||||
|
connects;
|
||||||
|
- on the first Connect the app provisions the demo credentials once (the card
|
||||||
|
says "Provisioning the demo credentials"); they stay in NVS from then on;
|
||||||
|
- a phone that was paired with the board before must forget `micrOBU-XXXX` in
|
||||||
|
Android's Bluetooth settings and pair again (passkey 123456).
|
||||||
|
|
||||||
|
Erasing NVS later (e.g. after a partition change) has the same effects.
|
||||||
|
|
||||||
|
## Going back to the previous firmware
|
||||||
|
|
||||||
|
The previous, unsigned C firmware (frame types 0x01-0x05, CAM over USB only)
|
||||||
|
can come back two ways. The app detects it and falls back to its protocol.
|
||||||
|
|
||||||
|
- **Image:** `firmware-backups/` in the repository root (gitignored, on the lab
|
||||||
|
laptop only) holds a full-flash image of the COM3 board as it was before the
|
||||||
|
port, with the esptool command in its README.txt. It restores the old
|
||||||
|
partition table and NVS too.
|
||||||
|
- **Source:** commit `7285fa1` is the last one before the port. Check it out in
|
||||||
|
a separate worktree and build it with the receiver firmware's IDF 6.1
|
||||||
|
(`its-g5-receiver-firmware\esp-idf\export.ps1`). Erase the NVS range as above
|
||||||
|
first, then `flash` (full, since the partition table differs); erasing after
|
||||||
|
flashing would wipe the start of the old app, which sits at 0x10000.
|
||||||
|
|
||||||
## If the build fails
|
## If the build fails
|
||||||
|
|
||||||
@@ -64,9 +108,9 @@ Ports). `monitor` opens the serial console after flashing — `Ctrl+]` to exit.
|
|||||||
The board has two USB-C ports — use the right one:
|
The board has two USB-C ports — use the right one:
|
||||||
|
|
||||||
- **Native USB-C port** (labeled for JTAG/native USB, up to 12 Mbps) — this
|
- **Native USB-C port** (labeled for JTAG/native USB, up to 12 Mbps) — this
|
||||||
is where the phone plugs in via USB-OTG. The CAM serial link
|
is where the phone plugs in via USB-OTG. The station link
|
||||||
(`serial_link.c`) runs over the ESP32-C5's native USB Serial/JTAG
|
(`serial_link.cpp`: station-link messages as frame type 0x10 in the 0xAA55
|
||||||
peripheral on this port, enumerating as a CDC-ACM device under Espressif's
|
framing) runs over the ESP32-C5's native USB Serial/JTAG peripheral on this port, enumerating as a CDC-ACM device under Espressif's
|
||||||
VID/PID (0x303A/0x1001).
|
VID/PID (0x303A/0x1001).
|
||||||
- **UART-bridge port** (labeled for flashing) — this is what you use for
|
- **UART-bridge port** (labeled for flashing) — this is what you use for
|
||||||
`idf.py flash monitor` from your PC. Leave the phone unplugged from this
|
`idf.py flash monitor` from your PC. Leave the phone unplugged from this
|
||||||
@@ -83,10 +127,10 @@ at all — that isolates a bad/charge-only OTG cable from an app-side issue.
|
|||||||
|
|
||||||
Work down this list — each step isolates the layer below it.
|
Work down this list — each step isolates the layer below it.
|
||||||
|
|
||||||
1. **Flash and install together.** `SERIAL_LINK_MAX_PAYLOAD` is 512 on both sides.
|
1. **Flash and install together.** The app detects the firmware generation by
|
||||||
A phone at 512 talking to firmware still at 160 (or vice versa) silently
|
its heartbeat and speaks either protocol, but only an app from 2026-09-23 on
|
||||||
rejects every large frame at the `length exceeds max, resync` branch. Never
|
knows the station-link protocol; messages are at most 512 octets on both
|
||||||
update one side alone.
|
sides.
|
||||||
2. **Does Android see the device at all?** Plug the phone into the **native**
|
2. **Does Android see the device at all?** Plug the phone into the **native**
|
||||||
USB-C port, hit Connect, and read logcat for `UsbSerialTransport`. It logs
|
USB-C port, hit Connect, and read logcat for `UsbSerialTransport`. It logs
|
||||||
every attached device *and* each device's interfaces. Empty list = cable /
|
every attached device *and* each device's interfaces. Empty list = cable /
|
||||||
@@ -95,10 +139,12 @@ Work down this list — each step isolates the layer below it.
|
|||||||
composite device — expect CDC control (class 2) + CDC data (class 10) +
|
composite device — expect CDC control (class 2) + CDC data (class 10) +
|
||||||
vendor-specific JTAG (class 255) in that dump. Compare against the `ports=`
|
vendor-specific JTAG (class 255) in that dump. Compare against the `ports=`
|
||||||
count on the `matched device` line.
|
count on the `matched device` line.
|
||||||
4. **Is the link alive?** The firmware sends a STATUS heartbeat at 1 Hz
|
4. **Is the link alive?** The firmware sends a STATUS at 1 Hz regardless of
|
||||||
regardless of radio traffic, and the app marks the link ERROR after ~3.5 s of
|
radio traffic, and the app marks the link ERROR after ~3.5 s of silence.
|
||||||
silence. Connected-and-staying-connected means device→host actually works.
|
Connected-and-staying-connected means device→host actually works. The board
|
||||||
5. **If it connects but no CAM_RX ever arrives** — suspect DTR. The app now
|
starts its radio only after the app's STATION_CONFIGURE, so nothing is
|
||||||
|
received before Connect.
|
||||||
|
5. **If it connects but no V2X_RX ever arrives** — suspect DTR. The app now
|
||||||
asserts DTR/RTS on open (`openDevice()` in `UsbSerialTransport.kt`), because
|
asserts DTR/RTS on open (`openDevice()` in `UsbSerialTransport.kt`), because
|
||||||
`CdcAcmSerialDriver` doesn't do it by default and the ESP32's USB Serial/JTAG
|
`CdcAcmSerialDriver` doesn't do it by default and the ESP32's USB Serial/JTAG
|
||||||
endpoint may gate TX on the host opening the CDC line. **This is still
|
endpoint may gate TX on the host opening the CDC line. **This is still
|
||||||
@@ -107,9 +153,11 @@ Work down this list — each step isolates the layer below it.
|
|||||||
next to the VID/PID note, so nobody has to guess again.
|
next to the VID/PID note, so nobody has to guess again.
|
||||||
6. **Watch the counters, not just "Sent: N".** The CAM Pinger card shows
|
6. **Watch the counters, not just "Sent: N".** The CAM Pinger card shows
|
||||||
consecutive write failures (phone side) and the firmware's tx-failure /
|
consecutive write failures (phone side) and the firmware's tx-failure /
|
||||||
oversize-drop / CRC-error totals from the heartbeat. A rising `tx fail` means
|
RX-queue-drop / CRC-error totals from the heartbeat; the connection card
|
||||||
CAMs reach the ESP32 but `esp_wifi_80211_tx` rejects them — a radio problem,
|
shows tickets, signed and refused counts. A rising `tx fail` means messages
|
||||||
not a link problem.
|
reach the ESP32 but the radio refuses them — a radio problem, not a link
|
||||||
|
problem. A rising `refused` with signing on usually means no ticket (NVS
|
||||||
|
erased: reconnect so the app provisions again).
|
||||||
|
|
||||||
## Connecting over Bluetooth instead
|
## Connecting over Bluetooth instead
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user