diff --git a/components/control_plane/src/runtime/control_plane_remote_log_service.c b/components/control_plane/src/runtime/control_plane_remote_log_service.c index eea5e11..665f9ee 100644 --- a/components/control_plane/src/runtime/control_plane_remote_log_service.c +++ b/components/control_plane/src/runtime/control_plane_remote_log_service.c @@ -98,7 +98,7 @@ typedef struct { char text[CONFIG_TQ_REMOTE_LOG_ENTRY_MAX_BYTES]; } remote_log_entry_t; -static remote_log_entry_t s_queue[CONFIG_TQ_REMOTE_LOG_QUEUE_LEN]; +static remote_log_entry_t *s_queue; static size_t s_queue_read; static size_t s_queue_count; static uint32_t s_dropped_count; @@ -119,6 +119,50 @@ static bool s_coredump_reported; static size_t s_coredump_addr; static size_t s_coredump_size; +static void *remote_log_psram_calloc(size_t count, size_t size) +{ + if (count == 0U || size == 0U) { + return NULL; + } + return heap_caps_calloc(count, size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); +} + +static void *remote_log_psram_malloc(size_t size) +{ + if (size == 0U) { + return NULL; + } + return heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); +} + +static bool allocate_queue(void) +{ + if (s_queue != NULL) { + return true; + } + + s_queue = (remote_log_entry_t *)remote_log_psram_calloc( + CONFIG_TQ_REMOTE_LOG_QUEUE_LEN, + sizeof(*s_queue)); + if (s_queue != NULL) { + s_queue_read = 0U; + s_queue_count = 0U; + } + return s_queue != NULL; +} + +static void release_queue(void) +{ + if (s_queue == NULL) { + return; + } + + heap_caps_free(s_queue); + s_queue = NULL; + s_queue_read = 0U; + s_queue_count = 0U; +} + static bool remote_log_path_active(void) { return xTaskGetCurrentTaskHandle() == s_remote_log_task; @@ -165,7 +209,7 @@ static bool should_capture_level(char level) static void enqueue_line(const char *line, bool truncated) { - if (line == NULL || line[0] == '\0') { + if (line == NULL || line[0] == '\0' || s_queue == NULL) { return; } @@ -228,7 +272,7 @@ static int remote_log_vprintf(const char *fmt, va_list args) static bool dequeue_entry(remote_log_entry_t *out_entry) { - if (out_entry == NULL) { + if (out_entry == NULL || s_queue == NULL) { return false; } @@ -760,8 +804,8 @@ static esp_err_t build_upload_body(uint32_t sequence, static bool upload_one_file(uint32_t sequence) { uint32_t dropped = snapshot_and_clear_dropped_count(); - char *body = (char *)malloc(REMOTE_LOG_UPLOAD_BODY_MAX); - char *response = (char *)malloc(REMOTE_LOG_RESPONSE_MAX); + char *body = (char *)remote_log_psram_malloc(REMOTE_LOG_UPLOAD_BODY_MAX); + char *response = (char *)remote_log_psram_malloc(REMOTE_LOG_RESPONSE_MAX); if (body == NULL || response == NULL) { free(body); free(response); @@ -924,8 +968,8 @@ static bool upload_coredump_report(void) return false; } - char *body = (char *)malloc(2048); - char *response = (char *)malloc(REMOTE_LOG_RESPONSE_MAX); + char *body = (char *)remote_log_psram_malloc(2048); + char *response = (char *)remote_log_psram_malloc(REMOTE_LOG_RESPONSE_MAX); if (body == NULL || response == NULL) { free(body); free(response); @@ -971,11 +1015,12 @@ static bool upload_coredump_report(void) static void log_startup_self_check(void) { ESP_LOGW("remote_log", - "enabled endpoint=%s dir=%s pending_files=%u queue=%u max_files=%u file_max=%u coredump_present=%d coredump_size=%u", + "enabled endpoint=%s dir=%s pending_files=%u queue=%u queue_bytes=%u storage=PSRAM max_files=%u file_max=%u coredump_present=%d coredump_size=%u", CONFIG_TQ_REMOTE_LOG_ENDPOINT, REMOTE_LOG_DIR, (unsigned)count_pending_files(), (unsigned)CONFIG_TQ_REMOTE_LOG_QUEUE_LEN, + (unsigned)(CONFIG_TQ_REMOTE_LOG_QUEUE_LEN * sizeof(*s_queue)), (unsigned)CONFIG_TQ_REMOTE_LOG_MAX_FILES, (unsigned)CONFIG_TQ_REMOTE_LOG_FILE_MAX_BYTES, s_coredump_present, @@ -1007,6 +1052,7 @@ static void remote_log_task(void *arg) esp_err_t mount_err = domain_runtime_mount_logfs(); if (mount_err != ESP_OK) { + release_queue(); s_remote_log_task = NULL; vTaskDelete(NULL); return; @@ -1062,6 +1108,14 @@ esp_err_t control_plane_remote_log_start(void) return ESP_OK; } + if (!allocate_queue()) { + ESP_LOGE("remote_log", + "PSRAM queue allocation failed: entries=%u entry_bytes=%u", + (unsigned)CONFIG_TQ_REMOTE_LOG_QUEUE_LEN, + (unsigned)sizeof(*s_queue)); + return ESP_ERR_NO_MEM; + } + s_stop_requested = false; BaseType_t created = xTaskCreatePinnedToCore(remote_log_task, "cp_remote_log", @@ -1071,7 +1125,11 @@ esp_err_t control_plane_remote_log_start(void) &s_remote_log_task, CONFIG_TQ_NETWORK_TASK_CORE < 0 ? tskNO_AFFINITY : (BaseType_t)CONFIG_TQ_NETWORK_TASK_CORE); - return created == pdPASS ? ESP_OK : ESP_ERR_NO_MEM; + if (created != pdPASS) { + release_queue(); + return ESP_ERR_NO_MEM; + } + return ESP_OK; } esp_err_t control_plane_remote_log_flush_now(void) @@ -1152,6 +1210,7 @@ esp_err_t control_plane_remote_log_format_status(char *out, size_t out_len) void control_plane_remote_log_stop(int timeout_ms) { if (s_remote_log_task == NULL) { + release_queue(); return; } @@ -1167,6 +1226,7 @@ void control_plane_remote_log_stop(int timeout_ms) vTaskDelete(s_remote_log_task); s_remote_log_task = NULL; } + release_queue(); } #else esp_err_t control_plane_remote_log_start(void) diff --git a/components/control_plane/src/runtime/control_plane_runtime_workers.c b/components/control_plane/src/runtime/control_plane_runtime_workers.c index 47a29f7..5744fa9 100644 --- a/components/control_plane/src/runtime/control_plane_runtime_workers.c +++ b/components/control_plane/src/runtime/control_plane_runtime_workers.c @@ -22,8 +22,8 @@ #define CONTROL_PLANE_MODEL_CMD_TASK_STACK_SIZE (1024 * 4) #define CONTROL_PLANE_LCD_RENDER_LOOP_TASK_STACK_SIZE (1024 * 12) -#define CONTROL_PLANE_WIFI_STATE_TASK_STACK_SIZE (1024 * 12) -#define CONTROL_PLANE_TASK_MONITOR_TASK_STACK_SIZE (1024 * 6) +#define CONTROL_PLANE_WIFI_STATE_TASK_STACK_SIZE (1024 * 10) +#define CONTROL_PLANE_TASK_MONITOR_TASK_STACK_SIZE (1024 * 4) #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 diff --git a/sdkconfig.defaults b/sdkconfig.defaults index 187c280..0340c22 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -12,6 +12,9 @@ CONFIG_BT_NIMBLE_ROLE_OBSERVER=n CONFIG_BT_NIMBLE_ROLE_BROADCASTER=y CONFIG_BT_NIMBLE_MAX_CONNECTIONS=1 CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE=6144 +CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL=y +# CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL is not set +# CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_DEFAULT is not set CONFIG_TQ_MINI_PROGRAM_PROVISIONING_ENABLE=y CONFIG_TQ_MINI_PROGRAM_PROVISIONING_CONNECT_TIMEOUT_MS=30000 CONFIG_TQ_MINI_PROGRAM_PROVISIONING_RECONNECT_FAILURES=2 @@ -56,7 +59,7 @@ CONFIG_TQ_REMOTE_LOG_ENTRY_MAX_BYTES=256 CONFIG_TQ_REMOTE_LOG_BATCH_MAX_ENTRIES=30 CONFIG_TQ_REMOTE_LOG_FLUSH_INTERVAL_MS=5000 CONFIG_TQ_REMOTE_LOG_UPLOAD_TIMEOUT_MS=8000 -CONFIG_TQ_REMOTE_LOG_MAX_FILES=24 +CONFIG_TQ_REMOTE_LOG_MAX_FILES=12 CONFIG_TQ_REMOTE_LOG_FILE_MAX_BYTES=16384 CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH=y # CONFIG_ESP_COREDUMP_ENABLE_TO_UART is not set @@ -186,14 +189,14 @@ CONFIG_MULTIMODAL_AUDIO_I2S_WS_GPIO=41 CONFIG_MULTIMODAL_AUDIO_I2S_DOUT_GPIO=40 CONFIG_MULTIMODAL_AUDIO_I2S_DIN_GPIO=42 CONFIG_MULTIMODAL_AUDIO_UPLINK_TASK_STACK=32768 -CONFIG_MULTIMODAL_AUDIO_UPLINK_SEND_TASK_STACK=12288 +CONFIG_MULTIMODAL_AUDIO_UPLINK_SEND_TASK_STACK=8192 CONFIG_MULTIMODAL_AUDIO_UPLINK_SEND_QUEUE_LEN=24 CONFIG_MULTIMODAL_AUDIO_UPLINK_SEND_TIMEOUT_MS=5 CONFIG_MULTIMODAL_AUDIO_CODEC_CHANNELS=2 CONFIG_MULTIMODAL_AUDIO_AEC_REFERENCE_CHANNEL=1 CONFIG_MULTIMODAL_AUDIO_AEC_FILTER_LENGTH=4 CONFIG_MULTIMODAL_AUDIO_UPLINK_MAX_PACKET_BYTES=1024 -CONFIG_MULTIMODAL_AUDIO_DOWNSTREAM_PLAYBACK_TASK_STACK=12288 +CONFIG_MULTIMODAL_AUDIO_DOWNSTREAM_PLAYBACK_TASK_STACK=10240 # CONFIG_MULTIMODAL_AUDIO_DOWNSTREAM_DIAGNOSTICS_ENABLE is not set CONFIG_MULTIMODAL_AUDIO_DOWNSTREAM_ACTIVE_STALL_MUTE_MS=3000 CONFIG_MULTIMODAL_AUDIO_DOWNSTREAM_PREBUFFER_MS=160 @@ -232,10 +235,10 @@ CONFIG_MULTIMODAL_RECONNECT_DELAY_MS=2000 CONFIG_ESP_WS_CLIENT_SEPARATE_TX_LOCK=y CONFIG_ESP_WS_CLIENT_TX_LOCK_TIMEOUT_MS=2000 # mbedTLS certificate parsing and dynamic record buffers otherwise compete for -# internal DRAM with LCD/audio/network startup. Use the default allocator so -# ordinary TLS heap can spill to PSRAM when the internal heap is fragmented. +# internal DRAM with LCD/audio/network startup. Allocate TLS heap from PSRAM. # CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC is not set -CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC=y +# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set +CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y CONFIG_MBEDTLS_DYNAMIC_BUFFER=y # TLS renegotiation is not used by the device's HTTPS/WSS clients. With dynamic # TLS buffers and concurrent WebSocket RX/TX, its write-side counter check can