fix(connectivity): harden BLE reprovisioning under memory pressure

This commit is contained in:
chenjintao
2026-08-25 14:09:44 +08:00
parent 140e90447c
commit 6495f0e107
6 changed files with 323 additions and 58 deletions
@@ -105,22 +105,37 @@ static esp_err_t app_composition_run_plan_a_boot_sequence(void)
esp_err_to_name(battery_guard_err));
}
app_composition_log_stage(APP_COMPOSITION_BOOT_STAGE_AUDIO_INIT,
"audio_init",
"boot_sound_policy_begin");
app_composition_log_stage(APP_COMPOSITION_BOOT_STAGE_BOOT_SOUND,
"boot_sound",
"play_boot_sound_with_timeout");
esp_err_t boot_sound_err =
control_plane_play_boot_sound(CONFIG_TQ_BOOT_SOUND_TIMEOUT_MS);
if (boot_sound_err != ESP_OK) {
ESP_LOGW(TAG,
"Boot sound unavailable, continue boot: %s",
esp_err_to_name(boot_sound_err));
bool provisioning_recovery_boot =
control_plane_take_mini_program_recovery_boot_request();
if (provisioning_recovery_boot) {
app_composition_log_stage_skipped(APP_COMPOSITION_BOOT_STAGE_AUDIO_INIT,
"audio_init",
"ble_recovery_boot");
app_composition_log_stage_skipped(APP_COMPOSITION_BOOT_STAGE_BOOT_SOUND,
"boot_sound",
"ble_recovery_boot");
app_composition_log_stage_skipped(APP_COMPOSITION_BOOT_STAGE_AUDIO_READY,
"audio_ready",
"ble_recovery_boot");
} else {
app_composition_log_stage(APP_COMPOSITION_BOOT_STAGE_AUDIO_INIT,
"audio_init",
"boot_sound_policy_begin");
app_composition_log_stage(APP_COMPOSITION_BOOT_STAGE_BOOT_SOUND,
"boot_sound",
"play_boot_sound_with_timeout");
esp_err_t boot_sound_err =
control_plane_play_boot_sound(CONFIG_TQ_BOOT_SOUND_TIMEOUT_MS);
if (boot_sound_err != ESP_OK) {
ESP_LOGW(TAG,
"Boot sound unavailable, continue boot: %s",
esp_err_to_name(boot_sound_err));
}
app_composition_log_stage(APP_COMPOSITION_BOOT_STAGE_AUDIO_READY,
"audio_ready",
"boot_sound_policy_end_keep_runtime");
}
app_composition_log_stage(APP_COMPOSITION_BOOT_STAGE_AUDIO_READY,
"audio_ready",
"boot_sound_policy_end_keep_runtime");
#if CONFIG_TQ_SCREEN_ENABLE
app_composition_log_stage(APP_COMPOSITION_BOOT_STAGE_LCD_DEVICE,
@@ -131,7 +146,7 @@ static esp_err_t app_composition_run_plan_a_boot_sequence(void)
"lcd_device",
lcd_err);
bool lcd_ready = (lcd_err == ESP_OK);
if (lcd_ready) {
if (lcd_ready && !provisioning_recovery_boot) {
app_composition_log_stage(APP_COMPOSITION_BOOT_STAGE_LCD_RENDER_LOOP,
"lcd_render_loop",
"control_plane_start_lcd_render_worker");
@@ -142,10 +157,14 @@ static esp_err_t app_composition_run_plan_a_boot_sequence(void)
if (lcd_worker_err != ESP_OK) {
lcd_ready = false;
}
} else {
} else if (!lcd_ready) {
app_composition_log_stage_skipped(APP_COMPOSITION_BOOT_STAGE_LCD_RENDER_LOOP,
"lcd_render_loop",
"lcd_device_unavailable");
} else {
app_composition_log_stage_skipped(APP_COMPOSITION_BOOT_STAGE_LCD_RENDER_LOOP,
"lcd_render_loop",
"ble_recovery_boot");
}
#else
app_composition_log_stage_skipped(APP_COMPOSITION_BOOT_STAGE_LCD_DEVICE,
@@ -173,15 +192,17 @@ static esp_err_t app_composition_run_plan_a_boot_sequence(void)
}
#if CONFIG_TQ_FACTORY_CLI_ENABLE
err = control_plane_factory_cli_start();
if (err != ESP_OK) {
ESP_LOGE(TAG, "Factory CLI start failed: %s", esp_err_to_name(err));
return err;
if (!provisioning_recovery_boot) {
err = control_plane_factory_cli_start();
if (err != ESP_OK) {
ESP_LOGE(TAG, "Factory CLI start failed: %s", esp_err_to_name(err));
return err;
}
}
#endif
#if CONFIG_TQ_SCREEN_ENABLE
if (lcd_ready) {
if (lcd_ready && !provisioning_recovery_boot) {
esp_err_t expression_err = control_plane_request_boot_expression();
if (expression_err != ESP_OK) {
ESP_LOGW(TAG,
@@ -192,14 +213,21 @@ static esp_err_t app_composition_run_plan_a_boot_sequence(void)
#endif
#if CONFIG_TQ_BOOT_TURNTABLE_CALIBRATION_ENABLE
app_composition_log_stage(APP_COMPOSITION_BOOT_STAGE_TURNTABLE_CALIBRATION,
"turntable_calibration",
"control_plane_calibrate");
esp_err_t calibration_err = control_plane_calibrate();
if (calibration_err != ESP_OK) {
ESP_LOGW(TAG,
"Boot turntable calibration failed, continue degraded: %s",
esp_err_to_name(calibration_err));
if (provisioning_recovery_boot) {
app_composition_log_stage_skipped(
APP_COMPOSITION_BOOT_STAGE_TURNTABLE_CALIBRATION,
"turntable_calibration",
"ble_recovery_boot");
} else {
app_composition_log_stage(APP_COMPOSITION_BOOT_STAGE_TURNTABLE_CALIBRATION,
"turntable_calibration",
"control_plane_calibrate");
esp_err_t calibration_err = control_plane_calibrate();
if (calibration_err != ESP_OK) {
ESP_LOGW(TAG,
"Boot turntable calibration failed, continue degraded: %s",
esp_err_to_name(calibration_err));
}
}
#else
app_composition_log_stage_skipped(APP_COMPOSITION_BOOT_STAGE_TURNTABLE_CALIBRATION,
@@ -236,6 +236,15 @@ esp_err_t control_plane_calibrate(void);
esp_err_t control_plane_bootstrap_connectivity(const char *seed_ssid,
const char *seed_password,
int connect_timeout_ms);
/**
* @brief Consume a one-shot request to use the low-memory BLE recovery boot.
*
* The request survives a software restart in RTC no-init memory. A true result
* is latched for the current boot so connectivity skips STA reconnect and
* starts BLE provisioning before full runtime workers.
*/
bool control_plane_take_mini_program_recovery_boot_request(void);
bool control_plane_is_sta_connected(void);
esp_err_t control_plane_stop_mini_program_provisioning(int timeout_ms);
bool control_plane_is_mini_program_provisioning_running(void);
@@ -9,6 +9,7 @@
#include <string.h>
#include "control_plane_internal.h"
#include "esp_attr.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
@@ -40,26 +41,103 @@
#define CONFIG_TQ_MINI_PROGRAM_PROVISIONING_CONNECT_TIMEOUT_MS 30000
#endif
#ifndef CONFIG_TQ_MINI_PROGRAM_PROVISIONING_MIN_FREE_INTERNAL_BYTES
#define CONFIG_TQ_MINI_PROGRAM_PROVISIONING_MIN_FREE_INTERNAL_BYTES 49152
#endif
#ifndef CONFIG_TQ_MINI_PROGRAM_PROVISIONING_MIN_LARGEST_DMA_BYTES
#define CONFIG_TQ_MINI_PROGRAM_PROVISIONING_MIN_LARGEST_DMA_BYTES 12288
#endif
#define CONTROL_PLANE_WIFI_SUCCESS_PROMPT_FILE "/littlefs/audio_prompts/network_connect_success.opus"
#define CONTROL_PLANE_STA_CONNECT_MAX_ATTEMPTS 3
#define CONTROL_PLANE_STA_RETRY_BASE_DELAY_MS 300
#define CONTROL_PLANE_PROVISIONING_QUEUE_LENGTH 1
#define CONTROL_PLANE_PROVISIONING_TASK_STACK_WORDS 4096
#define CONTROL_PLANE_PROVISIONING_TASK_STACK_BYTES 4096
#define CONTROL_PLANE_PROVISIONING_TASK_PRIORITY 5
#define CONTROL_PLANE_PROVISIONING_STOP_REQUESTED_BIT BIT0
#define CONTROL_PLANE_PROVISIONING_WORKER_DONE_BIT BIT1
#define CONTROL_PLANE_PROVISIONING_POLL_MS 100
#define CONTROL_PLANE_PROVISIONING_WAIT_LOG_MS 10000
#define CONTROL_PLANE_PROVISIONING_NOTIFY_SETTLE_MS 750
#define CONTROL_PLANE_PROVISIONING_TRANSPORT_STOP_MS 2000
#define CONTROL_PLANE_PROVISIONING_RUNTIME_QUIESCE_MS 2000
#define CONTROL_PLANE_PROVISIONING_RESTART_DELAY_MS 100
#define CONTROL_PLANE_PROVISIONING_RECOVERY_MAGIC 0x5451424cU
static const char *TAG = "control_plane_rt";
static bool s_wifi_success_prompt_played;
static bool s_provisioning_recovery_boot;
RTC_NOINIT_ATTR static uint32_t s_provisioning_recovery_marker;
RTC_NOINIT_ATTR static uint32_t s_provisioning_recovery_marker_inverse;
static portMUX_TYPE s_provisioning_lock = portMUX_INITIALIZER_UNLOCKED;
static QueueHandle_t s_provisioning_queue;
static EventGroupHandle_t s_provisioning_events;
static TaskHandle_t s_provisioning_task;
bool control_plane_take_mini_program_recovery_boot_request(void)
{
bool requested =
s_provisioning_recovery_marker == CONTROL_PLANE_PROVISIONING_RECOVERY_MAGIC &&
s_provisioning_recovery_marker_inverse ==
~CONTROL_PLANE_PROVISIONING_RECOVERY_MAGIC;
s_provisioning_recovery_marker = 0U;
s_provisioning_recovery_marker_inverse = 0U;
s_provisioning_recovery_boot = requested;
if (requested) {
ESP_LOGW(TAG, "Consumed one-shot low-memory BLE recovery boot request");
}
return requested;
}
static void control_plane_request_provisioning_recovery_restart(
const domain_ota_memory_headroom_t *headroom)
{
s_provisioning_recovery_marker = CONTROL_PLANE_PROVISIONING_RECOVERY_MAGIC;
s_provisioning_recovery_marker_inverse =
~CONTROL_PLANE_PROVISIONING_RECOVERY_MAGIC;
ESP_LOGW(TAG,
"Restarting into low-memory BLE recovery boot: free_internal=%u largest_internal=%u largest_dma=%u",
headroom != NULL ? (unsigned)headroom->free_internal : 0U,
headroom != NULL ? (unsigned)headroom->largest_internal : 0U,
headroom != NULL ? (unsigned)headroom->largest_dma : 0U);
vTaskDelay(pdMS_TO_TICKS(CONTROL_PLANE_PROVISIONING_RESTART_DELAY_MS));
domain_runtime_restart();
}
static esp_err_t control_plane_check_provisioning_memory_headroom(void)
{
domain_ota_memory_headroom_t headroom = {0};
esp_err_t err = domain_runtime_ota_get_memory_headroom(&headroom);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Read BLE provisioning memory headroom failed: %s",
esp_err_to_name(err));
return err;
}
ESP_LOGI(TAG,
"BLE provisioning memory headroom: free_internal=%u largest_internal=%u largest_dma=%u",
(unsigned)headroom.free_internal,
(unsigned)headroom.largest_internal,
(unsigned)headroom.largest_dma);
if (headroom.free_internal >=
CONFIG_TQ_MINI_PROGRAM_PROVISIONING_MIN_FREE_INTERNAL_BYTES &&
headroom.largest_dma >=
CONFIG_TQ_MINI_PROGRAM_PROVISIONING_MIN_LARGEST_DMA_BYTES) {
return ESP_OK;
}
ESP_LOGE(TAG,
"BLE provisioning memory headroom insufficient: need free_internal>=%u largest_dma>=%u",
(unsigned)CONFIG_TQ_MINI_PROGRAM_PROVISIONING_MIN_FREE_INTERNAL_BYTES,
(unsigned)CONFIG_TQ_MINI_PROGRAM_PROVISIONING_MIN_LARGEST_DMA_BYTES);
if (!s_provisioning_recovery_boot) {
control_plane_request_provisioning_recovery_restart(&headroom);
}
return ESP_ERR_NO_MEM;
}
static int elapsed_ms_since(TickType_t start_tick)
{
TickType_t elapsed_ticks = xTaskGetTickCount() - start_tick;
@@ -225,6 +303,19 @@ static void control_plane_finish_provisioning_ui(void)
}
}
static void control_plane_show_provisioning_ui(void)
{
const domain_expression_request_t request = {
.id = DOMAIN_EXPRESSION_WIFI_CONNECTING,
.trigger = DOMAIN_EXPRESSION_TRIGGER_WIFI_BOOTSTRAP,
};
esp_err_t err = domain_runtime_request_expression(&request);
if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) {
ESP_LOGW(TAG, "Wi-Fi provisioning display unavailable: %s",
esp_err_to_name(err));
}
}
static void control_plane_provisioning_event_callback(
const domain_wifi_provisioning_event_t *event,
void *user_data)
@@ -254,12 +345,24 @@ static void control_plane_provisioning_worker(void *arg)
{
(void)arg;
bool provisioning_succeeded = false;
TickType_t last_wait_log_tick = xTaskGetTickCount();
TickType_t wait_log_ticks =
pdMS_TO_TICKS(CONTROL_PLANE_PROVISIONING_WAIT_LOG_MS);
if (wait_log_ticks == 0U) {
wait_log_ticks = 1U;
}
while (!control_plane_provisioning_stop_requested()) {
domain_wifi_provisioning_event_t event = {0};
if (xQueueReceive(s_provisioning_queue,
&event,
pdMS_TO_TICKS(CONTROL_PLANE_PROVISIONING_POLL_MS)) != pdTRUE) {
TickType_t now_tick = xTaskGetTickCount();
if ((now_tick - last_wait_log_tick) >= wait_log_ticks) {
ESP_LOGI(TAG,
"BLE provisioning active; waiting for mini-program credentials");
last_wait_log_tick = now_tick;
}
continue;
}
@@ -319,7 +422,14 @@ static void control_plane_provisioning_worker(void *arg)
(void)xEventGroupSetBits(s_provisioning_events,
CONTROL_PLANE_PROVISIONING_WORKER_DONE_BIT);
if (provisioning_succeeded && stop_err == ESP_OK) {
if (provisioning_succeeded && stop_err == ESP_OK &&
s_provisioning_recovery_boot) {
ESP_LOGI(TAG,
"BLE recovery provisioning completed; restarting into normal runtime");
s_provisioning_recovery_boot = false;
vTaskDelay(pdMS_TO_TICKS(CONTROL_PLANE_PROVISIONING_RESTART_DELAY_MS));
domain_runtime_restart();
} else if (provisioning_succeeded && stop_err == ESP_OK) {
control_plane_finish_provisioning_ui();
ESP_LOGI(TAG,
"BLE provisioning completed; starting deferred runtime workers");
@@ -365,31 +475,31 @@ static esp_err_t control_plane_start_mini_program_provisioning(void)
CONTROL_PLANE_PROVISIONING_STOP_REQUESTED_BIT |
CONTROL_PLANE_PROVISIONING_WORKER_DONE_BIT);
esp_err_t err = control_plane_check_provisioning_memory_headroom();
if (err != ESP_OK) {
return err;
}
err = domain_runtime_mini_program_provisioning_start(
control_plane_provisioning_event_callback,
NULL);
if (err != ESP_OK) {
return err;
}
BaseType_t created = xTaskCreate(control_plane_provisioning_worker,
"mini_prog_wifi",
CONTROL_PLANE_PROVISIONING_TASK_STACK_WORDS,
CONTROL_PLANE_PROVISIONING_TASK_STACK_BYTES,
NULL,
CONTROL_PLANE_PROVISIONING_TASK_PRIORITY,
&s_provisioning_task);
if (created != pdPASS) {
s_provisioning_task = NULL;
ESP_LOGE(TAG, "Create mini-program provisioning worker failed after BLE start");
(void)domain_runtime_mini_program_provisioning_stop(
CONTROL_PLANE_PROVISIONING_TRANSPORT_STOP_MS);
return ESP_ERR_NO_MEM;
}
esp_err_t err = domain_runtime_mini_program_provisioning_start(
control_plane_provisioning_event_callback,
NULL);
if (err != ESP_OK) {
(void)xEventGroupSetBits(s_provisioning_events,
CONTROL_PLANE_PROVISIONING_STOP_REQUESTED_BIT);
(void)xEventGroupWaitBits(
s_provisioning_events,
CONTROL_PLANE_PROVISIONING_WORKER_DONE_BIT,
pdFALSE,
pdTRUE,
pdMS_TO_TICKS(CONTROL_PLANE_PROVISIONING_TRANSPORT_STOP_MS));
return err;
}
ESP_LOGI(TAG, "Mini-program Wi-Fi provisioning started");
return ESP_OK;
#endif
@@ -443,12 +553,24 @@ esp_err_t control_plane_enter_mini_program_reprovisioning(const char *reason)
ESP_LOGW(TAG, "Entering mini-program BLE reprovisioning: reason=%s",
reason != NULL ? reason : "unspecified");
control_plane_wifi_set_keep_awake(true);
control_plane_set_runtime_stop_requested(true);
control_plane_set_ptt_active(false);
(void)control_plane_local_wake_stop(
CONTROL_PLANE_PROVISIONING_RUNTIME_QUIESCE_MS);
(void)control_plane_stop_multimodal_client();
(void)domain_runtime_multimodal_audio_stop_downstream_playback();
domain_runtime_multimodal_audio_deinit();
control_plane_show_provisioning_ui();
esp_err_t err = domain_runtime_wifi_portal_stop_sta();
if (err == ESP_OK) {
err = control_plane_start_mini_program_provisioning();
}
if (err != ESP_OK) {
control_plane_wifi_set_keep_awake(false);
if (!s_provisioning_recovery_boot) {
control_plane_request_provisioning_recovery_restart(NULL);
}
}
return err;
#endif
@@ -469,7 +591,10 @@ esp_err_t control_plane_bootstrap_connectivity(const char *seed_ssid,
return err;
}
if (domain_runtime_wifi_portal_has_saved_credentials()) {
if (s_provisioning_recovery_boot) {
ESP_LOGW(TAG,
"Low-memory recovery boot skips STA reconnect and enters BLE provisioning");
} else if (domain_runtime_wifi_portal_has_saved_credentials()) {
int timeout_ms = control_plane_normalize_connect_timeout_ms(connect_timeout_ms, 0);
err = control_plane_connect_sta_with_feedback(timeout_ms, true);
if (err == ESP_OK) {
@@ -480,20 +605,26 @@ esp_err_t control_plane_bootstrap_connectivity(const char *seed_ssid,
esp_err_to_name(err));
}
const domain_expression_request_t connecting_request = {
.id = DOMAIN_EXPRESSION_WIFI_CONNECTING,
.trigger = DOMAIN_EXPRESSION_TRIGGER_WIFI_BOOTSTRAP,
};
esp_err_t display_err = domain_runtime_request_expression(&connecting_request);
if (display_err != ESP_OK && display_err != ESP_ERR_INVALID_STATE) {
ESP_LOGW(TAG, "Wi-Fi connecting QR display unavailable: %s",
esp_err_to_name(display_err));
}
control_plane_show_provisioning_ui();
control_plane_wifi_set_keep_awake(true);
err = control_plane_start_mini_program_provisioning();
if (err == ESP_OK && s_provisioning_recovery_boot) {
esp_err_t lcd_err = control_plane_start_lcd_render_worker();
if (lcd_err != ESP_OK && lcd_err != ESP_ERR_NOT_SUPPORTED) {
ESP_LOGW(TAG,
"Start LCD after BLE recovery provisioning failed: %s",
esp_err_to_name(lcd_err));
}
}
if (err != ESP_OK) {
control_plane_wifi_set_keep_awake(false);
if (s_provisioning_recovery_boot) {
ESP_LOGE(TAG,
"Low-memory BLE recovery boot failed; resume normal boot: %s",
esp_err_to_name(err));
s_provisioning_recovery_boot = false;
}
ESP_LOGE(TAG, "BLE provisioning unavailable; SoftAP fallback disabled: %s",
esp_err_to_name(err));
}
+74
View File
@@ -0,0 +1,74 @@
# BLE Provisioning Memory Recovery
## Failure Mode
Runtime Wi-Fi recovery can fall back to mini-program BLE provisioning after
saved network candidates fail. The BLE controller requires contiguous internal
DMA-capable memory even when the NimBLE host is configured to use external RAM.
Starting BLE late in a fragmented runtime previously allowed a controller
allocation to fail inside ROM code, followed by an assertion and an interrupt
watchdog reset.
## Runtime Transition
Before runtime reprovisioning starts BLE, the control plane now:
1. Blocks new runtime work through the runtime stop gate.
2. Clears active PTT state.
3. Stops local wake detection and its owned capture path.
4. Stops the multimodal client and downstream playback.
5. Fully deinitializes the multimodal audio pipeline.
6. Switches the running LCD renderer to the provisioning QR expression.
7. Stops the Wi-Fi station.
The provisioning queue and event group are allocated first. Memory headroom is
then checked before entering the BLE controller. NimBLE is initialized before
the 4096-byte provisioning worker is created, preserving one additional
contiguous internal block during controller startup.
## Memory Gate
BLE initialization proceeds only when both configured thresholds are met:
```text
CONFIG_TQ_MINI_PROGRAM_PROVISIONING_MIN_FREE_INTERNAL_BYTES=49152
CONFIG_TQ_MINI_PROGRAM_PROVISIONING_MIN_LARGEST_DMA_BYTES=12288
```
Both current values and thresholds are logged before BLE startup. These values
are conservative guards against the observed 4096-byte controller allocation
failure and leave room for the controller's preceding allocations.
## Recovery Boot
If the runtime cannot provide enough headroom, the control plane writes a
magic value and its inverse to RTC no-init memory, waits 100 ms for logs, and
performs a controlled software restart. The marker is one-shot and does not
write flash.
On the next boot, application composition keeps the battery safety service but
defers the boot sound, LCD render worker, factory CLI worker, and turntable
calibration. Connectivity skips the saved-credential STA attempt and starts
BLE provisioning before full runtime workers. The LCD renderer starts only
after BLE has secured its controller memory. Successful provisioning tears
down BLE and restarts into the normal boot sequence.
While provisioning is active, the worker logs every 10 seconds that it is
waiting for mini-program credentials. Runtime transitions keep the LCD active
on the provisioning QR expression, so a healthy wait state is distinguishable
from a stalled device.
If recovery-boot BLE startup itself fails, the one-shot mode is cleared and
normal runtime startup resumes instead of entering a restart loop.
## Validation
Required device validation covers:
- normal boot provisioning with no saved credentials;
- runtime Wi-Fi loss followed by failed candidate traversal;
- low-memory fallback through the one-shot recovery boot;
- successful provisioning followed by a normal reboot;
- repeated Wi-Fi/BLE transitions under audio and local-wake load;
- confirmation that no `BLE_INIT: Malloc failed`, ROM assertion, or interrupt
watchdog reset occurs.
+21
View File
@@ -180,6 +180,27 @@ menu "TQ Cat Configuration"
default 2
range 1 10
config TQ_MINI_PROGRAM_PROVISIONING_MIN_FREE_INTERNAL_BYTES
int "Minimum free internal memory before BLE provisioning"
depends on TQ_MINI_PROGRAM_PROVISIONING_ENABLE
default 49152
range 16384 131072
help
BLE controller initialization requires internal DMA-capable
memory even when the NimBLE host uses external RAM. Runtime
reprovisioning performs a controlled recovery boot when free
internal memory remains below this threshold after teardown.
config TQ_MINI_PROGRAM_PROVISIONING_MIN_LARGEST_DMA_BYTES
int "Minimum largest DMA block before BLE provisioning"
depends on TQ_MINI_PROGRAM_PROVISIONING_ENABLE
default 12288
range 4096 65536
help
Minimum contiguous DMA-capable block required before entering
the BLE controller. This headroom prevents the controller ROM
from asserting after a late allocation failure.
endmenu
menu "Runtime Diagnostics"
+2
View File
@@ -19,6 +19,8 @@ CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL=y
CONFIG_TQ_MINI_PROGRAM_PROVISIONING_ENABLE=y
CONFIG_TQ_MINI_PROGRAM_PROVISIONING_CONNECT_TIMEOUT_MS=30000
CONFIG_TQ_MINI_PROGRAM_PROVISIONING_RECONNECT_FAILURES=2
CONFIG_TQ_MINI_PROGRAM_PROVISIONING_MIN_FREE_INTERNAL_BYTES=49152
CONFIG_TQ_MINI_PROGRAM_PROVISIONING_MIN_LARGEST_DMA_BYTES=12288
CONFIG_TQ_WIFI_CONNECT_CYCLE_TIMEOUT_MS=20000
# External PSRAM (ESP32-S3 octal mode)