优化内存占用
This commit is contained in:
@@ -122,5 +122,7 @@ void voice_websocket_event_handler(void *handler_args,
|
|||||||
int32_t event_id,
|
int32_t event_id,
|
||||||
void *event_data);
|
void *event_data);
|
||||||
|
|
||||||
|
void voice_interaction_ws_init_cjson_hooks(void);
|
||||||
|
|
||||||
void voice_uplink_task(void *arg);
|
void voice_uplink_task(void *arg);
|
||||||
void voice_heartbeat_task(void *arg);
|
void voice_heartbeat_task(void *arg);
|
||||||
|
|||||||
@@ -380,7 +380,7 @@ void image_generation_schedule_prewarm(void) {
|
|||||||
s_prewarm_running = true;
|
s_prewarm_running = true;
|
||||||
xSemaphoreGive(s_prewarm_lock);
|
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 (arg == NULL) {
|
||||||
if (xSemaphoreTake(s_prewarm_lock, pdMS_TO_TICKS(100)) == pdTRUE) {
|
if (xSemaphoreTake(s_prewarm_lock, pdMS_TO_TICKS(100)) == pdTRUE) {
|
||||||
s_prewarm_running = false;
|
s_prewarm_running = false;
|
||||||
@@ -390,6 +390,7 @@ void image_generation_schedule_prewarm(void) {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
memset(arg, 0, sizeof(*arg));
|
||||||
image_generation_copy_oss_origin(arg->oss_origin, sizeof(arg->oss_origin));
|
image_generation_copy_oss_origin(arg->oss_origin, sizeof(arg->oss_origin));
|
||||||
|
|
||||||
BaseType_t ok = xTaskCreatePinnedToCore(image_generation_prewarm_task,
|
BaseType_t ok = xTaskCreatePinnedToCore(image_generation_prewarm_task,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "ble_printer_client.h"
|
#include "ble_printer_client.h"
|
||||||
|
#include "esp_heap_caps.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_timer.h"
|
#include "esp_timer.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
@@ -39,6 +40,34 @@ static const char *TAG = "printer_protocol";
|
|||||||
#define PRINT_WORKER_CORE_ID 1
|
#define PRINT_WORKER_CORE_ID 1
|
||||||
#endif
|
#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) {
|
void printer_protocol_set_status_poll_paused(bool paused) {
|
||||||
if (s_mutex == NULL) {
|
if (s_mutex == NULL) {
|
||||||
return;
|
return;
|
||||||
@@ -332,24 +361,18 @@ esp_err_t printer_protocol_init(void) {
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseType_t ok = xTaskCreatePinnedToCore(printer_protocol_worker_task,
|
BaseType_t ok = printer_create_task_prefer_psram(printer_protocol_worker_task,
|
||||||
"print_worker",
|
"print_worker",
|
||||||
6144,
|
6144,
|
||||||
NULL,
|
6);
|
||||||
6,
|
|
||||||
NULL,
|
|
||||||
PRINT_WORKER_CORE_ID);
|
|
||||||
if (ok != pdPASS) {
|
if (ok != pdPASS) {
|
||||||
return ESP_ERR_NO_MEM;
|
return ESP_ERR_NO_MEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
ok = xTaskCreatePinnedToCore(status_poll_task,
|
ok = printer_create_task_prefer_psram(status_poll_task,
|
||||||
"status_poll",
|
"status_poll",
|
||||||
4096,
|
4096,
|
||||||
NULL,
|
4);
|
||||||
4,
|
|
||||||
NULL,
|
|
||||||
PRINT_WORKER_CORE_ID);
|
|
||||||
if (ok != pdPASS) {
|
if (ok != pdPASS) {
|
||||||
return ESP_ERR_NO_MEM;
|
return ESP_ERR_NO_MEM;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ esp_err_t voice_interaction_start(char *err, size_t err_len) {
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
voice_interaction_ws_init_cjson_hooks();
|
||||||
|
|
||||||
ESP_LOGI(TAG, "[stage] opus_setup_begin");
|
ESP_LOGI(TAG, "[stage] opus_setup_begin");
|
||||||
esp_err_t opus_setup_err = voice_setup_opus(err, err_len);
|
esp_err_t opus_setup_err = voice_setup_opus(err, err_len);
|
||||||
if (opus_setup_err != ESP_OK) {
|
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");
|
ESP_LOGI(TAG, "[stage] ws_init_ok");
|
||||||
|
|
||||||
size_t auth_len = strlen(CONFIG_TQ_VOICE_API_KEY) + 8;
|
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) {
|
if (auth_value == NULL) {
|
||||||
voice_fill_err(err, err_len, "no memory for auth header");
|
voice_fill_err(err, err_len, "no memory for auth header");
|
||||||
ESP_LOGE(TAG, "[stage] ws_auth_header_alloc_failed");
|
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_unlock();
|
||||||
|
voice_log_heap_snapshot("tap_start_before_audio_open");
|
||||||
|
|
||||||
esp_err_t audio_err = voice_open_audio_for_dialog(err, err_len);
|
esp_err_t audio_err = voice_open_audio_for_dialog(err, err_len);
|
||||||
if (audio_err != ESP_OK) {
|
if (audio_err != ESP_OK) {
|
||||||
|
voice_log_heap_snapshot("tap_start_audio_open_failed");
|
||||||
return audio_err;
|
return audio_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,18 +71,22 @@ void voice_log_status_snapshot(const char *stage) {
|
|||||||
void voice_log_heap_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_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_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 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_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_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);
|
size_t largest_spiram = heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||||
ESP_LOGI(TAG,
|
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,
|
stage,
|
||||||
(unsigned)free_8bit,
|
(unsigned)free_8bit,
|
||||||
(unsigned)free_internal,
|
(unsigned)free_internal,
|
||||||
|
(unsigned)free_dma,
|
||||||
(unsigned)free_spiram,
|
(unsigned)free_spiram,
|
||||||
(unsigned)largest_8bit,
|
(unsigned)largest_8bit,
|
||||||
(unsigned)largest_internal,
|
(unsigned)largest_internal,
|
||||||
|
(unsigned)largest_dma,
|
||||||
(unsigned)largest_spiram);
|
(unsigned)largest_spiram);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,11 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#define cJSON_malloc voice_malloc_prefer_psram
|
||||||
|
#define cJSON_realloc voice_realloc_prefer_psram
|
||||||
#include "cJSON.h"
|
#include "cJSON.h"
|
||||||
|
#undef cJSON_realloc
|
||||||
|
#undef cJSON_malloc
|
||||||
#include "esp_audio_dec.h"
|
#include "esp_audio_dec.h"
|
||||||
#include "esp_audio_enc.h"
|
#include "esp_audio_enc.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
@@ -25,9 +29,33 @@ typedef struct {
|
|||||||
char dialog_id[40];
|
char dialog_id[40];
|
||||||
} voice_image_generation_task_arg_t;
|
} 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,
|
static char *voice_build_directive_message(const char *action,
|
||||||
const char *directive,
|
const char *directive,
|
||||||
bool with_dialog_id) {
|
bool with_dialog_id) {
|
||||||
|
voice_cjson_init_hooks_once();
|
||||||
|
|
||||||
cJSON *root = cJSON_CreateObject();
|
cJSON *root = cJSON_CreateObject();
|
||||||
if (root == NULL) {
|
if (root == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -51,6 +79,8 @@ static char *voice_build_directive_message(const char *action,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static char *voice_build_start_message(void) {
|
static char *voice_build_start_message(void) {
|
||||||
|
voice_cjson_init_hooks_once();
|
||||||
|
|
||||||
cJSON *root = cJSON_CreateObject();
|
cJSON *root = cJSON_CreateObject();
|
||||||
if (root == NULL) {
|
if (root == NULL) {
|
||||||
return 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) {
|
static void voice_handle_text_message(const char *text, size_t len) {
|
||||||
|
voice_cjson_init_hooks_once();
|
||||||
|
|
||||||
cJSON *root = cJSON_ParseWithLength(text, len);
|
cJSON *root = cJSON_ParseWithLength(text, len);
|
||||||
if (root == NULL) {
|
if (root == NULL) {
|
||||||
ESP_LOGW(TAG, "Invalid ws text payload");
|
ESP_LOGW(TAG, "Invalid ws text payload");
|
||||||
|
|||||||
@@ -2,9 +2,25 @@
|
|||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "esp_heap_caps.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "mbedtls/platform.h"
|
||||||
#include "nvs_flash.h"
|
#include "nvs_flash.h"
|
||||||
|
|
||||||
static bool s_initialized;
|
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) {
|
esp_err_t platform_bootstrap_init(void) {
|
||||||
if (s_initialized) {
|
if (s_initialized) {
|
||||||
@@ -18,6 +34,21 @@ esp_err_t platform_bootstrap_init(void) {
|
|||||||
}
|
}
|
||||||
ESP_ERROR_CHECK(err);
|
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;
|
s_initialized = true;
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user