fix(control-plane): optimize task monitoring and worker stacks

This commit is contained in:
chenjintao
2026-08-21 17:52:10 +08:00
parent cb203a74f4
commit a60f98a4c6
6 changed files with 139 additions and 37 deletions
@@ -36,10 +36,14 @@
#define CONFIG_MULTIMODAL_AUDIO_PREWARM_OPUS_BEFORE_WS 1
#endif
#ifndef CONFIG_TQ_MULTIMODAL_WATCHDOG_TASK_STACK_BYTES
#define CONFIG_TQ_MULTIMODAL_WATCHDOG_TASK_STACK_BYTES (6U * 1024U)
#endif
#define CONTROL_PLANE_DOWNSTREAM_PLAYBACK_GUARD_MS 220
#define CONTROL_PLANE_DOWNSTREAM_STALL_STOP_GRACE_MS 2000
#define CONTROL_PLANE_IDLE_TRANSPORT_SHUTDOWN_MS 30000
#define CONTROL_PLANE_WATCHDOG_TASK_STACK_SIZE 8192
#define CONTROL_PLANE_WATCHDOG_TASK_STACK_SIZE CONFIG_TQ_MULTIMODAL_WATCHDOG_TASK_STACK_BYTES
#define CONTROL_PLANE_SERVER_SUCCESS_PROMPT_FILE "/littlefs/audio_prompts/server_connect_success.opus"
#define CONTROL_PLANE_CLIENT_LIFECYCLE_WAIT_MS 30000U
#define CONTROL_PLANE_SERVER_SUCCESS_PROMPT_RETRY_MS 1000U
@@ -30,7 +30,11 @@
#define FACTORY_CLI_SERIAL_MAX_LEN 64
#define FACTORY_CLI_JSON_MAX_LEN 640
#define FACTORY_CLI_READ_TIMEOUT_MS 100
#define FACTORY_CLI_WORKER_STACK_BYTES (12U * 1024U)
#ifndef CONFIG_TQ_FACTORY_CLI_TASK_STACK_BYTES
#define CONFIG_TQ_FACTORY_CLI_TASK_STACK_BYTES (10U * 1024U)
#endif
#define FACTORY_CLI_WORKER_STACK_BYTES CONFIG_TQ_FACTORY_CLI_TASK_STACK_BYTES
#define FACTORY_CLI_WORKER_PRIORITY 4
#define FACTORY_CLI_STOP_WAIT_STEPS 100
#define FACTORY_CLI_STOP_WAIT_STEP_MS 20
@@ -20,10 +20,16 @@
#include "freertos/task.h"
#include "sdkconfig.h"
#ifndef CONFIG_TQ_LCD_RENDER_TASK_STACK_BYTES
#define CONFIG_TQ_LCD_RENDER_TASK_STACK_BYTES (10U * 1024U)
#endif
#define CONTROL_PLANE_MODEL_CMD_TASK_STACK_SIZE (1024 * 4)
#define CONTROL_PLANE_LCD_RENDER_LOOP_TASK_STACK_SIZE (1024 * 12)
#define CONTROL_PLANE_LCD_RENDER_LOOP_TASK_STACK_SIZE CONFIG_TQ_LCD_RENDER_TASK_STACK_BYTES
#define CONTROL_PLANE_WIFI_STATE_TASK_STACK_SIZE (1024 * 10)
#define CONTROL_PLANE_TASK_MONITOR_TASK_STACK_SIZE (1024 * 4)
#define CONTROL_PLANE_TASK_MONITOR_STACK_WARN_BYTES 1024U
#define CONTROL_PLANE_TASK_MONITOR_FULL_REPORT_PERIOD 5U
#define CONTROL_PLANE_REMOTE_LOG_STOP_WAIT_MS 1500
#define CONTROL_PLANE_MODEL_CMD_QUEUE_LEN 4
#define CONTROL_PLANE_MODEL_CMD_RECV_TIMEOUT_MS 200
@@ -1404,7 +1410,39 @@ static const char *control_plane_task_core_name(BaseType_t core_id,
return buffer;
}
static void control_plane_log_task_table(void)
static void control_plane_log_task_status(const TaskStatus_t *task, bool warn)
{
if (task == NULL) {
return;
}
char core_buf[12] = {0};
const char *name = task->pcTaskName != NULL ? task->pcTaskName : "?";
const char *state = control_plane_task_state_name(task->eCurrentState);
const char *core = control_plane_task_core_name(
xTaskGetCoreID(task->xHandle), core_buf, sizeof(core_buf));
if (warn) {
ESP_LOGW(TAG,
"Task stack headroom low: name=%s state=%s priority=%u headroom=%uB core=%s",
name,
state,
(unsigned int)task->uxCurrentPriority,
(unsigned int)task->usStackHighWaterMark,
core);
return;
}
ESP_LOGI(TAG,
"%-16s %-5s %-4u %-10u %-4s %-10lu",
name,
state,
(unsigned int)task->uxCurrentPriority,
(unsigned int)task->usStackHighWaterMark,
core,
(unsigned long)task->ulRunTimeCounter);
}
static void control_plane_log_task_table(bool full_report)
{
#if !configUSE_TRACE_FACILITY
ESP_LOGW(TAG, "Task monitor requires CONFIG_FREERTOS_USE_TRACE_FACILITY");
@@ -1422,42 +1460,61 @@ static void control_plane_log_task_table(void)
return;
}
TaskStatus_t *tasks = (TaskStatus_t *)calloc(capture_count, sizeof(TaskStatus_t));
TaskStatus_t *tasks = (TaskStatus_t *)heap_caps_calloc(
capture_count,
sizeof(TaskStatus_t),
MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
if (tasks == NULL) {
ESP_LOGW(TAG, "Task monitor allocation failed: entries=%u",
ESP_LOGW(TAG, "Task monitor PSRAM snapshot allocation failed: entries=%u",
(unsigned int)capture_count);
return;
}
uint32_t total_runtime = 0;
UBaseType_t captured = uxTaskGetSystemState(tasks, capture_count, &total_runtime);
const TaskStatus_t *lowest = NULL;
UBaseType_t low_count = 0U;
for (UBaseType_t i = 0; i < captured; ++i) {
if (lowest == NULL ||
tasks[i].usStackHighWaterMark < lowest->usStackHighWaterMark) {
lowest = &tasks[i];
}
if (tasks[i].usStackHighWaterMark <
CONTROL_PLANE_TASK_MONITOR_STACK_WARN_BYTES) {
low_count++;
}
}
ESP_LOGI(TAG,
"Task monitor: total=%u captured=%u runtime=%lu",
"Task monitor summary: total=%u captured=%u runtime=%lu lowest=%s/%uB low=%u snapshot=PSRAM full=%d",
(unsigned int)task_count,
(unsigned int)captured,
(unsigned long)total_runtime);
ESP_LOGI(TAG, "%-16s %-5s %-4s %-7s %-4s %-10s",
(unsigned long)total_runtime,
lowest != NULL && lowest->pcTaskName != NULL ? lowest->pcTaskName : "?",
lowest != NULL ? (unsigned int)lowest->usStackHighWaterMark : 0U,
(unsigned int)low_count,
full_report ? 1 : 0);
if (!full_report) {
heap_caps_free(tasks);
return;
}
ESP_LOGI(TAG, "%-16s %-5s %-4s %-10s %-4s %-10s",
"name",
"state",
"prio",
"stack",
"headroom",
"core",
"runtime");
for (UBaseType_t i = 0; i < captured; ++i) {
char core_buf[12] = {0};
ESP_LOGI(TAG,
"%-16s %-5s %-4u %-7u %-4s %-10lu",
tasks[i].pcTaskName != NULL ? tasks[i].pcTaskName : "?",
control_plane_task_state_name(tasks[i].eCurrentState),
(unsigned int)tasks[i].uxCurrentPriority,
(unsigned int)tasks[i].usStackHighWaterMark,
control_plane_task_core_name(xTaskGetCoreID(tasks[i].xHandle), core_buf, sizeof(core_buf)),
(unsigned long)tasks[i].ulRunTimeCounter);
control_plane_log_task_status(
&tasks[i],
tasks[i].usStackHighWaterMark <
CONTROL_PLANE_TASK_MONITOR_STACK_WARN_BYTES);
}
free(tasks);
heap_caps_free(tasks);
#endif
}
@@ -1466,9 +1523,11 @@ static void control_plane_task_monitor_task(void *arg)
(void)arg;
ESP_LOGI(TAG,
"Task monitor started interval=%dms max_tasks=%d",
"Task monitor started interval=%dms max_tasks=%d stack=PSRAM-preferred snapshot=PSRAM full_period=%u warn=%uB",
CONFIG_TQ_TASK_MONITOR_INTERVAL_MS,
CONFIG_TQ_TASK_MONITOR_MAX_TASKS);
CONFIG_TQ_TASK_MONITOR_MAX_TASKS,
(unsigned)CONTROL_PLANE_TASK_MONITOR_FULL_REPORT_PERIOD,
(unsigned)CONTROL_PLANE_TASK_MONITOR_STACK_WARN_BYTES);
TickType_t interval_ticks = pdMS_TO_TICKS(CONFIG_TQ_TASK_MONITOR_INTERVAL_MS);
if (interval_ticks == 0) {
@@ -1478,8 +1537,12 @@ static void control_plane_task_monitor_task(void *arg)
interval_ticks = 1;
}
uint32_t report_count = 0U;
while (!control_plane_runtime_stop_requested()) {
control_plane_log_task_table();
bool full_report =
(report_count % CONTROL_PLANE_TASK_MONITOR_FULL_REPORT_PERIOD) == 0U;
control_plane_log_task_table(full_report);
report_count++;
vTaskDelay(interval_ticks);
}
@@ -2549,12 +2612,13 @@ esp_err_t control_plane_start_runtime_workers(void)
#if CONFIG_TQ_TASK_MONITOR_ENABLE
if (control_plane_get_task_handle(&s_task_monitor_task) == NULL) {
esp_err_t task_err = control_plane_create_task(control_plane_task_monitor_task,
"cp_task_monitor",
CONTROL_PLANE_TASK_MONITOR_TASK_STACK_SIZE,
3,
CONTROL_PLANE_LOCAL_TASK_CORE,
&s_task_monitor_task);
esp_err_t task_err = control_plane_create_task_psram_first(
control_plane_task_monitor_task,
"cp_task_monitor",
CONTROL_PLANE_TASK_MONITOR_TASK_STACK_SIZE,
3,
CONTROL_PLANE_LOCAL_TASK_CORE,
&s_task_monitor_task);
if (task_err != ESP_OK) {
control_plane_stop_runtime_workers();
return task_err;
@@ -2703,7 +2767,7 @@ void control_plane_stop_runtime_workers(void)
}
#if CONFIG_TQ_TASK_MONITOR_ENABLE
if (!control_plane_wait_task_exit(&s_task_monitor_task, CONTROL_PLANE_TASK_STOP_WAIT_MS)) {
control_plane_force_delete_task(&s_task_monitor_task, "cp_task_monitor");
control_plane_force_delete_task_with_caps(&s_task_monitor_task, "cp_task_monitor");
}
#endif
#if CONFIG_FORTUNE_ENABLE
@@ -27,7 +27,7 @@
#endif
#ifndef CONFIG_TQ_SYSTEM_EVENT_TASK_STACK
#define CONFIG_TQ_SYSTEM_EVENT_TASK_STACK 4096
#define CONFIG_TQ_SYSTEM_EVENT_TASK_STACK 6144
#endif
#if !defined(CONFIG_TQ_PTT_MODE_HOLD_TO_TALK) && !defined(CONFIG_TQ_PTT_MODE_CLICK_TO_TALK)