Skip to content
Draft
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
1 change: 0 additions & 1 deletion examples/platform/silabs/FreeRTOSRuntimeStats.c
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,6 @@ uint32_t ulGetAllTaskInfo(TaskInfo * taskInfoArray, uint32_t taskInfoArraySize,
if (systemStats != NULL)
{
systemStats->terminatedTaskCount = deletedCount;
systemStats->totalTaskCount = systemStats->activeTaskCount + deletedCount;
systemStats->activeTaskCount = actualTasks;
}

Expand Down
1 change: 0 additions & 1 deletion examples/platform/silabs/FreeRTOSRuntimeStats.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ typedef struct
uint32_t systemPreemptionRatio;
uint32_t activeTaskCount;
uint32_t terminatedTaskCount;
uint32_t totalTaskCount;
} SystemTaskStats;

/**
Expand Down
1 change: 1 addition & 0 deletions examples/platform/silabs/MatterConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,7 @@ CHIP_ERROR SilabsMatterConfig::InitMatter(const char * appName)
#if MATTER_TRACING_ENABLED
static Tracing::Silabs::BackendImpl backend;
Tracing::Register(backend);
backend.RegisterPowerManagerTracing();
#endif // MATTER_TRACING_ENABLED

chip::DeviceLayer::PlatformMgr().UnlockChipStack();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ CHIP_ERROR TasksCommandHandler(int argc, char ** argv)
return SilabsTracer::Instance().OutputTaskStatistics();
}

CHIP_ERROR EnergyCommandHandler(int argc, char ** argv)
{
return SilabsTracer::Instance().OutputPowerManagerStatistics();
}

} // namespace

namespace TracingCommands {
Expand All @@ -111,6 +116,7 @@ void RegisterCommands()
{ &MetricsCommandHandler, "metrics", "Display runtime metrics. Usage: metrics <TimeTraceOperation>" },
{ &FlushCommandHandler, "flush", "Display buffered traces. Usage: flush <TimeTraceOperation>" },
{ &TasksCommandHandler, "tasks", "Display FreeRTOS task statistics." },
{ &EnergyCommandHandler, "energy", "Display energy mode statistics." },
};
static const Shell::Command cmds_silabs_tracing = { &TracingCommandHandler, "tracing",
"Dispatch Silicon Labs Tracing command" };
Expand Down
5 changes: 5 additions & 0 deletions src/platform/silabs/tracing/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ declare_args() {
# - Runtime statistics timer configuration
# - Task switching hooks for statistics collection
silabs_tracing_runtime_stats = false
silabs_tracing_energy_stats = false
}

buildconfig_header("silabs_tracing_config") {
Expand All @@ -34,6 +35,10 @@ buildconfig_header("silabs_tracing_config") {

defines = []

if (silabs_tracing_energy_stats == true) {
defines += [ "SILABS_TRACING_ENERGY_STATS=1" ]
}

if (silabs_tracing_runtime_stats == true) {
defines += [
"TRACING_RUNTIME_STATS=1",
Expand Down
5 changes: 5 additions & 0 deletions src/platform/silabs/tracing/BackendImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ void BackendImpl::LogMetricEvent(const MetricEvent & event)
}
}

void BackendImpl::RegisterPowerManagerTracing()
{
SilabsTracer::Instance().RegisterPowerManagerTracing();
}

} // namespace Silabs
} // namespace Tracing
} // namespace chip
2 changes: 2 additions & 0 deletions src/platform/silabs/tracing/BackendImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ class BackendImpl : public ::chip::Tracing::Backend
* SilabsTracer.Init() needs to be called before this is called.
*/
void LogMetricEvent(const MetricEvent &) override;

void RegisterPowerManagerTracing();
};

} // namespace Silabs
Expand Down
91 changes: 89 additions & 2 deletions src/platform/silabs/tracing/SilabsTracing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include <lib/support/PersistentData.h>
#include <string> // Include the necessary header for std::string

#include "sl_power_manager_debug.h"

