Skip to content

Commit

Permalink
[EFR32] OTA: Use word-aligned buffer in bootloader storage APIs (proj…
Browse files Browse the repository at this point in the history
…ect-chip#17281)

* Test added march 8 (project-chip#15957)

* Added new manual scripts

* Added Auto generated File

* [OTA] Fix OTARequestorDriverImpl inclusion (project-chip#15981)

* Regen to fix CI failures (project-chip#15990)

* [ota] Store Default OTA Providers in flash (project-chip#15970)

* [ota] Store Default OTA Providers in flash

Store Default OTA Providers in flash each time the attribute
is modified and load it back on the application startup.

* Restyled by clang-format

* Fix build and reduce flash usage

Co-authored-by: Restyled.io <commits@restyled.io>

* Use an intermediate buffer for writing the image to the booloader storage

* Use critical section in the bootloader API call

* Cleanup log messages, move variables into a class

* Remove merge artifacts

* Update EFR32 documentation

* Fix typo

* Restyled by whitespace

* Restyled by clang-format

* Restyled by prettier-markdown

* Rename array size parameter, add aligned attribute

* Trivial change to restart the CI (restyle job need to be kicked)

* Restyled by clang-format

* Update comments

Co-authored-by: kowsisoundhar12 <57476670+kowsisoundhar12@users.noreply.github.com>
Co-authored-by: Carol Yang <clyang@apple.com>
Co-authored-by: Boris Zbarsky <bzbarsky@apple.com>
Co-authored-by: Damian Królik <66667989+Damian-Nordic@users.noreply.github.com>
Co-authored-by: Restyled.io <commits@restyled.io>
  • Loading branch information
6 people authored and andrei-menzopol committed Apr 14, 2022
1 parent 5cca99b commit cff5b32
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 20 deletions.
8 changes: 6 additions & 2 deletions docs/guides/silabs_efr32_software_update.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,12 @@ all of the EFR32 example applications.
scripts/examples/gn_build_example.sh examples/ota-provider-app/linux out/debug chip_config_network_layer_ble=false

- Build or download the Gecko Bootloader binary. Bootloader should be built
with the Gecko SDK version 3.2.1 or earlier, type "external SPI" configured
with a single slot of at least 1000 KB. Pre-built binaries should be
with the Gecko SDK version 3.2.1 or earlier. For the bootloader using the
external flash select the "external SPI" bootloader type configured with a
single slot of at least 1000 KB. For the bootloader using the internal flash
(supported on MG24 boards only) select the "internal storage" bootloader
type. Follow the instructions in "UG266: Silicon Labs Gecko Bootloader
User’s Guide". Pre-built binaries for some configurations should be
available in

third_party/efr32_sdk/repo/platform/bootloader/sample-apps/bootloader-storage-spiflash-single
Expand Down
76 changes: 59 additions & 17 deletions src/platform/EFR32/OTAImageProcessorImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

extern "C" {
#include "platform/bootloader/api/btl_interface.h"
#include "platform/emlib/inc/em_bus.h" // For CORE_CRITICAL_SECTION
}

/// No error, operation OK
Expand All @@ -29,8 +30,10 @@ extern "C" {
namespace chip {

// Define static memebers
uint8_t OTAImageProcessorImpl::mSlotId;
uint32_t OTAImageProcessorImpl::mWriteOffset;
uint8_t OTAImageProcessorImpl::mSlotId = 0;
uint32_t OTAImageProcessorImpl::mWriteOffset = 0;
uint16_t OTAImageProcessorImpl::writeBufOffset = 0;
uint8_t OTAImageProcessorImpl::writeBuffer[kAlignmentBytes] __attribute__((aligned(4))) = { 0 };

CHIP_ERROR OTAImageProcessorImpl::PrepareDownload()
{
Expand Down Expand Up @@ -89,9 +92,13 @@ void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context)
return;
}

bootloader_init();
mSlotId = 0; // Single slot until we support multiple images
mWriteOffset = 0;
ChipLogProgress(SoftwareUpdate, "HandlePrepareDownload");

CORE_CRITICAL_SECTION(bootloader_init();)
mSlotId = 0; // Single slot until we support multiple images
writeBufOffset = 0;
mWriteOffset = 0;
imageProcessor->mParams.downloadedBytes = 0;

imageProcessor->mHeaderParser.Init();

Expand All @@ -102,12 +109,34 @@ void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context)

void OTAImageProcessorImpl::HandleFinalize(intptr_t context)
{
uint32_t err = SL_BOOTLOADER_OK;
auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(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;

while (writeBufOffset != kAlignmentBytes)
{
writeBuffer[writeBufOffset] = 0;
writeBufOffset++;
}

CORE_CRITICAL_SECTION(err = bootloader_eraseWriteStorage(mSlotId, mWriteOffset, writeBuffer, kAlignmentBytes);)
if (err)
{
ChipLogError(SoftwareUpdate, "ERROR: In HandleFinalize bootloader_eraseWriteStorage() error %ld", err);
imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED);
return;
}
}

imageProcessor->ReleaseBlock();

ChipLogProgress(SoftwareUpdate, "OTA image downloaded successfully");
Expand All @@ -119,22 +148,23 @@ void OTAImageProcessorImpl::HandleApply(intptr_t context)

ChipLogProgress(SoftwareUpdate, "OTAImageProcessorImpl::HandleApply()");

err = bootloader_verifyImage(mSlotId, NULL);
CORE_CRITICAL_SECTION(err = bootloader_verifyImage(mSlotId, NULL);)

if (err != SL_BOOTLOADER_OK)
{
ChipLogError(SoftwareUpdate, "ERROR: bootloader_verifyImage() error %ld", err);
return;
}

err = bootloader_setImageToBootload(mSlotId);
CORE_CRITICAL_SECTION(err = bootloader_setImageToBootload(mSlotId);)
if (err != SL_BOOTLOADER_OK)
{
ChipLogError(SoftwareUpdate, "ERROR: bootloader_setImageToBootload() error %ld", err);
return;
}

// This reboots the device
bootloader_rebootAndInstall();
CORE_CRITICAL_SECTION(bootloader_rebootAndInstall();)
}

void OTAImageProcessorImpl::HandleAbort(intptr_t context)
Expand Down Expand Up @@ -174,18 +204,30 @@ void OTAImageProcessorImpl::HandleProcessBlock(intptr_t context)
return;
}

err = bootloader_eraseWriteStorage(mSlotId, mWriteOffset, (uint8_t *) (block.data()), block.size());

if (err)
// Copy data into the word-aligned writeBuffer, once it fills write its contents to the bootloader storage
// Final data block is handled in HandleFinalize().
uint32_t blockReadOffset = 0;
while (blockReadOffset < block.size())
{
ChipLogError(SoftwareUpdate, "ERROR (possible wrong bootloader version): bootloader_eraseWriteStorage() error %ld", err);

imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED);
return;
writeBuffer[writeBufOffset] = *((block.data()) + blockReadOffset);
writeBufOffset++;
blockReadOffset++;
if (writeBufOffset == kAlignmentBytes)
{
writeBufOffset = 0;

CORE_CRITICAL_SECTION(err = bootloader_eraseWriteStorage(mSlotId, mWriteOffset, writeBuffer, kAlignmentBytes);)
if (err)
{
ChipLogError(SoftwareUpdate, "ERROR: In HandleProcessBlock bootloader_eraseWriteStorage() error %ld", err);
imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED);
return;
}
mWriteOffset += kAlignmentBytes;
imageProcessor->mParams.downloadedBytes += kAlignmentBytes;
}
}

mWriteOffset += block.size(); // Keep our own track of how far we've written
imageProcessor->mParams.downloadedBytes += block.size();
imageProcessor->mDownloader->FetchNextData();
}

Expand Down
10 changes: 9 additions & 1 deletion src/platform/EFR32/OTAImageProcessorImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,20 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface
*/
CHIP_ERROR ReleaseBlock();

// EFR32 platform creates a single instance of OTAImageProcessorImpl class.
// If that changes then the use of static members and functions must be revisited
static uint32_t mWriteOffset; // End of last written block
static uint8_t mSlotId; // Bootloader storage slot
MutableByteSpan mBlock;
OTADownloader * mDownloader;
OTAImageHeaderParser mHeaderParser;
const char * mImageFile = nullptr;
const char * mImageFile = nullptr;
static constexpr size_t kAlignmentBytes = 64;
// Intermediate, word-aligned buffer for writing to the bootloader storage.
// Bootloader storage API requires the buffer size to be a multiple of 4.
static uint8_t writeBuffer[kAlignmentBytes] __attribute__((aligned(4)));
// Offset indicates how far the write buffer has been filled
static uint16_t writeBufOffset;
};

} // namespace chip

0 comments on commit cff5b32

Please sign in to comment.