diff --git a/examples/platform/silabs/BaseApplication.cpp b/examples/platform/silabs/BaseApplication.cpp index fd22a7ea3a48fc..44e6a4ff3b1827 100644 --- a/examples/platform/silabs/BaseApplication.cpp +++ b/examples/platform/silabs/BaseApplication.cpp @@ -51,6 +51,7 @@ #if CHIP_ENABLE_OPENTHREAD #include #include +#include #include #endif // CHIP_ENABLE_OPENTHREAD @@ -115,9 +116,10 @@ app::Clusters::NetworkCommissioning::Instance sWiFiNetworkCommissioningInstance(0 /* Endpoint Id */, &(NetworkCommissioning::SlWiFiDriver::GetInstance())); #endif /* SL_WIFI */ +bool sIsEnabled = false; +bool sIsAttached = false; + #if !(defined(CHIP_CONFIG_ENABLE_ICD_SERVER) && CHIP_CONFIG_ENABLE_ICD_SERVER) -bool sIsEnabled = false; -bool sIsAttached = false; bool sHaveBLEConnections = false; #endif // CHIP_CONFIG_ENABLE_ICD_SERVER @@ -156,14 +158,13 @@ Identify gIdentify = { }; #endif // MATTER_DM_PLUGIN_IDENTIFY_SERVER + } // namespace -bool BaseApplication::sIsProvisioned = false; -bool BaseApplication::sIsFactoryResetTriggered = false; -LEDWidget * BaseApplication::sAppActionLed = nullptr; -#if CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI917 +bool BaseApplication::sIsProvisioned = false; +bool BaseApplication::sIsFactoryResetTriggered = false; +LEDWidget * BaseApplication::sAppActionLed = nullptr; BaseApplicationDelegate BaseApplication::sAppDelegate = BaseApplicationDelegate(); -#endif // CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI917 #ifdef DIC_ENABLE namespace { @@ -181,17 +182,19 @@ void AppSpecificConnectivityEventCallback(const ChipDeviceEvent * event, intptr_ } // namespace #endif // DIC_ENABLE -#if CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI917 void BaseApplicationDelegate::OnCommissioningSessionStarted() { isComissioningStarted = true; } + void BaseApplicationDelegate::OnCommissioningSessionStopped() { isComissioningStarted = false; } + void BaseApplicationDelegate::OnCommissioningWindowClosed() { +#if CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI917 if (!BaseApplication::GetProvisionStatus() && !isComissioningStarted) { int32_t status = wfx_power_save(RSI_SLEEP_MODE_8, STANDBY_POWER_SAVE_WITH_RAM_RETENTION); @@ -200,8 +203,27 @@ void BaseApplicationDelegate::OnCommissioningWindowClosed() ChipLogError(DeviceLayer, "Failed to enable the TA Deep Sleep"); } } +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI917qq +} + +void BaseApplicationDelegate::OnFabricCommitted(const FabricTable & fabricTable, FabricIndex fabricIndex) +{ + // If we commissioned our first fabric, Update the commissioned status of the App + if (fabricTable.FabricCount() == 1) + { + BaseApplication::UpdateCommissioningStatus(true); + } +} + +void BaseApplicationDelegate::OnFabricRemoved(const FabricTable & fabricTable, FabricIndex fabricIndex) +{ + if (fabricTable.FabricCount() == 0) + { + BaseApplication::UpdateCommissioningStatus(false); + + BaseApplication::DoProvisioningReset(); + } } -#endif // CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI917 /********************************************************** * AppTask Definitions @@ -298,6 +320,8 @@ CHIP_ERROR BaseApplication::Init() #if CHIP_ENABLE_OPENTHREAD BaseApplication::sIsProvisioned = ConnectivityMgr().IsThreadProvisioned(); #endif + + err = chip::Server::GetInstance().GetFabricTable().AddFabricDelegate(&sAppDelegate); return err; } @@ -411,6 +435,23 @@ bool BaseApplication::ActivateStatusLedPatterns() return isPatternSet; } +void BaseApplication::UpdateCommissioningStatus(bool newState) +{ +#ifdef SL_WIFI + BaseApplication::sIsProvisioned = ConnectivityMgr().IsWiFiStationProvisioned(); + sIsEnabled = ConnectivityMgr().IsWiFiStationEnabled(); + sIsAttached = ConnectivityMgr().IsWiFiStationConnected(); +#endif /* SL_WIFI */ +#if CHIP_ENABLE_OPENTHREAD + // TODO: This is a temporary solution until we can read Thread provisioning status from RAM instead of NVM. + BaseApplication::sIsProvisioned = newState; + sIsEnabled = ConnectivityMgr().IsThreadEnabled(); + sIsAttached = ConnectivityMgr().IsThreadAttached(); +#endif /* CHIP_ENABLE_OPENTHREAD */ + + ActivateStatusLedPatterns(); +} + // TODO Move State Monitoring elsewhere void BaseApplication::LightEventHandler() { @@ -750,15 +791,40 @@ void BaseApplication::ScheduleFactoryReset() { Provision::Manager::GetInstance().SetProvisionRequired(true); } - PlatformMgr().HandleServerShuttingDown(); + PlatformMgr().HandleServerShuttingDown(); // HandleServerShuttingDown calls OnShutdown() which is only implemented for the + // basic information cluster it seems. And triggers and Event flush, which is not + // relevant when there are no fabrics left ConfigurationMgr().InitiateFactoryReset(); }); } +void BaseApplication::DoProvisioningReset() +{ + PlatformMgr().ScheduleWork([](intptr_t) { +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + ConfigurationManagerImpl::GetDefaultInstance().ClearThreadStack(); + ThreadStackMgrImpl().FactoryResetThreadStack(); + ThreadStackMgr().InitThreadStack(); +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD + +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION + ChipLogProgress(DeviceLayer, "Clearing WiFi provision"); + chip::DeviceLayer::ConnectivityMgr().ClearWiFiStationProvision(); +#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION + + CHIP_ERROR err = Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow(); + if (err != CHIP_NO_ERROR) + { + SILABS_LOG("Failed to open the Basic Commissioning Window"); + } + }); +} + void BaseApplication::OnPlatformEvent(const ChipDeviceEvent * event, intptr_t) { if (event->Type == DeviceEventType::kServiceProvisioningChange) { + // Note: This is only called on Attach, we need to add a method to detect Thread Network Detach BaseApplication::sIsProvisioned = event->ServiceProvisioningChange.IsServiceProvisioned; } } diff --git a/examples/platform/silabs/BaseApplication.h b/examples/platform/silabs/BaseApplication.h index 8a231aa6c51513..161f1cdc9eb2fd 100644 --- a/examples/platform/silabs/BaseApplication.h +++ b/examples/platform/silabs/BaseApplication.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -62,16 +63,19 @@ #define APP_ERROR_START_TIMER_FAILED CHIP_APPLICATION_ERROR(0x05) #define APP_ERROR_STOP_TIMER_FAILED CHIP_APPLICATION_ERROR(0x06) -#if CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI917 -class BaseApplicationDelegate : public AppDelegate +class BaseApplicationDelegate : public AppDelegate, public chip::FabricTable::Delegate { private: + // AppDelegate bool isComissioningStarted; void OnCommissioningSessionStarted() override; void OnCommissioningSessionStopped() override; void OnCommissioningWindowClosed() override; + + // FabricTable::Delegate + void OnFabricCommitted(const chip::FabricTable & fabricTable, chip::FabricIndex fabricIndex) override; + void OnFabricRemoved(const chip::FabricTable & fabricTable, chip::FabricIndex fabricIndex) override; }; -#endif // CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI917 /********************************************************** * BaseApplication Declaration @@ -86,9 +90,7 @@ class BaseApplication static bool sIsProvisioned; static bool sIsFactoryResetTriggered; static LEDWidget * sAppActionLed; -#if CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI917 static BaseApplicationDelegate sAppDelegate; -#endif // CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI917 /** * @brief Create AppTask task and Event Queue @@ -156,6 +158,18 @@ class BaseApplication static void OnTriggerIdentifyEffect(Identify * identify); #endif + /** + * @brief Updates the static boolean isCommissioned to the desired state + * + */ + static void UpdateCommissioningStatus(bool newState); + + /** + * @brief Called when the last Fabric is removed, clears all Fabric related data, including Thread and Wifi provision. + * @note This function preserves some NVM3 data that is not Fabric scoped, like Attribute Value or Boot Count. + */ + static void DoProvisioningReset(); + protected: CHIP_ERROR Init(); diff --git a/examples/platform/silabs/MatterConfig.cpp b/examples/platform/silabs/MatterConfig.cpp index 0f25e2e25a40ed..1aabd29bb75ab6 100644 --- a/examples/platform/silabs/MatterConfig.cpp +++ b/examples/platform/silabs/MatterConfig.cpp @@ -222,9 +222,12 @@ void SilabsMatterConfig::ConnectivityEventCallback(const ChipDeviceEvent * event CHIP_ERROR SilabsMatterConfig::InitMatter(const char * appName) { CHIP_ERROR err; - +#ifdef SL_WIFI + // Because OpenThread needs to use memory allocation during its Key operations, we initialize the memory management for thread + // and set the allocation functions inside sl_ot_create_instance, which is called by sl_system_init in the OpenThread stack + // initialization. mbedtls_platform_set_calloc_free(CHIPPlatformMemoryCalloc, CHIPPlatformMemoryFree); - +#endif SILABS_LOG("=================================================="); SILABS_LOG("%s starting", appName); SILABS_LOG("=================================================="); @@ -241,11 +244,11 @@ CHIP_ERROR SilabsMatterConfig::InitMatter(const char * appName) // Init Matter Stack //============================================== SILABS_LOG("Init CHIP Stack"); - // Init Chip memory management before the stack - ReturnErrorOnFailure(chip::Platform::MemoryInit()); -// WiFi needs to be initialized after Memory Init for some reason #ifdef SL_WIFI + // Init Chip memory management before the stack + // See comment above about OpenThread memory allocation as to why this is WIFI only here. + ReturnErrorOnFailure(chip::Platform::MemoryInit()); ReturnErrorOnFailure(InitWiFi()); #endif @@ -304,9 +307,7 @@ CHIP_ERROR SilabsMatterConfig::InitMatter(const char * appName) initParams.endpointNativeParams = static_cast(&nativeParams); #endif -#if CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI917 initParams.appDelegate = &BaseApplication::sAppDelegate; -#endif // CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI917 // Init Matter Server and Start Event Loop err = chip::Server::GetInstance().Init(initParams); diff --git a/examples/platform/silabs/efr32/uart.cpp b/examples/platform/silabs/efr32/uart.cpp index 5feaaa66d86923..80d2dbba63b3a8 100644 --- a/examples/platform/silabs/efr32/uart.cpp +++ b/examples/platform/silabs/efr32/uart.cpp @@ -361,6 +361,12 @@ int16_t uartConsoleWrite(const char * Buf, uint16_t BufLength) return UART_CONSOLE_ERR; } + if (NULL == sUartTxQueue) + { + // This is to prevent the first prompt from OTCLI to be rejected and to break the OTCli output + uartConsoleInit(); + } + #ifdef PW_RPC_ENABLED // Pigweed Logger is already thread safe. UARTDRV_ForceTransmit(vcom_handle, (uint8_t *) Buf, BufLength); diff --git a/examples/platform/silabs/matter-platform.slcp b/examples/platform/silabs/matter-platform.slcp index c8075656e9f74d..bfde28d9f721f9 100644 --- a/examples/platform/silabs/matter-platform.slcp +++ b/examples/platform/silabs/matter-platform.slcp @@ -72,6 +72,9 @@ component: - {id: mbedtls_platform_dynamic_memory_allocation_config_init_runtime } - {id: mbedtls_base64} - {id: ot_psa_crypto} +- {id: ot_platform_abstraction} +- {id: ot_rtos_wrappers_real} +- {id: sl_ot_custom_cli} # Necessary componenets for ot coap cert lib # - {id: mbedtls_dtls} # Requried by COAP lib # - {id: mbedtls_tls_server} # Requried by COAP lib @@ -86,6 +89,10 @@ config_file: directory: btconf configuration: +- name: SL_OPENTHREAD_ENABLE_APP_TASK + value: 0 +- name: SL_OPENTHREAD_ENABLE_CLI_TASK + value: 0 - {name: SL_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED, value: '0'} - {name: SL_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED, value: '1'} - condition: [uartdrv_usart] diff --git a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h index 317bff7c05403e..c45ff84bb0f26e 100644 --- a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h +++ b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h @@ -142,6 +142,7 @@ class GenericThreadStackManagerImpl_OpenThread // ===== Members available to the implementation subclass. + CHIP_ERROR ConfigureThreadStack(otInstance * otInst); CHIP_ERROR DoInit(otInstance * otInst); bool IsThreadAttachedNoLock(void); bool IsThreadInterfaceUpNoLock(void); diff --git a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp index 876cb54385efe6..61452f5ff0ec90 100644 --- a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp +++ b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp @@ -1088,29 +1088,21 @@ CHIP_ERROR GenericThreadStackManagerImpl_OpenThread::_GetPollPeriod(u return CHIP_NO_ERROR; } +/** + * @brief Helper that sets callbacks for OpenThread state changes and configures the Thread stack. + * Assigns mOTInst to an instance, and configures the OT stack on a device by setting state change callbacks enabling features + * for IPv6 address configuration, enabling the Thread network if necessary, and handling SRP if enabled. + * Allows for the configuration of the Thread stack on a device where the instance and the otCLI are already initialised. + * + * @param otInst Pointer to the OT instance + * @return CHIP_ERROR OpenThread error mapped to CHIP_ERROR + */ template -CHIP_ERROR GenericThreadStackManagerImpl_OpenThread::DoInit(otInstance * otInst) +CHIP_ERROR GenericThreadStackManagerImpl_OpenThread::ConfigureThreadStack(otInstance * otInst) { CHIP_ERROR err = CHIP_NO_ERROR; otError otErr = OT_ERROR_NONE; - // Arrange for OpenThread errors to be translated to text. - RegisterOpenThreadErrorFormatter(); - - mOTInst = NULL; - - // If an OpenThread instance hasn't been supplied, call otInstanceInitSingle() to - // create or acquire a singleton instance of OpenThread. - if (otInst == NULL) - { - otInst = otInstanceInitSingle(); - VerifyOrExit(otInst != NULL, err = MapOpenThreadError(OT_ERROR_FAILED)); - } - -#if !defined(PW_RPC_ENABLED) && CHIP_DEVICE_CONFIG_THREAD_ENABLE_CLI - otAppCliInit(otInst); -#endif - mOTInst = otInst; // Arrange for OpenThread to call the OnOpenThreadStateChange method whenever a @@ -1146,14 +1138,42 @@ CHIP_ERROR GenericThreadStackManagerImpl_OpenThread::DoInit(otInstanc } #endif - initNetworkCommissioningThreadDriver(); - exit: ChipLogProgress(DeviceLayer, "OpenThread started: %s", otThreadErrorToString(otErr)); return err; } +template +CHIP_ERROR GenericThreadStackManagerImpl_OpenThread::DoInit(otInstance * otInst) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + // Arrange for OpenThread errors to be translated to text. + RegisterOpenThreadErrorFormatter(); + + mOTInst = NULL; + + // If an OpenThread instance hasn't been supplied, call otInstanceInitSingle() to + // create or acquire a singleton instance of OpenThread. + if (otInst == NULL) + { + otInst = otInstanceInitSingle(); + VerifyOrExit(otInst != NULL, err = MapOpenThreadError(OT_ERROR_FAILED)); + } + +#if !defined(PW_RPC_ENABLED) && CHIP_DEVICE_CONFIG_THREAD_ENABLE_CLI + otAppCliInit(otInst); +#endif + + err = ConfigureThreadStack(otInst); + + initNetworkCommissioningThreadDriver(); + +exit: + return err; +} + template bool GenericThreadStackManagerImpl_OpenThread::IsThreadAttachedNoLock(void) { diff --git a/src/platform/silabs/ConfigurationManagerImpl.cpp b/src/platform/silabs/ConfigurationManagerImpl.cpp index 9454367d3bf030..5a511038c799ed 100644 --- a/src/platform/silabs/ConfigurationManagerImpl.cpp +++ b/src/platform/silabs/ConfigurationManagerImpl.cpp @@ -260,6 +260,18 @@ void ConfigurationManagerImpl::RunConfigUnitTest(void) #endif // CONFIG_BUILD_FOR_HOST_UNIT_TEST } +/// @brief Helper to erase Thread info from device +void ConfigurationManagerImpl::ClearThreadStack() +{ +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + ThreadStackMgr().ClearAllSrpHostAndServices(); +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + ChipLogProgress(DeviceLayer, "Clearing Thread provision"); + ThreadStackMgr().ErasePersistentInfo(); +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD +} + void ConfigurationManagerImpl::DoFactoryReset(intptr_t arg) { CHIP_ERROR err; @@ -272,13 +284,7 @@ void ConfigurationManagerImpl::DoFactoryReset(intptr_t arg) ChipLogError(DeviceLayer, "FactoryResetConfig() failed: %s", chip::ErrorStr(err)); } -#if CHIP_DEVICE_CONFIG_ENABLE_THREAD -#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT - ThreadStackMgr().ClearAllSrpHostAndServices(); -#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT - ChipLogProgress(DeviceLayer, "Clearing Thread provision"); - ThreadStackMgr().ErasePersistentInfo(); -#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD + GetDefaultInstance().ClearThreadStack(); PersistedStorage::KeyValueStoreMgrImpl().ErasePartition(); diff --git a/src/platform/silabs/ConfigurationManagerImpl.h b/src/platform/silabs/ConfigurationManagerImpl.h index f34e37ed91bb52..262b68053a3214 100644 --- a/src/platform/silabs/ConfigurationManagerImpl.h +++ b/src/platform/silabs/ConfigurationManagerImpl.h @@ -46,6 +46,8 @@ class ConfigurationManagerImpl : public Internal::GenericConfigurationManagerImp CHIP_ERROR GetTotalOperationalHours(uint32_t & totalOperationalHours); CHIP_ERROR StoreTotalOperationalHours(uint32_t totalOperationalHours); + void ClearThreadStack(); + private: // ===== Members that implement the ConfigurationManager public interface. diff --git a/src/platform/silabs/ThreadStackManagerImpl.h b/src/platform/silabs/ThreadStackManagerImpl.h index c56990fb0d3712..411c8eeb0676e1 100644 --- a/src/platform/silabs/ThreadStackManagerImpl.h +++ b/src/platform/silabs/ThreadStackManagerImpl.h @@ -25,12 +25,17 @@ #pragma once -#include #include #include #include +#include "cmsis_os2.h" + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT +static constexpr uint32_t threadSrpClearAllFlags = 0x0001U; +#endif + extern "C" void otSysEventSignalPending(void); namespace chip { @@ -47,8 +52,7 @@ extern int GetEntropy_EFR32(uint8_t * buf, size_t bufSize); * using the Silicon Labs SDK and the OpenThread stack. */ class ThreadStackManagerImpl final : public ThreadStackManager, - public Internal::GenericThreadStackManagerImpl_OpenThread, - public Internal::GenericThreadStackManagerImpl_FreeRTOS + public Internal::GenericThreadStackManagerImpl_OpenThread { // Allow the ThreadStackManager interface class to delegate method calls to // the implementation methods provided by this class. @@ -58,8 +62,6 @@ class ThreadStackManagerImpl final : public ThreadStackManager, // this class. #ifndef DOXYGEN_SHOULD_SKIP_THIS friend Internal::GenericThreadStackManagerImpl_OpenThread; - friend Internal::GenericThreadStackManagerImpl_OpenThread; - friend Internal::GenericThreadStackManagerImpl_FreeRTOS; #endif // Allow glue functions called by OpenThread to call helper methods on this @@ -72,11 +74,21 @@ class ThreadStackManagerImpl final : public ThreadStackManager, using ThreadStackManager::InitThreadStack; CHIP_ERROR InitThreadStack(otInstance * otInst); + void FactoryResetThreadStack(void); private: // ===== Methods that implement the ThreadStackManager abstract interface. CHIP_ERROR _InitThreadStack(void); + CHIP_ERROR _StartThreadTask(void); + void _LockThreadStack(void); + bool _TryLockThreadStack(void); + void _UnlockThreadStack(void); + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + void _WaitOnSrpClearAllComplete(); + void _NotifySrpClearAllComplete(); +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT // ===== Members for internal use by the following friends. friend ThreadStackManager & ::chip::DeviceLayer::ThreadStackMgr(void); @@ -90,6 +102,10 @@ class ThreadStackManagerImpl final : public ThreadStackManager, // ===== Private members for use by this class only. ThreadStackManagerImpl() = default; + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + osThreadId_t mSrpClearAllRequester = NULL; +#endif }; /** diff --git a/src/platform/silabs/efr32/ThreadStackManagerImpl.cpp b/src/platform/silabs/efr32/ThreadStackManagerImpl.cpp index 2cab401837e8d8..d2ae058a8a03f1 100644 --- a/src/platform/silabs/efr32/ThreadStackManagerImpl.cpp +++ b/src/platform/silabs/efr32/ThreadStackManagerImpl.cpp @@ -26,7 +26,8 @@ /* this file behaves like a config.h, comes first */ #include -#include +#include +#include #include #include #include @@ -35,11 +36,42 @@ #include -// Forward declaration -extern "C" otInstance * otGetInstance(void); +#include +#include + +extern "C" { +#include "platform-efr32.h" +otInstance * otGetInstance(void); +#if CHIP_DEVICE_CONFIG_THREAD_ENABLE_CLI +void otAppCliInit(otInstance * aInstance); +#endif // CHIP_DEVICE_CONFIG_THREAD_ENABLE_CLI +} namespace chip { namespace DeviceLayer { +namespace { +otInstance * sOTInstance = NULL; + +// Network commissioning +#ifndef _NO_GENERIC_THREAD_NETWORK_COMMISSIONING_DRIVER_ +NetworkCommissioning::GenericThreadDriver sGenericThreadDriver; +app::Clusters::NetworkCommissioning::Instance sThreadNetworkCommissioningInstance(0 /* Endpoint Id */, &sGenericThreadDriver); +#endif + +void initStaticNetworkCommissioningThreadDriver(void) +{ +#ifndef _NO_GENERIC_THREAD_NETWORK_COMMISSIONING_DRIVER_ + sThreadNetworkCommissioningInstance.Init(); +#endif +} + +void shutdownStaticNetworkCommissioningThreadDriver(void) +{ +#ifndef _NO_GENERIC_THREAD_NETWORK_COMMISSIONING_DRIVER_ + sThreadNetworkCommissioningInstance.Shutdown(); +#endif +} +}; // namespace using namespace ::chip::DeviceLayer::Internal; @@ -47,61 +79,81 @@ ThreadStackManagerImpl ThreadStackManagerImpl::sInstance; CHIP_ERROR ThreadStackManagerImpl::_InitThreadStack(void) { - return InitThreadStack(NULL); + return InitThreadStack(sOTInstance); } -CHIP_ERROR ThreadStackManagerImpl::InitThreadStack(otInstance * otInst) +CHIP_ERROR ThreadStackManagerImpl::_StartThreadTask(void) { - CHIP_ERROR err = CHIP_NO_ERROR; - - // Initialize the generic implementation base classes. - err = GenericThreadStackManagerImpl_FreeRTOS::DoInit(); - SuccessOrExit(err); - err = GenericThreadStackManagerImpl_OpenThread::DoInit(otInst); - SuccessOrExit(err); + // Stubbed since our thread task is created in the InitThreadStack function and it will start once the scheduler starts. + return CHIP_NO_ERROR; +} -exit: - return err; +void ThreadStackManagerImpl::_LockThreadStack(void) +{ + sl_ot_rtos_acquire_stack_mutex(); } -bool ThreadStackManagerImpl::IsInitialized() +bool ThreadStackManagerImpl::_TryLockThreadStack(void) { - return sInstance.mThreadStackLock != NULL; + // TODO: Implement a non-blocking version of the mutex lock + sl_ot_rtos_acquire_stack_mutex(); + return true; } -} // namespace DeviceLayer -} // namespace chip +void ThreadStackManagerImpl::_UnlockThreadStack(void) +{ + sl_ot_rtos_release_stack_mutex(); +} -using namespace ::chip::DeviceLayer; +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT +void ThreadStackManagerImpl::_WaitOnSrpClearAllComplete() +{ + // Only 1 task can be blocked on a srpClearAll request + if (mSrpClearAllRequester == NULL) + { + mSrpClearAllRequester = osThreadGetId(); + // Wait on OnSrpClientNotification which confirms the clearing is done. + // It will notify this current task with NotifySrpClearAllComplete. + // However, we won't wait more than 2s. + osThreadFlagsWait(threadSrpClearAllFlags, osFlagsWaitAny, pdMS_TO_TICKS(2000)); + mSrpClearAllRequester = NULL; + } +} -/** - * Glue function called directly by the OpenThread stack when tasklet processing work - * is pending. - */ -extern "C" void otTaskletsSignalPending(otInstance * p_instance) +void ThreadStackManagerImpl::_NotifySrpClearAllComplete() { - ThreadStackMgrImpl().SignalThreadActivityPending(); + if (mSrpClearAllRequester) + { + osThreadFlagsSet(mSrpClearAllRequester, threadSrpClearAllFlags); + } } +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT -/** - * Glue function called directly by the OpenThread stack when system event processing work - * is pending. - */ -extern "C" void otSysEventSignalPending(void) +CHIP_ERROR ThreadStackManagerImpl::InitThreadStack(otInstance * otInst) { - BaseType_t yieldRequired = ThreadStackMgrImpl().SignalThreadActivityPendingFromISR(); - portYIELD_FROM_ISR(yieldRequired); + CHIP_ERROR err = CHIP_NO_ERROR; + err = GenericThreadStackManagerImpl_OpenThread::ConfigureThreadStack(otInst); + initStaticNetworkCommissioningThreadDriver(); + return err; } -extern "C" void * otPlatCAlloc(size_t aNum, size_t aSize) +void ThreadStackManagerImpl::FactoryResetThreadStack(void) { - return CHIPPlatformMemoryCalloc(aNum, aSize); + VerifyOrReturn(sOTInstance != NULL); + otInstanceFactoryReset(sOTInstance); + shutdownStaticNetworkCommissioningThreadDriver(); } -extern "C" void otPlatFree(void * aPtr) +bool ThreadStackManagerImpl::IsInitialized() { - CHIPPlatformMemoryFree(aPtr); + return otGetInstance() != NULL; } + +} // namespace DeviceLayer +} // namespace chip + +using namespace ::chip::DeviceLayer; + #ifndef SL_COMPONENT_CATALOG_PRESENT extern "C" __WEAK void sl_openthread_init(void) { @@ -137,7 +189,22 @@ extern "C" otError otPlatUartEnable(void) extern "C" otInstance * otGetInstance(void) { - return ThreadStackMgrImpl().OTInstance(); + return sOTInstance; +} + +extern "C" void sl_ot_create_instance(void) +{ + VerifyOrDie(chip::Platform::MemoryInit() == CHIP_NO_ERROR); + mbedtls_platform_set_calloc_free(CHIPPlatformMemoryCalloc, CHIPPlatformMemoryFree); + sOTInstance = otInstanceInitSingle(); +} + +extern "C" void sl_ot_cli_init(void) +{ +#if !defined(PW_RPC_ENABLED) && CHIP_DEVICE_CONFIG_THREAD_ENABLE_CLI + VerifyOrDie(sOTInstance != NULL); + otAppCliInit(sOTInstance); +#endif } #if CHIP_DEVICE_CONFIG_THREAD_ENABLE_CLI diff --git a/src/platform/silabs/platformAbstraction/GsdkSpam.cpp b/src/platform/silabs/platformAbstraction/GsdkSpam.cpp index 0881bea848112b..514003305868cf 100644 --- a/src/platform/silabs/platformAbstraction/GsdkSpam.cpp +++ b/src/platform/silabs/platformAbstraction/GsdkSpam.cpp @@ -79,10 +79,6 @@ CHIP_ERROR SilabsPlatform::Init(void) sl_iostream_set_default(sl_iostream_stdio_handle); #endif -#if CHIP_ENABLE_OPENTHREAD - sl_ot_sys_init(); -#endif - #ifdef SL_CATALOG_SYSTEMVIEW_TRACE_PRESENT SEGGER_SYSVIEW_Conf(); #endif diff --git a/third_party/openthread/platforms/efr32/BUILD.gn b/third_party/openthread/platforms/efr32/BUILD.gn index 381c6407f2c7cd..69e55a5d76151d 100644 --- a/third_party/openthread/platforms/efr32/BUILD.gn +++ b/third_party/openthread/platforms/efr32/BUILD.gn @@ -32,11 +32,9 @@ config("openthread_efr32_config") { "${sl_ot_efr32_root}", "${chip_root}/examples/platform/efr32", "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}", + "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/config", "${sl_ot_platform_abstraction}/include", "${sl_ot_platform_abstraction}/rtos", - - #TODO this is for sl_openthread_features_config.h. should use generated one per board when sl_ot_abstraction is integrated - "${sl_ot_libs_path}/config", ] # temporarily disable check until gsdk pulls in a more recent version of openthread diff --git a/third_party/silabs/BUILD.gn b/third_party/silabs/BUILD.gn index 915cf8ba2bf164..e08c7cd0bd11bd 100644 --- a/third_party/silabs/BUILD.gn +++ b/third_party/silabs/BUILD.gn @@ -211,6 +211,7 @@ if (wifi_soc != true) { # CCP board include_dirs = [ "${sl_ot_platform_abstraction}/include" ] } + sources += [ "${sl_ot_platform_abstraction}/efr32/sleep.c" ] # Use silabs openthread library stack with or without coap api enabled COAP_API = "" diff --git a/third_party/silabs/efr32_sdk.gni b/third_party/silabs/efr32_sdk.gni index 87d0b0bc078d06..08695af1fc3800 100644 --- a/third_party/silabs/efr32_sdk.gni +++ b/third_party/silabs/efr32_sdk.gni @@ -222,12 +222,15 @@ template("efr32_sdk") { "${efr32_sdk_root}/util/third_party/freertos/kernel/include", "${silabs_gen_folder}/config", "${silabs_gen_folder}/autogen", + "${sl_ot_platform_abstraction}/rtos", + "${efr32_sdk_root}/protocol/openthread/include", + "${efr32_sdk_root}/util/third_party/openthread/include", + "${efr32_sdk_root}/util/third_party/openthread/src/core", + "${efr32_sdk_root}/util/third_party/openthread/examples/platforms/", + "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/config", # Headers needed for Init no function will be called if OT is not used "${sl_ot_efr32_root}", - - # TODO this is for sl_openthread_features_config.h. should use generated one per board when sl_ot_abstraction is integrated - "${sl_ot_libs_path}/config", ] if (is_series_2) { @@ -437,7 +440,6 @@ template("efr32_sdk") { "SL_OPENTHREAD_STACK_FEATURES_CONFIG_FILE=\"sl_openthread_features_config.h\"", "SL_CSL_TIMEOUT=${sl_ot_csl_timeout_sec}", "CIRCULAR_QUEUE_USE_LOCAL_CONFIG_HEADER=1", - "MATTER_INTEGRATION=1", ] if (silabs_log_enabled && chip_logging) { @@ -475,6 +477,25 @@ template("efr32_sdk") { ] } + if (defined(invoker.chip_enable_openthread) && + invoker.chip_enable_openthread) { + defines += [ + "SL_OT_ENABLE=1", + + #TODO: Remove these defines once sl_openthread_rtos_config is included in sl_ot_rtos_adaptation.c + "SL_OPENTHREAD_RTOS_STACK_TASK_PRIORITY=24", + "SL_OPENTHREAD_RTOS_APP_TASK_PRIORITY=23", + "SL_OPENTHREAD_RTOS_CLI_TASK_PRIORITY=16", + "SL_OPENTHREAD_STACK_TASK_MEM_SIZE=4608", + "SL_OPENTHREAD_APP_TASK_MEM_SIZE=4608", + "SL_OPENTHREAD_CLI_TASK_MEM_SIZE=2048", + "SL_OPENTHREAD_RTOS_CLI_TASK_PRIORITY=16", + "SL_OPENTHREAD_OS_CLI_TASK_SIZE=2048", + "SL_OPENTHREAD_ENABLE_APP_TASK=0", + "SL_OPENTHREAD_ENABLE_CLI_TASK=0", + ] + } + if (defined(invoker.chip_enable_wifi) && invoker.chip_enable_wifi) { if (enable_dic) { assert(chip_enable_wifi_ipv4, "enable chip_enable_wifi_ipv4") @@ -809,6 +830,15 @@ template("efr32_sdk") { ] } + if (defined(invoker.chip_enable_openthread) && + invoker.chip_enable_openthread) { + sources += [ + "${silabs_gen_folder}/autogen/sl_ot_custom_cli.c", + "${silabs_gen_folder}/autogen/sl_ot_init.c", + "${sl_ot_platform_abstraction}/rtos/sl_ot_rtos_adaptation.c", + ] + } + if (use_wstk_buttons) { sources += [ "${efr32_sdk_root}/platform/driver/button/src/sl_button.c", @@ -886,6 +916,8 @@ template("efr32_sdk") { sources += [ "${efr32_sdk_root}/hardware/driver/configuration_over_swo/src/sl_cos.c", "${efr32_sdk_root}/platform/driver/debug/src/sl_debug_swo.c", + "${efr32_sdk_root}/util/third_party/mbedtls/library/hmac_drbg.c", + "${efr32_sdk_root}/util/third_party/mbedtls/library/psa_crypto_ecp.c", ] } @@ -947,7 +979,6 @@ template("efr32_sdk") { "${efr32_sdk_root}/platform/Device/SiliconLabs/MGM24/Source/startup_mgm24.c", "${efr32_sdk_root}/platform/Device/SiliconLabs/MGM24/Source/system_mgm24.c", "${efr32_sdk_root}/platform/radio/rail_lib/plugin/fem_util/sl_fem_util.c", - "${efr32_sdk_root}/platform/radio/rail_lib/plugin/rail_util_rssi/sl_rail_util_rssi.c", "${efr32_sdk_root}/platform/service/device_manager/clocks/sl_device_clock_efr32xg24.c", "${efr32_sdk_root}/platform/service/device_manager/devices/sl_device_peripheral_hal_efr32xg24.c", ] @@ -963,6 +994,7 @@ template("efr32_sdk") { if (is_series_2) { sources += [ "${efr32_sdk_root}/platform/radio/rail_lib/plugin/pa-conversions/pa_curves_efr32.c", + "${efr32_sdk_root}/platform/radio/rail_lib/plugin/rail_util_rssi/sl_rail_util_rssi.c", "${efr32_sdk_root}/platform/radio/rail_lib/plugin/rail_util_sequencer/sl_rail_util_sequencer.c", "${efr32_sdk_root}/platform/security/sl_component/se_manager/src/sl_se_manager.c", "${efr32_sdk_root}/platform/security/sl_component/se_manager/src/sl_se_manager_attestation.c", diff --git a/third_party/silabs/lwip.gni b/third_party/silabs/lwip.gni index 9a35e7c45f7a61..b0b6a0db0d2c9f 100644 --- a/third_party/silabs/lwip.gni +++ b/third_party/silabs/lwip.gni @@ -169,8 +169,10 @@ template("lwip_target") { "${_lwip_root}/src/core/ipv6/ip6.c", "${_lwip_root}/src/core/ipv6/ip6_addr.c", "${_lwip_root}/src/core/ipv6/ip6_frag.c", - "${_lwip_root}/src/core/ipv6/mld6.c", "${_lwip_root}/src/core/ipv6/nd6.c", + + # TODO: When updating to next Si SDK version, revert change. + "${sdk_support_root}/src/core/ipv6/mld6.c", ] } diff --git a/third_party/silabs/matter_support b/third_party/silabs/matter_support index 9e983904a64d2f..9084b6fa2f9407 160000 --- a/third_party/silabs/matter_support +++ b/third_party/silabs/matter_support @@ -1 +1 @@ -Subproject commit 9e983904a64d2f74280cd48b65ffd4457abd64f7 +Subproject commit 9084b6fa2f9407396a7f2db12975e6e89fe07a8c