优化内存占用
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user