fix: three stack overflows crashing firmware on TimerCamera-F

loopTask: cv_init() created a CVState{} temporary (9KB background
array) on the stack — fixed by initializing members directly.

cam task: cv_process() had uint8_t fg[CV_PIXELS] (9KB) as a local
variable — made static, matching the existing fg_copy fix.

cam task stack bumped from 4096 to 8192 for headroom.

Also: switch to 4MB OTA partition table (TimerCamera-F has 4MB flash,
not 8MB), add CONFIG_ARDUINO_LOOP_STACK_SIZE=16384 build flag,
upload_speed=115200 and --no-stub for reliable CH340 flashing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-15 10:58:06 -07:00
parent 265fb727ab
commit 4b671843b3
4 changed files with 21 additions and 6 deletions

View File

@@ -6,8 +6,15 @@
#include <vector> #include <vector>
void cv_init(CVState& state) { void cv_init(CVState& state) {
state = CVState{}; // value-initialize — calls vector default ctor correctly // Initialize members directly — avoid CVState{} temporary which puts 9KB on stack
memset(state.background, 0, sizeof(state.background));
state.bg_valid = false;
state.last_motion_frame = 0;
state.frame_index = 0;
state.next_id = 1; state.next_id = 1;
state.tracks.clear();
state.entries = 0;
state.exits = 0;
} }
void cv_reset_counts(CVState& state) { void cv_reset_counts(CVState& state) {
@@ -83,7 +90,7 @@ CVResult cv_process(CVState& state, const uint8_t* frame, uint8_t line_pct) {
return result; return result;
} }
uint8_t fg[CV_PIXELS]; static uint8_t fg[CV_PIXELS]; // static: avoids 9KB on task stack
frame_diff(frame, state.background, fg, CV_PIXELS); frame_diff(frame, state.background, fg, CV_PIXELS);
int fg_count = 0; int fg_count = 0;

View File

@@ -0,0 +1,6 @@
# Name, Type, SubType, Offset, Size
nvs, data, nvs, 0x9000, 0x5000
otadata, data, ota, 0xe000, 0x2000
app0, app, ota_0, 0x10000, 0x180000
app1, app, ota_1, 0x190000, 0x180000
spiffs, data, spiffs, 0x310000, 0xF0000
1 # Name Type SubType Offset Size
2 nvs data nvs 0x9000 0x5000
3 otadata data ota 0xe000 0x2000
4 app0 app ota_0 0x10000 0x180000
5 app1 app ota_1 0x190000 0x180000
6 spiffs data spiffs 0x310000 0xF0000

View File

@@ -6,15 +6,17 @@ default_envs = timercam
platform = espressif32@6.6.0 platform = espressif32@6.6.0
board = m5stack-timer-cam board = m5stack-timer-cam
framework = arduino framework = arduino
board_build.partitions = partitions_8mb_ota.csv board_build.partitions = partitions_4mb_ota.csv
build_flags = build_flags =
-DBOARD_HAS_PSRAM -DBOARD_HAS_PSRAM
-mfix-esp32-psram-cache-issue -mfix-esp32-psram-cache-issue
-DCORE_DEBUG_LEVEL=3 -DCORE_DEBUG_LEVEL=3
-DCONFIG_BT_NIMBLE_ENABLED=1 -DCONFIG_BT_NIMBLE_ENABLED=1
-DCONFIG_SPIRAM_USE_MALLOC=1 -DCONFIG_SPIRAM_USE_MALLOC=1
-DCONFIG_ARDUINO_LOOP_STACK_SIZE=16384
monitor_speed = 115200 monitor_speed = 115200
upload_speed = 921600 upload_speed = 115200
upload_flags = --no-stub
lib_deps = lib_deps =
tzapu/WiFiManager@^2.0.17 tzapu/WiFiManager@^2.0.17
bblanchon/ArduinoJson@^7.0.0 bblanchon/ArduinoJson@^7.0.0

View File

@@ -153,7 +153,7 @@ void setup() {
s_cv_mutex = xSemaphoreCreateMutex(); s_cv_mutex = xSemaphoreCreateMutex();
xTaskCreatePinnedToCore(task_camera, "cam", 4096, nullptr, 2, nullptr, 1); xTaskCreatePinnedToCore(task_camera, "cam", 8192, nullptr, 2, nullptr, 1);
xTaskCreatePinnedToCore(task_reporter, "rep", 8192, nullptr, 1, nullptr, 0); xTaskCreatePinnedToCore(task_reporter, "rep", 8192, nullptr, 1, nullptr, 0);
} }