Skip to content

Commit

Permalink
[Silabs] Update ThreadStackManagerImpl (#34389)
Browse files Browse the repository at this point in the history
* Updated Silabs ThreadStackManagerImpl for the Simplicity_sdk changes, added a helper in GenericThreadStackManagerImpl_OpenThread.hpp to avoid code repetition
Fixes for memory allocation initialization added since, unlike in SLC, here we use MBEDTLS_CONFIG_FILE="efr32-chip-mbedtls-config.h"

* Updated matter support

* Added ClearThreadStack Helper

* Grouped extern C statements
  • Loading branch information
lpbeliveau-silabs authored Jul 20, 2024
1 parent 6c590c6 commit 6adf0c9
Show file tree
Hide file tree
Showing 17 changed files with 340 additions and 105 deletions.
86 changes: 76 additions & 10 deletions examples/platform/silabs/BaseApplication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#if CHIP_ENABLE_OPENTHREAD
#include <platform/OpenThread/OpenThreadUtils.h>
#include <platform/ThreadStackManager.h>
#include <platform/silabs/ConfigurationManagerImpl.h>
#include <platform/silabs/ThreadStackManagerImpl.h>
#endif // CHIP_ENABLE_OPENTHREAD

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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 {
Expand All @@ -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);
Expand All @@ -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
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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()
{
Expand Down Expand Up @@ -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;
}
}
Expand Down
24 changes: 19 additions & 5 deletions examples/platform/silabs/BaseApplication.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <app/util/config.h>
#include <ble/Ble.h>
#include <cmsis_os2.h>
#include <credentials/FabricTable.h>
#include <lib/core/CHIPError.h>
#include <platform/CHIPDeviceEvent.h>
#include <platform/CHIPDeviceLayer.h>
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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();

Expand Down
15 changes: 8 additions & 7 deletions examples/platform/silabs/MatterConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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("==================================================");
Expand All @@ -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

Expand Down Expand Up @@ -304,9 +307,7 @@ CHIP_ERROR SilabsMatterConfig::InitMatter(const char * appName)
initParams.endpointNativeParams = static_cast<void *>(&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);

Expand Down
6 changes: 6 additions & 0 deletions examples/platform/silabs/efr32/uart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
7 changes: 7 additions & 0 deletions examples/platform/silabs/matter-platform.slcp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1088,29 +1088,21 @@ CHIP_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::_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 <class ImplClass>
CHIP_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::DoInit(otInstance * otInst)
CHIP_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::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
Expand Down Expand Up @@ -1146,14 +1138,42 @@ CHIP_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::DoInit(otInstanc
}
#endif

initNetworkCommissioningThreadDriver();

exit:

ChipLogProgress(DeviceLayer, "OpenThread started: %s", otThreadErrorToString(otErr));
return err;
}

template <class ImplClass>
CHIP_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::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 <class ImplClass>
bool GenericThreadStackManagerImpl_OpenThread<ImplClass>::IsThreadAttachedNoLock(void)
{
Expand Down
Loading

0 comments on commit 6adf0c9

Please sign in to comment.