Add memory diagnostics and optimize PSRAM usage
This commit is contained in:
+31
-3
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "esp_heap_caps.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/semphr.h"
|
||||
@@ -16,6 +17,9 @@
|
||||
#define SESSION_BROKER_SLOT_BITS 3U
|
||||
#define SESSION_BROKER_SLOT_MASK ((1U << SESSION_BROKER_SLOT_BITS) - 1U)
|
||||
#define SESSION_BROKER_MAX_GENERATION (UINT32_MAX >> SESSION_BROKER_SLOT_BITS)
|
||||
#define SESSION_BROKER_OUTPUT_STORAGE_SIZE (SESSION_BROKER_OUTPUT_SIZE + 1U)
|
||||
#define SESSION_BROKER_EVENT_STORAGE_SIZE \
|
||||
(SESSION_BROKER_EVENT_QUEUE_LENGTH * sizeof(session_broker_event_t))
|
||||
|
||||
_Static_assert(
|
||||
SESSION_BROKER_MAX_CLIENTS == (1U << SESSION_BROKER_SLOT_BITS),
|
||||
@@ -24,6 +28,10 @@ _Static_assert(
|
||||
typedef struct {
|
||||
StreamBufferHandle_t output;
|
||||
QueueHandle_t events;
|
||||
StaticStreamBuffer_t output_control;
|
||||
StaticQueue_t events_control;
|
||||
uint8_t *output_storage;
|
||||
uint8_t *event_storage;
|
||||
session_broker_client_id_t id;
|
||||
uint32_t generation;
|
||||
session_broker_client_type_t type;
|
||||
@@ -183,6 +191,10 @@ static void cleanup_allocations(void)
|
||||
vStreamBufferDelete(s_slots[i].output);
|
||||
s_slots[i].output = NULL;
|
||||
}
|
||||
heap_caps_free(s_slots[i].event_storage);
|
||||
s_slots[i].event_storage = NULL;
|
||||
heap_caps_free(s_slots[i].output_storage);
|
||||
s_slots[i].output_storage = NULL;
|
||||
}
|
||||
if (s_mutex != NULL) {
|
||||
vSemaphoreDelete(s_mutex);
|
||||
@@ -209,9 +221,25 @@ esp_err_t session_broker_init(void)
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < SESSION_BROKER_MAX_CLIENTS; ++i) {
|
||||
s_slots[i].output = xStreamBufferCreate(SESSION_BROKER_OUTPUT_SIZE, 1U);
|
||||
s_slots[i].events = xQueueCreate(SESSION_BROKER_EVENT_QUEUE_LENGTH,
|
||||
sizeof(session_broker_event_t));
|
||||
s_slots[i].output_storage = heap_caps_calloc_prefer(
|
||||
1U, SESSION_BROKER_OUTPUT_STORAGE_SIZE, 2,
|
||||
MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT,
|
||||
MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
s_slots[i].event_storage = heap_caps_calloc_prefer(
|
||||
1U, SESSION_BROKER_EVENT_STORAGE_SIZE, 2,
|
||||
MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT,
|
||||
MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
if (s_slots[i].output_storage != NULL) {
|
||||
s_slots[i].output = xStreamBufferCreateStatic(
|
||||
SESSION_BROKER_OUTPUT_STORAGE_SIZE, 1U,
|
||||
s_slots[i].output_storage, &s_slots[i].output_control);
|
||||
}
|
||||
if (s_slots[i].event_storage != NULL) {
|
||||
s_slots[i].events = xQueueCreateStatic(
|
||||
SESSION_BROKER_EVENT_QUEUE_LENGTH,
|
||||
sizeof(session_broker_event_t),
|
||||
s_slots[i].event_storage, &s_slots[i].events_control);
|
||||
}
|
||||
if (s_slots[i].output == NULL || s_slots[i].events == NULL) {
|
||||
cleanup_allocations();
|
||||
return ESP_ERR_NO_MEM;
|
||||
|
||||
@@ -94,6 +94,10 @@ static int show_status(bool sessions_only)
|
||||
esp_err_to_name(username_error));
|
||||
}
|
||||
printf("Admission: shell/PTY only; exec, subsystem, forwarding, SCP, and SFTP disabled\n");
|
||||
printf("Owner task: core=%" PRId32 " stack=%" PRIu32
|
||||
" minimum-free=%" PRIu32 " bytes\n",
|
||||
snapshot.task_core_id, snapshot.task_stack_size,
|
||||
snapshot.task_stack_free_minimum);
|
||||
}
|
||||
return print_sessions(&snapshot);
|
||||
}
|
||||
|
||||
+11
-3
@@ -28,6 +28,7 @@
|
||||
|
||||
#define SSH_TRANSPORT_TASK_STACK_SIZE 20480U
|
||||
#define SSH_TRANSPORT_TASK_PRIORITY 5U
|
||||
#define SSH_TRANSPORT_TASK_CORE 1
|
||||
#define SSH_TRANSPORT_LOOP_DELAY_MS 10U
|
||||
#define SSH_TRANSPORT_COMMAND_TIMEOUT_MS 10000U
|
||||
#define SSH_TRANSPORT_RECONCILE_INTERVAL_US 250000LL
|
||||
@@ -984,9 +985,9 @@ esp_err_t ssh_transport_init(void)
|
||||
s_session_snapshots[index].socket_fd = -1;
|
||||
s_session_snapshots[index].state = SSH_TRANSPORT_SESSION_FREE;
|
||||
}
|
||||
BaseType_t created = xTaskCreate(transport_task, "ssh_transport",
|
||||
SSH_TRANSPORT_TASK_STACK_SIZE, NULL,
|
||||
SSH_TRANSPORT_TASK_PRIORITY, &s_task);
|
||||
BaseType_t created = xTaskCreatePinnedToCore(
|
||||
transport_task, "ssh_transport", SSH_TRANSPORT_TASK_STACK_SIZE, NULL,
|
||||
SSH_TRANSPORT_TASK_PRIORITY, &s_task, SSH_TRANSPORT_TASK_CORE);
|
||||
if (created != pdPASS) {
|
||||
s_task = NULL;
|
||||
vSemaphoreDelete(command_mutex);
|
||||
@@ -1127,12 +1128,15 @@ esp_err_t ssh_transport_get_snapshot(ssh_transport_snapshot_t *snapshot)
|
||||
taskEXIT_CRITICAL(&s_lock);
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
TaskHandle_t task = s_task;
|
||||
memset(snapshot, 0, sizeof(*snapshot));
|
||||
snapshot->initialized = s_initialized;
|
||||
snapshot->running = s_running;
|
||||
snapshot->transitioning = s_transitioning;
|
||||
snapshot->port = SSH_TRANSPORT_PORT;
|
||||
snapshot->last_error = s_last_error;
|
||||
snapshot->task_core_id = SSH_TRANSPORT_TASK_CORE;
|
||||
snapshot->task_stack_size = SSH_TRANSPORT_TASK_STACK_SIZE;
|
||||
snapshot->counters = s_counters;
|
||||
for (size_t index = 0U; index < SSH_TRANSPORT_MAX_SESSIONS; ++index) {
|
||||
snapshot->sessions[index] = s_session_snapshots[index];
|
||||
@@ -1141,6 +1145,10 @@ esp_err_t ssh_transport_get_snapshot(ssh_transport_snapshot_t *snapshot)
|
||||
}
|
||||
}
|
||||
taskEXIT_CRITICAL(&s_lock);
|
||||
if (task != NULL) {
|
||||
snapshot->task_stack_free_minimum =
|
||||
(uint32_t)uxTaskGetStackHighWaterMark(task);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -75,6 +75,9 @@ typedef struct {
|
||||
uint16_t port;
|
||||
esp_err_t last_error;
|
||||
uint32_t active_sessions;
|
||||
int32_t task_core_id;
|
||||
uint32_t task_stack_size;
|
||||
uint32_t task_stack_free_minimum;
|
||||
ssh_transport_session_snapshot_t sessions[SSH_TRANSPORT_MAX_SESSIONS];
|
||||
ssh_transport_counters_t counters;
|
||||
} ssh_transport_snapshot_t;
|
||||
|
||||
+43
-2
@@ -3,13 +3,42 @@
|
||||
|
||||
#include "system_console.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "esp_console.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_system.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
static void print_heap_region(const char *name, uint32_t capabilities)
|
||||
{
|
||||
printf("%s: free=%u minimum-free=%u largest-block=%u bytes\n",
|
||||
name,
|
||||
(unsigned int)heap_caps_get_free_size(capabilities),
|
||||
(unsigned int)heap_caps_get_minimum_free_size(capabilities),
|
||||
(unsigned int)heap_caps_get_largest_free_block(capabilities));
|
||||
}
|
||||
|
||||
static int command_memory(int argc, char **argv)
|
||||
{
|
||||
(void)argv;
|
||||
if (argc != 1) {
|
||||
printf("Usage: memory\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
print_heap_region("Internal 8-bit heap",
|
||||
MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
print_heap_region("Internal DMA heap",
|
||||
MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA | MALLOC_CAP_8BIT);
|
||||
print_heap_region("External PSRAM",
|
||||
MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||
printf("Minimum-free is a conservative sum of each matching heap region's lifetime minimum.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int command_reboot(int argc, char **argv)
|
||||
{
|
||||
(void)argv;
|
||||
@@ -28,12 +57,24 @@ static int command_reboot(int argc, char **argv)
|
||||
|
||||
esp_err_t system_console_register_commands(void)
|
||||
{
|
||||
const esp_console_cmd_t command = {
|
||||
const esp_console_cmd_t reboot_command = {
|
||||
.command = "reboot",
|
||||
.help = "Restart the ESP32; unsaved RAM-only configuration is lost",
|
||||
.hint = NULL,
|
||||
.func = &command_reboot,
|
||||
.argtable = NULL,
|
||||
};
|
||||
return esp_console_cmd_register(&command);
|
||||
esp_err_t error = esp_console_cmd_register(&reboot_command);
|
||||
if (error != ESP_OK) {
|
||||
return error;
|
||||
}
|
||||
|
||||
const esp_console_cmd_t memory_command = {
|
||||
.command = "memory",
|
||||
.help = "Show internal and PSRAM heap availability/low-water marks",
|
||||
.hint = NULL,
|
||||
.func = &command_memory,
|
||||
.argtable = NULL,
|
||||
};
|
||||
return esp_console_cmd_register(&memory_command);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user