some stuff

This commit is contained in:
2025-10-12 13:51:50 +02:00
parent df57e55171
commit 83ba775971
3 changed files with 291 additions and 33 deletions

View File

@@ -1,17 +1,18 @@
// Cardboy firmware entry point: boot platform services and run the modular app system.
#include "cardboy/backend/esp_backend.hpp"
#include "cardboy/apps/clock_app.hpp"
#include "cardboy/apps/gameboy_app.hpp"
#include "cardboy/apps/menu_app.hpp"
#include "cardboy/apps/tetris_app.hpp"
#include "cardboy/backend/esp_backend.hpp"
#include "cardboy/sdk/app_system.hpp"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_err.h"
#include "esp_pm.h"
#include "esp_sleep.h"
#include "esp_system.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "sdkconfig.h"
#include <algorithm>
@@ -19,9 +20,9 @@
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <span>
#include <string>
#include <string_view>
#include <span>
#include <vector>
namespace {
@@ -53,11 +54,11 @@ constexpr apps::EmbeddedRomDescriptor kEmbeddedRoms[] = {
#if CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS && CONFIG_FREERTOS_USE_TRACE_FACILITY
namespace {
constexpr TickType_t kStatsTaskDelayTicks = pdMS_TO_TICKS(5000);
constexpr TickType_t kStatsWarmupDelay = pdMS_TO_TICKS(2000);
constexpr UBaseType_t kStatsTaskPriority = tskIDLE_PRIORITY + 1;
constexpr uint32_t kStatsTaskStack = 4096;
constexpr char kStatsTaskName[] = "TaskStats";
constexpr TickType_t kStatsTaskDelayTicks = pdMS_TO_TICKS(5000);
constexpr TickType_t kStatsWarmupDelay = pdMS_TO_TICKS(2000);
constexpr UBaseType_t kStatsTaskPriority = tskIDLE_PRIORITY + 1;
constexpr uint32_t kStatsTaskStack = 4096;
constexpr char kStatsTaskName[] = "TaskStats";
struct TaskRuntimeSample {
TaskHandle_t handle;
@@ -65,11 +66,11 @@ struct TaskRuntimeSample {
};
struct TaskUsageRow {
std::string name;
uint64_t delta;
UBaseType_t priority;
uint32_t stackHighWaterBytes;
bool isIdle;
std::string name;
uint64_t delta;
UBaseType_t priority;
uint32_t stackHighWaterBytes;
bool isIdle;
};
[[nodiscard]] uint64_t deltaWithWrap(uint32_t current, uint32_t previous) {
@@ -79,7 +80,7 @@ struct TaskUsageRow {
}
void task_usage_monitor(void*) {
static constexpr char tag[] = "TaskUsage";
static constexpr char tag[] = "TaskUsage";
std::vector<TaskRuntimeSample> lastSamples;
uint32_t lastTotal = 0;
@@ -94,7 +95,7 @@ void task_usage_monitor(void*) {
std::vector<TaskStatus_t> statusBuffer(taskCount);
uint32_t totalRuntime = 0;
const UBaseType_t captured = uxTaskGetSystemState(statusBuffer.data(), statusBuffer.size(), &totalRuntime);
const UBaseType_t captured = uxTaskGetSystemState(statusBuffer.data(), statusBuffer.size(), &totalRuntime);
if (captured == 0)
continue;
statusBuffer.resize(captured);
@@ -118,8 +119,8 @@ void task_usage_monitor(void*) {
std::vector<TaskUsageRow> rows;
rows.reserve(statusBuffer.size());
uint64_t idleDelta = 0;
uint64_t activeDelta = 0;
uint64_t idleDelta = 0;
uint64_t activeDelta = 0;
uint64_t accountedDelta = 0;
for (const auto& status: statusBuffer) {
@@ -128,18 +129,18 @@ void task_usage_monitor(void*) {
});
const uint32_t previousRuntime = (it != lastSamples.end()) ? it->runtime : status.ulRunTimeCounter;
const uint64_t taskDelta = (it != lastSamples.end()) ? deltaWithWrap(status.ulRunTimeCounter, previousRuntime) : 0ULL;
const uint64_t taskDelta =
(it != lastSamples.end()) ? deltaWithWrap(status.ulRunTimeCounter, previousRuntime) : 0ULL;
currentSamples.push_back({status.xHandle, status.ulRunTimeCounter});
TaskUsageRow row{
.name = std::string(status.pcTaskName ? status.pcTaskName : ""),
.delta = taskDelta,
.priority = status.uxCurrentPriority,
.stackHighWaterBytes = static_cast<uint32_t>(status.usStackHighWaterMark) * sizeof(StackType_t),
.isIdle = status.uxCurrentPriority == tskIDLE_PRIORITY ||
(status.pcTaskName && std::strncmp(status.pcTaskName, "IDLE", 4) == 0)
};
TaskUsageRow row{.name = std::string(status.pcTaskName ? status.pcTaskName : ""),
.delta = taskDelta,
.priority = status.uxCurrentPriority,
.stackHighWaterBytes =
static_cast<uint32_t>(status.usStackHighWaterMark) * sizeof(StackType_t),
.isIdle = status.uxCurrentPriority == tskIDLE_PRIORITY ||
(status.pcTaskName && std::strncmp(status.pcTaskName, "IDLE", 4) == 0)};
rows.push_back(std::move(row));
@@ -156,9 +157,8 @@ void task_usage_monitor(void*) {
if (rows.empty())
continue;
std::sort(rows.begin(), rows.end(), [](const TaskUsageRow& a, const TaskUsageRow& b) {
return a.delta > b.delta;
});
std::sort(rows.begin(), rows.end(),
[](const TaskUsageRow& a, const TaskUsageRow& b) { return a.delta > b.delta; });
const double windowMs = static_cast<double>(totalDelta) / 1000.0;
@@ -181,14 +181,20 @@ void task_usage_monitor(void*) {
std::printf(" %-16s %6.2f%% (ISRs / scheduler)\n", "<isr>", residualPct);
}
std::printf("[%s] Active %.2f%% | Idle %.2f%%\n", tag,
(activeDelta * 100.0) / static_cast<double>(totalDelta), idlePct);
std::printf("[%s] Active %.2f%% | Idle %.2f%%\n", tag, (activeDelta * 100.0) / static_cast<double>(totalDelta),
idlePct);
const uint32_t heapFree = esp_get_free_heap_size();
const uint32_t heapMinimum = esp_get_minimum_free_heap_size();
std::printf("[%s] Heap free %lu B | Min free %lu B\n", tag, static_cast<unsigned long>(heapFree),
static_cast<unsigned long>(heapMinimum));
std::fflush(stdout);
}
}
void start_task_usage_monitor() {
xTaskCreatePinnedToCore(task_usage_monitor, kStatsTaskName, kStatsTaskStack, nullptr, kStatsTaskPriority, nullptr, 0);
xTaskCreatePinnedToCore(task_usage_monitor, kStatsTaskName, kStatsTaskStack, nullptr, kStatsTaskPriority, nullptr,
0);
}
} // namespace