Count and surface RX-queue drops on the ESP32-C5's promiscuous path

wifi_promisc_rx_cb() fed s_rx_queue with a 0-timeout xQueueSend() and never
checked whether it succeeded, so a burst of captured frames arriving faster
than rx_forward_task could drain them vanished with no counter anywhere -
none of oversizeDrops/txFailures/rxCrcErrors caught it. Added a rxQueueDrops
counter, threaded it through the STATUS heartbeat as a new trailing uint16
(old firmware/app on either side still parse fine), and surfaced it on the
CAM Pinger card.

Confirmed on the bench: flashed to the production OBU (COM3) and installed
the matching app build on the phone, then watched the counter over logcat
against obu-cam-transmistter's ~3.3 Hz beacon - it is real (0 -> 89 -> 90
across two sessions) but bursty around connect/reconnect rather than a
continuous overflow under steady single-station traffic.
This commit is contained in:
Ashin Walpola
2026-09-22 14:45:17 +02:00
parent 21e01499d8
commit 7285fa19b7
9 changed files with 209 additions and 15 deletions
+13 -3
View File
@@ -21,6 +21,7 @@ static serial_link_cam_tx_pv_cb_t s_on_cam_tx_pv;
static uint16_t s_oversize_drops;
static uint16_t s_tx_failures;
static uint16_t s_rx_crc_errors;
static uint16_t s_rx_queue_drops;
// Serializes send_frame(): it writes a frame as four separate usb_serial_jtag_write_bytes() calls
// and shares one static CRC scratch buffer, and it's now called from three tasks (rx_forward for
@@ -45,6 +46,12 @@ void serial_link_note_oversize_drop(uint16_t btp_dest_port)
btp_dest_port, s_oversize_drops);
}
void serial_link_note_rx_queue_drop(void)
{
bump(&s_rx_queue_drops);
ESP_LOGW(TAG, "rx queue full, dropped a captured frame, total rx queue drops %u", s_rx_queue_drops);
}
// ---- CRC-16/CCITT-FALSE (poly 0x1021, init 0xFFFF, no reflect, no xorout) ----
// Bytewise (no table) - frames here are at most SERIAL_LINK_MAX_PAYLOAD + 3 bytes, so table
// lookup isn't worth the flash/RAM tradeoff. MUST match the Kotlin-side implementation exactly
@@ -165,9 +172,10 @@ bool serial_link_send_v2x_rx(uint16_t btp_dest_port, int8_t rssi,
bool serial_link_send_status(uint8_t status)
{
// [status:1][oversize_drops:2 LE][tx_failures:2 LE][rx_crc_errors:2 LE][capabilities:1] -
// keep in lockstep with EspLinkStatus.parse() in the app's SerialFrame.kt.
uint8_t payload[8];
// [status:1][oversize_drops:2 LE][tx_failures:2 LE][rx_crc_errors:2 LE][capabilities:1]
// [rx_queue_drops:2 LE] - keep in lockstep with EspLinkStatus.parse() in the app's
// SerialFrame.kt.
uint8_t payload[10];
payload[0] = status;
payload[1] = (uint8_t)(s_oversize_drops & 0xFF);
payload[2] = (uint8_t)((s_oversize_drops >> 8) & 0xFF);
@@ -178,6 +186,8 @@ bool serial_link_send_status(uint8_t status)
// What this firmware accepts. The app reads it to decide whether it may send CAM_TX_PV, which
// is what lets a new app keep working against firmware that predates that message.
payload[7] = SERIAL_CAP_CAM_TX_PV;
payload[8] = (uint8_t)(s_rx_queue_drops & 0xFF);
payload[9] = (uint8_t)((s_rx_queue_drops >> 8) & 0xFF);
return send_frame(SERIAL_MSG_STATUS, payload, sizeof(payload));
}