Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement run time value to the General diagnostics attributes for EFR32 platform #12376

Merged
merged 2 commits into from
Dec 1, 2021
Merged
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
97 changes: 97 additions & 0 deletions src/platform/EFR32/ConfigurationManagerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#include <platform/ConfigurationManager.h>
#include <platform/EFR32/EFR32Config.h>

#include "em_rmu.h"

namespace chip {
namespace DeviceLayer {

Expand All @@ -51,6 +53,12 @@ CHIP_ERROR ConfigurationManagerImpl::Init()

// TODO: Initialize the global GroupKeyStore object here (#1626)

IncreaseBootCount();
// It is possible to configure the possible reset sources with RMU_ResetControl
// In this case, we keep Reset control at default setting
rebootCause = RMU_ResetCauseGet();
RMU_ResetCauseClear();

// If the fail-safe was armed when the device last shutdown, initiate a factory reset.
if (GetFailSafeArmed(failSafeArmed) == CHIP_NO_ERROR && failSafeArmed)
{
Expand All @@ -74,6 +82,95 @@ void ConfigurationManagerImpl::InitiateFactoryReset()
PlatformMgr().ScheduleWork(DoFactoryReset);
}

CHIP_ERROR ConfigurationManagerImpl::GetRebootCount(uint32_t & rebootCount)
{
return EFR32Config::ReadConfigValue(EFR32Config::kConfigKey_BootCount, rebootCount);
}

CHIP_ERROR ConfigurationManagerImpl::IncreaseBootCount(void)
{
uint32_t bootCount = 0;

if (EFR32Config::ConfigValueExists(EFR32Config::kConfigKey_BootCount))
{
GetRebootCount(bootCount);
}

return EFR32Config::WriteConfigValue(EFR32Config::kConfigKey_BootCount, bootCount + 1);
}

uint32_t ConfigurationManagerImpl::GetBootReason(void)
{
// rebootCause is obtained at bootup.
uint32_t matterBootCause;
#if defined(_SILICON_LABS_32B_SERIES_1)
if (rebootCause & RMU_RSTCAUSE_PORST || rebootCause & RMU_RSTCAUSE_EXTRST) // PowerOn or External pin reset
{
matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_POWER_ON_REBOOT;
}
else if (rebootCause & RMU_RSTCAUSE_AVDDBOD || rebootCause & RMU_RSTCAUSE_DVDDBOD || rebootCause & RMU_RSTCAUSE_DECBOD)
{
matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_BROWN_OUT_RESET;
}
else if (rebootCause & RMU_RSTCAUSE_SYSREQRST)
{
matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_SOFTWARE_RESET;
}
else if (rebootCause & RMU_RSTCAUSE_WDOGRST)
{
matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_SOFTWARE_WATCHDOG_RESET;
}
else
{
matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_UNSPECIFIED;
}
// Not tracked HARDWARE_WATCHDOG_RESET && SOFTWARE_UPDATE_COMPLETED
#elif defined(_SILICON_LABS_32B_SERIES_2)
if (rebootCause & EMU_RSTCAUSE_POR || rebootCause & EMU_RSTCAUSE_PIN) // PowerOn or External pin reset
{
matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_POWER_ON_REBOOT;
}
else if (rebootCause & EMU_RSTCAUSE_AVDDBOD || rebootCause & EMU_RSTCAUSE_DVDDBOD || rebootCause & EMU_RSTCAUSE_DECBOD ||
rebootCause & EMU_RSTCAUSE_VREGIN || rebootCause & EMU_RSTCAUSE_IOVDD0BOD || rebootCause & EMU_RSTCAUSE_DVDDLEBOD)
{
matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_BROWN_OUT_RESET;
}
else if (rebootCause & EMU_RSTCAUSE_SYSREQ)
{
matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_SOFTWARE_RESET;
}
else if (rebootCause & EMU_RSTCAUSE_WDOG0 || rebootCause & EMU_RSTCAUSE_WDOG1)
{
matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_SOFTWARE_WATCHDOG_RESET;
}
else
{
matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_UNSPECIFIED;
}
// Not tracked HARDWARE_WATCHDOG_RESET && SOFTWARE_UPDATE_COMPLETED
#else
matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_UNSPECIFIED;
#endif

return matterBootCause;
}

CHIP_ERROR ConfigurationManagerImpl::GetTotalOperationalHours(uint32_t & totalOperationalHours)
{
if (!EFR32Config::ConfigValueExists(EFR32Config::kConfigKey_TotalOperationalHours))
{
totalOperationalHours = 0;
return CHIP_NO_ERROR;
}

return EFR32Config::ReadConfigValue(EFR32Config::kConfigKey_TotalOperationalHours, totalOperationalHours);
}

CHIP_ERROR ConfigurationManagerImpl::StoreTotalOperationalHours(uint32_t totalOperationalHours)
{
return EFR32Config::WriteConfigValue(EFR32Config::kConfigKey_TotalOperationalHours, totalOperationalHours);
}

CHIP_ERROR ConfigurationManagerImpl::ReadPersistedStorageValue(::chip::Platform::PersistedStorage::Key persistedStorageKey,
uint32_t & value)
{
Expand Down
8 changes: 7 additions & 1 deletion src/platform/EFR32/ConfigurationManagerImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ class ConfigurationManagerImpl : public Internal::GenericConfigurationManagerImp
// This returns an instance of this class.
static ConfigurationManagerImpl & GetDefaultInstance();

uint32_t GetBootReason(void);
CHIP_ERROR GetRebootCount(uint32_t & rebootCount);
CHIP_ERROR IncreaseBootCount(void);
CHIP_ERROR GetTotalOperationalHours(uint32_t & totalOperationalHours);
CHIP_ERROR StoreTotalOperationalHours(uint32_t totalOperationalHours);

private:
// ===== Members that implement the ConfigurationManager public interface.

Expand Down Expand Up @@ -67,7 +73,7 @@ class ConfigurationManagerImpl : public Internal::GenericConfigurationManagerImp
void RunConfigUnitTest(void) override;

// ===== Private members reserved for use by this class only.

uint32_t rebootCause;
static void DoFactoryReset(intptr_t arg);
};

Expand Down
128 changes: 128 additions & 0 deletions src/platform/EFR32/DiagnosticDataProviderImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,15 @@

#include <platform/DiagnosticDataProvider.h>
#include <platform/EFR32/DiagnosticDataProviderImpl.h>
#include <platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h>

#include <lwip/tcpip.h>

#include "AppConfig.h"
#include "FreeRTOS.h"

using namespace ::chip::app::Clusters::GeneralDiagnostics;

namespace chip {
namespace DeviceLayer {

Expand All @@ -40,6 +43,7 @@ DiagnosticDataProviderImpl & DiagnosticDataProviderImpl::GetDefaultInstance()
return sInstance;
}

// Software Diagnostics Getters
/*
* The following Heap stats are compiled values done by the FreeRTOS Heap4 implementation.
* See /examples/platform/efr32/heap_4_silabs.c
Expand Down Expand Up @@ -77,5 +81,129 @@ CHIP_ERROR DiagnosticDataProviderImpl::GetCurrentHeapHighWatermark(uint64_t & cu
return CHIP_NO_ERROR;
}

// General Diagnostics Getters

CHIP_ERROR DiagnosticDataProviderImpl::GetRebootCount(uint16_t & rebootCount)
{
uint32_t count = 0;
CHIP_ERROR err = ConfigurationMgr().GetRebootCount(count);

if (err == CHIP_NO_ERROR)
{
VerifyOrReturnError(count <= UINT16_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE);
rebootCount = static_cast<uint16_t>(count);
}

return err;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetBootReason(uint8_t & bootReason)
{
uint32_t reason = 0;
CHIP_ERROR err = ConfigurationMgr().GetBootReason(reason);

if (err == CHIP_NO_ERROR)
{
VerifyOrReturnError(reason <= UINT8_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE);
bootReason = static_cast<uint8_t>(reason);
}

return err;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetUpTime(uint64_t & upTime)
{
System::Clock::Timestamp currentTime = System::SystemClock().GetMonotonicTimestamp();
System::Clock::Timestamp startTime = PlatformMgrImpl().GetStartTime();

if (currentTime >= startTime)
{
upTime = std::chrono::duration_cast<System::Clock::Seconds64>(currentTime - startTime).count();
return CHIP_NO_ERROR;
}

return CHIP_ERROR_INVALID_TIME;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetTotalOperationalHours(uint32_t & totalOperationalHours)
{
uint64_t upTime = 0;

if (GetUpTime(upTime) == CHIP_NO_ERROR)
{
uint32_t totalHours = 0;
if (ConfigurationMgr().GetTotalOperationalHours(totalHours) == CHIP_NO_ERROR)
{
VerifyOrReturnError(upTime / 3600 <= UINT32_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE);
totalOperationalHours = totalHours + static_cast<uint32_t>(upTime / 3600);
return CHIP_NO_ERROR;
}
}

return CHIP_ERROR_INVALID_TIME;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetActiveHardwareFaults(GeneralFaults<kMaxHardwareFaults> & hardwareFaults)
{
#if CHIP_CONFIG_TEST
ReturnErrorOnFailure(hardwareFaults.add(EMBER_ZCL_HARDWARE_FAULT_TYPE_RADIO));
ReturnErrorOnFailure(hardwareFaults.add(EMBER_ZCL_HARDWARE_FAULT_TYPE_SENSOR));
ReturnErrorOnFailure(hardwareFaults.add(EMBER_ZCL_HARDWARE_FAULT_TYPE_POWER_SOURCE));
ReturnErrorOnFailure(hardwareFaults.add(EMBER_ZCL_HARDWARE_FAULT_TYPE_USER_INTERFACE_FAULT));
#endif

return CHIP_NO_ERROR;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetActiveRadioFaults(GeneralFaults<kMaxRadioFaults> & radioFaults)
{
#if CHIP_CONFIG_TEST
ReturnErrorOnFailure(radioFaults.add(EMBER_ZCL_RADIO_FAULT_TYPE_THREAD_FAULT));
ReturnErrorOnFailure(radioFaults.add(EMBER_ZCL_RADIO_FAULT_TYPE_BLE_FAULT));
#endif

return CHIP_NO_ERROR;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetActiveNetworkFaults(GeneralFaults<kMaxNetworkFaults> & networkFaults)
{
#if CHIP_CONFIG_TEST
ReturnErrorOnFailure(networkFaults.add(EMBER_ZCL_NETWORK_FAULT_TYPE_HARDWARE_FAILURE));
ReturnErrorOnFailure(networkFaults.add(EMBER_ZCL_NETWORK_FAULT_TYPE_NETWORK_JAMMED));
ReturnErrorOnFailure(networkFaults.add(EMBER_ZCL_NETWORK_FAULT_TYPE_CONNECTION_FAILED));
#endif

return CHIP_NO_ERROR;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetNetworkInterfaces(NetworkInterface ** netifpp)
{
NetworkInterface * ifp = new NetworkInterface();

const char * threadNetworkName = otThreadGetNetworkName(ThreadStackMgrImpl().OTInstance());
ifp->name = Span<const char>(threadNetworkName, strlen(threadNetworkName));
ifp->fabricConnected = true;
ifp->offPremiseServicesReachableIPv4 = false;
ifp->offPremiseServicesReachableIPv6 = false;
ifp->type = InterfaceType::EMBER_ZCL_INTERFACE_TYPE_THREAD;

uint8_t macBuffer[ConfigurationManager::kPrimaryMACAddressLength];
ConfigurationMgr().GetPrimary802154MACAddress(macBuffer);
ifp->hardwareAddress = ByteSpan(macBuffer, ConfigurationManager::kPrimaryMACAddressLength);

*netifpp = ifp;
return CHIP_NO_ERROR;
}

void DiagnosticDataProviderImpl::ReleaseNetworkInterfaces(NetworkInterface * netifp)
{
while (netifp)
{
NetworkInterface * del = netifp;
netifp = netifp->Next;
delete del;
}
}

} // namespace DeviceLayer
} // namespace chip
9 changes: 9 additions & 0 deletions src/platform/EFR32/DiagnosticDataProviderImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ class DiagnosticDataProviderImpl : public DiagnosticDataProvider
CHIP_ERROR GetCurrentHeapFree(uint64_t & currentHeapFree) override;
CHIP_ERROR GetCurrentHeapUsed(uint64_t & currentHeapUsed) override;
CHIP_ERROR GetCurrentHeapHighWatermark(uint64_t & currentHeapHighWatermark) override;
CHIP_ERROR GetRebootCount(uint16_t & rebootCount) override;
CHIP_ERROR GetBootReason(uint8_t & bootReason) override;
CHIP_ERROR GetUpTime(uint64_t & upTime) override;
CHIP_ERROR GetTotalOperationalHours(uint32_t & totalOperationalHours) override;
CHIP_ERROR GetActiveHardwareFaults(GeneralFaults<kMaxHardwareFaults> & hardwareFaults) override;
CHIP_ERROR GetActiveRadioFaults(GeneralFaults<kMaxRadioFaults> & radioFaults) override;
CHIP_ERROR GetActiveNetworkFaults(GeneralFaults<kMaxNetworkFaults> & networkFaults) override;
CHIP_ERROR GetNetworkInterfaces(NetworkInterface ** netifpp) override;
void ReleaseNetworkInterfaces(NetworkInterface * netifp) override;
};

} // namespace DeviceLayer
Expand Down
7 changes: 5 additions & 2 deletions src/platform/EFR32/EFR32Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,11 @@ class EFR32Config
static constexpr Key kConfigKey_CountryCode = EFR32ConfigKey(kChipConfig_KeyBase, 0x0A);
static constexpr Key kConfigKey_Breadcrumb = EFR32ConfigKey(kChipConfig_KeyBase, 0x0B);

static constexpr Key kConfigKey_GroupKeyBase = EFR32ConfigKey(kChipConfig_KeyBase, 0x0C);
static constexpr Key kConfigKey_GroupKeyMax = EFR32ConfigKey(kChipConfig_KeyBase, 0x1B); // Allows 16 Group Keys to be created.
static constexpr Key kConfigKey_BootCount = EFR32ConfigKey(kChipCounter_KeyBase, 0x0C);
static constexpr Key kConfigKey_TotalOperationalHours = EFR32ConfigKey(kChipCounter_KeyBase, 0x0D);

static constexpr Key kConfigKey_GroupKeyBase = EFR32ConfigKey(kChipConfig_KeyBase, 0x0E);
static constexpr Key kConfigKey_GroupKeyMax = EFR32ConfigKey(kChipConfig_KeyBase, 0x1D); // Allows 16 Group Keys to be created.

// Set key id limits for each group.
static constexpr Key kMinConfigKey_ChipFactory = EFR32ConfigKey(kChipFactory_KeyBase, 0x00);
Expand Down
25 changes: 25 additions & 0 deletions src/platform/EFR32/PlatformManagerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,30 @@ CHIP_ERROR PlatformManagerImpl::_InitChipStack(void)
return err;
}

CHIP_ERROR PlatformManagerImpl::_Shutdown()
{
uint64_t upTime = 0;

if (GetDiagnosticDataProvider().GetUpTime(upTime) == CHIP_NO_ERROR)
{
uint32_t totalOperationalHours = 0;

if (ConfigurationMgr().GetTotalOperationalHours(totalOperationalHours) == CHIP_NO_ERROR)
{
ConfigurationMgr().StoreTotalOperationalHours(totalOperationalHours + static_cast<uint32_t>(upTime / 3600));
}
else
{
ChipLogError(DeviceLayer, "Failed to get total operational hours of the Node");
}
}
else
{
ChipLogError(DeviceLayer, "Failed to get current uptime since the Node’s last reboot");
}

return Internal::GenericPlatformManagerImpl_FreeRTOS<PlatformManagerImpl>::_Shutdown();
}

} // namespace DeviceLayer
} // namespace chip
5 changes: 4 additions & 1 deletion src/platform/EFR32/PlatformManagerImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,22 @@ class PlatformManagerImpl final : public PlatformManager, public Internal::Gener
public:
// ===== Platform-specific members that may be accessed directly by the application.

/* none so far */
System::Clock::Timestamp GetStartTime() { return mStartTime; }

private:
// ===== Methods that implement the PlatformManager abstract interface.

CHIP_ERROR _InitChipStack(void);
CHIP_ERROR _Shutdown(void);

// ===== Members for internal use by the following friends.

friend PlatformManager & PlatformMgr(void);
friend PlatformManagerImpl & PlatformMgrImpl(void);
friend class Internal::BLEManagerImpl;

System::Clock::Timestamp mStartTime = System::Clock::kZero;

static PlatformManagerImpl sInstance;

using Internal::GenericPlatformManagerImpl_FreeRTOS<PlatformManagerImpl>::PostEventFromISR;
Expand Down