Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions components/esp_websocket_client/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,27 @@ menu "ESP WebSocket client"
default 2000
help
Timeout for acquiring the TX lock when using separate TX lock.

config ESP_WS_CLIENT_ALLOC_IN_EXT_RAM
bool "Allocate esp_websocket_client structure and config storage in PSRAM"
default n
depends on SPIRAM
help
Enable this option to allocate the esp_websocket_client structure and its
internal configuration storage in external RAM (PSRAM). This is useful for
freeing up internal RAM in memory-constrained applications.
If PSRAM allocation fails, esp_websocket_client_init() returns NULL.
There is no fallback to internal RAM.

config ESP_WS_CLIENT_TASK_STACK_IN_EXT_RAM
bool "Allocate websocket task stack in PSRAM"
default n
depends on SPIRAM
depends on FREERTOS_SUPPORT_STATIC_ALLOCATION
help
Enable this option to allocate the WebSocket task stack in external RAM (PSRAM)
using xTaskCreateStaticPinnedToCore. Only the task stack is placed in PSRAM;
the TCB (Task Control Block) remains in internal RAM as required by the API.
If PSRAM stack allocation fails, esp_websocket_client_start() returns ESP_FAIL.
There is no fallback to internal RAM.
endmenu
62 changes: 59 additions & 3 deletions components/esp_websocket_client/esp_websocket_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ struct esp_websocket_client {
int close_status_code; /*!< Status code from the last received CLOSE frame (0 = none / client-initiated) */
esp_transport_keep_alive_t keep_alive_cfg;
struct ifreq *if_name;
#if CONFIG_ESP_WS_CLIENT_TASK_STACK_IN_EXT_RAM
StackType_t *task_stack_buffer;
StaticTask_t *task_buffer;
Comment thread
shardt68 marked this conversation as resolved.
#endif
};

static uint64_t _tick_get_ms(void)
Expand Down Expand Up @@ -527,6 +531,16 @@ static void destroy_and_free_resources(esp_websocket_client_handle_t client)
vEventGroupDelete(client->status_bits);
client->status_bits = NULL;
}
#if CONFIG_ESP_WS_CLIENT_TASK_STACK_IN_EXT_RAM
if (client->task_stack_buffer) {
heap_caps_free(client->task_stack_buffer);
client->task_stack_buffer = NULL;
}
if (client->task_buffer) {
heap_caps_free(client->task_buffer);
client->task_buffer = NULL;
}
Comment thread
cursor[bot] marked this conversation as resolved.
#endif
free(client);
client = NULL;
}
Expand All @@ -546,7 +560,6 @@ static esp_err_t stop_wait_task(esp_websocket_client_handle_t client)
client->state = WEBSOCKET_STATE_UNKNOW;
return ESP_OK;
}

#if WS_TRANSPORT_HEADER_CALLBACK_SUPPORT
static void websocket_header_hook(void * client, const char * line, int line_len)
{
Expand Down Expand Up @@ -777,7 +790,11 @@ static int esp_websocket_client_send_with_exact_opcode(esp_websocket_client_hand

esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_client_config_t *config)
{
#if CONFIG_ESP_WS_CLIENT_ALLOC_IN_EXT_RAM
esp_websocket_client_handle_t client = heap_caps_calloc(1, sizeof(struct esp_websocket_client), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
#else
esp_websocket_client_handle_t client = calloc(1, sizeof(struct esp_websocket_client));
#endif
ESP_WS_CLIENT_MEM_CHECK(TAG, client, return NULL);

esp_event_loop_args_t event_args = {
Expand Down Expand Up @@ -812,7 +829,11 @@ esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_clie
ESP_WS_CLIENT_MEM_CHECK(TAG, client->tx_lock, goto _websocket_init_fail);
#endif

#if CONFIG_ESP_WS_CLIENT_ALLOC_IN_EXT_RAM
client->config = heap_caps_calloc(1, sizeof(websocket_config_storage_t), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
#else
client->config = calloc(1, sizeof(websocket_config_storage_t));
#endif
ESP_WS_CLIENT_MEM_CHECK(TAG, client->config, goto _websocket_init_fail);

if (config->transport == WEBSOCKET_TRANSPORT_OVER_TCP) {
Expand Down Expand Up @@ -1429,6 +1450,7 @@ esp_err_t esp_websocket_client_start(esp_websocket_client_handle_t client)
if (client == NULL) {
return ESP_ERR_INVALID_ARG;
}

if (client->state >= WEBSOCKET_STATE_INIT) {
ESP_LOGE(TAG, "The client has started");
return ESP_FAIL;
Expand All @@ -1442,8 +1464,42 @@ esp_err_t esp_websocket_client_start(esp_websocket_client_handle_t client)
}
}

if (xTaskCreatePinnedToCore(esp_websocket_client_task, client->config->task_name ? client->config->task_name : "websocket_task",
client->config->task_stack, client, client->config->task_prio, &client->task_handle, client->config->task_core_id) != pdTRUE) {
BaseType_t res = pdPASS;
#if CONFIG_ESP_WS_CLIENT_TASK_STACK_IN_EXT_RAM
if (client->task_stack_buffer == NULL) {
client->task_stack_buffer = (StackType_t *)heap_caps_calloc(1, client->config->task_stack, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
}
// TCB must be in internal RAM for xTaskCreateStaticPinnedToCore
if (client->task_buffer == NULL) {
client->task_buffer = (StaticTask_t *)heap_caps_calloc(1, sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
}

if (client->task_stack_buffer && client->task_buffer) {
ESP_LOGI(TAG, "Allocated %d bytes stack in PSRAM for WebSocket task", client->config->task_stack);
client->task_handle = xTaskCreateStaticPinnedToCore(
esp_websocket_client_task,
client->config->task_name ? client->config->task_name : "websocket_task",
client->config->task_stack,
client,
client->config->task_prio,
client->task_stack_buffer,
client->task_buffer,
client->config->task_core_id
);
if (client->task_handle == NULL) {
res = pdFAIL;
}
} else {
ESP_LOGE(TAG, "Failed to allocate PSRAM stack for WebSocket task");
res = pdFAIL;
}
Comment thread
cursor[bot] marked this conversation as resolved.
#else
res = xTaskCreatePinnedToCore(esp_websocket_client_task, client->config->task_name ? client->config->task_name : "websocket_task",
client->config->task_stack, client, client->config->task_prio, &client->task_handle, client->config->task_core_id);
#endif

if (res != pdPASS || client->task_handle == NULL) {
client->task_handle = NULL;
ESP_LOGE(TAG, "Error create websocket task");
return ESP_FAIL;
}
Expand Down
Loading