diff --git a/examples/lighting-app/silabs/src/AppTask.cpp b/examples/lighting-app/silabs/src/AppTask.cpp index 4f74ca7f34..852163087d 100644 --- a/examples/lighting-app/silabs/src/AppTask.cpp +++ b/examples/lighting-app/silabs/src/AppTask.cpp @@ -105,6 +105,7 @@ CHIP_ERROR AppTask::Init() #endif // QR_CODE_ENABLED #endif + BaseApplication::InitCompleteCallback(err); return err; } diff --git a/examples/platform/silabs/BaseApplication.cpp b/examples/platform/silabs/BaseApplication.cpp index b3e3df1744..c80dc1091b 100644 --- a/examples/platform/silabs/BaseApplication.cpp +++ b/examples/platform/silabs/BaseApplication.cpp @@ -89,6 +89,13 @@ #include "sl_cmp_config.h" #endif +// Tracing +#include +#if MATTER_TRACING_ENABLED +#include +#include +#endif // MATTER_TRACING_ENABLED + /********************************************************** * Defines and Constants *********************************************************/ @@ -113,6 +120,11 @@ using namespace chip::app; using namespace ::chip::DeviceLayer; using namespace ::chip::DeviceLayer::Silabs; +#if MATTER_TRACING_ENABLED +using TimeTraceOperation = chip::Tracing::Silabs::TimeTraceOperation; +using SilabsTracer = chip::Tracing::Silabs::SilabsTracer; +#endif // MATTER_TRACING_ENABLED + namespace { /********************************************************** @@ -322,6 +334,9 @@ CHIP_ERROR BaseApplication::Init() #if CHIP_CONFIG_ENABLE_ICD_SERVER ICDCommands::RegisterCommands(); #endif // CHIP_CONFIG_ENABLE_ICD_SERVER +#if MATTER_TRACING_ENABLED + TracingCommands::RegisterCommands(); +#endif // MATTER_TRACING_ENABLED #endif // ENABLE_CHIP_SHELL #ifdef PERFORMANCE_TEST_ENABLED @@ -340,6 +355,14 @@ CHIP_ERROR BaseApplication::Init() return err; } +void BaseApplication::InitCompleteCallback(CHIP_ERROR err) +{ +#if MATTER_TRACING_ENABLED + SilabsTracer::Instance().TimeTraceEnd(TimeTraceOperation::kAppInit); + SilabsTracer::Instance().TimeTraceEnd(TimeTraceOperation::kBootup); +#endif // MATTER_TRACING_ENABLED +} + void BaseApplication::FunctionTimerEventHandler(void * timerCbArg) { AppEvent event; diff --git a/examples/platform/silabs/BaseApplication.h b/examples/platform/silabs/BaseApplication.h index 39c0e2cab3..994d62f14f 100644 --- a/examples/platform/silabs/BaseApplication.h +++ b/examples/platform/silabs/BaseApplication.h @@ -89,7 +89,7 @@ class BaseApplication public: BaseApplication() = default; - virtual ~BaseApplication() {}; + virtual ~BaseApplication(){}; static bool sIsProvisioned; static bool sIsFactoryResetTriggered; static LEDWidget * sAppActionLed; @@ -122,6 +122,7 @@ class BaseApplication * * @param event AppEvent to post */ + static void PostEvent(const AppEvent * event); /** @@ -176,6 +177,14 @@ class BaseApplication protected: CHIP_ERROR Init(); + /** @brief + * Function to be called at the end of Init to indicate that the application has completed its initialization. + * Currently only used for tracing, might want to move logging here as well in the future + * @param err CHIP_NO_ERROR on success, corresponding error code on Init failure, note that Init failure leads to an app error so + * this is purely to have a trace logged with the error code + */ + void InitCompleteCallback(CHIP_ERROR err); + /** * @brief Function called to start the function timer * diff --git a/examples/platform/silabs/MatterConfig.cpp b/examples/platform/silabs/MatterConfig.cpp index 3bdac99034..b146a12547 100644 --- a/examples/platform/silabs/MatterConfig.cpp +++ b/examples/platform/silabs/MatterConfig.cpp @@ -32,6 +32,10 @@ #endif // CHIP_CONFIG_ENABLE_ICD_SERVER #endif /* SL_WIFI */ +#if SL_MATTER_ENABLE_APP_SLEEP_MANAGER +#include "ApplicationSleepManager.h" +#endif // SL_MATTER_ENABLE_APP_SLEEP_MANAGER + #if PW_RPC_ENABLED #include "Rpc.h" #endif @@ -91,6 +95,13 @@ static chip::DeviceLayer::Internal::Efr32PsaOperationalKeystore gOperationalKeys #include "sl_power_manager.h" #endif +#include +#if MATTER_TRACING_ENABLED +#include +#include +#include +#endif // MATTER_TRACING_ENABLED + /********************************************************** * Defines *********************************************************/ @@ -101,6 +112,11 @@ using namespace ::chip::DeviceLayer; using namespace ::chip::Credentials; using namespace chip::DeviceLayer::Silabs; +#if MATTER_TRACING_ENABLED +using TimeTraceOperation = chip::Tracing::Silabs::TimeTraceOperation; +using SilabsTracer = chip::Tracing::Silabs::SilabsTracer; +#endif // MATTER_TRACING_ENABLED + #if CHIP_ENABLE_OPENTHREAD #include #include @@ -175,6 +191,11 @@ void ApplicationStart(void * unused) if (err != CHIP_NO_ERROR) appError(err); +#if MATTER_TRACING_ENABLED + SilabsTracer::Instance().TimeTraceEnd(TimeTraceOperation::kMatterInit); + SilabsTracer::Instance().TimeTraceBegin(TimeTraceOperation::kAppInit); +#endif // MATTER_TRACING_ENABLED + gExampleDeviceInfoProvider.SetStorageDelegate(&chip::Server::GetInstance().GetPersistentStorage()); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); @@ -205,6 +226,10 @@ void SilabsMatterConfig::AppInit() sMainTaskHandle = osThreadNew(ApplicationStart, nullptr, &kMainTaskAttr); ChipLogProgress(DeviceLayer, "Starting scheduler"); VerifyOrDie(sMainTaskHandle); // We can't proceed if the Main Task creation failed. + +#if MATTER_TRACING_ENABLED + SilabsTracer::Instance().TimeTraceEnd(TimeTraceOperation::kBootup); +#endif // MATTER_TRACING_ENABLED GetPlatform().StartScheduler(); // Should never get here. @@ -312,6 +337,26 @@ CHIP_ERROR SilabsMatterConfig::InitMatter(const char * appName) // Init Matter Server and Start Event Loop err = chip::Server::GetInstance().Init(initParams); + // [sl-only]: Configure Wi-Fi App Sleep Manager +#if SL_MATTER_ENABLE_APP_SLEEP_MANAGER + err = app::Silabs::ApplicationSleepManager::GetInstance() + .SetFabricTable(&Server::GetInstance().GetFabricTable()) + .SetSubscriptionInfoProvider(app::InteractionModelEngine::GetInstance()) + .SetCommissioningWindowManager(&Server::GetInstance().GetCommissioningWindowManager()) + .SetWifiSleepManager(&WifiSleepManager::GetInstance()) + .Init(); + VerifyOrReturnError(err == CHIP_NO_ERROR, err, ChipLogError(DeviceLayer, "ApplicationSleepManager init failed")); + + // Register ReadHandler::ApplicationCallback + app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback( + &app::Silabs::ApplicationSleepManager::GetInstance()); +#endif // SL_MATTER_ENABLE_APP_SLEEP_MANAGER + +#if MATTER_TRACING_ENABLED + static Tracing::Silabs::BackendImpl backend; + Tracing::Register(backend); +#endif // MATTER_TRACING_ENABLED + chip::DeviceLayer::PlatformMgr().UnlockChipStack(); ReturnErrorOnFailure(err); diff --git a/examples/platform/silabs/SiWx917/BUILD.gn b/examples/platform/silabs/SiWx917/BUILD.gn index 2d6d3574ea..78b530942a 100644 --- a/examples/platform/silabs/SiWx917/BUILD.gn +++ b/examples/platform/silabs/SiWx917/BUILD.gn @@ -16,6 +16,7 @@ import("//build_overrides/chip.gni") import("//build_overrides/efr32_sdk.gni") import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni") import("${chip_root}/examples/platform/silabs/args.gni") +import("${chip_root}/src/app/icd/icd.gni") import("${chip_root}/src/lib/lib.gni") import("${chip_root}/src/platform/device.gni") import("${chip_root}/src/platform/silabs/wifi/args.gni") @@ -204,6 +205,10 @@ source_set("siwx917-common") { ] } + if (chip_enable_icd_server) { + public_deps += [ "${silabs_common_plat_dir}/wifi/icd:app-sleep-manager" ] + } + if (app_data_model != "") { public_deps += [ app_data_model ] } diff --git a/examples/platform/silabs/efr32/BUILD.gn b/examples/platform/silabs/efr32/BUILD.gn index e0e7b45070..f7478beaab 100644 --- a/examples/platform/silabs/efr32/BUILD.gn +++ b/examples/platform/silabs/efr32/BUILD.gn @@ -18,6 +18,7 @@ import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni") import("${chip_root}/src/app/icd/icd.gni") import("${chip_root}/src/lib/lib.gni") import("${chip_root}/src/platform/device.gni") +import("${chip_root}/src/tracing/tracing_args.gni") import("${silabs_sdk_build_root}/efr32_sdk.gni") import("${silabs_sdk_build_root}/silabs_board.gni") @@ -110,6 +111,9 @@ source_set("matter-shell") { "${chip_root}/src/lib/shell:shell", "${chip_root}/src/lib/shell:shell_core", ] + if (matter_enable_tracing_support) { + public_deps += [ "${chip_root}/src/platform/silabs/tracing:SilabsTracing" ] + } } config("efr32-common-config") { @@ -210,6 +214,9 @@ source_set("efr32-common") { if (chip_enable_icd_server) { deps += [ "${silabs_common_plat_dir}/shell:icd" ] } + if (matter_enable_tracing_support) { + public_deps += [ "${silabs_common_plat_dir}/shell:tracing" ] + } } public_deps += [ @@ -233,4 +240,8 @@ source_set("efr32-common") { if (app_data_model != "") { public_deps += [ app_data_model ] } + + if (matter_enable_tracing_support) { + public_deps += [ "${chip_root}/src/platform/silabs/tracing:SilabsTracing" ] + } } diff --git a/examples/platform/silabs/main.cpp b/examples/platform/silabs/main.cpp index d01e27f178..6d3c6145d8 100644 --- a/examples/platform/silabs/main.cpp +++ b/examples/platform/silabs/main.cpp @@ -21,10 +21,27 @@ #include "sl_system_kernel.h" #include +#include +#if MATTER_TRACING_ENABLED +#include +#endif // MATTER_TRACING_ENABLED + +#if MATTER_TRACING_ENABLED +using TimeTraceOperation = chip::Tracing::Silabs::TimeTraceOperation; +using SilabsTracer = chip::Tracing::Silabs::SilabsTracer; +#endif // MATTER_TRACING_ENABLED + int main(void) { +#if MATTER_TRACING_ENABLED + SilabsTracer::Instance().TimeTraceBegin(TimeTraceOperation::kBootup); + SilabsTracer::Instance().TimeTraceBegin(TimeTraceOperation::kSilabsInit); +#endif // MATTER_TRACING_ENABLED sl_system_init(); - +#if MATTER_TRACING_ENABLED + SilabsTracer::Instance().TimeTraceEnd(TimeTraceOperation::kSilabsInit); + SilabsTracer::Instance().TimeTraceBegin(TimeTraceOperation::kMatterInit); +#endif // MATTER_TRACING_ENABLED // Initialize the application. For example, create periodic timer(s) or // task(s) if the kernel is present. SilabsMatterConfig::AppInit(); diff --git a/examples/platform/silabs/sensors/AirQuality/AirQualitySensor.cpp b/examples/platform/silabs/sensors/AirQuality/AirQualitySensor.cpp index 43c5a5573b..e693a26021 100644 --- a/examples/platform/silabs/sensors/AirQuality/AirQualitySensor.cpp +++ b/examples/platform/silabs/sensors/AirQuality/AirQualitySensor.cpp @@ -26,7 +26,6 @@ extern "C" { #endif #include -#include } #include "sl_i2cspm_instances.h" #endif // USE_SPARKFUN_AIR_QUALITY_SENSOR diff --git a/examples/platform/silabs/shell/BUILD.gn b/examples/platform/silabs/shell/BUILD.gn index 74613aeac9..80b867d547 100644 --- a/examples/platform/silabs/shell/BUILD.gn +++ b/examples/platform/silabs/shell/BUILD.gn @@ -23,17 +23,32 @@ if (use_SiWx917) { shell_dependency_path = "${chip_root}/examples/platform/silabs/SiWx917" } -config("shell-config") { - include_dirs = [ "." ] +config("icd-shell-config") { + include_dirs = [ "./icd/" ] +} + +config("tracing-shell-config") { + include_dirs = [ "./tracing/" ] } source_set("icd") { sources = [ - "ICDShellCommands.cpp", - "ICDShellCommands.h", + "./icd/ICDShellCommands.cpp", + "./icd/ICDShellCommands.h", + ] + + public_configs = [ ":icd-shell-config" ] + + deps = [ "${shell_dependency_path}:matter-shell" ] +} + +source_set("tracing") { + sources = [ + "./tracing/TracingShellCommands.cpp", + "./tracing/TracingShellCommands.h", ] - public_configs = [ ":shell-config" ] + public_configs = [ ":tracing-shell-config" ] deps = [ "${shell_dependency_path}:matter-shell" ] } diff --git a/examples/platform/silabs/shell/ICDShellCommands.cpp b/examples/platform/silabs/shell/icd/ICDShellCommands.cpp similarity index 100% rename from examples/platform/silabs/shell/ICDShellCommands.cpp rename to examples/platform/silabs/shell/icd/ICDShellCommands.cpp diff --git a/examples/platform/silabs/shell/ICDShellCommands.h b/examples/platform/silabs/shell/icd/ICDShellCommands.h similarity index 100% rename from examples/platform/silabs/shell/ICDShellCommands.h rename to examples/platform/silabs/shell/icd/ICDShellCommands.h diff --git a/examples/platform/silabs/shell/tracing/TracingShellCommands.cpp b/examples/platform/silabs/shell/tracing/TracingShellCommands.cpp new file mode 100644 index 0000000000..7bfe89cbea --- /dev/null +++ b/examples/platform/silabs/shell/tracing/TracingShellCommands.cpp @@ -0,0 +1,213 @@ +/*************************************************************************** + * @file SilabsTracing.cpp + * @brief Instrumenting for matter operation tracing for the Silicon Labs platform. + ******************************************************************************* + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ******************************************************************************* + * + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + ******************************************************************************/ +#include "TracingShellCommands.h" +#include +#include +#include +#include + +using namespace chip; +using Shell::Engine; +using Shell::shell_command_t; +using Shell::streamer_get; +using Shell::streamer_printf; + +namespace { + +using TimeTraceOperation = Tracing::Silabs::TimeTraceOperation; + +TimeTraceOperation StringToTimeTraceOperation(const char * str) +{ + if (strcmp(str, "Spake2p") == 0) + { + return TimeTraceOperation::kSpake2p; + } + else if (strcmp(str, "Pake1") == 0) + { + return TimeTraceOperation::kPake1; + } + else if (strcmp(str, "Pake2") == 0) + { + return TimeTraceOperation::kPake2; + } + else if (strcmp(str, "Pake3") == 0) + { + return TimeTraceOperation::kPake3; + } + else if (strcmp(str, "OperationalCredentials") == 0) + { + return TimeTraceOperation::kOperationalCredentials; + } + else if (strcmp(str, "AttestationVerification") == 0) + { + return TimeTraceOperation::kAttestationVerification; + } + else if (strcmp(str, "CSR") == 0) + { + return TimeTraceOperation::kCSR; + } + else if (strcmp(str, "NOC") == 0) + { + return TimeTraceOperation::kNOC; + } + else if (strcmp(str, "TransportLayer") == 0) + { + return TimeTraceOperation::kTransportLayer; + } + else if (strcmp(str, "TransportSetup") == 0) + { + return TimeTraceOperation::kTransportSetup; + } + else if (strcmp(str, "FindOperational") == 0) + { + return TimeTraceOperation::kFindOperational; + } + else if (strcmp(str, "CaseSession") == 0) + { + return TimeTraceOperation::kCaseSession; + } + else if (strcmp(str, "Sigma1") == 0) + { + return TimeTraceOperation::kSigma1; + } + else if (strcmp(str, "Sigma2") == 0) + { + return TimeTraceOperation::kSigma2; + } + else if (strcmp(str, "Sigma3") == 0) + { + return TimeTraceOperation::kSigma3; + } + else if (strcmp(str, "OTA") == 0) + { + return TimeTraceOperation::kOTA; + } + else if (strcmp(str, "ImageUpload") == 0) + { + return TimeTraceOperation::kImageUpload; + } + else if (strcmp(str, "ImageVerification") == 0) + { + return TimeTraceOperation::kImageVerification; + } + else if (strcmp(str, "AppApplyTime") == 0) + { + return TimeTraceOperation::kAppApplyTime; + } + else if (strcmp(str, "Bootup") == 0) + { + return TimeTraceOperation::kBootup; + } + else if (strcmp(str, "SilabsInit") == 0) + { + return TimeTraceOperation::kSilabsInit; + } + else if (strcmp(str, "MatterInit") == 0) + { + return TimeTraceOperation::kMatterInit; + } + else if (strcmp(str, "BufferFull") == 0) + { + return TimeTraceOperation::kBufferFull; + } + else + { + return TimeTraceOperation::kNumTraces; + } +} + +Engine sShellTracingSubCommands; + +/******************************************************** + * Silabs Tracing shell functions + *********************************************************/ + +CHIP_ERROR TracingHelpHandler(int argc, char ** argv) +{ + sShellTracingSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr); + return CHIP_NO_ERROR; +} + +CHIP_ERROR TracingListTimeOperations(int argc, char ** argv) +{ + for (size_t i = 0; i < static_cast(TimeTraceOperation::kNumTraces); ++i) + { + streamer_printf(streamer_get(), "Operation: %s\r\n", TimeTraceOperationToString(static_cast(i))); + } + return CHIP_NO_ERROR; +} + +CHIP_ERROR TracingCommandHandler(int argc, char ** argv) +{ + if (argc == 0) + { + return TracingHelpHandler(argc, argv); + } + + return sShellTracingSubCommands.ExecCommand(argc, argv); +} + +CHIP_ERROR WatermarksCommandHandler(int argc, char ** argv) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + if (strcmp(argv[0], "all") == 0) + { + error = Tracing::Silabs::SilabsTracer::Instance().OutputAllWaterMarks(); + } + else + { + TimeTraceOperation operation = StringToTimeTraceOperation(argv[0]); + error = Tracing::Silabs::SilabsTracer::Instance().OutputWaterMark(operation); + } + return error; +} + +CHIP_ERROR FlushCommandHandler(int argc, char ** argv) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + if (strcmp(argv[0], "all") == 0) + { + error = Tracing::Silabs::SilabsTracer::Instance().TraceBufferFlushAll(); + } + else + { + TimeTraceOperation operation = StringToTimeTraceOperation(argv[0]); + error = Tracing::Silabs::SilabsTracer::Instance().TraceBufferFlushByOperation(operation); + } + return error; +} + +} // namespace + +namespace TracingCommands { + +void RegisterCommands() +{ + static const Shell::Command sTracingSubCommands[] = { + { &TracingHelpHandler, "help", "Output the help menu" }, + { &TracingListTimeOperations, "list", "List all available TimeTraceOperations" }, + { &WatermarksCommandHandler, "watermarks", "Display runtime watermarks. Usage: watermarks " }, + { &FlushCommandHandler, "flush", "Display buffered traces. Usage: flush " }, + }; + static const Shell::Command cmds_silabs_tracing = { &TracingCommandHandler, "tracing", + "Dispatch Silicon Labs Tracing command" }; + + sShellTracingSubCommands.RegisterCommands(sTracingSubCommands, ArraySize(sTracingSubCommands)); + Engine::Root().RegisterCommands(&cmds_silabs_tracing, 1); +} + +} // namespace TracingCommands diff --git a/examples/platform/silabs/shell/tracing/TracingShellCommands.h b/examples/platform/silabs/shell/tracing/TracingShellCommands.h new file mode 100644 index 0000000000..8e8090ecd4 --- /dev/null +++ b/examples/platform/silabs/shell/tracing/TracingShellCommands.h @@ -0,0 +1,23 @@ +/*************************************************************************** + * @file SilabsTracing.cpp + * @brief Instrumenting for matter operation tracing for the Silicon Labs platform. + ******************************************************************************* + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ******************************************************************************* + * + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + ******************************************************************************/ +#pragma once + +namespace TracingCommands { + +void RegisterCommands(); + +} // namespace TracingCommands diff --git a/examples/platform/silabs/wifi/icd/ApplicationSleepManager.cpp b/examples/platform/silabs/wifi/icd/ApplicationSleepManager.cpp new file mode 100644 index 0000000000..cdf32f07e2 --- /dev/null +++ b/examples/platform/silabs/wifi/icd/ApplicationSleepManager.cpp @@ -0,0 +1,82 @@ +/******************************************************************************* + * @file ApplicationSleepManager.cpp + * @brief Implementation for the buisness logic around Optimizing Wi-Fi sleep states + ******************************************************************************* + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ******************************************************************************* + * + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + ******************************************************************************/ + +#include "ApplicationSleepManager.h" +#include + +namespace chip { +namespace app { +namespace Silabs { + +ApplicationSleepManager ApplicationSleepManager::mInstance; + +CHIP_ERROR ApplicationSleepManager::Init() +{ + VerifyOrReturnError(mFabricTable != nullptr, CHIP_ERROR_INVALID_ARGUMENT, ChipLogError(AppServer, "FabricTable is null")); + VerifyOrReturnError(mSubscriptionsInfoProvider != nullptr, CHIP_ERROR_INVALID_ARGUMENT, + ChipLogError(AppServer, "SubscriptionsInfoProvider is null")); + VerifyOrReturnError(mCommissioningWindowManager != nullptr, CHIP_ERROR_INVALID_ARGUMENT, + ChipLogError(AppServer, "CommissioningWindowManager is null")); + VerifyOrReturnError(mWifiSleepManager != nullptr, CHIP_ERROR_INVALID_ARGUMENT, + ChipLogError(AppServer, "WifiSleepManager is null")); + + ReturnErrorOnFailure(mFabricTable->AddFabricDelegate(this)); + + // Register WifiSleepManager::ApplicationCallback + mWifiSleepManager->SetApplicationCallback(this); + + return CHIP_NO_ERROR; +} + +void ApplicationSleepManager::OnSubscriptionEstablished(chip::app::ReadHandler & aReadHandler) +{ + mWifiSleepManager->VerifyAndTransitionToLowPowerMode(); +} + +void ApplicationSleepManager::OnSubscriptionTerminated(chip::app::ReadHandler & aReadHandler) +{ + mWifiSleepManager->VerifyAndTransitionToLowPowerMode(); +} + +CHIP_ERROR ApplicationSleepManager::OnSubscriptionRequested(chip::app::ReadHandler & aReadHandler, + chip::Transport::SecureSession & aSecureSession) +{ + // Nothing to execute for the ApplicationSleepManager + return CHIP_NO_ERROR; +} + +void ApplicationSleepManager::OnFabricRemoved(const chip::FabricTable & fabricTable, chip::FabricIndex fabricIndex) +{ + mWifiSleepManager->VerifyAndTransitionToLowPowerMode(); +} + +void ApplicationSleepManager::OnFabricCommitted(const chip::FabricTable & fabricTable, chip::FabricIndex fabricIndex) +{ + mWifiSleepManager->VerifyAndTransitionToLowPowerMode(); +} + +bool ApplicationSleepManager::CanGoToLIBasedSleep() +{ + // TODO: Implement your logic here + + ChipLogProgress(AppServer, "CanGoToLIBasedSleep was called!"); + return false; +} + +} // namespace Silabs +} // namespace app +} // namespace chip diff --git a/examples/platform/silabs/wifi/icd/ApplicationSleepManager.h b/examples/platform/silabs/wifi/icd/ApplicationSleepManager.h new file mode 100644 index 0000000000..8eba8fcdc4 --- /dev/null +++ b/examples/platform/silabs/wifi/icd/ApplicationSleepManager.h @@ -0,0 +1,138 @@ +/******************************************************************************* + * @file ApplicationSleepManager.h + * @brief Header for the buisness logic around Optimizing Wi-Fi sleep states + ******************************************************************************* + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ******************************************************************************* + * + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + ******************************************************************************/ + +#pragma once + +#include +#include +#include +#include +#include + +namespace chip { +namespace app { +namespace Silabs { + +class ApplicationSleepManager : public chip::app::ReadHandler::ApplicationCallback, + public chip::DeviceLayer::Silabs::WifiSleepManager::ApplicationCallback, + public chip::FabricTable::Delegate +{ +public: + static ApplicationSleepManager & GetInstance() { return mInstance; } + + /** + * @brief Init function validates that the necessary pointers where correctly set + * before registering the object with the FabricTable and the WifiSleepManager. + * + * Init function does not register with the InteractionModelEngine since depending on the whole interation model engine + * complexifies unit testing when we can use the SubscriptionInfoProvider which provides the necessary APIs. + * + * + * @return CHIP_ERROR CHIP_NO_ERROR if the init succeed + * CHIP_ERROR_INVALID_ARGUMENT, if the fabricTable, subscriptionsInfoProvider or commissioningWindowManager, + * wifiSleepManager were not set correctly + * other, if the FabricTable::AddFabricDelegate failed + */ + CHIP_ERROR Init(); + + ApplicationSleepManager & SetFabricTable(chip::FabricTable * fabricTable) + { + mFabricTable = fabricTable; + return *this; + } + + ApplicationSleepManager & SetSubscriptionInfoProvider(chip::app::SubscriptionsInfoProvider * subscriptionsInfoProvider) + { + mSubscriptionsInfoProvider = subscriptionsInfoProvider; + return *this; + } + + ApplicationSleepManager & SetCommissioningWindowManager(chip::CommissioningWindowManager * commissioningWindowManager) + { + mCommissioningWindowManager = commissioningWindowManager; + return *this; + } + + ApplicationSleepManager & SetWifiSleepManager(chip::DeviceLayer::Silabs::WifiSleepManager * wifiSleepManager) + { + mWifiSleepManager = wifiSleepManager; + return *this; + } + + // ReadHandler::ApplicationCallback implementation + + /** + * @brief Calls the WifiSleepManager VerifyAndTransitionToLowPowerMode. + * The VerifyAndTransitionToLowPowerMode function is responsible of then queriyng the ApplicationSleepManager to + * determine in which low power state the Wi-Fi device can transition to. + */ + void OnSubscriptionTerminated(chip::app::ReadHandler & aReadHandler); + + /** + * @brief Calls the WifiSleepManager VerifyAndTransitionToLowPowerMode. + * The VerifyAndTransitionToLowPowerMode function is responsible of then queriyng the ApplicationSleepManager to + * determine in which low power state the Wi-Fi device can transition to. + */ + void OnSubscriptionEstablished(chip::app::ReadHandler & aReadHandler); + + CHIP_ERROR OnSubscriptionRequested(chip::app::ReadHandler & aReadHandler, chip::Transport::SecureSession & aSecureSession); + + // WifiSleepManager::ApplicationCallback implementation + + /** + * @brief TODO + * + * @return true + * @return false + */ + bool CanGoToLIBasedSleep() override; + + // FabricTable::Delegate implementation + + /** + * @brief Calls the WifiSleepManager VerifyAndTransitionToLowPowerMode. + * The VerifyAndTransitionToLowPowerMode function is responsible of queriyng the ApplicationSleepManager to + * determine in which low power state the Wi-Fi device can transition to. + */ + void OnFabricRemoved(const chip::FabricTable & fabricTable, chip::FabricIndex fabricIndex) override; + + /** + * @brief Calls the WifiSleepManager VerifyAndTransitionToLowPowerMode. + * The VerifyAndTransitionToLowPowerMode function is responsible of queriyng the ApplicationSleepManager to + * determine in which low power state the Wi-Fi device can transition to. + */ + void OnFabricCommitted(const chip::FabricTable & fabricTable, chip::FabricIndex fabricIndex) override; + + void OnFabricUpdated(const chip::FabricTable & fabricTable, chip::FabricIndex fabricIndex) override {} + +private: + ApplicationSleepManager() = default; + ~ApplicationSleepManager() = default; + + ApplicationSleepManager(const ApplicationSleepManager &) = delete; + ApplicationSleepManager & operator=(const ApplicationSleepManager &) = delete; + + static ApplicationSleepManager mInstance; + chip::FabricTable * mFabricTable = nullptr; + chip::app::SubscriptionsInfoProvider * mSubscriptionsInfoProvider = nullptr; + chip::CommissioningWindowManager * mCommissioningWindowManager = nullptr; + chip::DeviceLayer::Silabs::WifiSleepManager * mWifiSleepManager = nullptr; +}; + +} // namespace Silabs +} // namespace app +} // namespace chip diff --git a/examples/platform/silabs/wifi/icd/BUILD.gn b/examples/platform/silabs/wifi/icd/BUILD.gn new file mode 100644 index 0000000000..a1360e2ba9 --- /dev/null +++ b/examples/platform/silabs/wifi/icd/BUILD.gn @@ -0,0 +1,39 @@ +#****************************************************************************** +# @file BUILD.gn +# @brief BUILD.gn to build the Application Sleep Manager implementation +#****************************************************************************** +# # License +# Copyright 2024 Silicon Laboratories Inc. www.silabs.com +#****************************************************************************** +# +# The licensor of this software is Silicon Laboratories Inc. Your use of this +# software is governed by the terms of Silicon Labs Master Software License +# Agreement (MSLA) available at +# www.silabs.com/about-us/legal/master-software-license-agreement. This +# software is distributed to you in Source Code format and is governed by the +# sections of the MSLA applicable to Source Code. +# +#*****************************************************************************/ + +import("//build_overrides/chip.gni") + +config("app-sleep-manager-config") { + include_dirs = [ "." ] + defines = [ "SL_MATTER_ENABLE_APP_SLEEP_MANAGER=1" ] +} + +source_set("app-sleep-manager") { + sources = [ + "ApplicationSleepManager.cpp", + "ApplicationSleepManager.h", + ] + + deps = [ + "${chip_root}/src/app", + "${chip_root}/src/app/server:server", + "${chip_root}/src/lib/core", + "${chip_root}/src/platform/silabs/wifi:wifi-platform", + ] + + public_configs = [ ":app-sleep-manager-config" ] +} diff --git a/src/app/ReadHandler.cpp b/src/app/ReadHandler.cpp index 4794ead97e..7861dcc1d5 100644 --- a/src/app/ReadHandler.cpp +++ b/src/app/ReadHandler.cpp @@ -55,8 +55,7 @@ uint16_t ReadHandler::GetPublisherSelectedIntervalLimit() ReadHandler::ReadHandler(ManagementCallback & apCallback, Messaging::ExchangeContext * apExchangeContext, InteractionType aInteractionType, Observer * observer, DataModel::Provider * apDataModel) : - mAttributePathExpandIterator(apDataModel, nullptr), - mExchangeCtx(*this), mManagementCallback(apCallback) + mAttributePathExpandIterator(apDataModel, nullptr), mExchangeCtx(*this), mManagementCallback(apCallback) { VerifyOrDie(apExchangeContext != nullptr); @@ -152,6 +151,7 @@ ReadHandler::~ReadHandler() auto * appCallback = mManagementCallback.GetAppCallback(); if (mFlags.Has(ReadHandlerFlags::ActiveSubscription) && appCallback) { + mFlags.Clear(ReadHandlerFlags::ActiveSubscription); appCallback->OnSubscriptionTerminated(*this); } diff --git a/src/platform/silabs/efr32/BUILD.gn b/src/platform/silabs/efr32/BUILD.gn index f39628d484..920168ce8a 100644 --- a/src/platform/silabs/efr32/BUILD.gn +++ b/src/platform/silabs/efr32/BUILD.gn @@ -17,6 +17,7 @@ import("//build_overrides/chip.gni") import("${chip_root}/build/chip/buildconfig_header.gni") import("${chip_root}/src/crypto/crypto.gni") import("${chip_root}/src/platform/device.gni") +import("${chip_root}/src/tracing/tracing_args.gni") import("${chip_root}/third_party/silabs/efr32_sdk.gni") import("${chip_root}/third_party/silabs/silabs_board.gni") @@ -114,9 +115,17 @@ static_library("efr32") { "${chip_root}/src/platform:platform_base", "${chip_root}/src/platform/logging:headers", ] - deps = [ "${silabs_platform_dir}/provision:provision-headers" ] + deps = [ + "${chip_root}/src/tracing", + "${silabs_platform_dir}/provision:provision-headers", + ] + public_configs = [] + if (matter_enable_tracing_support) { + public_deps += [ "${chip_root}/src/platform/silabs/tracing:SilabsTracing" ] + } + # Add platform crypto implementation if (chip_crypto == "platform") { sources += [ diff --git a/src/platform/silabs/efr32/OTAImageProcessorImpl.cpp b/src/platform/silabs/efr32/OTAImageProcessorImpl.cpp index a0efd10100..47716d6383 100644 --- a/src/platform/silabs/efr32/OTAImageProcessorImpl.cpp +++ b/src/platform/silabs/efr32/OTAImageProcessorImpl.cpp @@ -25,6 +25,11 @@ #include #endif // SL_WIFI +#include +#if MATTER_TRACING_ENABLED +#include +#endif // MATTER_TRACING_ENABLED + extern "C" { #include "btl_interface.h" #include "sl_core.h" @@ -51,6 +56,11 @@ static chip::OTAImageProcessorImpl gImageProcessor; namespace chip { +#if MATTER_TRACING_ENABLED +using TimeTraceOperation = chip::Tracing::Silabs::TimeTraceOperation; +using SilabsTracer = chip::Tracing::Silabs::SilabsTracer; +#endif // MATTER_TRACING_ENABLED + // Define static memebers uint8_t OTAImageProcessorImpl::mSlotId = 0; uint32_t OTAImageProcessorImpl::mWriteOffset = 0; @@ -158,12 +168,19 @@ void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context) ChipLogProgress(SoftwareUpdate, "HandlePrepareDownload: started"); +#if MATTER_TRACING_ENABLED + SilabsTracer::Instance().TimeTraceBegin(TimeTraceOperation::kImageUpload); +#endif // MATTER_TRACING_ENABLED + #ifdef _SILICON_LABS_32B_SERIES_2 // TODO sl-temp: bootloader_init is called previously sl_platform_init(). Recalling it for series3 causes a crash. WRAP_BL_DFU_CALL(err = bootloader_init()) if (err != SL_BOOTLOADER_OK) { ChipLogProgress(SoftwareUpdate, "bootloader_init Failed error: %ld", err); +#if MATTER_TRACING_ENABLED + SilabsTracer::Instance().TimeTraceEnd(TimeTraceOperation::kImageUpload, CHIP_ERROR_INTERNAL); +#endif // MATTER_TRACING_ENABLED } #endif @@ -205,6 +222,9 @@ void OTAImageProcessorImpl::HandleFinalize(intptr_t context) if (err != SL_STATUS_OK) { ChipLogError(SoftwareUpdate, "sl_wfx_host_pre_bootloader_spi_transfer() error: %ld", err); +#if MATTER_TRACING_ENABLED + SilabsTracer::Instance().TimeTraceEnd(TimeTraceOperation::kImageUpload, CHIP_ERROR_INTERNAL); +#endif // MATTER_TRACING_ENABLED return; } #endif // SL_BTLCTRL_MUX @@ -215,6 +235,9 @@ void OTAImageProcessorImpl::HandleFinalize(intptr_t context) if (err != SL_STATUS_OK) { ChipLogError(SoftwareUpdate, "sl_wfx_host_post_bootloader_spi_transfer() error: %ld", err); +#if MATTER_TRACING_ENABLED + SilabsTracer::Instance().TimeTraceEnd(TimeTraceOperation::kImageUpload, CHIP_ERROR_INTERNAL); +#endif // MATTER_TRACING_ENABLED return; } #endif // SL_BTLCTRL_MUX @@ -222,6 +245,9 @@ void OTAImageProcessorImpl::HandleFinalize(intptr_t context) { ChipLogError(SoftwareUpdate, "bootloader_eraseWriteStorage() error: %ld", err); imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED); +#if MATTER_TRACING_ENABLED + SilabsTracer::Instance().TimeTraceEnd(TimeTraceOperation::kImageUpload, CHIP_ERROR_WRITE_FAILED); +#endif // MATTER_TRACING_ENABLED return; } } @@ -229,6 +255,9 @@ void OTAImageProcessorImpl::HandleFinalize(intptr_t context) imageProcessor->ReleaseBlock(); ChipLogProgress(SoftwareUpdate, "OTA image downloaded successfully"); +#if MATTER_TRACING_ENABLED + SilabsTracer::Instance().TimeTraceEnd(TimeTraceOperation::kImageUpload); +#endif // MATTER_TRACING_ENABLED } // TODO: SE access is not thread safe. It assert if other tasks accesses it during bootloader_verifyImage or @@ -252,6 +281,9 @@ void OTAImageProcessorImpl::HandleApply(intptr_t context) uint32_t err = SL_BOOTLOADER_OK; ChipLogProgress(SoftwareUpdate, "HandleApply: verifying image"); +#if MATTER_TRACING_ENABLED + SilabsTracer::Instance().TimeTraceBegin(TimeTraceOperation::kImageVerification); +#endif // MATTER_TRACING_ENABLED // Force KVS to store pending keys such as data from StoreCurrentUpdateInfo() chip::DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().ForceKeyMapSave(); @@ -260,6 +292,9 @@ void OTAImageProcessorImpl::HandleApply(intptr_t context) if (err != SL_STATUS_OK) { ChipLogError(SoftwareUpdate, "sl_wfx_host_pre_bootloader_spi_transfer() error: %ld", err); +#if MATTER_TRACING_ENABLED + SilabsTracer::Instance().TimeTraceEnd(TimeTraceOperation::kImageVerification, CHIP_ERROR_INTERNAL); +#endif // MATTER_TRACING_ENABLED return; } #endif // SL_BTLCTRL_MUX @@ -282,6 +317,9 @@ void OTAImageProcessorImpl::HandleApply(intptr_t context) ChipLogError(SoftwareUpdate, "sl_wfx_host_post_bootloader_spi_transfer() error: %ld", err); } #endif // SL_BTLCTRL_MUX +#if MATTER_TRACING_ENABLED + SilabsTracer::Instance().TimeTraceEnd(TimeTraceOperation::kImageVerification, err); +#endif // MATTER_TRACING_ENABLED return; } ChipLogProgress(SoftwareUpdate, "Image verified, Set image to bootload"); @@ -300,6 +338,9 @@ void OTAImageProcessorImpl::HandleApply(intptr_t context) ChipLogError(SoftwareUpdate, "sl_wfx_host_post_bootloader_spi_transfer() error: %ld", err); } #endif // SL_BTLCTRL_MUX +#if MATTER_TRACING_ENABLED + SilabsTracer::Instance().TimeTraceEnd(TimeTraceOperation::kImageVerification, err); +#endif // MATTER_TRACING_ENABLED return; } @@ -308,11 +349,23 @@ void OTAImageProcessorImpl::HandleApply(intptr_t context) if (err != SL_STATUS_OK) { ChipLogError(SoftwareUpdate, "sl_wfx_host_post_bootloader_spi_transfer() error: %ld", err); +#if MATTER_TRACING_ENABLED + SilabsTracer::Instance().TimeTraceEnd(TimeTraceOperation::kImageVerification, err); +#endif // MATTER_TRACING_ENABLED return; } #endif // SL_BTLCTRL_MUX +#if MATTER_TRACING_ENABLED + SilabsTracer::Instance().TimeTraceEnd(TimeTraceOperation::kImageVerification); + SilabsTracer::Instance().TimeTraceInstant(TimeTraceOperation::kAppApplyTime); +#endif // MATTER_TRACING_ENABLED ChipLogProgress(SoftwareUpdate, "Reboot and install new image..."); + +#if MATTER_TRACING_ENABLED + // Flush all traces before reboot since we do not store them in NVM currently + SilabsTracer::Instance().TraceBufferFlushAll(); +#endif // MATTER_TRACING_ENABLED #if defined(_SILICON_LABS_32B_SERIES_3) && CHIP_PROGRESS_LOGGING osDelay(100); // sl-temp: delay for uart print before reboot #endif // _SILICON_LABS_32B_SERIES_3 && CHIP_PROGRESS_LOGGING diff --git a/src/platform/silabs/tracing/BUILD.gn b/src/platform/silabs/tracing/BUILD.gn index 78b339d19c..2c144fae04 100644 --- a/src/platform/silabs/tracing/BUILD.gn +++ b/src/platform/silabs/tracing/BUILD.gn @@ -20,6 +20,8 @@ import("//build_overrides/chip.gni") static_library("SilabsTracing") { sources = [ + "BackendImpl.cpp", + "BackendImpl.h", "SilabsTracing.cpp", "SilabsTracing.h", ] @@ -27,7 +29,8 @@ static_library("SilabsTracing") { deps = [ "${chip_root}/src/lib/core", "${chip_root}/src/lib/support", - "${chip_root}/src/platform", "${chip_root}/src/system", ] + + public_deps = [ "${chip_root}/src/tracing:tracing" ] } diff --git a/src/platform/silabs/tracing/BackendImpl.cpp b/src/platform/silabs/tracing/BackendImpl.cpp new file mode 100644 index 0000000000..35836011f2 --- /dev/null +++ b/src/platform/silabs/tracing/BackendImpl.cpp @@ -0,0 +1,90 @@ +#include "BackendImpl.h" +#include "SilabsTracing.h" +#include +#include + +namespace chip { +namespace Tracing { +namespace Silabs { + +TimeTraceOperation MapMetricKeyToOperation(MetricKey metricKey) +{ + if (metricKey == kMetricDeviceCommissionerPASESession) + return TimeTraceOperation::kPake1; + if (metricKey == kMetricDeviceCommissionerCommission) + return TimeTraceOperation::kOperationalCredentials; + if (metricKey == kMetricDeviceCommissionerCommissionStage) + return TimeTraceOperation::kTransportSetup; + if (metricKey == kMetricSetupCodePairerPairDevice) + return TimeTraceOperation::kFindOperational; + if (metricKey == kMetricDeviceCommissioningOperationalSetup) + return TimeTraceOperation::kCaseSession; + if (metricKey == kMetricDeviceOperationalDiscovery) + return TimeTraceOperation::kFindOperational; + if (metricKey == kMetricDeviceOperationalDiscoveryAttemptCount) + return TimeTraceOperation::kFindOperational; + if (metricKey == kMetricDeviceCASESession) + return TimeTraceOperation::kCaseSession; + if (metricKey == kMetricDeviceCASESessionSigma1) + return TimeTraceOperation::kSigma1; + if (metricKey == kMetricDeviceCASESessionSigma1Resume) + return TimeTraceOperation::kSigma1; + if (metricKey == kMetricDeviceCASESessionSigma2) + return TimeTraceOperation::kSigma2; + if (metricKey == kMetricDeviceCASESessionSigma3) + return TimeTraceOperation::kSigma3; + if (metricKey == kMetricDeviceCASESessionSigma2Resume) + return TimeTraceOperation::kSigma2; + if (metricKey == kMetricDeviceCASESessionSigmaFinished) + return TimeTraceOperation::kCaseSession; + if (metricKey == kMetricDeviceRMPRetryCount) + return TimeTraceOperation::kTransportLayer; + + return TimeTraceOperation::kNumTraces; +} + +void BackendImpl::TraceBegin(const char * label, const char * group) +{ + SilabsTracer::Instance().TimeTraceBegin(MapMetricKeyToOperation(label)); +} +void BackendImpl::TraceEnd(const char * label, const char * group) +{ + SilabsTracer::Instance().TimeTraceEnd(MapMetricKeyToOperation(label), CHIP_NO_ERROR); +} +void BackendImpl::TraceInstant(const char * label, const char * group) +{ + SilabsTracer::Instance().TimeTraceInstant(MapMetricKeyToOperation(label), CHIP_NO_ERROR); +} + +void BackendImpl::LogMetricEvent(const MetricEvent & event) +{ + Silabs::TimeTraceOperation operation = MapMetricKeyToOperation(event.key()); + CHIP_ERROR err = CHIP_NO_ERROR; + switch (event.ValueType()) + { + case MetricEvent::Value::Type::kChipErrorCode: + err = ChipError(event.ValueErrorCode()); + break; + default: + break; + } + + switch (event.type()) + { + case MetricEvent::Type::kBeginEvent: + SilabsTracer::Instance().TimeTraceBegin(operation); + break; + case MetricEvent::Type::kEndEvent: + SilabsTracer::Instance().TimeTraceEnd(operation, err); + break; + case MetricEvent::Type::kInstantEvent: + SilabsTracer::Instance().TimeTraceInstant(operation, err); + break; + default: + break; + } +} + +} // namespace Silabs +} // namespace Tracing +} // namespace chip diff --git a/src/platform/silabs/tracing/BackendImpl.h b/src/platform/silabs/tracing/BackendImpl.h new file mode 100644 index 0000000000..f9ae3b5e6c --- /dev/null +++ b/src/platform/silabs/tracing/BackendImpl.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include +#include +#include + +#define _MATTER_TRACE_DISABLE(...) \ + do \ + { \ + } while (false) + +// This gets forwarded to the multiplexed instance +#define MATTER_TRACE_BEGIN(label, group) ::chip::Tracing::Internal::Begin(label, group) +#define MATTER_TRACE_END(label, group) ::chip::Tracing::Internal::End(label, group) +#define MATTER_TRACE_INSTANT(label, group) ::chip::Tracing::Internal::Instant(label, group) +#define MATTER_TRACE_COUNTER(label) ::chip::Tracing::Internal::Counter(label) + +// We are not using this in our current implementation, so we are disabling it. +#define MATTER_TRACE_SCOPE(...) _MATTER_TRACE_DISABLE(__VA_ARGS__) + +namespace chip { +namespace Tracing { +namespace Silabs { + +/** @brief + * Backend implementation for Silabs platform acting as an interface with SilabsTracer and the matter layer. + */ +class BackendImpl : public ::chip::Tracing::Backend +{ +public: + BackendImpl() = default; + // TraceBegin, TraceEnd and TraceInstant are redundant with LogMetricEvent in the usecases that we are trying to track, + // so we are not implementing these at the moment to avoid duplication of the same information in the trace. We might implement them + // in the future if we want to add new traces that are not related to our metrics measurements + void TraceBegin(const char * label, const char * group) override; + void TraceEnd(const char * label, const char * group) override; + void TraceInstant(const char * label, const char * group) override; + + // Our tracing counter is embedded in our metrics, so we are not implementing it. + void TraceCounter(const char * label) override {} + + // Not implmented yet, might be implemented in the future. + void LogMessageSend(MessageSendInfo &) override {} + void LogMessageReceived(MessageReceivedInfo &) override {} + void LogNodeLookup(NodeLookupInfo &) override {} + void LogNodeDiscovered(NodeDiscoveredInfo &) override {} + void LogNodeDiscoveryFailed(NodeDiscoveryFailedInfo &) override {} + + /** @brief Log a metric event using SilabsTracer interface + * SilabsTracer.Init() needs to be called before this is called. + */ + void LogMetricEvent(const MetricEvent &) override; +}; + +} // namespace Silabs +} // namespace Tracing +} // namespace chip diff --git a/src/platform/silabs/tracing/SilabsTracing.cpp b/src/platform/silabs/tracing/SilabsTracing.cpp index e9940bac02..91788b1829 100644 --- a/src/platform/silabs/tracing/SilabsTracing.cpp +++ b/src/platform/silabs/tracing/SilabsTracing.cpp @@ -20,7 +20,7 @@ #include #if !CONFIG_BUILD_FOR_HOST_UNIT_TEST -#include // for isLogInitialized +#include // for isLogInitialized #endif // The following functions needs to be implemented by the application to allows logging or storing the traces / @@ -82,6 +82,8 @@ const char * TimeTraceOperationToString(TimeTraceOperation operation) return "SilabsInit"; case TimeTraceOperation::kMatterInit: return "MatterInit"; + case TimeTraceOperation::kAppInit: + return "AppInit"; case TimeTraceOperation::kNumTraces: return "NumTraces"; case TimeTraceOperation::kBufferFull: @@ -120,18 +122,20 @@ int TimeTracker::ToCharArray(MutableByteSpan & buffer) const { case OperationType::kBegin: return snprintf(reinterpret_cast(buffer.data()), buffer.size(), - "TimeTracker - StartTime: %" PRIu32 ", Operation: %s, Type: %s, Error: 0x%" PRIx32, mStartTime.count(), - TimeTraceOperationToString(mOperation), OperationTypeToString(mType), mError.AsInteger()); + "TimeTracker - Type: %s, Operation: %s, Status: 0x%" PRIx32 ", StartTime: %" PRIu32 "", + OperationTypeToString(mType), TimeTraceOperationToString(mOperation), mError.AsInteger(), + mStartTime.count()); case OperationType::kEnd: return snprintf(reinterpret_cast(buffer.data()), buffer.size(), - "TimeTracker - StartTime: %" PRIu32 ", EndTime: %" PRIu32 ", Duration: %" PRIu32 - " ms, Operation: %s, Type: %s, Error: 0x%" PRIx32, - mStartTime.count(), mEndTime.count(), (mEndTime - mStartTime).count(), - TimeTraceOperationToString(mOperation), OperationTypeToString(mType), mError.AsInteger()); + "TimeTracker - Type: %s, Operation: %s, Status: 0x%" PRIx32 ", StartTime: %" PRIu32 ", EndTime: %" PRIu32 + ", Duration: %" PRIu32 " ms", + OperationTypeToString(mType), TimeTraceOperationToString(mOperation), mError.AsInteger(), + mStartTime.count(), mEndTime.count(), (mEndTime - mStartTime).count()); case OperationType::kInstant: return snprintf(reinterpret_cast(buffer.data()), buffer.size(), - "TimeTracker - EventTime: %" PRIu32 ", Operation: %s, Type: %s, Error: 0x%" PRIx32, mStartTime.count(), - TimeTraceOperationToString(mOperation), OperationTypeToString(mType), mError.AsInteger()); + "TimeTracker - Type: %s, Operation: %s, Status: 0x%" PRIx32 ", EventTime: %" PRIu32 "", + OperationTypeToString(mType), TimeTraceOperationToString(mOperation), mError.AsInteger(), + mStartTime.count()); default: return snprintf(reinterpret_cast(buffer.data()), buffer.size(), "TimeTracker - Unknown operation type"); } @@ -175,13 +179,13 @@ CHIP_ERROR SilabsTracer::StartWatermarksStorage(PersistentStorageDelegate * stor CHIP_ERROR SilabsTracer::TimeTraceBegin(TimeTraceOperation aOperation) { // Log the start time of the operation - auto & tracker = mLatestTimeTrackers[static_cast(aOperation)]; + auto & tracker = mLatestTimeTrackers[to_underlying(aOperation)]; tracker.mStartTime = System::SystemClock().GetMonotonicTimestamp(); tracker.mOperation = aOperation; tracker.mType = OperationType::kBegin; tracker.mError = CHIP_NO_ERROR; - auto & watermark = mWatermarks[static_cast(aOperation)]; + auto & watermark = mWatermarks[to_underlying(aOperation)]; watermark.mTotalCount++; return OutputTrace(tracker); @@ -189,7 +193,7 @@ CHIP_ERROR SilabsTracer::TimeTraceBegin(TimeTraceOperation aOperation) CHIP_ERROR SilabsTracer::TimeTraceEnd(TimeTraceOperation aOperation, CHIP_ERROR error) { - auto & tracker = mLatestTimeTrackers[static_cast(aOperation)]; + auto & tracker = mLatestTimeTrackers[to_underlying(aOperation)]; tracker.mEndTime = System::SystemClock().GetMonotonicTimestamp(); tracker.mType = OperationType::kEnd; tracker.mError = error; @@ -199,7 +203,7 @@ CHIP_ERROR SilabsTracer::TimeTraceEnd(TimeTraceOperation aOperation, CHIP_ERROR // Calculate the duration and update the time tracker auto duration = tracker.mEndTime - tracker.mStartTime; - auto & watermark = mWatermarks[static_cast(aOperation)]; + auto & watermark = mWatermarks[to_underlying(aOperation)]; watermark.mSuccessfullCount++; watermark.mMovingAverage = System::Clock::Milliseconds32( (watermark.mMovingAverage.count() * (watermark.mSuccessfullCount - 1) + duration.count()) / @@ -237,6 +241,8 @@ CHIP_ERROR SilabsTracer::TimeTraceInstant(TimeTraceOperation aOperation, CHIP_ER CHIP_ERROR SilabsTracer::OutputTimeTracker(const TimeTracker & tracker) { + VerifyOrReturnError(to_underlying(tracker.mOperation) < kNumTraces, CHIP_ERROR_INVALID_ARGUMENT, + ChipLogError(DeviceLayer, "Invalid tracker")); VerifyOrReturnError(isLogInitialized(), CHIP_ERROR_UNINITIALIZED); // Allocate a buffer to store the trace uint8_t buffer[kMaxTraceSize]; @@ -279,16 +285,18 @@ CHIP_ERROR SilabsTracer::OutputTrace(const TimeTracker & tracker) CHIP_ERROR SilabsTracer::OutputWaterMark(TimeTraceOperation aOperation) { - size_t index = static_cast(aOperation); - auto & watermark = mWatermarks[index]; + VerifyOrReturnError(to_underlying(aOperation) < kNumTraces, CHIP_ERROR_INVALID_ARGUMENT, + ChipLogError(DeviceLayer, "Invalid TimeTraceOperation")); VerifyOrReturnError(isLogInitialized(), CHIP_ERROR_UNINITIALIZED); ChipLogProgress(DeviceLayer, - "Operation: %s, TotalCount=%" PRIu32 ", SuccessFullCount=%" PRIu32 ", MaxTime=%" PRIu32 ", MinTime=%" PRIu32 - ", AvgTime=%" PRIu32 ", CountAboveAvg=%" PRIu32 "", - TimeTraceOperationToString(aOperation), watermark.mTotalCount, watermark.mSuccessfullCount, - watermark.mMaxTimeMs.count(), watermark.mMinTimeMs.count(), watermark.mMovingAverage.count(), - watermark.mCountAboveAvg); + "| Operation: %-25s| MaxTime:%-5" PRIu32 "| MinTime:%-5" PRIu32 "| AvgTime:%-5" PRIu32 "| TotalCount:%-8" PRIu32 + ", SuccessFullCount:%-8" PRIu32 "| CountAboveAvg:%-8" PRIu32 "|", + TimeTraceOperationToString(aOperation), mWatermarks[to_underlying(aOperation)].mMaxTimeMs.count(), + mWatermarks[to_underlying(aOperation)].mMinTimeMs.count(), + mWatermarks[to_underlying(aOperation)].mMovingAverage.count(), + mWatermarks[to_underlying(aOperation)].mTotalCount, mWatermarks[to_underlying(aOperation)].mSuccessfullCount, + mWatermarks[to_underlying(aOperation)].mCountAboveAvg); return CHIP_NO_ERROR; } @@ -322,7 +330,8 @@ CHIP_ERROR SilabsTracer::TraceBufferFlushAll() CHIP_ERROR SilabsTracer::TraceBufferFlushByOperation(TimeTraceOperation aOperation) { - + VerifyOrReturnError(to_underlying(aOperation) < kNumTraces, CHIP_ERROR_INVALID_ARGUMENT, + ChipLogError(DeviceLayer, "Invalid TimeTraceOperation")); auto * current = mTimeTrackerList.head; auto * prev = static_cast *>(nullptr); while (current != nullptr) diff --git a/src/platform/silabs/tracing/SilabsTracing.h b/src/platform/silabs/tracing/SilabsTracing.h index 5bfc912f8c..8c257bb194 100644 --- a/src/platform/silabs/tracing/SilabsTracing.h +++ b/src/platform/silabs/tracing/SilabsTracing.h @@ -61,6 +61,7 @@ enum class TimeTraceOperation : uint8_t kBootup, kSilabsInit, kMatterInit, + kAppInit, kBufferFull, kNumTraces, }; @@ -151,6 +152,7 @@ class SilabsTracer * @return CHIP_ERROR, returns CHIP_ERROR_BUFFER_TOO_SMALL if the buffer is full */ CHIP_ERROR TimeTraceEnd(TimeTraceOperation aOperation, CHIP_ERROR error = CHIP_NO_ERROR); + CHIP_ERROR TimeTraceEnd(TimeTraceOperation aOperation, uint32_t error) { return TimeTraceEnd(aOperation, ChipError((error))); } /** @brief Trace an instant time operation * This calls the OutputTrace method to log the trace if logs are enabled, and stores the time tracker in the buffer if the @@ -160,6 +162,10 @@ class SilabsTracer * @return CHIP_ERROR, returns CHIP_ERROR_BUFFER_TOO_SMALL if the buffer is full */ CHIP_ERROR TimeTraceInstant(TimeTraceOperation aOperation, CHIP_ERROR error = CHIP_NO_ERROR); + CHIP_ERROR TimeTraceInstant(TimeTraceOperation aOperation, uint32_t error) + { + return TimeTraceInstant(aOperation, ChipError((error))); + } /** @brief Output a time tracker * This will output the latest time tracker for a specific operation, without affecting the buffer. @@ -297,6 +303,8 @@ class SilabsTracer CHIP_ERROR OutputTrace(const TimeTracker & tracker); }; +const char * TimeTraceOperationToString(TimeTraceOperation operation); + } // namespace Silabs } // namespace Tracing } // namespace chip diff --git a/src/platform/silabs/wifi/BUILD.gn b/src/platform/silabs/wifi/BUILD.gn index e70a6023b9..b7b652037b 100644 --- a/src/platform/silabs/wifi/BUILD.gn +++ b/src/platform/silabs/wifi/BUILD.gn @@ -32,6 +32,9 @@ declare_args() { #default Wifi Password chip_default_wifi_psk = "" + + # Argument to enable LwIP debug logs + sl_enable_wifi_debug_logs = false } if (chip_enable_wifi && !wifi_soc) { @@ -49,9 +52,15 @@ if (chip_enable_wifi && !wifi_soc) { } config("wifi-platform-config") { - defines = [ "WIFI_DEBUG_ENABLED=0" ] + defines = [] include_dirs = [] + if (sl_enable_wifi_debug_logs) { + defines += [ "WIFI_DEBUG_ENABLED=1" ] + } else { + defines += [ "WIFI_DEBUG_ENABLED=0" ] + } + if (use_rs9116) { # All the stuff from wiseconnect include_dirs += rs911x_inc_plat diff --git a/src/platform/silabs/wifi/icd/WifiSleepManager.cpp b/src/platform/silabs/wifi/icd/WifiSleepManager.cpp index c29c1bbce5..2bff2372b8 100644 --- a/src/platform/silabs/wifi/icd/WifiSleepManager.cpp +++ b/src/platform/silabs/wifi/icd/WifiSleepManager.cpp @@ -160,6 +160,8 @@ CHIP_ERROR WifiSleepManager::VerifyAndTransitionToLowPowerMode() #elif RS911X_WIFI // rs9116 VerifyOrReturnError(ConfigurePowerSave() == SL_STATUS_OK, CHIP_ERROR_INTERNAL); return CHIP_NO_ERROR; +#else // wf200 + return CHIP_NO_ERROR; #endif } diff --git a/src/platform/silabs/wifi/wf200/WifiInterface.cpp b/src/platform/silabs/wifi/wf200/WifiInterface.cpp index 675ee8fb67..eefad47d31 100644 --- a/src/platform/silabs/wifi/wf200/WifiInterface.cpp +++ b/src/platform/silabs/wifi/wf200/WifiInterface.cpp @@ -26,6 +26,7 @@ #include "sl_wfx_cmd_api.h" #include "sl_wfx_constants.h" #include "task.h" +#include #include #include #include @@ -729,7 +730,7 @@ static void wfx_events_task(void * p_arg) retryJoin = 0; wfx_lwip_set_sta_link_up(); #if CHIP_CONFIG_ENABLE_ICD_SERVER - if (!(wfx_get_wifi_state() & SL_WFX_AP_INTERFACE_UP)) + if (!(wifiContext.state & SL_WFX_AP_INTERFACE_UP)) { // Enable the power save ChipLogProgress(DeviceLayer, "WF200 going to DTIM based sleep"); diff --git a/src/platform/silabs/wifi/wf200/platform/wf200_init.c b/src/platform/silabs/wifi/wf200/platform/wf200_init.c index 40f1aaf08a..92663f9b05 100644 --- a/src/platform/silabs/wifi/wf200/platform/wf200_init.c +++ b/src/platform/silabs/wifi/wf200/platform/wf200_init.c @@ -319,6 +319,7 @@ sl_status_t sl_wfx_host_reset_chip(void) *****************************************************************************/ sl_status_t sl_wfx_host_wait_for_wake_up(void) { + xSemaphoreTake(wfx_wakeup_sem, pdMS_TO_TICKS(0)); xSemaphoreTake(wfx_wakeup_sem, pdMS_TO_TICKS(3)); return SL_STATUS_OK; diff --git a/src/platform/tests/TestSilabsTracing.cpp b/src/platform/tests/TestSilabsTracing.cpp index 1634b93191..f4a34985fa 100644 --- a/src/platform/tests/TestSilabsTracing.cpp +++ b/src/platform/tests/TestSilabsTracing.cpp @@ -667,14 +667,14 @@ TEST_F(TestSilabsTracing, TestLogs) // Verify OTA log EXPECT_EQ(SilabsTracer::Instance().GetTraceByOperation(TimeTraceOperation::kOTA, span), CHIP_NO_ERROR); const char * expectedOTALogFormat = - "TimeTracker - StartTime: 0, EndTime: 100, Duration: 100 ms, Operation: OTA, Type: End, Error: 0x0"; + "TimeTracker - Type: End, Operation: OTA, Status: 0x0, StartTime: 0, EndTime: 100, Duration: 100 ms"; EXPECT_STREQ(reinterpret_cast(span.data()), expectedOTALogFormat); // Verify Bootup log span = MutableByteSpan(logBuffer); EXPECT_EQ(SilabsTracer::Instance().GetTraceByOperation(TimeTraceOperation::kBootup, span), CHIP_NO_ERROR); const char * expectedBootupLogFormat = - "TimeTracker - StartTime: 100, EndTime: 300, Duration: 200 ms, Operation: Bootup, Type: End, Error: 0x0"; + "TimeTracker - Type: End, Operation: Bootup, Status: 0x0, StartTime: 100, EndTime: 300, Duration: 200 ms"; EXPECT_STREQ(reinterpret_cast(span.data()), expectedBootupLogFormat); // Test buffer too small behavior @@ -733,7 +733,7 @@ TEST_F(TestSilabsTracing, TestBufferBusting) uint8_t logBuffer[256]; MutableByteSpan logSpan(logBuffer); EXPECT_EQ(SilabsTracer::Instance().GetTraceByOperation(TimeTraceOperation::kBufferFull, logSpan), CHIP_NO_ERROR); - const char * expectedNumLogFormat = "TimeTracker - EventTime: 6200, Operation: BufferFull, Type: Instant, Error: 0x19"; + const char * expectedNumLogFormat = "TimeTracker - Type: Instant, Operation: BufferFull, Status: 0x19, EventTime: 6200"; EXPECT_STREQ(reinterpret_cast(logSpan.data()), expectedNumLogFormat); // Verify the kImageUpload operation was not added diff --git a/src/tracing/silabs/BUILD.gn b/src/tracing/silabs/BUILD.gn new file mode 100644 index 0000000000..0b744d4536 --- /dev/null +++ b/src/tracing/silabs/BUILD.gn @@ -0,0 +1,25 @@ +# Copyright (c) 2024 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/build.gni") +import("//build_overrides/chip.gni") + +config("tracing") { + include_dirs = [ "include" ] +} + +source_set("silabs_tracing") { + public = [ "include/matter/tracing/macros_impl.h" ] + public_configs = [ ":tracing" ] +} diff --git a/src/tracing/silabs/include/matter/tracing/macros_impl.h b/src/tracing/silabs/include/matter/tracing/macros_impl.h new file mode 100644 index 0000000000..f9ec7e5697 --- /dev/null +++ b/src/tracing/silabs/include/matter/tracing/macros_impl.h @@ -0,0 +1,25 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +/* Ensure we do not have double tracing macros defined */ +#if defined(MATTER_TRACE_BEGIN) +#error "Tracing macros seem to be double defined" +#endif + +#include diff --git a/src/tracing/tracing_args.gni b/src/tracing/tracing_args.gni index 085844e4a5..376c981282 100644 --- a/src/tracing/tracing_args.gni +++ b/src/tracing/tracing_args.gni @@ -49,6 +49,8 @@ declare_args() { matter_trace_config = "${chip_root}/src/tracing/perfetto:perfetto_tracing" } else if (chip_device_platform == "darwin") { matter_trace_config = "${chip_root}/src/tracing/darwin:darwin_tracing" + } else if (chip_device_platform == "efr32") { + matter_trace_config = "${chip_root}/src/tracing/silabs:silabs_tracing" } else { matter_trace_config = "${chip_root}/src/tracing/none" }