obu-firmware is now a port of the colleague's standalone VRU station (microbu-esp32c5/firmware, kept beside this repository and gitignored): the vanetza-idf C-ITS stack with the TS 103 097 security entity, credentials in NVS, the station-link v1 protocol over the native USB port (frame type 0x10 in the existing 0xAA55 framing) and over a BLE GATT peripheral, and its ITS-G5 radio adapter. The phone still builds CAM and VAM; the board adds GeoNetworking/BTP and signs with the provisioned authorization ticket. The private key never leaves the board. Builds with ESP-IDF 6.0.2 only, which vanetza-idf pins for the radio's private driver ABI. The previous C firmware stays on disk unbuilt; a full-flash backup of the bench board is kept in firmware-backups/ (gitignored). Changed against the colleague's firmware, marked MicrOBU: in the sources: - Reception unchanged for the app. vanetza-idf drops what it cannot verify (unsigned traffic, every RSU), so each captured frame also goes through the previous gn_unwrap.c and reaches the phone as link opcode V2X_RX (0x85), whose body is the old SERIAL_MSG_V2X_RX payload. - Unsigned transmission still possible, with the previous geonet.c header; the phone chooses per message. - Console on UART0 (CH343 port); the native USB port carries only link frames. - BLE advertising pauses while the USB link is in use: BLE and ITS-G5 share one RF front end. - NVS 80 KB (app at 0x20000). At 24 KB, with Wi-Fi settings the previous firmware left behind, the BLE bond could not be stored and the phone had to pair on every connection. - Bench fixes: the radio queue is drained before the first PoTi (no RX and ~177 queue drops before); the station loop waited pdMS_TO_TICKS(5) = 0 ticks at 100 Hz and starved the idle task; the 2.4 KB RX capture buffer is off the Wi-Fi task stack; BLE notifications longer than the MTU are dropped instead of cut short, MTU 517; serial writes are skipped with no USB host. - Manual country policy and TX-power read-back from the previous radio setup; logs for BLE encryption changes and the number of stored bonds. Verified on the bench board (COM3) with the phone over USB and BLE: CAM and VAM, signed and unsigned, go out; reception of the sim car and the RSU's CAM/SPATEM/MAPEM continues; the board survives app restarts and reconnects. See docs/06-signed-its-vam-ble.md.
6.5 KiB
obu-firmware — setup & flashing notes
Two toolchains - use a dedicated terminal for each
Since 2026-09-23 this project builds against ESP-IDF 6.0.2 exactly
(C:\Espressif\frameworks\esp-idf-v6.0.2): it is the vanetza-idf port (see
NOTES.md), and vanetza-idf's radio_c5.cmake refuses any other version because
the raw TX path pokes private Wi-Fi driver structures only validated there. The
previous C firmware used the receiver firmware's IDF 6.1; the separate
obu-cam-transmistter project builds against the global ESP-IDF 5.5.4.
Exporting two of them in one PowerShell window fails: the second export
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
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
repository (gitignored here): vanetza-idf is taken from its
external/vanetza-idf. Pass -DVANETZA_IDF_DIR=<path> to idf.py if it lives
elsewhere. The first build downloads espressif/esp-boost into
managed_components/.
Every new PowerShell session
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
$env:IDF_TOOLS_PATH = "C:\Espressif"
C:\Espressif\frameworks\esp-idf-v6.0.2\export.ps1
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
cd C:\Users\Ashin\AndroidStudioProjects\MicrOBU\obu-firmware
idf.py set-target esp32c5 # only needed once per clean build folder
idf.py build
idf.py -p COM5 -b 921600 flash monitor
Swap COM5 for whatever port the ESP32-C5 enumerates as (Device Manager →
Ports). monitor opens the serial console after flashing — Ctrl+] to exit.
If the build fails
- "includes X.h, provided by Y component(s)... not in the requirements
list" — IDF 5.x split the old monolithic
drivercomponent apart (esp_driver_gpio,esp_driver_uart, etc.). Add the named component toREQUIRESinmain/CMakeLists.txtand rebuild. Already fixed once foresp_driver_gpio+esp_driver_uart— if a new header comes up, same fix. - Otherwise, start clean before re-building:
idf.py fullclean idf.py build
Connecting the phone (ESP32-C5-WIFI6-KIT)
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
is where the phone plugs in via USB-OTG. The CAM serial link
(
serial_link.c) 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). - UART-bridge port (labeled for flashing) — this is what you use for
idf.py flash monitorfrom your PC. Leave the phone unplugged from this one; it only carriesidf.py's flashing protocol and the ESP_LOG console.
The app recognizes the ESP32-C5's VID/PID via a custom probe table in
UsbSerialTransport.kt (the default usb-serial-for-android prober doesn't
know Espressif's device IDs). If the phone doesn't detect anything when
plugged into the native port, first confirm with a tool like "USB Device
Info" (or adb shell dumpsys usb from a PC) that Android sees a USB device
at all — that isolates a bad/charge-only OTG cable from an app-side issue.
Bring-up checklist (phone <-> ESP32-C5 link)
Work down this list — each step isolates the layer below it.
- Flash and install together.
SERIAL_LINK_MAX_PAYLOADis 512 on both sides. A phone at 512 talking to firmware still at 160 (or vice versa) silently rejects every large frame at thelength exceeds max, resyncbranch. Never update one side alone. - 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 every attached device and each device's interfaces. Empty list = cable / OTG / wrong port, below the app entirely. - Did the right interface get claimed? The C5's USB Serial/JTAG is a
composite device — expect CDC control (class 2) + CDC data (class 10) +
vendor-specific JTAG (class 255) in that dump. Compare against the
ports=count on thematched deviceline. - Is the link alive? The firmware sends a STATUS heartbeat at 1 Hz regardless of radio traffic, and the app marks the link ERROR after ~3.5 s of silence. Connected-and-staying-connected means device→host actually works.
- If it connects but no CAM_RX ever arrives — suspect DTR. The app now
asserts DTR/RTS on open (
openDevice()inUsbSerialTransport.kt), becauseCdcAcmSerialDriverdoesn'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 unverified on real hardware — test it both ways (with thesetDTR(true)call and with it commented out) and record the answer inserial_link.hnext to the VID/PID note, so nobody has to guess again. - Watch the counters, not just "Sent: N". The CAM Pinger card shows
consecutive write failures (phone side) and the firmware's tx-failure /
oversize-drop / CRC-error totals from the heartbeat. A rising
tx failmeans CAMs reach the ESP32 butesp_wifi_80211_txrejects them — a radio problem, not a link problem.
Connecting over Bluetooth instead
Settings > Connection > ESP32-C5 > link: Bluetooth, then Connect. The board
advertises as micrOBU-XXXX (last two bytes of its BT MAC; micrOBU-4AFA on
COM3), but only while nothing uses its native USB port. Android asks to pair
the first time: passkey 123456 (fixed in simple_ble.cpp). The bond is kept
on both sides; the board keeps one bond, so pairing a second phone or a PC
replaces the first. Log lines on the console start with cits_ble:.
Notes
- No
git submodule updateneeded here — obu-firmware has no pinned submodule of its own, unlike its-g5-receiver-firmware. - Don't use the global "ESP-IDF 5.5 PowerShell" shortcut or the receiver
firmware's 6.1 checkout — export from
esp-idf-v6.0.2, the version the vanetza-idf radio's undocumented driver internals were verified against. - The console (ESP_LOG, boot messages, panics) stays on the UART-bridge port. Opening it resets the board; do that only while nothing else depends on the session.