release: ESP32-S3 firmware v0.6.5 — Tmr Svc stack + OTA init refactor (#628)

Three fixes wrapped for the v0.6.5-esp32 release tag:

1. **`sdkconfig.defaults` adds `CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=8192`**.
   The fix was already in `sdkconfig.defaults.template` (ADR-081, prevents
   "stack overflow in task Tmr Svc" bootloop when adaptive_controller emits
   feature_state from inside a Timer Svc callback). It was MISSING from the
   canonical `sdkconfig.defaults` file used by the build, so any fresh
   build picked up the 2 KiB FreeRTOS default and bootlooped on hardware.
   Verified on COM7: with the fix, no panics in 30 s of operation; without
   it, "***ERROR*** A stack overflow in task Tmr Svc has been detected."
   followed by sustained bootloop.

2. **`ota_update.c` extracts `ota_load_psk_from_nvs()` and calls it from
   both `ota_update_init()` and `ota_update_init_ex()`.** `main.c:230` uses
   the `_ex` variant, but only `ota_update_init()` was loading the PSK
   from NVS. Result: `s_ota_psk` stayed empty regardless of NVS contents,
   so the RuView#596 fail-closed posture rejected every request — but the
   diagnostic warning never printed at boot, leaving operators no signal
   about why their OTA uploads were 403'ing. Verified on COM7:
       W (3126) ota_update: NVS namespace 'security' not found —
       OTA upload endpoint will REJECT all requests until provisioned.
       Fail-closed per RuView#596.

3. **`version.txt`: 0.6.4 → 0.6.5**, paired with the v0.6.5-esp32 tag so the
   firmware-ci version-guard job (RuView#505 fix-marker) stays happy.

Both validations done end-to-end on hardware (COM7, ESP32-S3 8MB,
provisioned with --edge-tier 2 to also incidentally re-verify #438 is not
reproducible on current main).
This commit is contained in:
rUv
2026-05-18 17:05:35 -04:00
committed by GitHub
parent 281c4cb0ce
commit f5e2b5474b
3 changed files with 28 additions and 3 deletions
+19 -2
View File
@@ -251,9 +251,16 @@ static esp_err_t ota_start_server(httpd_handle_t *out_handle)
return ESP_OK;
}
esp_err_t ota_update_init(void)
/**
* Load the OTA PSK from NVS into the module-local s_ota_psk cache and log
* the resulting posture. Called by both ota_update_init() and
* ota_update_init_ex() so the per-boot diagnostic prints no matter which
* entry point main.c uses — historically only ota_update_init() loaded the
* PSK, which left ota_update_init_ex() with an empty s_ota_psk and an
* invisible fail-closed posture (RuView#596 follow-up).
*/
static void ota_load_psk_from_nvs(void)
{
/* ADR-050: Load OTA PSK from NVS if provisioned. */
nvs_handle_t nvs;
if (nvs_open(OTA_NVS_NAMESPACE, NVS_READONLY, &nvs) == ESP_OK) {
size_t len = sizeof(s_ota_psk);
@@ -268,11 +275,21 @@ esp_err_t ota_update_init(void)
ESP_LOGW(TAG, "NVS namespace '%s' not found — OTA upload endpoint will REJECT all "
"requests until provisioned. Fail-closed per RuView#596.", OTA_NVS_NAMESPACE);
}
}
esp_err_t ota_update_init(void)
{
/* ADR-050: Load OTA PSK from NVS if provisioned. */
ota_load_psk_from_nvs();
return ota_start_server(NULL);
}
esp_err_t ota_update_init_ex(void **out_server)
{
/* ADR-050: Load OTA PSK from NVS if provisioned. main.c uses this
* variant (not ota_update_init), so without this call s_ota_psk
* stayed empty forever and the fail-closed posture was invisible
* in serial logs. */
ota_load_psk_from_nvs();
return ota_start_server((httpd_handle_t *)out_server);
}
@@ -34,3 +34,11 @@ CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192
# Extra WiFi IRAM placement (defense-in-depth for RuView#396 SPI cache race)
CONFIG_ESP_WIFI_EXTRA_IRAM_OPT=y
# ADR-081: adaptive_controller runs emit_feature_state + stream_sender
# network I/O inside Timer Svc callbacks, exceeding the 2 KiB default.
# Without this, the device bootloops with
# "***ERROR*** A stack overflow in task Tmr Svc has been detected."
# Was present in sdkconfig.defaults.template but missing here — fixed
# in the v0.6.5-esp32 release.
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=8192
+1 -1
View File
@@ -1 +1 @@
0.6.4
0.6.5