From 52290d49d723f876528018203075d836816a911c Mon Sep 17 00:00:00 2001 From: Yassine El Aissaoui Date: Mon, 10 Jun 2024 15:02:19 +0200 Subject: [PATCH] [NXP] Update platform code for RW61x Zephyr Use common Zephyr wifi driver OTA: wait until Matter app is built before building MCUBOOT Use subscriptions interval to compute OTA reboot delay to avoid not sending events before restart Increase NVS lookup cache size to reduce NVS operation time execution Align the default software version with FreeRTOS Update ota software update doc Signed-off-by: Axel Le Bourhis Signed-off-by: Yassine El Aissaoui --- config/nxp/chip-module/CMakeLists.txt | 4 +- config/nxp/chip-module/Kconfig.defaults | 7 +- .../nxp/nxp_zephyr_ota_software_update.md | 4 +- .../common/app_task/source/AppTaskZephyr.cpp | 8 +- .../nxp/common/icd/source/ICDUtil.cpp | 8 +- .../source/AppFactoryDataExample.cpp | 101 ++++++++++++++++++ .../nxp/common/OTAImageProcessorImpl.cpp | 15 ++- .../nxp/common/OTAImageProcessorImpl.h | 5 +- .../nxp/zephyr/CHIPDevicePlatformConfig.h | 5 - .../boards/rd_rw612_bga/rd_rw612_bga.overlay | 68 ++++++++++++ .../nxp/zephyr/ota/OTAImageProcessorImpl.cpp | 17 ++- .../nxp/zephyr/ota/OTAImageProcessorImpl.h | 4 +- 12 files changed, 223 insertions(+), 23 deletions(-) create mode 100644 examples/platform/nxp/zephyr/factory_data/source/AppFactoryDataExample.cpp create mode 100644 src/platform/nxp/zephyr/boards/rd_rw612_bga/rd_rw612_bga.overlay mode change 100755 => 100644 src/platform/nxp/zephyr/ota/OTAImageProcessorImpl.h diff --git a/config/nxp/chip-module/CMakeLists.txt b/config/nxp/chip-module/CMakeLists.txt index 0e35f27a44d153..6b8266970dc883 100644 --- a/config/nxp/chip-module/CMakeLists.txt +++ b/config/nxp/chip-module/CMakeLists.txt @@ -237,7 +237,7 @@ if (CONFIG_CHIP_OTA_REQUESTOR) COMMAND cp ${PROJECT_BINARY_DIR}/../modules/connectedhomeip/build_mcuboot/zephyr/zephyr.bin ${PROJECT_BINARY_DIR}/zephyr.mcuboot.bin ) - + add_dependencies(build_mcuboot ${ZEPHYR_FINAL_EXECUTABLE}) set(BLOCK_SIZE "1024") dt_nodelabel(dts_partition_path NODELABEL "boot_partition") dt_reg_size(mcuboot_size PATH ${dts_partition_path}) @@ -249,7 +249,7 @@ if (CONFIG_CHIP_OTA_REQUESTOR) COMMAND dd if=${PROJECT_BINARY_DIR}/${ZEPHYR_OUTPUT_NAME}.bin of=${PROJECT_BINARY_DIR}/zephyr_full.bin bs=${BLOCK_SIZE} seek=${boot_blocks} ) - add_dependencies(merge_mcuboot ${ZEPHYR_FINAL_EXECUTABLE}) + add_dependencies(merge_mcuboot build_mcuboot) if (CONFIG_CHIP_OTA_IMAGE_BUILD) chip_ota_image(chip-ota-image diff --git a/config/nxp/chip-module/Kconfig.defaults b/config/nxp/chip-module/Kconfig.defaults index 178a9eddd6b057..36a9934a6a63e1 100644 --- a/config/nxp/chip-module/Kconfig.defaults +++ b/config/nxp/chip-module/Kconfig.defaults @@ -205,7 +205,7 @@ config BT_BUF_ACL_TX_SIZE config BT_RX_STACK_SIZE default 2048 if NO_OPTIMIZATIONS && DEBUG - default 1536 + default 1600 config BT_DEVICE_NAME_GATT_WRITABLE bool @@ -217,6 +217,9 @@ config HCI_NXP_ENABLE_AUTO_SLEEP config CHIP_OTA_REQUESTOR default n +config CHIP_DEVICE_SOFTWARE_VERSION + default 1 + # Enable extended discovery config CHIP_EXTENDED_DISCOVERY default y @@ -225,7 +228,7 @@ config NVS_LOOKUP_CACHE default y config NVS_LOOKUP_CACHE_SIZE - default 512 + default 1024 if CHIP_WIFI diff --git a/docs/guides/nxp/nxp_zephyr_ota_software_update.md b/docs/guides/nxp/nxp_zephyr_ota_software_update.md index 314765aaa4d7c6..805afb7741c944 100644 --- a/docs/guides/nxp/nxp_zephyr_ota_software_update.md +++ b/docs/guides/nxp/nxp_zephyr_ota_software_update.md @@ -157,9 +157,9 @@ The same procedure can be followed from the sub-section, replacing `CONFIG_CHIP_DEVICE_SOFTWARE_VERSION` with a number greater than the initial one used on the active application (Candidate application version number should be greater than the one used on the active -application). By default the value is set to 0, try resetting this option to 1 +application). By default the value is set to 1, try resetting this option to 2 to generate the OTA update Image. You can do this by adding -`-DCONFIG_CHIP_DEVICE_SOFTWARE_VERSION=1` to the west build command. +`-DCONFIG_CHIP_DEVICE_SOFTWARE_VERSION=2` to the west build command. The current implementation automates the following procedures: diff --git a/examples/platform/nxp/common/app_task/source/AppTaskZephyr.cpp b/examples/platform/nxp/common/app_task/source/AppTaskZephyr.cpp index 03a86a572a82c2..05257c3a88c190 100644 --- a/examples/platform/nxp/common/app_task/source/AppTaskZephyr.cpp +++ b/examples/platform/nxp/common/app_task/source/AppTaskZephyr.cpp @@ -29,7 +29,7 @@ #include #ifdef CONFIG_CHIP_WIFI -#include +#include #endif #if CONFIG_CHIP_FACTORY_DATA @@ -62,14 +62,16 @@ K_MSGQ_DEFINE(sAppEventQueue, sizeof(AppEvent), kAppEventQueueSize, alignof(AppE #if defined(CONFIG_CHIP_WIFI) chip::DeviceLayer::NetworkCommissioning::WiFiDriver * chip::NXP::App::AppTaskZephyr::GetWifiDriverInstance() { - return static_cast(&(NetworkCommissioning::NxpWifiDriver::Instance())); + return static_cast( + &(NetworkCommissioning::ZephyrWifiDriver::Instance())); } #endif // CONFIG_CHIP_WIFI CHIP_ERROR chip::NXP::App::AppTaskZephyr::Start() { - + PreInitMatterStack(); ReturnErrorOnFailure(Init()); + PostInitMatterStack(); AppEvent event{}; diff --git a/examples/platform/nxp/common/icd/source/ICDUtil.cpp b/examples/platform/nxp/common/icd/source/ICDUtil.cpp index 648bb6fe202629..98986c4a7a09f9 100644 --- a/examples/platform/nxp/common/icd/source/ICDUtil.cpp +++ b/examples/platform/nxp/common/icd/source/ICDUtil.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2023 Project CHIP Authors + * Copyright (c) 2023-2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,6 +17,9 @@ */ #include "ICDUtil.h" +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR +#include "OTARequestorInitiator.h" +#endif chip::NXP::App::ICDUtil chip::NXP::App::ICDUtil::sICDUtil; @@ -32,5 +35,8 @@ CHIP_ERROR chip::NXP::App::ICDUtil::OnSubscriptionRequested(chip::app::ReadHandl { agreedMaxInterval = requestedMaxInterval; } +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR + chip::NXP::App::OTARequestorInitiator::Instance().gImageProcessor.SetRebootDelaySec(requestedMinInterval); +#endif return aReadHandler.SetMaxReportingInterval(agreedMaxInterval); } diff --git a/examples/platform/nxp/zephyr/factory_data/source/AppFactoryDataExample.cpp b/examples/platform/nxp/zephyr/factory_data/source/AppFactoryDataExample.cpp new file mode 100644 index 00000000000000..977e526947d83f --- /dev/null +++ b/examples/platform/nxp/zephyr/factory_data/source/AppFactoryDataExample.cpp @@ -0,0 +1,101 @@ +/* + * + * 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. + */ + +#include "AppFactoryData.h" + +#include +#include +#include + +#if CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA +#include "FactoryDataProvider.h" +/* + * Test key used to encrypt factory data before storing it to the flash. + * The software key should be used only during development stage. + * For production usage, it is recommended to use the OTP key which needs to be fused in the RT1060 SW_GP2. + */ +static const uint8_t aes128TestKey[] + __attribute__((aligned)) = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; +#else +#include +#endif + +#if CONFIG_CHIP_FACTORY_DATA +#include +#else +#include +#endif + +#if CONFIG_CHIP_FACTORY_DATA && CONFIG_CHIP_ENCRYPTED_FACTORY_DATA +#ifdef CONFIG_CHIP_ENCRYPTED_FACTORY_DATA_AES128_KEY + +#define KEY CONFIG_CHIP_ENCRYPTED_FACTORY_DATA_AES128_KEY +#define HEXTONIBBLE(c) (*(c) >= 'A' ? (*(c) - 'A') + 10 : (*(c) - '0')) +#define HEXTOBYTE(c) (HEXTONIBBLE(c) * 16 + HEXTONIBBLE(c + 1)) +#define AES128_KEY_ARRAY \ + HEXTOBYTE(KEY + 0), HEXTOBYTE(KEY + 2), HEXTOBYTE(KEY + 4), HEXTOBYTE(KEY + 6), HEXTOBYTE(KEY + 8), HEXTOBYTE(KEY + 10), \ + HEXTOBYTE(KEY + 12), HEXTOBYTE(KEY + 14), HEXTOBYTE(KEY + 16), HEXTOBYTE(KEY + 18), HEXTOBYTE(KEY + 20), \ + HEXTOBYTE(KEY + 22), HEXTOBYTE(KEY + 24), HEXTOBYTE(KEY + 26), HEXTOBYTE(KEY + 28), HEXTOBYTE(KEY + 30) +#else +#define AES128_KEY_ARRAY 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c +#endif /* CONFIG_CHIP_ENCRYPTED_FACTORY_DATA_AES128_KEY */ + +/* + * Test key used to encrypt factory data before storing it to the flash. + */ +static const uint8_t aes128TestKey[] __attribute__((aligned)) = { AES128_KEY_ARRAY }; + +#endif /* CONFIG_CHIP_FACTORY_DATA && CONFIG_CHIP_ENCRYPTED_FACTORY_DATA */ + +using namespace chip; +using namespace ::chip::Credentials; +using namespace ::chip::DeviceLayer; + +/** + * Allows to register Matter factory data before initializing the Matter stack + * Load factory data from the flash to the RAM. + * Needs to be done before starting other Matter modules to avoid concurrent access issues with DCP hardware module. + * + * This example demonstrates the usage of the ecb with a software key, to use other encryption mode, + * or to use hardware keys, check available methodes from the FactoryDataProviderImpl class. + */ +CHIP_ERROR NXP::App::AppFactoryData_PreMatterStackInit(void) +{ + return CHIP_NO_ERROR; +} + +/** + * Allows to register Matter factory data after initializing the Matter stack + */ +CHIP_ERROR NXP::App::AppFactoryData_PostMatterStackInit(void) +{ +#if CONFIG_CHIP_FACTORY_DATA +#if CONFIG_CHIP_ENCRYPTED_FACTORY_DATA + FactoryDataPrvdImpl().SetEncryptionMode(FactoryDataProvider::encrypt_ecb); + FactoryDataPrvdImpl().SetAes128Key(&aes128TestKey[0]); +#endif /* CONFIG_CHIP_ENCRYPTED_FACTORY_DATA */ + ReturnErrorOnFailure(FactoryDataPrvdImpl().Init()); + SetDeviceInstanceInfoProvider(&FactoryDataPrvd()); + SetDeviceAttestationCredentialsProvider(&FactoryDataPrvd()); + SetCommissionableDataProvider(&FactoryDataPrvd()); +#else + SetDeviceInstanceInfoProvider(&DeviceInstanceInfoProviderMgrImpl()); + SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); +#endif /* CONFIG_CHIP_FACTORY_DATA */ + return CHIP_NO_ERROR; +} diff --git a/src/platform/nxp/common/OTAImageProcessorImpl.cpp b/src/platform/nxp/common/OTAImageProcessorImpl.cpp index 757e3fc33a09eb..a471b57f512105 100644 --- a/src/platform/nxp/common/OTAImageProcessorImpl.cpp +++ b/src/platform/nxp/common/OTAImageProcessorImpl.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2022 Project CHIP Authors + * Copyright (c) 2022-2024 Project CHIP Authors * Copyright 2023 NXP * All rights reserved. * @@ -22,6 +22,8 @@ #include "OTAImageProcessorImpl.h" +static constexpr uint16_t deltaRebootDelayMs = 200; + namespace chip { CHIP_ERROR OTAImageProcessorImpl::PrepareDownload() @@ -279,8 +281,10 @@ void OTAImageProcessorImpl::HandleApply(intptr_t context) * This should be done with a delay so the device has enough time to send * the state-transition event when applying the update. */ - ChipLogProgress(SoftwareUpdate, "Restarting device in 5 seconds ..."); - DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(5 * 1000), HandleRestart, nullptr); + ChipLogProgress(SoftwareUpdate, "Restarting device, will reboot in %d seconds ...", imageProcessor->mDelayBeforeRebootSec); + DeviceLayer::PlatformMgr().HandleServerShuttingDown(); + DeviceLayer::SystemLayer().StartTimer( + System::Clock::Milliseconds32(imageProcessor->mDelayBeforeRebootSec * 1000 + deltaRebootDelayMs), HandleRestart, nullptr); /* * At next boot time, the bootloader will test + validate new image. @@ -350,4 +354,9 @@ CHIP_ERROR OTAImageProcessorImpl::ReleaseBlock() return CHIP_NO_ERROR; } +void OTAImageProcessorImpl::SetRebootDelaySec(uint16_t rebootDelay) +{ + mDelayBeforeRebootSec = rebootDelay; +} + } // namespace chip diff --git a/src/platform/nxp/common/OTAImageProcessorImpl.h b/src/platform/nxp/common/OTAImageProcessorImpl.h index eefda5bf496182..633efe43998e8e 100644 --- a/src/platform/nxp/common/OTAImageProcessorImpl.h +++ b/src/platform/nxp/common/OTAImageProcessorImpl.h @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2022 Project CHIP Authors + * Copyright (c) 2022-2024 Project CHIP Authors * Copyright 2023 NXP * All rights reserved. * @@ -47,6 +47,7 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface static void TriggerNewRequestForData(intptr_t context); void SetOTADownloader(OTADownloader * downloader) { mDownloader = downloader; } + void SetRebootDelaySec(uint16_t rebootDelay); private: //////////// Actual handlers for the OTAImageProcessorInterface /////////////// @@ -77,6 +78,8 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface /* Buffer used for transaction storage */ uint8_t mPostedOperationsStorage[NB_PENDING_TRANSACTIONS * TRANSACTION_SZ]; + + uint16_t mDelayBeforeRebootSec = 0; }; } // namespace chip diff --git a/src/platform/nxp/zephyr/CHIPDevicePlatformConfig.h b/src/platform/nxp/zephyr/CHIPDevicePlatformConfig.h index 900aa846e49d5c..99f34137ed0418 100644 --- a/src/platform/nxp/zephyr/CHIPDevicePlatformConfig.h +++ b/src/platform/nxp/zephyr/CHIPDevicePlatformConfig.h @@ -76,11 +76,6 @@ #define CHIP_DEVICE_CONFIG_SETTINGS_KEY "mt" #endif // CHIP_DEVICE_CONFIG_SETTINGS_KEY -#ifndef CHIP_DEVICE_CONFIG_OTA_REQUESTOR_REBOOT_DELAY_MS -/// Delay between completing a firmware update download and reboot to apply the update -#define CHIP_DEVICE_CONFIG_OTA_REQUESTOR_REBOOT_DELAY_MS 1000 -#endif // CHIP_DEVICE_CONFIG_OTA_REQUESTOR_REBOOT_DELAY_MS - #ifndef CHIP_DEVICE_CONFIG_SERVER_SHUTDOWN_ACTIONS_SLEEP_MS /// Time to sleep after running server shutdown actions to let lower layers complete the actions. /// This may include transmitting packets created by the actions. diff --git a/src/platform/nxp/zephyr/boards/rd_rw612_bga/rd_rw612_bga.overlay b/src/platform/nxp/zephyr/boards/rd_rw612_bga/rd_rw612_bga.overlay new file mode 100644 index 00000000000000..c4db68870c2d84 --- /dev/null +++ b/src/platform/nxp/zephyr/boards/rd_rw612_bga/rd_rw612_bga.overlay @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2023-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. + */ + +&sram { + #address-cells = <1>; + #size-cells = <1>; + + sram_data: memory@20000000 { + compatible = "mmio-sram"; + reg = <0x20000000 DT_SIZE_K(1216)>; + }; +}; + +/delete-node/ &boot_partition; +/delete-node/ &slot0_partition; +/delete-node/ &slot1_partition; +/delete-node/ &fw_storage; +/delete-node/ &storage_partition; + +&flexspi { + status = "okay"; + + mx25u51245g: mx25u51245g@0 { + status = "okay"; + + partitions { + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 DT_SIZE_K(128)>; + }; + + slot0_partition: partition@20000 { + label = "image-0"; + reg = <0x00020000 0x440000>; + }; + + slot1_partition: partition@460000 { + label = "image-1"; + reg = <0x00460000 0x440000>; + }; + + storage_partition: partition@3FEF000 { + label = "storage"; + reg = <0x03FEF000 DT_SIZE_K(64)>; + }; + + factory_partition: partition@3FFF000 { + label = "factory-data"; + reg = <0x03FFF000 DT_SIZE_K(4)>; + }; + + }; + }; +}; diff --git a/src/platform/nxp/zephyr/ota/OTAImageProcessorImpl.cpp b/src/platform/nxp/zephyr/ota/OTAImageProcessorImpl.cpp index 59718e2fcc3919..89907c0fff3bdd 100644 --- a/src/platform/nxp/zephyr/ota/OTAImageProcessorImpl.cpp +++ b/src/platform/nxp/zephyr/ota/OTAImageProcessorImpl.cpp @@ -20,7 +20,6 @@ #include #include #include - #include #include #include @@ -34,6 +33,8 @@ static struct stream_flash_ctx stream; #define UPDATE_TYPE BOOT_UPGRADE_TEST #endif +static constexpr uint16_t deltaRebootDelayMs = 200; + namespace chip { namespace DeviceLayer { @@ -96,10 +97,16 @@ CHIP_ERROR OTAImageProcessorImpl::Apply() #ifdef CONFIG_CHIP_OTA_REQUESTOR_REBOOT_ON_APPLY if (!err) { + PlatformMgr().HandleServerShuttingDown(); + /* + * Restart the device in order to apply the update image. + * This should be done with a delay so the device has enough time to send + * the state-transition event when applying the update. + */ + ChipLogProgress(SoftwareUpdate, "Restarting device, will reboot in %d seconds ...", mDelayBeforeRebootSec); return SystemLayer().StartTimer( - System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_OTA_REQUESTOR_REBOOT_DELAY_MS), + System::Clock::Milliseconds32(mDelayBeforeRebootSec * 1000 + deltaRebootDelayMs), [](System::Layer *, void * /* context */) { - PlatformMgr().HandleServerShuttingDown(); k_msleep(CHIP_DEVICE_CONFIG_SERVER_SHUTDOWN_ACTIONS_SLEEP_MS); sys_reboot(SYS_REBOOT_WARM); }, @@ -176,5 +183,9 @@ CHIP_ERROR OTAImageProcessorImpl::ProcessHeader(ByteSpan & aBlock) return CHIP_NO_ERROR; } +void OTAImageProcessorImpl::SetRebootDelaySec(uint16_t rebootDelay) +{ + mDelayBeforeRebootSec = rebootDelay; +} } // namespace DeviceLayer } // namespace chip diff --git a/src/platform/nxp/zephyr/ota/OTAImageProcessorImpl.h b/src/platform/nxp/zephyr/ota/OTAImageProcessorImpl.h old mode 100755 new mode 100644 index e4a8a95ba721ae..480615e449edd1 --- a/src/platform/nxp/zephyr/ota/OTAImageProcessorImpl.h +++ b/src/platform/nxp/zephyr/ota/OTAImageProcessorImpl.h @@ -40,12 +40,14 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface CHIP_ERROR ProcessBlock(ByteSpan & aBlock) override; bool IsFirstImageRun() override; CHIP_ERROR ConfirmCurrentImage() override; + void SetRebootDelaySec(uint16_t rebootDelay); private: CHIP_ERROR PrepareDownloadImpl(); CHIP_ERROR ProcessHeader(ByteSpan & aBlock); - OTADownloader * mDownloader = nullptr; + uint16_t mDelayBeforeRebootSec = 0; + OTADownloader * mDownloader = nullptr; OTAImageHeaderParser mHeaderParser; uint8_t mBuffer[kBufferSize]; };