From 0a80b8e860b685f171efa3f568b8199fd1b2c60e Mon Sep 17 00:00:00 2001 From: ruv Date: Fri, 27 Mar 2026 17:08:52 -0400 Subject: [PATCH] =?UTF-8?q?fix(firmware):=20address=20review=20findings=20?= =?UTF-8?q?=E2=80=94=20idle=20busy-spin=20and=20observability?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix pdMS_TO_TICKS(5)==0 at 100Hz causing busy-spin in idle path (use vTaskDelay(1) instead) - Post-batch yield now 2 ticks (20ms) for genuinely longer pause - Add s_ring_drops counter to ring_push for diagnosing frame drops - Expose drop count in periodic vitals log line Co-Authored-By: claude-flow --- .../esp32-csi-node/main/edge_processing.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/firmware/esp32-csi-node/main/edge_processing.c b/firmware/esp32-csi-node/main/edge_processing.c index ba28ef00..1cd74a65 100644 --- a/firmware/esp32-csi-node/main/edge_processing.c +++ b/firmware/esp32-csi-node/main/edge_processing.c @@ -41,12 +41,14 @@ static const char *TAG = "edge_proc"; * ====================================================================== */ static edge_ring_buf_t s_ring; +static uint32_t s_ring_drops; /* Frames dropped due to full ring buffer. */ static inline bool ring_push(const uint8_t *iq, uint16_t len, int8_t rssi, uint8_t channel) { uint32_t next = (s_ring.head + 1) % EDGE_RING_SLOTS; if (next == s_ring.tail) { + s_ring_drops++; return false; /* Full — drop frame. */ } @@ -788,12 +790,13 @@ static void process_frame(const edge_ring_slot_t *slot) if ((s_frame_count % 200) == 0) { ESP_LOGI(TAG, "Vitals: br=%.1f hr=%.1f motion=%.4f pres=%s " - "fall=%s persons=%u frames=%lu", + "fall=%s persons=%u frames=%lu drops=%lu", s_breathing_bpm, s_heartrate_bpm, s_motion_energy, s_presence_detected ? "YES" : "no", s_fall_detected ? "YES" : "no", (unsigned)s_latest_pkt.n_persons, - (unsigned long)s_frame_count); + (unsigned long)s_frame_count, + (unsigned long)s_ring_drops); } } @@ -849,12 +852,14 @@ static void edge_task(void *arg) } if (processed > 0) { - /* Longer yield after each batch so IDLE1 can run and feed - * the Core 1 watchdog even under sustained load. */ - vTaskDelay(pdMS_TO_TICKS(10)); + /* Post-batch yield: 2 ticks (~20 ms at 100 Hz) so IDLE1 can + * run and feed the Core 1 watchdog even under sustained load. + * This is intentionally longer than the 1-tick inter-frame yield. */ + vTaskDelay(2); } else { - /* No frames available — yield briefly. */ - vTaskDelay(pdMS_TO_TICKS(5)); + /* No frames available — sleep one full tick. + * NOTE: pdMS_TO_TICKS(5) == 0 at 100 Hz, which would busy-spin. */ + vTaskDelay(1); } } }