// Include FreeRTOS configuration first
#if defined(TRACING_RUNTIME_STATS) && TRACING_RUNTIME_STATS
extern "C" {
Expand Down Expand Up @@ -821,8 +823,8 @@ CHIP_ERROR SilabsTracer::OutputTaskStatistics()
VerifyOrReturnError(taskCount > 0, CHIP_ERROR_INTERNAL, ChipLogError(DeviceLayer, "Failed to get task information"));

ChipLogProgress(DeviceLayer, "=== Task Statistics ===");
ChipLogProgress(DeviceLayer, "Active tasks: %lu | Terminated tasks: %lu | Total tasks: %lu", systemStats.activeTaskCount,
systemStats.terminatedTaskCount, systemStats.totalTaskCount);
ChipLogProgress(DeviceLayer, "Active tasks: %lu | Terminated tasks: %lu", systemStats.activeTaskCount,
systemStats.terminatedTaskCount);
ChipLogProgress(DeviceLayer, "Total Runtime: %lu ms", systemStats.totalRunTime);
ChipLogProgress(DeviceLayer, "System Preemption Ratio: %lu.%02lu%% (%lu/%lu switches)",
(systemStats.systemPreemptionRatio / 100), (systemStats.systemPreemptionRatio % 100),
Expand Down Expand Up @@ -883,6 +885,91 @@ CHIP_ERROR SilabsTracer::OutputTaskStatistics()

#endif // configGENERATE_RUN_TIME_STATS == 1

#if defined(SILABS_TRACING_ENERGY_STATS) && SILABS_TRACING_ENERGY_STATS == 1

void SilabsTracer::PowerManagerTransitionCallback(sl_power_manager_em_t from, sl_power_manager_em_t to)
{
if (from == mCurrentEnergyMode)
{
auto currentTime = SILABS_GET_TIME();
auto timeDiff = currentTime - mLastEnergyStateTransitionTime;
mTimeInEnergyState[from] += timeDiff;
mTransitionCountToEnergyState[to]++;
}
else
{
ChipLogError(DeviceLayer, "Unexpected power manager transition from EM%d to EM%d (expected EM%d to EM%d)", from, to,
mCurrentEnergyMode, to);
}

// Update time spent in previous energy mode
mCurrentEnergyMode = to;
mLastEnergyStateTransitionTime = SILABS_GET_TIME();

if (mCurrentEnergyMode == SL_POWER_MANAGER_EM1)
{
OutputPowerManagerStatistics();
}
}

void SilabsTracer::StaticPowerManagerTransitionCallback(sl_power_manager_em_t from, sl_power_manager_em_t to)
{
Instance().PowerManagerTransitionCallback(from, to);
}

#endif // SILABS_TRACING_ENERGY_STATS

void SilabsTracer::RegisterPowerManagerTracing()
{
#if defined(SILABS_TRACING_ENERGY_STATS) && SILABS_TRACING_ENERGY_STATS == 1
memset(mTimeInEnergyState, 0, sizeof(mTimeInEnergyState));
memset(mTransitionCountToEnergyState, 0, sizeof(mTransitionCountToEnergyState));
mCurrentEnergyMode = static_cast<sl_power_manager_em_t>(0);
mLastEnergyStateTransitionTime = SILABS_GET_TIME();

sl_power_manager_init();
sl_power_manager_subscribe_em_transition_event(&mPowerManagerEmTransitionEventHandle, &mPowerManagerEmTransitionEventInfo);
#endif // SILABS_TRACING_ENERGY_STATS
}

CHIP_ERROR SilabsTracer::OutputPowerManagerStatistics()
{
#if defined(SILABS_TRACING_ENERGY_STATS) && SILABS_TRACING_ENERGY_STATS == 1
VerifyOrReturnError(isLogInitialized(), CHIP_ERROR_UNINITIALIZED);

auto currentTime = SILABS_GET_TIME();

ChipLogProgress(DeviceLayer, "=== Power Manager Energy Mode Statistics ===");
ChipLogProgress(DeviceLayer, "Total Runtime: %lu ms", currentTime.count());

// Table header
ChipLogProgress(DeviceLayer, "| %-12s| %-12s | %-10s | %-10s |", "Energy Mode", "Time (ms)", "Percentage", "Transitions");
ChipLogProgress(DeviceLayer, "|%-13s|%-14s|%-12s|%-12s|", "-------------", "--------------", "------------", "------------");

for (size_t em = 0; em <= SL_POWER_MANAGER_EM2; em++)
{
System::Clock::Milliseconds32 totalTimeInMode = mTimeInEnergyState[em];
if (mCurrentEnergyMode == static_cast<sl_power_manager_em_t>(em))
{
totalTimeInMode += currentTime - mLastEnergyStateTransitionTime;
}
// Use 64-bit arithmetic to avoid overflow, then calculate percentage with 4 decimal places
uint64_t percentage =
currentTime.count() > 0 ? (static_cast<uint64_t>(totalTimeInMode.count()) * 1000000) / currentTime.count() : 0;
ChipLogProgress(DeviceLayer, "| EM%-10d| %-12lu | %3lu.%04lu%% | %-10u |", static_cast<int>(em), totalTimeInMode.count(),
static_cast<uint32_t>(percentage / 10000), static_cast<uint32_t>(percentage % 10000),
mTransitionCountToEnergyState[em]);
}

sl_power_manager_debug_print_em_requirements();

return CHIP_NO_ERROR;
#else // SILABS_TRACING_ENERGY_STATS != 1
ChipLogError(DeviceLayer, "Power Manager statistics not available - SILABS_TRACING_ENERGY_STATS not enabled");
return CHIP_ERROR_UNINITIALIZED;
#endif // SILABS_TRACING_ENERGY_STATS
}

} // namespace Silabs
} // namespace Tracing
} // namespace chip
47 changes: 47 additions & 0 deletions src/platform/silabs/tracing/SilabsTracing.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@
#include <lib/support/LinkedList.h>
#include <lib/support/Span.h>
#include <platform/silabs/tracing/SilabsTracingConfig.h>
#if defined(SILABS_TRACING_ENERGY_STATS) && SILABS_TRACING_ENERGY_STATS == 1
#include <sl_power_manager.h>
#define SLEEP_EM_EVENT_MASK \
(SL_POWER_MANAGER_EVENT_TRANSITION_ENTERING_EM0 | SL_POWER_MANAGER_EVENT_TRANSITION_ENTERING_EM1 | \
SL_POWER_MANAGER_EVENT_TRANSITION_ENTERING_EM2)
#endif // SILABS_TRACING_ENERGY_STATS
#include <stdint.h>
#include <system/SystemClock.h>

