195 lines
6.5 KiB
C++
195 lines
6.5 KiB
C++
#include "utils.h"
|
|
#include "freertos_stats.h"
|
|
#include "sdkconfig.h"
|
|
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/portable.h"
|
|
|
|
#include "esp_heap_caps.h"
|
|
#include "esp_system.h"
|
|
#include "esp_spi_flash.h"
|
|
#include "esp_partition.h"
|
|
#include "LittleFS.h"
|
|
|
|
#include <vector>
|
|
#include <algorithm>
|
|
#include <functional>
|
|
|
|
#define FREERTOS_TASK_NUMBER_MAX_NUM 256 // RunTime stats for how many Tasks to be stored
|
|
|
|
std::string printBits(uint32_t value)
|
|
{
|
|
std::string result;
|
|
for (int i = 31; i >= 0; i--)
|
|
{
|
|
// ottieni il singolo bit
|
|
result += ((value >> i) & 1) ? '1' : '0';
|
|
// aggiungi uno spazio ogni 8 bit, tranne dopo l'ultimo
|
|
if (i % 8 == 0 && i != 0)
|
|
{
|
|
result += ' ';
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// ANSI colors
|
|
#define BAR_WIDTH 30
|
|
#define COLOR_RESET "\033[0m"
|
|
#define COLOR_RED "\033[31m"
|
|
#define COLOR_GREEN "\033[32m"
|
|
#define COLOR_BLUE "\033[34m"
|
|
#define COLOR_MAGENTA "\033[35m"
|
|
#define COLOR_CYAN "\033[36m"
|
|
#define COLOR_YELLOW "\033[33m"
|
|
#define COLOR_WHITE "\033[37m"
|
|
#define COLOR_LBLUE "\033[94m"
|
|
|
|
void printBar(Print &printer, const char *label, size_t used, size_t total, const char *color)
|
|
{
|
|
float perc = total > 0 ? ((float)used / total) : 0;
|
|
int filled = perc * BAR_WIDTH;
|
|
|
|
printer.printf("%s%-12s [" COLOR_RESET, color, label);
|
|
|
|
for (int i = 0; i < BAR_WIDTH; i++)
|
|
{
|
|
if (i < filled)
|
|
printer.printf("%s#%s", color, COLOR_RESET);
|
|
else
|
|
printer.printf("-");
|
|
}
|
|
|
|
printer.printf("] %s%6.2f%%%s (%5.3f/%5.3f)MB\n",
|
|
color,
|
|
perc * 100.0,
|
|
COLOR_RESET,
|
|
(used / 1024.0f / 1024.0f),
|
|
(total / 1024.0f / 1024.0f));
|
|
}
|
|
|
|
void printRunningTasksMod(Print &printer, std::function<bool(const TaskStatus_t &a, const TaskStatus_t &b)> orderBy)
|
|
{
|
|
static const char *taskStates[] = {"Running", "Ready", "Blocked", "Suspended", "Deleted", "Invalid"};
|
|
|
|
static uint32_t ulRunTimeCounters[FREERTOS_TASK_NUMBER_MAX_NUM];
|
|
static uint32_t ulLastRunTime = 0;
|
|
uint32_t ulCurrentRunTime = 0, ulTaskRunTime = 0;
|
|
uint32_t ulTotalRunTime = 0;
|
|
|
|
std::vector<TaskStatus_t> pxTaskStatusArray;
|
|
UBaseType_t uxArraySize = 0;
|
|
|
|
// Take a snapshot of the number of tasks in case it changes while this function is executing.
|
|
uxArraySize = uxTaskGetNumberOfTasks();
|
|
pxTaskStatusArray.resize(uxArraySize);
|
|
|
|
// Generate raw status information about each task.
|
|
uxArraySize = uxTaskGetSystemState(pxTaskStatusArray.data(), uxArraySize, &ulTotalRunTime);
|
|
|
|
if (orderBy == nullptr)
|
|
std::sort(pxTaskStatusArray.begin(), pxTaskStatusArray.end(), [](const TaskStatus_t &a, const TaskStatus_t &b)
|
|
{ return a.xTaskNumber < b.xTaskNumber; });
|
|
else
|
|
std::sort(pxTaskStatusArray.begin(), pxTaskStatusArray.end(), orderBy);
|
|
|
|
// Compute system total runtime
|
|
ulCurrentRunTime = ulTotalRunTime - ulLastRunTime;
|
|
ulLastRunTime = ulTotalRunTime;
|
|
|
|
// PRINT MEMORY INFO
|
|
printer.printf("\033[H");
|
|
printer.printf(COLOR_LBLUE "=================== ESP32 SYSTEM MONITOR ===================\n" COLOR_RESET);
|
|
|
|
std::string buffer;
|
|
time_t now = time(nullptr);
|
|
struct tm *t = localtime(&now);
|
|
buffer.resize(64);
|
|
strftime(buffer.data(), sizeof(buffer), "%Y-%m-%d %H:%M:%S", t);
|
|
printer.printf(COLOR_YELLOW "=============== Datetime: %s ===============\n\n" COLOR_RESET, buffer.c_str());
|
|
|
|
// ===== HEAP =====
|
|
size_t freeHeap = esp_get_free_heap_size();
|
|
size_t totalHeap = heap_caps_get_total_size(MALLOC_CAP_DEFAULT);
|
|
printBar(printer, "HEAP", totalHeap - freeHeap, totalHeap, COLOR_GREEN);
|
|
|
|
// ===== RAM INTERNA =====
|
|
size_t freeInternal = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
|
size_t totalInternal = heap_caps_get_total_size(MALLOC_CAP_INTERNAL);
|
|
printBar(printer, "INTERNAL", totalInternal - freeInternal, totalInternal, COLOR_BLUE);
|
|
|
|
// ===== PSRAM =====
|
|
size_t totalPsram = heap_caps_get_total_size(MALLOC_CAP_SPIRAM);
|
|
if (totalPsram > 0)
|
|
{
|
|
size_t freePsram = heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
|
|
printBar(printer, "PSRAM", totalPsram - freePsram, totalPsram, COLOR_MAGENTA);
|
|
}
|
|
|
|
printer.printf("\n");
|
|
|
|
// ===== FLASH APP (approssimato) =====
|
|
const esp_partition_t *app_partition =
|
|
esp_partition_find_first(ESP_PARTITION_TYPE_APP,
|
|
ESP_PARTITION_SUBTYPE_APP_FACTORY,
|
|
NULL);
|
|
|
|
if (app_partition)
|
|
{
|
|
size_t totalAPP = app_partition->size; // dimensione reale partizione
|
|
size_t sketchSize = ESP.getSketchSize();
|
|
printBar(printer, "FLASH APP", sketchSize, totalAPP, COLOR_CYAN);
|
|
}
|
|
else
|
|
{
|
|
printer.printf(COLOR_YELLOW "%-12s [NOT FOUND]\n" COLOR_RESET, "FLASH APP");
|
|
}
|
|
|
|
// ===== LITTLEFS (corretto con partition table) =====
|
|
const esp_partition_t *fs_partition =
|
|
esp_partition_find_first(ESP_PARTITION_TYPE_DATA,
|
|
ESP_PARTITION_SUBTYPE_DATA_LITTLEFS,
|
|
"littlefs");
|
|
|
|
if (fs_partition)
|
|
{
|
|
size_t totalFS = fs_partition->size; // dimensione reale partizione
|
|
size_t usedFS = LittleFS.usedBytes(); // spazio usato reale
|
|
printBar(printer, "LITTLEFS", usedFS, totalFS, COLOR_YELLOW);
|
|
}
|
|
else
|
|
{
|
|
printer.printf(COLOR_YELLOW "%-12s [NOT FOUND]\n" COLOR_RESET, "LITTLEFS");
|
|
}
|
|
|
|
// ===== MIN HEAP =====
|
|
size_t minHeap = esp_get_minimum_free_heap_size();
|
|
printer.printf("%s\nMin Heap Ever:%s %u KB\n\n", COLOR_RED, COLOR_RESET, minHeap / 1024);
|
|
|
|
// Print Runtime Information
|
|
printer.printf("Tasks: %u, Runtime: %lus, Period: %luus\r\n", uxArraySize, ulTotalRunTime / 1000000, ulCurrentRunTime);
|
|
|
|
// Print Task Headers
|
|
printer.printf("Num\t Name\tLoad\tPrio\t Free\tCore\tState\r\n");
|
|
for (const auto &task : pxTaskStatusArray)
|
|
{
|
|
|
|
ulTaskRunTime = (task.ulRunTimeCounter - ulRunTimeCounters[task.xTaskNumber]);
|
|
ulRunTimeCounters[task.xTaskNumber] = task.ulRunTimeCounter;
|
|
ulTaskRunTime = (ulTaskRunTime * 100) / ulCurrentRunTime; // in percentage
|
|
|
|
printer.printf(
|
|
"%3u\t%16s"
|
|
"\t%3lu%%"
|
|
"\t%4u\t%5lu"
|
|
"\t%4c"
|
|
"\t%s\r\n",
|
|
task.xTaskNumber, task.pcTaskName,
|
|
ulTaskRunTime,
|
|
task.uxCurrentPriority, task.usStackHighWaterMark,
|
|
(task.xCoreID == tskNO_AFFINITY) ? '*' : ('0' + task.xCoreID),
|
|
taskStates[task.eCurrentState]);
|
|
}
|
|
printer.println();
|
|
}
|