diff --git a/examples/platform/silabs/OTAConfig.cpp b/examples/platform/silabs/OTAConfig.cpp index 91c84054220b9c..adc6f23abb4606 100644 --- a/examples/platform/silabs/OTAConfig.cpp +++ b/examples/platform/silabs/OTAConfig.cpp @@ -17,10 +17,18 @@ */ #include "OTAConfig.h" +#include + +#ifndef SIWX_917 #include "application_properties.h" -#include +#if defined(SL_COMPONENT_CATALOG_PRESENT) +#include "sl_component_catalog.h" +#endif + +// Only include app properties if the Gecko SDK component that does it automatically isn't present +#if !defined(SL_CATALOG_GECKO_BOOTLOADER_INTERFACE_PRESENT) // Header used for building the image GBL file #define APP_PROPERTIES_VERSION 1 #define APP_PROPERTIES_ID \ @@ -65,6 +73,8 @@ __attribute__((used)) ApplicationProperties_t sl_app_properties = { /// Pointer to Long Token Data Section .longTokenSectionAddress = NULL, }; +#endif // SL_CATALOG_GECKO_BOOTLOADER_INTERFACE_PRESENT +#endif // SIWX_917 // Global OTA objects chip::DefaultOTARequestor gRequestorCore; diff --git a/examples/platform/silabs/SiWx917/BUILD.gn b/examples/platform/silabs/SiWx917/BUILD.gn index 36a5aef1a860c1..99be69fbbc9b14 100644 --- a/examples/platform/silabs/SiWx917/BUILD.gn +++ b/examples/platform/silabs/SiWx917/BUILD.gn @@ -144,10 +144,9 @@ config("siwx917-common-config") { defines += [ "QR_CODE_ENABLED" ] } - # TODO: Renable once ota is supported - # if (chip_enable_ota_requestor) { - # defines += [ "SILABS_OTA_ENABLED" ] - # } + if (chip_enable_ota_requestor) { + defines += [ "SILABS_OTA_ENABLED" ] + } if (enable_heap_monitoring) { defines += [ "HEAP_MONITORING" ] @@ -229,7 +228,7 @@ source_set("siwx917-common") { } if (chip_enable_ota_requestor) { - # TODO: OTA For CCP Platform + sources += [ "${silabs_common_plat_dir}/OTAConfig.cpp" ] } if (!disable_lcd) { diff --git a/examples/platform/silabs/SiWx917/SiWx917/sl_wifi_if.c b/examples/platform/silabs/SiWx917/SiWx917/sl_wifi_if.c index 27b677432b30d5..4c3df704dcae38 100644 --- a/examples/platform/silabs/SiWx917/SiWx917/sl_wifi_if.c +++ b/examples/platform/silabs/SiWx917/SiWx917/sl_wifi_if.c @@ -265,6 +265,16 @@ static sl_status_t wfx_rsi_init(void) return status; } #endif + + sl_wifi_version_string_t version = { 0 }; + status = sl_wifi_get_firmware_version(&version); + if (status != SL_STATUS_OK) + { + SILABS_LOG("Get fw version failed: %s", version.version); + return status; + } + SILABS_LOG("Get current fw version: %s", version.version); + status = sl_wifi_get_mac_address(SL_WIFI_CLIENT_INTERFACE, (sl_mac_address_t *) &wfx_rsi.sta_mac.octet[0]); if (status != SL_STATUS_OK) { diff --git a/src/platform/silabs/OTAImageProcessorImpl.h b/src/platform/silabs/OTAImageProcessorImpl.h index 30709bd7f32f3a..46b78b063f2172 100644 --- a/src/platform/silabs/OTAImageProcessorImpl.h +++ b/src/platform/silabs/OTAImageProcessorImpl.h @@ -75,6 +75,7 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface static uint8_t writeBuffer[kAlignmentBytes] __attribute__((aligned(4))); // Offset indicates how far the write buffer has been filled static uint16_t writeBufOffset; + static bool mReset; }; } // namespace chip diff --git a/src/platform/silabs/SiWx917/BUILD.gn b/src/platform/silabs/SiWx917/BUILD.gn index 039794e680e852..151c6e93bc5f40 100644 --- a/src/platform/silabs/SiWx917/BUILD.gn +++ b/src/platform/silabs/SiWx917/BUILD.gn @@ -66,11 +66,10 @@ static_library("SiWx917") { "PlatformManagerImpl.cpp", ] - # TODO: OTA on CCP platform if (chip_enable_ota_requestor) { sources += [ - #"OTAImageProcessorImpl.cpp", - #"${silabs_platform_dir}/OTAImageProcessorImpl.h", + "${silabs_platform_dir}/OTAImageProcessorImpl.h", + "OTAImageProcessorImpl.cpp", ] } diff --git a/src/platform/silabs/SiWx917/OTAImageProcessorImpl.cpp b/src/platform/silabs/SiWx917/OTAImageProcessorImpl.cpp index 2cfcc9694267e9..075317fb9cb2f3 100644 --- a/src/platform/silabs/SiWx917/OTAImageProcessorImpl.cpp +++ b/src/platform/silabs/SiWx917/OTAImageProcessorImpl.cpp @@ -20,19 +20,30 @@ #include #include +#include + +#ifdef __cplusplus extern "C" { -#include "btl_interface.h" -#include "em_bus.h" // For CORE_CRITICAL_SECTION +#endif +#include "sl_si91x_driver.h" +#ifdef RSI_M4_INTERFACE +#include "sl_si91x_hal_soc_soft_reset.h" +#endif +#ifdef __cplusplus } +#endif -#include - +#define RPS_HEADER 1 +#define RPS_DATA 2 /// No error, operation OK #define SL_BOOTLOADER_OK 0L +#define SL_STATUS_FW_UPDATE_DONE SL_STATUS_SI91X_NO_AP_FOUND +uint8_t flag = RPS_HEADER; namespace chip { // Define static memebers +bool OTAImageProcessorImpl::mReset = false; uint8_t OTAImageProcessorImpl::mSlotId = 0; uint32_t OTAImageProcessorImpl::mWriteOffset = 0; uint16_t OTAImageProcessorImpl::writeBufOffset = 0; @@ -129,7 +140,7 @@ void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context) ChipLogProgress(SoftwareUpdate, "HandlePrepareDownload"); - CORE_CRITICAL_SECTION(bootloader_init();) + mReset = false; mSlotId = 0; // Single slot until we support multiple images writeBufOffset = 0; mWriteOffset = 0; @@ -139,39 +150,39 @@ void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context) // Not calling bootloader_eraseStorageSlot(mSlotId) here because we erase during each write - imageProcessor->mDownloader->OnPreparedForDownload(err == SL_BOOTLOADER_OK ? CHIP_NO_ERROR : CHIP_ERROR_INTERNAL); + imageProcessor->mDownloader->OnPreparedForDownload(CHIP_NO_ERROR); } void OTAImageProcessorImpl::HandleFinalize(intptr_t context) { uint32_t err = SL_BOOTLOADER_OK; + int32_t status = 0; auto * imageProcessor = reinterpret_cast(context); if (imageProcessor == nullptr) { return; } - - // Pad the remainder of the write buffer with zeros and write it to bootloader storage if (writeBufOffset != 0) { // Account for last bytes of the image not yet written to storage imageProcessor->mParams.downloadedBytes += writeBufOffset; + status = sl_si91x_fwup_load(writeBuffer, writeBufOffset); + ChipLogProgress(SoftwareUpdate, "status: 0x%lX", status); - while (writeBufOffset != kAlignmentBytes) - { - writeBuffer[writeBufOffset] = 0; - writeBufOffset++; - } - - CORE_CRITICAL_SECTION(err = bootloader_eraseWriteStorage(mSlotId, mWriteOffset, writeBuffer, kAlignmentBytes);) - if (err) + if (status != SL_STATUS_OK) { - ChipLogError(SoftwareUpdate, "ERROR: In HandleFinalize bootloader_eraseWriteStorage() error %ld", err); - imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED); - return; + if (status == SL_STATUS_FW_UPDATE_DONE) + { + mReset = true; + } + else + { + ChipLogError(SoftwareUpdate, "ERROR: In HandleFinalize for last chunk rsi_fwup() error %ld", status); + imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED); + return; + } } } - imageProcessor->ReleaseBlock(); ChipLogProgress(SoftwareUpdate, "OTA image downloaded successfully"); @@ -186,28 +197,16 @@ void OTAImageProcessorImpl::HandleApply(intptr_t context) // Force KVS to store pending keys such as data from StoreCurrentUpdateInfo() chip::DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().ForceKeyMapSave(); - CORE_CRITICAL_SECTION(err = bootloader_verifyImage(mSlotId, NULL);) - if (err != SL_BOOTLOADER_OK) - { - ChipLogError(SoftwareUpdate, "ERROR: bootloader_verifyImage() error %ld", err); - // Call the OTARequestor API to reset the state - GetRequestorInstance()->CancelImageUpdate(); + ChipLogProgress(SoftwareUpdate, "OTA image downloaded successfully in HandleApply"); - return; - } - - CORE_CRITICAL_SECTION(err = bootloader_setImageToBootload(mSlotId);) - if (err != SL_BOOTLOADER_OK) + if (mReset) { - ChipLogError(SoftwareUpdate, "ERROR: bootloader_setImageToBootload() error %ld", err); - // Call the OTARequestor API to reset the state - GetRequestorInstance()->CancelImageUpdate(); - - return; + ChipLogProgress(SoftwareUpdate, "M4 Firmware update complete"); + // send system reset request to reset the MCU and upgrade the m4 image + ChipLogProgress(SoftwareUpdate, "SoC Soft Reset initiated!"); + // Reboots the device + sl_si91x_soc_soft_reset(); } - - // This reboots the device - CORE_CRITICAL_SECTION(bootloader_rebootAndInstall();) } void OTAImageProcessorImpl::HandleAbort(intptr_t context) @@ -225,6 +224,8 @@ void OTAImageProcessorImpl::HandleAbort(intptr_t context) void OTAImageProcessorImpl::HandleProcessBlock(intptr_t context) { uint32_t err = SL_BOOTLOADER_OK; + int32_t status = 0; + int32_t content_block = 0; auto * imageProcessor = reinterpret_cast(context); if (imageProcessor == nullptr) { @@ -258,19 +259,37 @@ void OTAImageProcessorImpl::HandleProcessBlock(intptr_t context) if (writeBufOffset == kAlignmentBytes) { writeBufOffset = 0; - - CORE_CRITICAL_SECTION(err = bootloader_eraseWriteStorage(mSlotId, mWriteOffset, writeBuffer, kAlignmentBytes);) - if (err) + if (flag == RPS_HEADER) { - ChipLogError(SoftwareUpdate, "ERROR: In HandleProcessBlock bootloader_eraseWriteStorage() error %ld", err); - imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED); - return; + // Send RPS header which is received as first chunk + status = sl_si91x_fwup_start(writeBuffer); + status = sl_si91x_fwup_load(writeBuffer, kAlignmentBytes); + flag = RPS_DATA; } - mWriteOffset += kAlignmentBytes; + else if (flag == RPS_DATA) + { + // Send RPS content + status = sl_si91x_fwup_load(writeBuffer, kAlignmentBytes); + if (status != SL_STATUS_OK) + { + // If the last chunk of last block-writeBufOffset length is exactly kAlignmentBytes(64) bytes then mReset value + // should be set to true in HandleProcessBlock + if (status == SL_STATUS_FW_UPDATE_DONE) + { + mReset = true; + } + else + { + ChipLogError(SoftwareUpdate, "ERROR: In HandleFinalize for last chunk rsi_fwup() error %ld", status); + imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED); + return; + } + } + } + // ChipLogProgress(SoftwareUpdate, "HandleProcessBlock status: 0x%lX", status); imageProcessor->mParams.downloadedBytes += kAlignmentBytes; } } - imageProcessor->mDownloader->FetchNextData(); } diff --git a/third_party/silabs/SiWx917_sdk.gni b/third_party/silabs/SiWx917_sdk.gni index 932ccebe79904c..b049d4b4b24073 100644 --- a/third_party/silabs/SiWx917_sdk.gni +++ b/third_party/silabs/SiWx917_sdk.gni @@ -130,6 +130,11 @@ template("siwx917_sdk") { "${efr32_sdk_root}/platform/service/iostream/inc", "${wifi_sdk_root}/components/siwx917_soc/drivers/hardware_drivers/button/inc", + + # OTA + "${wifi_sdk_root}/components/si91x/sl_net/protocols/firmware_upgrade", + "${wifi_sdk_root}/components/siwx917_soc/hal/inc", + "${wifi_sdk_root}/components/siwx917_soc/drivers/systemlevel/inc", ] if (silabs_board == "BRD4338A") { @@ -452,6 +457,11 @@ template("siwx917_sdk") { "${sdk_support_root}/matter/mbedtls/tinycrypt/src/x509write_csr.c", "${sdk_support_root}/matter/si91x/siwx917/${sdk_support_board}/autogen/sl_si91x_button_instances.c", "${wifi_sdk_root}/components/siwx917_soc/drivers/hardware_drivers/button/src/sl_si91x_button.c", + + # OTA + "${wifi_sdk_root}/components/si91x/sl_net/protocols/firmware_upgrade/firmware_upgradation.c", + "${wifi_sdk_root}/components/siwx917_soc/drivers/systemlevel/src/rsi_wwdt.c", + "${wifi_sdk_root}/components/siwx917_soc/hal/src/sl_si91x_hal_soc_soft_reset.c", ] # nvm3 ans startup