diff --git a/config/esp32/components/chip/CMakeLists.txt b/config/esp32/components/chip/CMakeLists.txt index c1b0e0b6440cbe..7d3cc5440d4653 100644 --- a/config/esp32/components/chip/CMakeLists.txt +++ b/config/esp32/components/chip/CMakeLists.txt @@ -345,8 +345,8 @@ endif() set(args_gn "${CMAKE_CURRENT_BINARY_DIR}/args.gn") add_custom_command(OUTPUT "${args_gn}" - COMMAND ${python} - ${CMAKE_CURRENT_LIST_DIR}/create_args_gn.py + COMMAND ${python} + ${CMAKE_CURRENT_LIST_DIR}/create_args_gn.py "${CMAKE_BINARY_DIR}" "${idf_path}" "${CMAKE_CURRENT_LIST_DIR}/chip.c" @@ -468,10 +468,19 @@ endif() # Build Matter OTA image if (CONFIG_CHIP_OTA_IMAGE_BUILD) - chip_ota_image(chip-ota-image - INPUT_FILES ${BUILD_DIR}/${CMAKE_PROJECT_NAME}.bin - OUTPUT_FILE ${BUILD_DIR}/${CMAKE_PROJECT_NAME}-ota.bin - ) - # Adding dependecy as app target so that this runs after images are ready - add_dependencies(chip-ota-image app) + if (CONFIG_OPENTHREAD_BORDER_ROUTER AND CONFIG_AUTO_UPDATE_RCP) + chip_ota_image(chip-ota-image + INPUT_FILES ${BUILD_DIR}/ota_with_rcp_image + OUTPUT_FILE ${BUILD_DIR}/ota_with_rcp_image-ota.bin + ) + # Adding dependecy as app target so that this runs after images are ready + add_dependencies(chip-ota-image gen_ota_image) + else() + chip_ota_image(chip-ota-image + INPUT_FILES ${BUILD_DIR}/${CMAKE_PROJECT_NAME}.bin + OUTPUT_FILE ${BUILD_DIR}/${CMAKE_PROJECT_NAME}-ota.bin + ) + # Adding dependecy as app target so that this runs after images are ready + add_dependencies(chip-ota-image app) + endif() endif() diff --git a/config/esp32/components/chip/idf_component.yml b/config/esp32/components/chip/idf_component.yml index e2b68574fc8bb7..6d5f2c2e38425c 100644 --- a/config/esp32/components/chip/idf_component.yml +++ b/config/esp32/components/chip/idf_component.yml @@ -26,7 +26,7 @@ dependencies: - if: "target != esp32h2" espressif/esp_rcp_update: - version: "1.2.0" + version: "~1.3.0" rules: - if: "idf_version >=5.0" diff --git a/examples/thread-br-app/esp32/README.md b/examples/thread-br-app/esp32/README.md index 2578a106abeb3b..3fdcfa5899659b 100644 --- a/examples/thread-br-app/esp32/README.md +++ b/examples/thread-br-app/esp32/README.md @@ -11,11 +11,13 @@ guides to get started. --- -- [OpenThread Border Router Board](#openthread-border-router-board) -- [OpenThread RCP](#openthread-rcp) -- [OpenThread CLI](#openthread-cli) -- [Setup Thread Network](#setup-thread-network) -- [Commissioning Thread End Devices](#commissioning-thread-end-devices) +- [Matter ESP32 Thread Border Router Example](#matter-esp32-thread-border-router-example) + - [OpenThread Border Router Board](#openthread-border-router-board) + - [OpenThread RCP](#openthread-rcp) + - [OpenThread CLI](#openthread-cli) + - [Setup Thread Network](#setup-thread-network) + - [Commissioning Thread End Devices](#commissioning-thread-end-devices) + - [Generate OTA Firmware For BR](#generate-ota-firmware-for-br) --- @@ -92,3 +94,9 @@ the Thread network. ``` ./chip-tool pairing ble-wifi 2 hex: ``` + +### Generate OTA Firmware For BR + +After enable the option `CONFIG_CREATE_OTA_IMAGE_WITH_RCP_FW` and +`CONFIG_CHIP_OTA_IMAGE_BUILD` in menuconfig, will generate OTA image with rcp +firmware, named `ota_with_rcp_image_ota.bin` in build folder. diff --git a/examples/thread-br-app/esp32/partitions.csv b/examples/thread-br-app/esp32/partitions.csv index 745321df3785fc..2b951b15d1e388 100644 --- a/examples/thread-br-app/esp32/partitions.csv +++ b/examples/thread-br-app/esp32/partitions.csv @@ -3,6 +3,6 @@ nvs, data, nvs, , 0xC000, otadata, data, ota, , 0x2000, phy_init, data, phy, , 0x1000, -ota_0, app, ota_0, , 1800K, -ota_1, app, ota_1, , 1800K, -rcp_fw, data, spiffs, , 300K, +ota_0, app, ota_0, , 1600k, +ota_1, app, ota_1, , 1600k, +rcp_fw, data, spiffs, , 640k, diff --git a/examples/thread-br-app/esp32/sdkconfig.defaults b/examples/thread-br-app/esp32/sdkconfig.defaults index 498081c21f8c47..e4780664e7692e 100644 --- a/examples/thread-br-app/esp32/sdkconfig.defaults +++ b/examples/thread-br-app/esp32/sdkconfig.defaults @@ -31,6 +31,7 @@ CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=n CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=7200 CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120 CONFIG_ESP_TIMER_TASK_STACK_SIZE=5120 +CONFIG_CHIP_TASK_STACK_SIZE=9216 # USB console for Thread border board CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y @@ -69,9 +70,27 @@ CONFIG_THREAD_NETWORK_COMMISSIONING_DRIVER=n # Auto update RCP firmware CONFIG_AUTO_UPDATE_RCP=y +CONFIG_ENABLE_OTA_REQUESTOR=y +CONFIG_CREATE_OTA_IMAGE_WITH_RCP_FW=y # Use platform mDNS CONFIG_USE_MINIMAL_MDNS=n -# Enable Matter shell -CONFIG_ENABLE_CHIP_SHELL=y +# Reduce flash size +CONFIG_ENABLE_CHIP_SHELL=n +CONFIG_OPENTHREAD_CLI=n +CONFIG_NEWLIB_NANO_FORMAT=y + +CONFIG_NIMBLE_MAX_CONNECTIONS=1 +CONFIG_BTDM_CTRL_BLE_MAX_CONN=1 +CONFIG_BT_NIMBLE_ROLE_CENTRAL=n +CONFIG_BT_NIMBLE_ROLE_OBSERVER=n + +CONFIG_EVENT_LOGGING_CRIT_BUFFER_SIZE=1024 + +CONFIG_LOG_DEFAULT_LEVEL_ERROR=y + +CONFIG_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y +CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y +CONFIG_ESP_ERR_TO_NAME_LOOKUP=n diff --git a/examples/thread-br-app/thread-br-common/thread-br-app.matter b/examples/thread-br-app/thread-br-common/thread-br-app.matter index 035c36d52b2dab..971bfe34dbe169 100644 --- a/examples/thread-br-app/thread-br-common/thread-br-app.matter +++ b/examples/thread-br-app/thread-br-common/thread-br-app.matter @@ -496,6 +496,160 @@ cluster BasicInformation = 40 { command MfgSpecificPing(): DefaultSuccess = 0; } +/** Provides an interface for providing OTA software updates */ +cluster OtaSoftwareUpdateProvider = 41 { + revision 1; // NOTE: Default/not specifically set + + enum ApplyUpdateActionEnum : enum8 { + kProceed = 0; + kAwaitNextAction = 1; + kDiscontinue = 2; + } + + enum DownloadProtocolEnum : enum8 { + kBDXSynchronous = 0; + kBDXAsynchronous = 1; + kHTTPS = 2; + kVendorSpecific = 3; + } + + enum StatusEnum : enum8 { + kUpdateAvailable = 0; + kBusy = 1; + kNotAvailable = 2; + kDownloadProtocolNotSupported = 3; + } + + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct QueryImageRequest { + vendor_id vendorID = 0; + int16u productID = 1; + int32u softwareVersion = 2; + DownloadProtocolEnum protocolsSupported[] = 3; + optional int16u hardwareVersion = 4; + optional char_string<2> location = 5; + optional boolean requestorCanConsent = 6; + optional octet_string<512> metadataForProvider = 7; + } + + response struct QueryImageResponse = 1 { + StatusEnum status = 0; + optional int32u delayedActionTime = 1; + optional char_string<256> imageURI = 2; + optional int32u softwareVersion = 3; + optional char_string<64> softwareVersionString = 4; + optional octet_string<32> updateToken = 5; + optional boolean userConsentNeeded = 6; + optional octet_string<512> metadataForRequestor = 7; + } + + request struct ApplyUpdateRequestRequest { + octet_string<32> updateToken = 0; + int32u newVersion = 1; + } + + response struct ApplyUpdateResponse = 3 { + ApplyUpdateActionEnum action = 0; + int32u delayedActionTime = 1; + } + + request struct NotifyUpdateAppliedRequest { + octet_string<32> updateToken = 0; + int32u softwareVersion = 1; + } + + /** Determine availability of a new Software Image */ + command QueryImage(QueryImageRequest): QueryImageResponse = 0; + /** Determine next action to take for a downloaded Software Image */ + command ApplyUpdateRequest(ApplyUpdateRequestRequest): ApplyUpdateResponse = 2; + /** Notify OTA Provider that an update was applied */ + command NotifyUpdateApplied(NotifyUpdateAppliedRequest): DefaultSuccess = 4; +} + +/** Provides an interface for downloading and applying OTA software updates */ +cluster OtaSoftwareUpdateRequestor = 42 { + revision 1; // NOTE: Default/not specifically set + + enum AnnouncementReasonEnum : enum8 { + kSimpleAnnouncement = 0; + kUpdateAvailable = 1; + kUrgentUpdateAvailable = 2; + } + + enum ChangeReasonEnum : enum8 { + kUnknown = 0; + kSuccess = 1; + kFailure = 2; + kTimeOut = 3; + kDelayByProvider = 4; + } + + enum UpdateStateEnum : enum8 { + kUnknown = 0; + kIdle = 1; + kQuerying = 2; + kDelayedOnQuery = 3; + kDownloading = 4; + kApplying = 5; + kDelayedOnApply = 6; + kRollingBack = 7; + kDelayedOnUserConsent = 8; + } + + fabric_scoped struct ProviderLocation { + node_id providerNodeID = 1; + endpoint_no endpoint = 2; + fabric_idx fabricIndex = 254; + } + + info event StateTransition = 0 { + UpdateStateEnum previousState = 0; + UpdateStateEnum newState = 1; + ChangeReasonEnum reason = 2; + nullable int32u targetSoftwareVersion = 3; + } + + critical event VersionApplied = 1 { + int32u softwareVersion = 0; + int16u productID = 1; + } + + info event DownloadError = 2 { + int32u softwareVersion = 0; + int64u bytesDownloaded = 1; + nullable int8u progressPercent = 2; + nullable int64s platformCode = 3; + } + + attribute access(write: administer) ProviderLocation defaultOTAProviders[] = 0; + readonly attribute boolean updatePossible = 1; + readonly attribute UpdateStateEnum updateState = 2; + readonly attribute nullable int8u updateStateProgress = 3; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct AnnounceOTAProviderRequest { + node_id providerNodeID = 0; + vendor_id vendorID = 1; + AnnouncementReasonEnum announcementReason = 2; + optional octet_string<512> metadataForNode = 3; + endpoint_no endpoint = 4; + } + + /** Announce the presence of an OTA Provider */ + command AnnounceOTAProvider(AnnounceOTAProviderRequest): DefaultSuccess = 0; +} + /** This cluster is used to manage global aspects of the Commissioning flow. */ cluster GeneralCommissioning = 48 { revision 1; // NOTE: Default/not specifically set @@ -1426,6 +1580,7 @@ cluster ThreadBorderRouterManagement = 1106 { endpoint 0 { device type ma_rootdevice = 22, version 1; + binding cluster OtaSoftwareUpdateProvider; server cluster Descriptor { callback attribute deviceTypeList; @@ -1481,6 +1636,23 @@ endpoint 0 { ram attribute clusterRevision default = 3; } + server cluster OtaSoftwareUpdateRequestor { + emits event StateTransition; + emits event VersionApplied; + emits event DownloadError; + callback attribute defaultOTAProviders; + ram attribute updatePossible default = true; + ram attribute updateState default = 0; + ram attribute updateStateProgress; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + + handle command AnnounceOTAProvider; + } + server cluster GeneralCommissioning { ram attribute breadcrumb default = 0x0000000000000000; callback attribute basicCommissioningInfo; diff --git a/examples/thread-br-app/thread-br-common/thread-br-app.zap b/examples/thread-br-app/thread-br-common/thread-br-app.zap index ba281bf59209dd..17902190fb0559 100644 --- a/examples/thread-br-app/thread-br-common/thread-br-app.zap +++ b/examples/thread-br-app/thread-br-common/thread-br-app.zap @@ -772,6 +772,243 @@ } ] }, + { + "name": "OTA Software Update Provider", + "code": 41, + "mfgCode": null, + "define": "OTA_SOFTWARE_UPDATE_PROVIDER_CLUSTER", + "side": "client", + "enabled": 1, + "commands": [ + { + "name": "QueryImage", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "QueryImageResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ApplyUpdateRequest", + "code": 2, + "mfgCode": null, + "source": "client", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "ApplyUpdateResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "NotifyUpdateApplied", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 0, + "isEnabled": 1 + } + ] + }, + { + "name": "OTA Software Update Requestor", + "code": 42, + "mfgCode": null, + "define": "OTA_SOFTWARE_UPDATE_REQUESTOR_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "AnnounceOTAProvider", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "DefaultOTAProviders", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "UpdatePossible", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "true", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "UpdateState", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "UpdateStateEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "UpdateStateProgress", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "StateTransition", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "VersionApplied", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "DownloadError", + "code": 2, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, { "name": "General Commissioning", "code": 48, diff --git a/src/platform/ESP32/OTAImageProcessorImpl.cpp b/src/platform/ESP32/OTAImageProcessorImpl.cpp index 284f21c0639eec..839b84134b6680 100644 --- a/src/platform/ESP32/OTAImageProcessorImpl.cpp +++ b/src/platform/ESP32/OTAImageProcessorImpl.cpp @@ -280,6 +280,36 @@ esp_err_t OTAImageProcessorImpl::DeltaOTAWriteCallback(const uint8_t * buf, size } #endif // CONFIG_ENABLE_DELTA_OTA +#if defined(CONFIG_AUTO_UPDATE_RCP) && defined(CONFIG_OPENTHREAD_BORDER_ROUTER) +esp_err_t OTAImageProcessorImpl::ProcessRcpImage(const uint8_t * buffer, uint32_t bufLen) +{ + esp_err_t err = ESP_OK; + + if (!mRcpFirmwareDownloaded) + { + size_t rcpOtaReceivedLen = 0; + err = esp_rcp_ota_receive(this->mRcpOtaHandle, buffer, bufLen, &rcpOtaReceivedLen); + + if (esp_rcp_ota_get_state(this->mRcpOtaHandle) == ESP_RCP_OTA_STATE_FINISHED) + { + this->mBrFirmwareSize = esp_rcp_ota_get_subfile_size(this->mRcpOtaHandle, FILETAG_HOST_FIRMWARE); + err = esp_ota_write(this->mOTAUpdateHandle, buffer + rcpOtaReceivedLen, bufLen - rcpOtaReceivedLen); + this->mRcpFirmwareDownloaded = true; + } + } + else if (this->mBrFirmwareSize > 0) + { + err = esp_ota_write(this->mOTAUpdateHandle, buffer, bufLen); + } + else + { + err = ESP_FAIL; + } + + return err; +} +#endif + void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context) { auto * imageProcessor = reinterpret_cast(context); @@ -337,6 +367,16 @@ void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context) } #endif // CONFIG_ENABLE_ENCRYPTED_OTA +#if defined(CONFIG_AUTO_UPDATE_RCP) && defined(CONFIG_OPENTHREAD_BORDER_ROUTER) + imageProcessor->mRcpOtaHandle = 0; + imageProcessor->mBrFirmwareSize = 0; + imageProcessor->mRcpFirmwareDownloaded = false; + if (esp_rcp_ota_begin(&imageProcessor->mRcpOtaHandle) != ESP_OK) + { + return; + } +#endif + imageProcessor->mHeaderParser.Init(); imageProcessor->mDownloader->OnPreparedForDownload(CHIP_NO_ERROR); PostOTAStateChangeEvent(DeviceLayer::kOtaDownloadInProgress); @@ -380,6 +420,12 @@ void OTAImageProcessorImpl::HandleFinalize(intptr_t context) err = esp_ota_end(imageProcessor->mOTAUpdateHandle); DeltaOTACleanUp(reinterpret_cast(imageProcessor)); +#elif defined(CONFIG_AUTO_UPDATE_RCP) && defined(CONFIG_OPENTHREAD_BORDER_ROUTER) + esp_err_t err = esp_rcp_ota_end(imageProcessor->mRcpOtaHandle); + err |= esp_ota_end(imageProcessor->mOTAUpdateHandle); + imageProcessor->mRcpOtaHandle = 0; + imageProcessor->mBrFirmwareSize = 0; + imageProcessor->mRcpFirmwareDownloaded = false; #else esp_err_t err = esp_ota_end(imageProcessor->mOTAUpdateHandle); #endif // CONFIG_ENABLE_DELTA_OTA @@ -421,6 +467,16 @@ void OTAImageProcessorImpl::HandleAbort(intptr_t context) DeltaOTACleanUp(reinterpret_cast(imageProcessor)); #endif // CONFIG_ENABLE_DELTA_OTA +#if defined(CONFIG_AUTO_UPDATE_RCP) && defined(CONFIG_OPENTHREAD_BORDER_ROUTER) + if (esp_rcp_ota_abort(imageProcessor->mRcpOtaHandle) != ESP_OK) + { + ESP_LOGE(TAG, "ESP RCP OTA abort failed"); + } + imageProcessor->mRcpOtaHandle = 0; + imageProcessor->mBrFirmwareSize = 0; + imageProcessor->mRcpFirmwareDownloaded = false; +#endif + if (esp_ota_abort(imageProcessor->mOTAUpdateHandle) != ESP_OK) { ESP_LOGE(TAG, "ESP OTA abort failed"); @@ -483,6 +539,8 @@ void OTAImageProcessorImpl::HandleProcessBlock(intptr_t context) // Apply the patch and writes that data to the passive partition. err = esp_delta_ota_feed_patch(imageProcessor->mDeltaOTAUpdateHandle, blockToWrite.data() + index, blockToWrite.size() - index); +#elif defined(CONFIG_AUTO_UPDATE_RCP) && defined(CONFIG_OPENTHREAD_BORDER_ROUTER) + err = imageProcessor->ProcessRcpImage(blockToWrite.data(), blockToWrite.size()); #else err = esp_ota_write(imageProcessor->mOTAUpdateHandle, blockToWrite.data(), blockToWrite.size()); #endif // CONFIG_ENABLE_DELTA_OTA diff --git a/src/platform/ESP32/OTAImageProcessorImpl.h b/src/platform/ESP32/OTAImageProcessorImpl.h index 3414f90b425505..ac607768e905d8 100644 --- a/src/platform/ESP32/OTAImageProcessorImpl.h +++ b/src/platform/ESP32/OTAImageProcessorImpl.h @@ -33,6 +33,12 @@ #define IMG_HEADER_LEN sizeof(esp_image_header_t) #endif // CONFIG_ENABLE_DELTA_OTA +#if defined(CONFIG_AUTO_UPDATE_RCP) && defined(CONFIG_OPENTHREAD_BORDER_ROUTER) +#include "esp_check.h" +#include "esp_rcp_ota.h" +#include "esp_rcp_update.h" +#endif + namespace chip { class OTAImageProcessorImpl : public OTAImageProcessorInterface @@ -99,6 +105,13 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface bool mEncryptedOTAEnabled = false; esp_decrypt_handle_t mOTADecryptionHandle = nullptr; #endif // CONFIG_ENABLE_ENCRYPTED_OTA + +#if defined(CONFIG_AUTO_UPDATE_RCP) && defined(CONFIG_OPENTHREAD_BORDER_ROUTER) + esp_rcp_ota_handle_t mRcpOtaHandle; + bool mRcpFirmwareDownloaded; + uint32_t mBrFirmwareSize; + esp_err_t ProcessRcpImage(const uint8_t * buffer, uint32_t bufLen); +#endif }; } // namespace chip diff --git a/src/platform/ESP32/OpenthreadLauncher.cpp b/src/platform/ESP32/OpenthreadLauncher.cpp index 0ab3dadf6862cb..99434675a6927e 100644 --- a/src/platform/ESP32/OpenthreadLauncher.cpp +++ b/src/platform/ESP32/OpenthreadLauncher.cpp @@ -156,7 +156,9 @@ static void update_rcp(void) { // Deinit uart to transfer UART to the serial loader esp_openthread_rcp_deinit(); - if (esp_rcp_update() == ESP_OK) + + esp_err_t err = esp_rcp_update(); + if (err == ESP_OK) { esp_rcp_mark_image_verified(true); } @@ -196,8 +198,18 @@ static void try_update_ot_rcp(const esp_openthread_platform_config_t * config) static void rcp_failure_handler(void) { esp_rcp_mark_image_unusable(); - try_update_ot_rcp(s_platform_config); - esp_rcp_reset(); + char internal_rcp_version[kRcpVersionMaxSize]; + if (esp_rcp_load_version_in_storage(internal_rcp_version, sizeof(internal_rcp_version)) == ESP_OK) + { + ESP_LOGI(TAG, "Internal RCP Version: %s", internal_rcp_version); + update_rcp(); + } + else + { + ESP_LOGI(TAG, "RCP firmware not found in storage, will reboot to try next image"); + esp_rcp_mark_image_verified(false); + esp_restart(); + } } #endif // CONFIG_OPENTHREAD_BORDER_ROUTER && CONFIG_AUTO_UPDATE_RCP