feat: Add PROFILE command — heap, stack watermarks, CPU runtime stats
- PROFILE command returns heap usage (free/min/dram/iram), per-task stack high watermark, and per-task CPU % (when CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is enabled) - Enable FreeRTOS runtime stats in sdkconfig.defaults - Enlarge cmd reply buffer to 1400 bytes for multi-line output - Add esp_heap_caps.h include
This commit is contained in:
@@ -31,6 +31,7 @@
|
||||
#include "esp_now.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_task_wdt.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_ota_ops.h"
|
||||
#include "esp_https_ota.h"
|
||||
#include "esp_http_client.h"
|
||||
@@ -848,6 +849,55 @@ static int cmd_handle(const char *cmd, char *reply, size_t reply_size)
|
||||
return strlen(reply);
|
||||
}
|
||||
|
||||
/* PROFILE */
|
||||
if (strcmp(cmd, "PROFILE") == 0) {
|
||||
int pos = 0;
|
||||
/* Heap info */
|
||||
size_t free_heap = esp_get_free_heap_size();
|
||||
size_t min_heap = esp_get_minimum_free_heap_size();
|
||||
size_t free_dram = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
size_t total_dram = heap_caps_get_total_size(MALLOC_CAP_8BIT);
|
||||
size_t free_iram = heap_caps_get_free_size(MALLOC_CAP_IRAM_8BIT);
|
||||
pos += snprintf(reply + pos, reply_size - pos,
|
||||
"OK PROFILE\nHEAP free=%u min=%u dram=%u/%u iram=%u\n",
|
||||
(unsigned)free_heap, (unsigned)min_heap,
|
||||
(unsigned)free_dram, (unsigned)total_dram, (unsigned)free_iram);
|
||||
|
||||
/* Per-task stack watermarks */
|
||||
pos += snprintf(reply + pos, reply_size - pos, "TASKS\n");
|
||||
const char *task_names[] = {"led_task", "cmd_task", "adaptive", "ble_host", "main", NULL};
|
||||
for (int i = 0; task_names[i] != NULL && pos < (int)reply_size - 60; i++) {
|
||||
TaskHandle_t th = xTaskGetHandle(task_names[i]);
|
||||
if (th) {
|
||||
UBaseType_t hwm = uxTaskGetStackHighWaterMark(th);
|
||||
pos += snprintf(reply + pos, reply_size - pos,
|
||||
" %-12s stack_free=%u\n", task_names[i], (unsigned)(hwm * sizeof(StackType_t)));
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS) && CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS
|
||||
/* CPU runtime stats */
|
||||
UBaseType_t n = uxTaskGetNumberOfTasks();
|
||||
TaskStatus_t *tasks = malloc(n * sizeof(TaskStatus_t));
|
||||
if (tasks) {
|
||||
uint32_t total_time;
|
||||
n = uxTaskGetSystemState(tasks, n, &total_time);
|
||||
if (total_time > 0) {
|
||||
pos += snprintf(reply + pos, reply_size - pos, "CPU\n");
|
||||
for (UBaseType_t i = 0; i < n && pos < (int)reply_size - 60; i++) {
|
||||
uint32_t pct = (tasks[i].ulRunTimeCounter * 100) / total_time;
|
||||
if (pct > 0 || tasks[i].ulRunTimeCounter > 0) {
|
||||
pos += snprintf(reply + pos, reply_size - pos,
|
||||
" %-12s %3lu%%\n", tasks[i].pcTaskName, (unsigned long)pct);
|
||||
}
|
||||
}
|
||||
}
|
||||
free(tasks);
|
||||
}
|
||||
#endif
|
||||
return pos;
|
||||
}
|
||||
|
||||
/* OTA <url> */
|
||||
if (strncmp(cmd, "OTA ", 4) == 0) {
|
||||
const char *url = cmd + 4;
|
||||
@@ -899,7 +949,7 @@ static void cmd_task(void *arg)
|
||||
ESP_LOGI(TAG, "Command listener on UDP port %d", CONFIG_CSI_CMD_PORT);
|
||||
|
||||
char rx_buf[128];
|
||||
char reply_buf[256];
|
||||
char reply_buf[1400];
|
||||
struct sockaddr_in src_addr;
|
||||
socklen_t src_len;
|
||||
|
||||
|
||||
@@ -35,6 +35,8 @@ CONFIG_COMPILER_OPTIMIZATION_PERF=y
|
||||
# FreeRTOS
|
||||
#
|
||||
CONFIG_FREERTOS_HZ=1000
|
||||
CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y
|
||||
CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y
|
||||
|
||||
#
|
||||
# ESP32-specific
|
||||
|
||||
Reference in New Issue
Block a user