Expand Down Expand Up @@ -283,6 +289,18 @@ class SilabsTracer
*/
CHIP_ERROR OutputTaskStatistics();

/**
* @brief Registers the power manager tracing functionality with the power manager to receive notifications when the device
* changes its power state.
*/
void RegisterPowerManagerTracing();

/** @brief Output power manager energy mode statistics
* This function outputs the total time spent in each energy mode and the percentage of total time.
* @return CHIP_ERROR, returns CHIP_ERROR_UNINITIALIZED if the feature or logs are not initialized
*/
CHIP_ERROR OutputPowerManagerStatistics();

private:
struct TimeTrackerList
{
Expand Down Expand Up @@ -358,6 +376,17 @@ class SilabsTracer
PersistentStorageDelegate * mStorage = nullptr;

size_t mBufferedTrackerCount = 0;
#if defined(SILABS_TRACING_ENERGY_STATS) && SILABS_TRACING_ENERGY_STATS == 1

System::Clock::Milliseconds32 mTimeInEnergyState[SL_POWER_MANAGER_EM2 + 1];
uint16_t mTransitionCountToEnergyState[SL_POWER_MANAGER_EM2 + 1];
System::Clock::Milliseconds32 mLastEnergyStateTransitionTime;
sl_power_manager_em_t mCurrentEnergyMode;
sl_power_manager_em_transition_event_handle_t mPowerManagerEmTransitionEventHandle;
sl_power_manager_em_transition_event_info_t mPowerManagerEmTransitionEventInfo = { .event_mask = SLEEP_EM_EVENT_MASK,
.on_event =
StaticPowerManagerTransitionCallback };
#endif // SILABS_TRACING_ENERGY_STATS

/** @brief Clear the trace buffer */
void TraceBufferClear();
Expand Down Expand Up @@ -397,6 +426,24 @@ class SilabsTracer
* @return CHIP_ERROR, returns CHIP_ERROR_INVALID_ARGUMENT if the format is not respected.
*/
CHIP_ERROR SplitNamedTraceString(CharSpan appOperationKey, CharSpan & groupSpan, CharSpan & labelSpan) const;

#if defined(SILABS_TRACING_ENERGY_STATS) && SILABS_TRACING_ENERGY_STATS == 1

/** @brief Callback for power manager energy mode transitions
* This function is called by the power manager when the device transitions between energy modes.
* It updates the time spent in each energy mode.
* @param from The energy mode the device is transitioning from
* @param to The energy mode the device is transitioning to
*/
void PowerManagerTransitionCallback(sl_power_manager_em_t from, sl_power_manager_em_t to);

/** @brief Static callback for power manager energy mode transitions
* This function is a static wrapper that calls the instance method PowerManagerTransitionCallback.
* @param from The energy mode the device is transitioning from
* @param to The energy mode the device is transitioning to
*/
static void StaticPowerManagerTransitionCallback(sl_power_manager_em_t from, sl_power_manager_em_t to);
#endif // SILABS_TRACING_ENERGY_STATS
};

} // namespace Silabs
Expand Down
Loading