Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 10 additions & 27 deletions firmware/esp32-csi-node/main/edge_processing.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,12 @@ 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. */
}

Expand Down Expand Up @@ -790,13 +788,12 @@ 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 drops=%lu",
"fall=%s persons=%u frames=%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_ring_drops);
(unsigned long)s_frame_count);
}
}

Expand Down Expand Up @@ -834,32 +831,18 @@ static void edge_task(void *arg)

edge_ring_slot_t slot;

/* Maximum frames to process before a longer yield. On busy LANs
* (corporate networks, many APs), the ring buffer fills continuously.
* Without a batch limit the task processes frames back-to-back with
* only 1-tick yields, which on high frame rates can still starve
* IDLE1 enough to trip the 5-second task watchdog. See #266, #321. */
const uint8_t BATCH_LIMIT = 4;

while (1) {
uint8_t processed = 0;

while (processed < BATCH_LIMIT && ring_pop(&slot)) {
if (ring_pop(&slot)) {
process_frame(&slot);
processed++;
/* 1-tick yield between frames within a batch. */
/* Yield after every frame to feed the Core 1 watchdog.
* process_frame() is CPU-intensive (biquad filters, Welford stats,
* BPM estimation, multi-person vitals) and can take several ms.
* Without this yield, edge_dsp at priority 5 starves IDLE1 at
* priority 0, triggering the task watchdog. See issue #266. */
vTaskDelay(1);
}

if (processed > 0) {
/* 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 — sleep one full tick.
* NOTE: pdMS_TO_TICKS(5) == 0 at 100 Hz, which would busy-spin. */
vTaskDelay(1);
/* No frames available — yield briefly. */
vTaskDelay(pdMS_TO_TICKS(1));
}
}
}
Expand Down
Loading