From 7948961d05521476c13b38f0189a368c99a67cfc Mon Sep 17 00:00:00 2001 From: Arkadiusz Balys Date: Thu, 7 Apr 2022 10:48:41 +0200 Subject: [PATCH] [nrfconnect] Added support for updating network core using new DFU Target library. * Updated NCS revision to cc0412169 to get new DFU Target revision * Utilized new DFU Target API * Handled both application and network core image swap for NRF5340 --- .../.nrfconnect-recommended-revision | 2 +- .../nrfconnect/OTAImageProcessorImpl.cpp | 88 +++++++++++++++---- .../nrfconnect/OTAImageProcessorImpl.h | 9 ++ 3 files changed, 82 insertions(+), 17 deletions(-) diff --git a/config/nrfconnect/.nrfconnect-recommended-revision b/config/nrfconnect/.nrfconnect-recommended-revision index ba1e8bf0bd53b5..64f70a191193e6 100644 --- a/config/nrfconnect/.nrfconnect-recommended-revision +++ b/config/nrfconnect/.nrfconnect-recommended-revision @@ -1 +1 @@ -v1.9.1 +5ea8f7fa91d7315fcc6cd9eb3aa74f9640d0abac diff --git a/src/platform/nrfconnect/OTAImageProcessorImpl.cpp b/src/platform/nrfconnect/OTAImageProcessorImpl.cpp index f7e3e6c8f4190a..fc4d49a9495172 100644 --- a/src/platform/nrfconnect/OTAImageProcessorImpl.cpp +++ b/src/platform/nrfconnect/OTAImageProcessorImpl.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -45,7 +46,7 @@ CHIP_ERROR OTAImageProcessorImpl::PrepareDownloadImpl() ReturnErrorOnFailure(System::MapErrorZephyr(dfu_target_mcuboot_set_buf(mBuffer, sizeof(mBuffer)))); ReturnErrorOnFailure(System::MapErrorZephyr(dfu_target_reset())); - return System::MapErrorZephyr(dfu_target_init(DFU_TARGET_IMAGE_TYPE_MCUBOOT, /* size */ 0, nullptr)); + return CHIP_NO_ERROR; } CHIP_ERROR OTAImageProcessorImpl::Finalize() @@ -60,19 +61,31 @@ CHIP_ERROR OTAImageProcessorImpl::Abort() CHIP_ERROR OTAImageProcessorImpl::Apply() { - ReturnErrorOnFailure(System::MapErrorZephyr(dfu_target_done(true))); + int err = dfu_target_done(true); + if (err == 0) + { + // schedule update of all possible targets by caling this function with argument -1 + err = dfu_target_schedule_update(-1); + } #ifdef CONFIG_CHIP_OTA_REQUESTOR_REBOOT_ON_APPLY - return SystemLayer().StartTimer( - System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_OTA_REQUESTOR_REBOOT_DELAY_MS), - [](System::Layer *, void * /* context */) { - PlatformMgr().HandleServerShuttingDown(); - k_msleep(CHIP_DEVICE_CONFIG_SERVER_SHUTDOWN_ACTIONS_SLEEP_MS); - sys_reboot(SYS_REBOOT_WARM); - }, - nullptr /* context */); + if (err == 0) + { + return SystemLayer().StartTimer( + System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_OTA_REQUESTOR_REBOOT_DELAY_MS), + [](System::Layer *, void * /* context */) { + PlatformMgr().HandleServerShuttingDown(); + k_msleep(CHIP_DEVICE_CONFIG_SERVER_SHUTDOWN_ACTIONS_SLEEP_MS); + sys_reboot(SYS_REBOOT_WARM); + }, + nullptr /* context */); + } + else + { + return System::MapErrorZephyr(err); + } #else - return CHIP_NO_ERROR; + return System::MapErrorZephyr(err); #endif } @@ -81,11 +94,45 @@ CHIP_ERROR OTAImageProcessorImpl::ProcessBlock(ByteSpan & block) VerifyOrReturnError(mDownloader != nullptr, CHIP_ERROR_INCORRECT_STATE); CHIP_ERROR error = ProcessHeader(block); - if (error == CHIP_NO_ERROR) { - // DFU target library buffers data internally, so do not clone the block data. - error = System::MapErrorZephyr(dfu_target_write(block.data(), block.size())); + mCurrentImage.mCurrentOffset += block.size(); + if (mCurrentImage.mCurrentOffset >= mCurrentImage.mFileInfo->mFileSize) + { + // calculate how many data should be moved to the next image + uint64_t remainingDataSize = mCurrentImage.mCurrentOffset - static_cast(mCurrentImage.mFileInfo->mFileSize); + // write last data of previous image + error = System::MapErrorZephyr(dfu_target_write(block.data(), block.size() - remainingDataSize)); + // switch to net image + mCurrentImage.mIndex++; + mCurrentImage.mFileInfo = &mContentHeader.mFiles[mCurrentImage.mIndex]; + + if (OTAImageContentHeader::FileId::kNetMcuboot == mCurrentImage.mFileInfo->mFileId && + mCurrentImage.mFileInfo->mFileSize > 0 && CHIP_NO_ERROR == error) + { + // finish previous image and reset target + dfu_target_done(true); + dfu_target_reset(); + // initialize next dfu target to store net-core image. + dfu_target_init(DFU_TARGET_IMAGE_TYPE_MCUBOOT, mCurrentImage.mIndex, /* size */ 0, nullptr); + // write remaining data to new image + error = + System::MapErrorZephyr(dfu_target_write(block.data() + (block.size() - remainingDataSize), remainingDataSize)); + mCurrentImage.mCurrentOffset = remainingDataSize; + } + else + { + // Finish process with error to ensure that only two images are available. + error = CHIP_ERROR_INVALID_DATA_LIST; + } + } + else + { + // DFU target library buffers data internally, so do not clone the block data. + error = System::MapErrorZephyr(dfu_target_write(block.data(), block.size())); + } + ChipLogDetail(SoftwareUpdate, "Processed %llu/%u Bytes of image no. %u", mCurrentImage.mCurrentOffset, + mCurrentImage.mFileInfo->mFileSize, mCurrentImage.mIndex); } // Report the result back to the downloader asynchronously. @@ -129,13 +176,22 @@ CHIP_ERROR OTAImageProcessorImpl::ProcessHeader(ByteSpan & block) if (mContentHeaderParser.IsInitialized() && !block.empty()) { - OTAImageContentHeader header = {}; - CHIP_ERROR error = mContentHeaderParser.AccumulateAndDecode(block, header); + CHIP_ERROR error = mContentHeaderParser.AccumulateAndDecode(block, mContentHeader); // Needs more data to decode the header ReturnErrorCodeIf(error == CHIP_ERROR_BUFFER_TOO_SMALL, CHIP_NO_ERROR); ReturnErrorOnFailure(error); + if (OTAImageContentHeader::FileId::kAppMcuboot == mContentHeader.mFiles[0].mFileId) + { + mCurrentImage.mIndex = 0; + mCurrentImage.mFileInfo = &mContentHeader.mFiles[mCurrentImage.mIndex]; + // Initialize dfu target to receive first image + error = + System::MapErrorZephyr(dfu_target_init(DFU_TARGET_IMAGE_TYPE_MCUBOOT, mCurrentImage.mIndex, /* size */ 0, nullptr)); + ReturnErrorOnFailure(error); + } + mContentHeaderParser.Clear(); } diff --git a/src/platform/nrfconnect/OTAImageProcessorImpl.h b/src/platform/nrfconnect/OTAImageProcessorImpl.h index acdd0c89e0d710..2e0507a5347422 100644 --- a/src/platform/nrfconnect/OTAImageProcessorImpl.h +++ b/src/platform/nrfconnect/OTAImageProcessorImpl.h @@ -34,6 +34,13 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface void SetOTADownloader(OTADownloader * downloader) { mDownloader = downloader; }; + struct OTAImage + { + OTAImageContentHeader::FileInfo * mFileInfo; + uint8_t mIndex; + uint64_t mCurrentOffset; + }; + CHIP_ERROR PrepareDownload() override; CHIP_ERROR Finalize() override; CHIP_ERROR Abort() override; @@ -50,6 +57,8 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface OTAImageHeaderParser mHeaderParser; OTAImageContentHeaderParser mContentHeaderParser; uint8_t mBuffer[kBufferSize]; + OTAImageContentHeader mContentHeader; + OTAImage mCurrentImage; }; class ExtFlashHandler