优化内存占用

This commit is contained in:
admin
2026-02-25 18:12:22 +08:00
parent ac4f4693b9
commit 1cb1f5de64
7 changed files with 114 additions and 17 deletions

View File

@@ -122,5 +122,7 @@ void voice_websocket_event_handler(void *handler_args,
int32_t event_id,
void *event_data);
void voice_interaction_ws_init_cjson_hooks(void);
void voice_uplink_task(void *arg);
void voice_heartbeat_task(void *arg);

View File

@@ -380,7 +380,7 @@ void image_generation_schedule_prewarm(void) {
s_prewarm_running = true;
xSemaphoreGive(s_prewarm_lock);
image_prewarm_task_arg_t *arg = (image_prewarm_task_arg_t *)calloc(1, sizeof(*arg));
image_prewarm_task_arg_t *arg = (image_prewarm_task_arg_t *)malloc_prefer_psram(sizeof(*arg));
if (arg == NULL) {
if (xSemaphoreTake(s_prewarm_lock, pdMS_TO_TICKS(100)) == pdTRUE) {
s_prewarm_running = false;
@@ -390,6 +390,7 @@ void image_generation_schedule_prewarm(void) {
}
return;
}
memset(arg, 0, sizeof(*arg));
image_generation_copy_oss_origin(arg->oss_origin, sizeof(arg->oss_origin));
BaseType_t ok = xTaskCreatePinnedToCore(image_generation_prewarm_task,

View File

@@ -5,6 +5,7 @@
#include <string.h>
#include "ble_printer_client.h"
#include "esp_heap_caps.h"
#include "esp_log.h"
#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
@@ -39,6 +40,34 @@ static const char *TAG = "printer_protocol";
#define PRINT_WORKER_CORE_ID 1
#endif
static BaseType_t printer_create_task_prefer_psram(TaskFunction_t task_fn,
const char *name,
uint32_t stack_size,
UBaseType_t priority) {
#if defined(CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY) && \
defined(CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM) && \
(configSUPPORT_STATIC_ALLOCATION == 1)
BaseType_t rc = xTaskCreatePinnedToCoreWithCaps(task_fn,
name,
(configSTACK_DEPTH_TYPE)stack_size,
NULL,
priority,
NULL,
PRINT_WORKER_CORE_ID,
MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
if (rc == pdPASS) {
return pdPASS;
}
#endif
return xTaskCreatePinnedToCore(task_fn,
name,
(configSTACK_DEPTH_TYPE)stack_size,
NULL,
priority,
NULL,
PRINT_WORKER_CORE_ID);
}
void printer_protocol_set_status_poll_paused(bool paused) {
if (s_mutex == NULL) {
return;
@@ -332,24 +361,18 @@ esp_err_t printer_protocol_init(void) {
return err;
}
BaseType_t ok = xTaskCreatePinnedToCore(printer_protocol_worker_task,
BaseType_t ok = printer_create_task_prefer_psram(printer_protocol_worker_task,
"print_worker",
6144,
NULL,
6,
NULL,
PRINT_WORKER_CORE_ID);
6);
if (ok != pdPASS) {
return ESP_ERR_NO_MEM;
}
ok = xTaskCreatePinnedToCore(status_poll_task,
ok = printer_create_task_prefer_psram(status_poll_task,
"status_poll",
4096,
NULL,
4,
NULL,
PRINT_WORKER_CORE_ID);
4);
if (ok != pdPASS) {
return ESP_ERR_NO_MEM;
}

View File

@@ -80,6 +80,8 @@ esp_err_t voice_interaction_start(char *err, size_t err_len) {
return ESP_OK;
}
voice_interaction_ws_init_cjson_hooks();
ESP_LOGI(TAG, "[stage] opus_setup_begin");
esp_err_t opus_setup_err = voice_setup_opus(err, err_len);
if (opus_setup_err != ESP_OK) {
@@ -138,7 +140,7 @@ esp_err_t voice_interaction_start(char *err, size_t err_len) {
ESP_LOGI(TAG, "[stage] ws_init_ok");
size_t auth_len = strlen(CONFIG_TQ_VOICE_API_KEY) + 8;
char *auth_value = (char *)malloc(auth_len);
char *auth_value = (char *)voice_malloc_prefer_psram(auth_len);
if (auth_value == NULL) {
voice_fill_err(err, err_len, "no memory for auth header");
ESP_LOGE(TAG, "[stage] ws_auth_header_alloc_failed");
@@ -360,9 +362,11 @@ esp_err_t voice_interaction_tap_start(char *err, size_t err_len) {
}
voice_unlock();
voice_log_heap_snapshot("tap_start_before_audio_open");
esp_err_t audio_err = voice_open_audio_for_dialog(err, err_len);
if (audio_err != ESP_OK) {
voice_log_heap_snapshot("tap_start_audio_open_failed");
return audio_err;
}

View File

@@ -71,18 +71,22 @@ void voice_log_status_snapshot(const char *stage) {
void voice_log_heap_snapshot(const char *stage) {
size_t free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
size_t free_internal = heap_caps_get_free_size(MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
size_t free_dma = heap_caps_get_free_size(MALLOC_CAP_DMA | MALLOC_CAP_8BIT);
size_t free_spiram = heap_caps_get_free_size(MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
size_t largest_8bit = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT);
size_t largest_internal = heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
size_t largest_dma = heap_caps_get_largest_free_block(MALLOC_CAP_DMA | MALLOC_CAP_8BIT);
size_t largest_spiram = heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
ESP_LOGI(TAG,
"[stage] %s heap: free8=%u free_internal=%u free_spiram=%u largest8=%u largest_internal=%u largest_spiram=%u",
"[stage] %s heap: free8=%u free_internal=%u free_dma=%u free_spiram=%u largest8=%u largest_internal=%u largest_dma=%u largest_spiram=%u",
stage,
(unsigned)free_8bit,
(unsigned)free_internal,
(unsigned)free_dma,
(unsigned)free_spiram,
(unsigned)largest_8bit,
(unsigned)largest_internal,
(unsigned)largest_dma,
(unsigned)largest_spiram);
}

View File

@@ -6,7 +6,11 @@
#include <stdlib.h>
#include <string.h>
#define cJSON_malloc voice_malloc_prefer_psram
#define cJSON_realloc voice_realloc_prefer_psram
#include "cJSON.h"
#undef cJSON_realloc
#undef cJSON_malloc
#include "esp_audio_dec.h"
#include "esp_audio_enc.h"
#include "esp_log.h"
@@ -25,9 +29,33 @@ typedef struct {
char dialog_id[40];
} voice_image_generation_task_arg_t;
static void *voice_cjson_malloc_hook(size_t size) {
return voice_malloc_prefer_psram(size);
}
static void voice_cjson_init_hooks_once(void) {
static bool s_cjson_hooks_ready;
if (s_cjson_hooks_ready) {
return;
}
cJSON_Hooks hooks = {
.malloc_fn = voice_cjson_malloc_hook,
.free_fn = free,
};
cJSON_InitHooks(&hooks);
s_cjson_hooks_ready = true;
}
void voice_interaction_ws_init_cjson_hooks(void) {
voice_cjson_init_hooks_once();
}
static char *voice_build_directive_message(const char *action,
const char *directive,
bool with_dialog_id) {
voice_cjson_init_hooks_once();
cJSON *root = cJSON_CreateObject();
if (root == NULL) {
return NULL;
@@ -51,6 +79,8 @@ static char *voice_build_directive_message(const char *action,
}
static char *voice_build_start_message(void) {
voice_cjson_init_hooks_once();
cJSON *root = cJSON_CreateObject();
if (root == NULL) {
return NULL;
@@ -617,6 +647,8 @@ static void voice_handle_output_event(cJSON *output) {
}
static void voice_handle_text_message(const char *text, size_t len) {
voice_cjson_init_hooks_once();
cJSON *root = cJSON_ParseWithLength(text, len);
if (root == NULL) {
ESP_LOGW(TAG, "Invalid ws text payload");

View File

@@ -2,9 +2,25 @@
#include <stdbool.h>
#include "esp_heap_caps.h"
#include "esp_log.h"
#include "mbedtls/platform.h"
#include "nvs_flash.h"
static bool s_initialized;
static const char *TAG = "platform_bootstrap";
static void *tls_calloc_prefer_psram(size_t n, size_t size) {
void *ptr = heap_caps_calloc(n, size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
if (ptr == NULL) {
ptr = heap_caps_calloc(n, size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
}
return ptr;
}
static void tls_free(void *ptr) {
heap_caps_free(ptr);
}
esp_err_t platform_bootstrap_init(void) {
if (s_initialized) {
@@ -18,6 +34,21 @@ esp_err_t platform_bootstrap_init(void) {
}
ESP_ERROR_CHECK(err);
#if CONFIG_SPIRAM_USE_MALLOC
// Keep very small allocations on internal RAM, push larger generic mallocs to PSRAM.
heap_caps_malloc_extmem_enable(4096);
ESP_LOGI(TAG, "extmem malloc threshold set to 4096 bytes");
#endif
#if defined(MBEDTLS_PLATFORM_MEMORY)
int tls_rc = mbedtls_platform_set_calloc_free(tls_calloc_prefer_psram, tls_free);
if (tls_rc == 0) {
ESP_LOGI(TAG, "mbedtls calloc/free redirected to PSRAM-preferred allocator");
} else {
ESP_LOGW(TAG, "mbedtls calloc/free redirect failed: rc=%d", tls_rc);
}
#endif
s_initialized = true;
return ESP_OK;
}