From d836b8018e44f880f581913afc1606f12c8cdb66 Mon Sep 17 00:00:00 2001
From: liyashuai <liyashuai@espressif.com>
Date: Tue, 3 Sep 2024 16:35:19 +0800
Subject: [PATCH 1/6] esp32: add thread border router ota function

---
 examples/thread-br-app/esp32/README.md        |  13 +
 examples/thread-br-app/esp32/partitions.csv   |   6 +-
 .../thread-br-app/esp32/sdkconfig.defaults    |  25 +-
 .../thread-br-common/thread-br-app.matter     | 172 +++++++++++++
 .../thread-br-common/thread-br-app.zap        | 237 ++++++++++++++++++
 src/platform/ESP32/OTAImageProcessorImpl.cpp  | 191 +++++++++++++-
 src/platform/ESP32/OTAImageProcessorImpl.h    |   4 +
 src/platform/ESP32/OpenthreadLauncher.cpp     |  14 +-
 8 files changed, 653 insertions(+), 9 deletions(-)

diff --git a/examples/thread-br-app/esp32/README.md b/examples/thread-br-app/esp32/README.md
index 2578a106abeb3b..f684c01e9241e6 100644
--- a/examples/thread-br-app/esp32/README.md
+++ b/examples/thread-br-app/esp32/README.md
@@ -16,6 +16,7 @@ guides to get started.
 -   [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 +93,15 @@ the Thread network.
 ```
 ./chip-tool pairing ble-wifi 2 hex:<dataset_tlvs> <pincode> <discriminator>
 ```
+
+### Generate OTA Firmware For BR
+
+Can use this python
+[script](https://github.com/espressif/esp-thread-br/blob/main/components/esp_rcp_update/create_ota_image.py)
+to merge thread border router firmware and the RCP firmware
+
+```
+python create_ota_image.py --rcp-build-dir /path/to/rcp_image/dir --br-firmware /path/to/br_image --target-file ota_target_file.bin
+```
+
+Then can use the generated bin file to create a Matter OTA file normally.
diff --git a/examples/thread-br-app/esp32/partitions.csv b/examples/thread-br-app/esp32/partitions.csv
index 745321df3785fc..b4a53561b00e43 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,   ,        1700k,
+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..f79e26cf0bdf86 100644
--- a/examples/thread-br-app/esp32/sdkconfig.defaults
+++ b/examples/thread-br-app/esp32/sdkconfig.defaults
@@ -29,8 +29,9 @@ CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=n
 
 # Increase some stack size
 CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=7200
-CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
+CONFIG_ESP_MAIN_TASK_STACK_SIZE=10240
 CONFIG_ESP_TIMER_TASK_STACK_SIZE=5120
+CONFIG_CHIP_TASK_STACK_SIZE=10240
 
 # 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..ed4b99bbccb8f5 100644
--- a/src/platform/ESP32/OTAImageProcessorImpl.cpp
+++ b/src/platform/ESP32/OTAImageProcessorImpl.cpp
@@ -36,6 +36,12 @@
 #include <esp_delta_ota.h>
 #endif // CONFIG_ENABLE_DELTA_OTA
 
+#if defined(CONFIG_AUTO_UPDATE_RCP) && defined(CONFIG_OPENTHREAD_BORDER_ROUTER)
+#include "esp_br_firmware.h"
+#include "esp_check.h"
+#include "esp_rcp_update.h"
+#endif
+
 #define TAG "OTAImageProcessor"
 
 #ifdef CONFIG_ENABLE_DELTA_OTA
@@ -43,6 +49,11 @@
 #define DIGEST_SIZE 32
 #endif // CONFIG_ENABLE_DELTA_OTA
 
+#if defined(CONFIG_AUTO_UPDATE_RCP) && defined(CONFIG_OPENTHREAD_BORDER_ROUTER)
+#define MAX_WRITE_RETRY_COUNT 5
+#define OTA_MAX_WRITE_SIZE 16
+#endif // defined(CONFIG_AUTO_UPDATE_RCP) && defined(CONFIG_OPENTHREAD_BORDER_ROUTER)
+
 using namespace chip::System;
 using namespace ::chip::DeviceLayer::Internal;
 
@@ -280,6 +291,182 @@ 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)
+typedef enum rcpImageState
+{
+    BR_OTA_INIT = 0,
+    RCP_DOWNLOAD,
+    BR_FW_DOWNLOAD,
+} RcpImageState_t;
+
+static int WriteFileForLength(FILE * fp, const void * buf, size_t size)
+{
+    int retryCount       = 0;
+    int offset           = 0;
+    const uint8_t * data = (const uint8_t *) buf;
+    while (offset < size)
+    {
+        int ret = fwrite(data + offset, 1, ((size - offset) < OTA_MAX_WRITE_SIZE ? (size - offset) : OTA_MAX_WRITE_SIZE), fp);
+        if (ret < 0)
+        {
+            return ret;
+        }
+        if (ret == 0)
+        {
+            retryCount++;
+        }
+        else
+        {
+            offset += ret;
+            retryCount = 0;
+        }
+
+        if (retryCount > MAX_WRITE_RETRY_COUNT)
+        {
+            return -1;
+        }
+    }
+    return size;
+}
+
+esp_err_t OTAImageProcessorImpl::ProcessRcpImage(esp_ota_handle_t handle, const uint8_t * buffer, uint32_t bufLengthen)
+{
+    static char rcpTargetPath[RCP_FILENAME_MAX_SIZE];
+    static RcpImageState_t state       = BR_OTA_INIT;
+    static const char * rcpFirmwareDir = esp_rcp_get_firmware_dir();
+    static int8_t rcpUpdateSeq         = esp_rcp_get_next_update_seq();
+    static uint32_t headerSize         = 0;
+    static uint32_t totalRevSize       = 0;
+    static uint32_t brFirmwareOffset   = 0;
+    static uint32_t brFirmwareSize     = 0;
+    static FILE * fp                   = NULL;
+
+    switch (state)
+    {
+    case BR_OTA_INIT: {
+        sprintf(rcpTargetPath, "%s_%d/" ESP_BR_RCP_IMAGE_FILENAME, rcpFirmwareDir, rcpUpdateSeq);
+        ESP_LOGI(TAG, "Downloading RCP target file %s", rcpTargetPath);
+
+        fp = fopen(rcpTargetPath, "w");
+        if (!fp)
+        {
+            ESP_LOGE(TAG, "Fail to open %s, will delete it", rcpTargetPath);
+            remove(rcpTargetPath);
+            return ESP_FAIL;
+        }
+
+        esp_br_subfile_info_t subFileInfo[7];
+        if (sizeof(subFileInfo) > bufLengthen)
+        {
+            ESP_LOGE(TAG, "Packet len is less than the RCP header len");
+            if (fp != NULL)
+            {
+                fclose(fp);
+            }
+            return ESP_FAIL;
+        }
+
+        memcpy((char *) subFileInfo, buffer, sizeof(subFileInfo));
+        for (int i = 0; i < 7; i++)
+        {
+            ESP_LOGD(TAG, "subFileInfo[%d].tag:0x%lx--offset:0x%lx---size:0x%lx\n", i, subFileInfo[i].tag, subFileInfo[i].offset,
+                     subFileInfo[i].size);
+            if (subFileInfo[i].tag == FILETAG_IMAGE_HEADER)
+            {
+                headerSize = subFileInfo[i].size;
+                ESP_LOGI(TAG, "RCP image header-----headerSize:%ld\n", headerSize);
+            }
+            else if (subFileInfo[i].tag == FILETAG_BR_FIRMWARE)
+            {
+                brFirmwareOffset = subFileInfo[i].offset;
+                brFirmwareSize   = subFileInfo[i].size;
+                ESP_LOGI(TAG, "Border Router image--offset:%ld--size:%ld\n", brFirmwareOffset, brFirmwareSize);
+            }
+        }
+
+        if ((headerSize != sizeof(subFileInfo)) || (brFirmwareOffset == 0) || (brFirmwareSize == 0))
+        {
+            ESP_LOGE(TAG, "RCP header error");
+            fclose(fp);
+            return ESP_FAIL;
+        }
+
+        if (WriteFileForLength(fp, buffer, bufLengthen) != bufLengthen)
+        {
+            ESP_LOGE(TAG, "Failed to write data");
+            fclose(fp);
+            return ESP_FAIL;
+        }
+
+        state        = RCP_DOWNLOAD;
+        totalRevSize = bufLengthen;
+        break;
+    }
+    case RCP_DOWNLOAD: {
+        if (totalRevSize + bufLengthen >= brFirmwareOffset)
+        {
+            uint32_t len = brFirmwareOffset - totalRevSize;
+            if (WriteFileForLength(fp, buffer, len) == len)
+            {
+                ESP_LOGI(TAG, "RCP receive done, total size %ld bytes", brFirmwareOffset);
+                state = BR_FW_DOWNLOAD;
+                fclose(fp);
+                if (esp_rcp_submit_new_image() != ESP_OK)
+                {
+                    ESP_LOGI(TAG, "Failed to submit RCP image");
+                    state = BR_OTA_INIT;
+                    return ESP_FAIL;
+                }
+            }
+            else
+            {
+                ESP_LOGE(TAG, "Failed to write data");
+                fclose(fp);
+                state = BR_OTA_INIT;
+                return ESP_FAIL;
+            }
+
+            if (esp_ota_write(handle, buffer + len, bufLengthen - len) != ESP_OK)
+            {
+                ESP_LOGE(TAG, "OTA write failed");
+                state = BR_OTA_INIT;
+                return ESP_FAIL;
+            }
+
+            totalRevSize = bufLengthen - len;
+        }
+        else
+        {
+            if (WriteFileForLength(fp, buffer, bufLengthen) != bufLengthen)
+            {
+                ESP_LOGE(TAG, "Failed to write data");
+                fclose(fp);
+                state = BR_OTA_INIT;
+                return ESP_FAIL;
+            }
+            totalRevSize += bufLengthen;
+        }
+        break;
+    }
+    case BR_FW_DOWNLOAD: {
+        if (esp_ota_write(handle, buffer, bufLengthen) != ESP_OK)
+        {
+            ESP_LOGE(TAG, "OTA write failed");
+            state = BR_OTA_INIT;
+            return ESP_FAIL;
+            ESP_LOGI(TAG, "Thread BR image receive done");
+        }
+        break;
+    }
+    default: {
+        return ESP_FAIL;
+    }
+    }
+
+    return ESP_OK;
+}
+#endif
+
 void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context)
 {
     auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
@@ -483,8 +670,10 @@ 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(imageProcessor->mOTAUpdateHandle, blockToWrite.data(), blockToWrite.size());
 #else
-    err           = esp_ota_write(imageProcessor->mOTAUpdateHandle, blockToWrite.data(), blockToWrite.size());
+    err = esp_ota_write(imageProcessor->mOTAUpdateHandle, blockToWrite.data(), blockToWrite.size());
 #endif // CONFIG_ENABLE_DELTA_OTA
 
 #ifdef CONFIG_ENABLE_ENCRYPTED_OTA
diff --git a/src/platform/ESP32/OTAImageProcessorImpl.h b/src/platform/ESP32/OTAImageProcessorImpl.h
index 3414f90b425505..058935b8d70cc8 100644
--- a/src/platform/ESP32/OTAImageProcessorImpl.h
+++ b/src/platform/ESP32/OTAImageProcessorImpl.h
@@ -99,6 +99,10 @@ 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_err_t ProcessRcpImage(esp_ota_handle_t handle, const uint8_t * buffer, uint32_t bufLengthen);
+#endif
 };
 
 } // namespace chip
diff --git a/src/platform/ESP32/OpenthreadLauncher.cpp b/src/platform/ESP32/OpenthreadLauncher.cpp
index 0ab3dadf6862cb..575e583eeb8bbd 100644
--- a/src/platform/ESP32/OpenthreadLauncher.cpp
+++ b/src/platform/ESP32/OpenthreadLauncher.cpp
@@ -196,8 +196,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
 

From b88108f4ef1991d1e233c0545f74c30a23016667 Mon Sep 17 00:00:00 2001
From: liyashuai <liyashuai@espressif.com>
Date: Mon, 10 Mar 2025 14:01:00 +0800
Subject: [PATCH 2/6] Update the implementation of some APIs

---
 .../esp32/components/chip/idf_component.yml   |   2 +-
 examples/thread-br-app/esp32/README.md        |  25 +-
 examples/thread-br-app/esp32/partitions.csv   |   2 +-
 .../thread-br-app/esp32/sdkconfig.defaults    |   6 +-
 src/platform/ESP32/OTAImageProcessorImpl.cpp  | 218 ++++--------------
 src/platform/ESP32/OTAImageProcessorImpl.h    |  11 +-
 src/platform/ESP32/OpenthreadLauncher.cpp     |   4 +-
 7 files changed, 74 insertions(+), 194 deletions(-)

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 f684c01e9241e6..46eabfe5ed0689 100644
--- a/examples/thread-br-app/esp32/README.md
+++ b/examples/thread-br-app/esp32/README.md
@@ -11,12 +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)
--   [Generate OTA Firmware For BR](#generate-ota-firmware-for-br)
+- [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)
 
 ---
 
@@ -96,12 +97,10 @@ the Thread network.
 
 ### Generate OTA Firmware For BR
 
-Can use this python
-[script](https://github.com/espressif/esp-thread-br/blob/main/components/esp_rcp_update/create_ota_image.py)
-to merge thread border router firmware and the RCP firmware
+After enable the option `CONFIG_CREATE_OTA_IMAGE_WITH_RCP_FW` in menuconfig, will generate
+OTA image with rcp firmware in build process, named `ota_with_rcp_image` in build folder.
 
+Then can add a Matter OTA header for the ota_with_rcp_image file.
 ```
-python create_ota_image.py --rcp-build-dir /path/to/rcp_image/dir --br-firmware /path/to/br_image --target-file ota_target_file.bin
-```
-
-Then can use the generated bin file to create a Matter OTA file normally.
+./ota_image_tool.py create -v 65521 -p 32768 --version 1 --version-str "v1.0" -da sha256 build/ota_with_rcp_image ota_with_rcp_image.ota
+```
\ No newline at end of file
diff --git a/examples/thread-br-app/esp32/partitions.csv b/examples/thread-br-app/esp32/partitions.csv
index b4a53561b00e43..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,   ,        1700k,
+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 f79e26cf0bdf86..e4780664e7692e 100644
--- a/examples/thread-br-app/esp32/sdkconfig.defaults
+++ b/examples/thread-br-app/esp32/sdkconfig.defaults
@@ -29,9 +29,9 @@ CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=n
 
 # Increase some stack size
 CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=7200
-CONFIG_ESP_MAIN_TASK_STACK_SIZE=10240
+CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120
 CONFIG_ESP_TIMER_TASK_STACK_SIZE=5120
-CONFIG_CHIP_TASK_STACK_SIZE=10240
+CONFIG_CHIP_TASK_STACK_SIZE=9216
 
 # USB console for Thread border board
 CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y
@@ -88,7 +88,7 @@ CONFIG_BT_NIMBLE_ROLE_OBSERVER=n
 
 CONFIG_EVENT_LOGGING_CRIT_BUFFER_SIZE=1024
 
-#CONFIG_LOG_DEFAULT_LEVEL_ERROR=y
+CONFIG_LOG_DEFAULT_LEVEL_ERROR=y
 
 CONFIG_COMPILER_OPTIMIZATION_SIZE=y
 CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
diff --git a/src/platform/ESP32/OTAImageProcessorImpl.cpp b/src/platform/ESP32/OTAImageProcessorImpl.cpp
index ed4b99bbccb8f5..3ae22f168b62a7 100644
--- a/src/platform/ESP32/OTAImageProcessorImpl.cpp
+++ b/src/platform/ESP32/OTAImageProcessorImpl.cpp
@@ -36,12 +36,6 @@
 #include <esp_delta_ota.h>
 #endif // CONFIG_ENABLE_DELTA_OTA
 
-#if defined(CONFIG_AUTO_UPDATE_RCP) && defined(CONFIG_OPENTHREAD_BORDER_ROUTER)
-#include "esp_br_firmware.h"
-#include "esp_check.h"
-#include "esp_rcp_update.h"
-#endif
-
 #define TAG "OTAImageProcessor"
 
 #ifdef CONFIG_ENABLE_DELTA_OTA
@@ -49,11 +43,6 @@
 #define DIGEST_SIZE 32
 #endif // CONFIG_ENABLE_DELTA_OTA
 
-#if defined(CONFIG_AUTO_UPDATE_RCP) && defined(CONFIG_OPENTHREAD_BORDER_ROUTER)
-#define MAX_WRITE_RETRY_COUNT 5
-#define OTA_MAX_WRITE_SIZE 16
-#endif // defined(CONFIG_AUTO_UPDATE_RCP) && defined(CONFIG_OPENTHREAD_BORDER_ROUTER)
-
 using namespace chip::System;
 using namespace ::chip::DeviceLayer::Internal;
 
@@ -292,178 +281,33 @@ 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)
-typedef enum rcpImageState
+esp_err_t OTAImageProcessorImpl::ProcessRcpImage(intptr_t context, const uint8_t * buffer, uint32_t bufLen)
 {
-    BR_OTA_INIT = 0,
-    RCP_DOWNLOAD,
-    BR_FW_DOWNLOAD,
-} RcpImageState_t;
+    esp_err_t err = ESP_OK;
+    auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
 
-static int WriteFileForLength(FILE * fp, const void * buf, size_t size)
-{
-    int retryCount       = 0;
-    int offset           = 0;
-    const uint8_t * data = (const uint8_t *) buf;
-    while (offset < size)
+    if (!imageProcessor->mRcpDone)
     {
-        int ret = fwrite(data + offset, 1, ((size - offset) < OTA_MAX_WRITE_SIZE ? (size - offset) : OTA_MAX_WRITE_SIZE), fp);
-        if (ret < 0)
-        {
-            return ret;
-        }
-        if (ret == 0)
-        {
-            retryCount++;
-        }
-        else
-        {
-            offset += ret;
-            retryCount = 0;
-        }
-
-        if (retryCount > MAX_WRITE_RETRY_COUNT)
-        {
-            return -1;
-        }
-    }
-    return size;
-}
-
-esp_err_t OTAImageProcessorImpl::ProcessRcpImage(esp_ota_handle_t handle, const uint8_t * buffer, uint32_t bufLengthen)
-{
-    static char rcpTargetPath[RCP_FILENAME_MAX_SIZE];
-    static RcpImageState_t state       = BR_OTA_INIT;
-    static const char * rcpFirmwareDir = esp_rcp_get_firmware_dir();
-    static int8_t rcpUpdateSeq         = esp_rcp_get_next_update_seq();
-    static uint32_t headerSize         = 0;
-    static uint32_t totalRevSize       = 0;
-    static uint32_t brFirmwareOffset   = 0;
-    static uint32_t brFirmwareSize     = 0;
-    static FILE * fp                   = NULL;
-
-    switch (state)
-    {
-    case BR_OTA_INIT: {
-        sprintf(rcpTargetPath, "%s_%d/" ESP_BR_RCP_IMAGE_FILENAME, rcpFirmwareDir, rcpUpdateSeq);
-        ESP_LOGI(TAG, "Downloading RCP target file %s", rcpTargetPath);
-
-        fp = fopen(rcpTargetPath, "w");
-        if (!fp)
-        {
-            ESP_LOGE(TAG, "Fail to open %s, will delete it", rcpTargetPath);
-            remove(rcpTargetPath);
-            return ESP_FAIL;
-        }
-
-        esp_br_subfile_info_t subFileInfo[7];
-        if (sizeof(subFileInfo) > bufLengthen)
-        {
-            ESP_LOGE(TAG, "Packet len is less than the RCP header len");
-            if (fp != NULL)
-            {
-                fclose(fp);
-            }
-            return ESP_FAIL;
-        }
-
-        memcpy((char *) subFileInfo, buffer, sizeof(subFileInfo));
-        for (int i = 0; i < 7; i++)
-        {
-            ESP_LOGD(TAG, "subFileInfo[%d].tag:0x%lx--offset:0x%lx---size:0x%lx\n", i, subFileInfo[i].tag, subFileInfo[i].offset,
-                     subFileInfo[i].size);
-            if (subFileInfo[i].tag == FILETAG_IMAGE_HEADER)
-            {
-                headerSize = subFileInfo[i].size;
-                ESP_LOGI(TAG, "RCP image header-----headerSize:%ld\n", headerSize);
-            }
-            else if (subFileInfo[i].tag == FILETAG_BR_FIRMWARE)
-            {
-                brFirmwareOffset = subFileInfo[i].offset;
-                brFirmwareSize   = subFileInfo[i].size;
-                ESP_LOGI(TAG, "Border Router image--offset:%ld--size:%ld\n", brFirmwareOffset, brFirmwareSize);
-            }
-        }
-
-        if ((headerSize != sizeof(subFileInfo)) || (brFirmwareOffset == 0) || (brFirmwareSize == 0))
-        {
-            ESP_LOGE(TAG, "RCP header error");
-            fclose(fp);
-            return ESP_FAIL;
-        }
+        size_t rcpOtaReceivedLen = 0;
+        err = esp_rcp_ota_receive(imageProcessor->mRcpOtaHandle, buffer, bufLen, &rcpOtaReceivedLen);
 
-        if (WriteFileForLength(fp, buffer, bufLengthen) != bufLengthen)
+        if (esp_rcp_ota_get_state(imageProcessor->mRcpOtaHandle) == ESP_RCP_OTA_STATE_FINISHED)
         {
-            ESP_LOGE(TAG, "Failed to write data");
-            fclose(fp);
-            return ESP_FAIL;
+            imageProcessor->mBrFirmwareSize = esp_rcp_ota_get_subfile_size(imageProcessor->mRcpOtaHandle, FILETAG_HOST_FIRMWARE);
+            err = esp_ota_write(imageProcessor->mOTAUpdateHandle, buffer + rcpOtaReceivedLen, bufLen - rcpOtaReceivedLen);
+            imageProcessor->mRcpDone = true;
         }
-
-        state        = RCP_DOWNLOAD;
-        totalRevSize = bufLengthen;
-        break;
-    }
-    case RCP_DOWNLOAD: {
-        if (totalRevSize + bufLengthen >= brFirmwareOffset)
-        {
-            uint32_t len = brFirmwareOffset - totalRevSize;
-            if (WriteFileForLength(fp, buffer, len) == len)
-            {
-                ESP_LOGI(TAG, "RCP receive done, total size %ld bytes", brFirmwareOffset);
-                state = BR_FW_DOWNLOAD;
-                fclose(fp);
-                if (esp_rcp_submit_new_image() != ESP_OK)
-                {
-                    ESP_LOGI(TAG, "Failed to submit RCP image");
-                    state = BR_OTA_INIT;
-                    return ESP_FAIL;
-                }
-            }
-            else
-            {
-                ESP_LOGE(TAG, "Failed to write data");
-                fclose(fp);
-                state = BR_OTA_INIT;
-                return ESP_FAIL;
-            }
-
-            if (esp_ota_write(handle, buffer + len, bufLengthen - len) != ESP_OK)
-            {
-                ESP_LOGE(TAG, "OTA write failed");
-                state = BR_OTA_INIT;
-                return ESP_FAIL;
-            }
-
-            totalRevSize = bufLengthen - len;
-        }
-        else
-        {
-            if (WriteFileForLength(fp, buffer, bufLengthen) != bufLengthen)
-            {
-                ESP_LOGE(TAG, "Failed to write data");
-                fclose(fp);
-                state = BR_OTA_INIT;
-                return ESP_FAIL;
-            }
-            totalRevSize += bufLengthen;
-        }
-        break;
-    }
-    case BR_FW_DOWNLOAD: {
-        if (esp_ota_write(handle, buffer, bufLengthen) != ESP_OK)
-        {
-            ESP_LOGE(TAG, "OTA write failed");
-            state = BR_OTA_INIT;
-            return ESP_FAIL;
-            ESP_LOGI(TAG, "Thread BR image receive done");
-        }
-        break;
     }
-    default: {
-        return ESP_FAIL;
+    else if (imageProcessor->mBrFirmwareSize > 0)
+    {
+        err = esp_ota_write(imageProcessor->mOTAUpdateHandle, buffer, bufLen);
     }
+    else
+    {
+        err = ESP_FAIL;
     }
 
-    return ESP_OK;
+    return err;
 }
 #endif
 
@@ -524,6 +368,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->mRcpDone = false;
+    if (esp_rcp_ota_begin(&imageProcessor->mRcpOtaHandle) != ESP_OK)
+    {
+        return;
+    }
+#endif
+
     imageProcessor->mHeaderParser.Init();
     imageProcessor->mDownloader->OnPreparedForDownload(CHIP_NO_ERROR);
     PostOTAStateChangeEvent(DeviceLayer::kOtaDownloadInProgress);
@@ -567,6 +421,12 @@ void OTAImageProcessorImpl::HandleFinalize(intptr_t context)
 
     err = esp_ota_end(imageProcessor->mOTAUpdateHandle);
     DeltaOTACleanUp(reinterpret_cast<intptr_t>(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->mRcpDone = false;
 #else
     esp_err_t err = esp_ota_end(imageProcessor->mOTAUpdateHandle);
 #endif // CONFIG_ENABLE_DELTA_OTA
@@ -608,6 +468,16 @@ void OTAImageProcessorImpl::HandleAbort(intptr_t context)
     DeltaOTACleanUp(reinterpret_cast<intptr_t>(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->mRcpDone = false;
+#endif
+
     if (esp_ota_abort(imageProcessor->mOTAUpdateHandle) != ESP_OK)
     {
         ESP_LOGE(TAG, "ESP OTA abort failed");
@@ -671,7 +541,7 @@ 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(imageProcessor->mOTAUpdateHandle, blockToWrite.data(), blockToWrite.size());
+    err           = imageProcessor->ProcessRcpImage(context, 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 058935b8d70cc8..206b38d8067ab7 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_update.h"
+#include "esp_rcp_ota.h"
+#endif
+
 namespace chip {
 
 class OTAImageProcessorImpl : public OTAImageProcessorInterface
@@ -101,7 +107,10 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface
 #endif // CONFIG_ENABLE_ENCRYPTED_OTA
 
 #if defined(CONFIG_AUTO_UPDATE_RCP) && defined(CONFIG_OPENTHREAD_BORDER_ROUTER)
-    esp_err_t ProcessRcpImage(esp_ota_handle_t handle, const uint8_t * buffer, uint32_t bufLengthen);
+    esp_rcp_ota_handle_t mRcpOtaHandle;
+    bool mRcpDone;
+    uint32_t mBrFirmwareSize;
+    esp_err_t ProcessRcpImage(intptr_t context, const uint8_t * buffer, uint32_t bufLen);
 #endif
 };
 
diff --git a/src/platform/ESP32/OpenthreadLauncher.cpp b/src/platform/ESP32/OpenthreadLauncher.cpp
index 575e583eeb8bbd..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);
     }

From 90244890309d1aad8d5bf7f14f9a2f1fe9e5b144 Mon Sep 17 00:00:00 2001
From: liyashuai <liyashuai@espressif.com>
Date: Tue, 11 Mar 2025 17:56:42 +0800
Subject: [PATCH 3/6] restyled update

---
 examples/thread-br-app/esp32/README.md       | 22 +++++++++++---------
 src/platform/ESP32/OTAImageProcessorImpl.cpp | 20 +++++++++---------
 src/platform/ESP32/OTAImageProcessorImpl.h   |  2 +-
 3 files changed, 23 insertions(+), 21 deletions(-)

diff --git a/examples/thread-br-app/esp32/README.md b/examples/thread-br-app/esp32/README.md
index 46eabfe5ed0689..4911db92f03987 100644
--- a/examples/thread-br-app/esp32/README.md
+++ b/examples/thread-br-app/esp32/README.md
@@ -11,13 +11,13 @@ guides to get started.
 
 ---
 
-- [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)
+-   [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)
 
 ---
 
@@ -97,10 +97,12 @@ the Thread network.
 
 ### Generate OTA Firmware For BR
 
-After enable the option `CONFIG_CREATE_OTA_IMAGE_WITH_RCP_FW` in menuconfig, will generate
-OTA image with rcp firmware in build process, named `ota_with_rcp_image` in build folder.
+After enable the option `CONFIG_CREATE_OTA_IMAGE_WITH_RCP_FW` in menuconfig,
+will generate OTA image with rcp firmware in build process, named
+`ota_with_rcp_image` in build folder.
 
 Then can add a Matter OTA header for the ota_with_rcp_image file.
+
 ```
 ./ota_image_tool.py create -v 65521 -p 32768 --version 1 --version-str "v1.0" -da sha256 build/ota_with_rcp_image ota_with_rcp_image.ota
-```
\ No newline at end of file
+```
diff --git a/src/platform/ESP32/OTAImageProcessorImpl.cpp b/src/platform/ESP32/OTAImageProcessorImpl.cpp
index 3ae22f168b62a7..656fe6d55f58ba 100644
--- a/src/platform/ESP32/OTAImageProcessorImpl.cpp
+++ b/src/platform/ESP32/OTAImageProcessorImpl.cpp
@@ -283,13 +283,13 @@ esp_err_t OTAImageProcessorImpl::DeltaOTAWriteCallback(const uint8_t * buf, size
 #if defined(CONFIG_AUTO_UPDATE_RCP) && defined(CONFIG_OPENTHREAD_BORDER_ROUTER)
 esp_err_t OTAImageProcessorImpl::ProcessRcpImage(intptr_t context, const uint8_t * buffer, uint32_t bufLen)
 {
-    esp_err_t err = ESP_OK;
+    esp_err_t err         = ESP_OK;
     auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
 
     if (!imageProcessor->mRcpDone)
     {
         size_t rcpOtaReceivedLen = 0;
-        err = esp_rcp_ota_receive(imageProcessor->mRcpOtaHandle, buffer, bufLen, &rcpOtaReceivedLen);
+        err                      = esp_rcp_ota_receive(imageProcessor->mRcpOtaHandle, buffer, bufLen, &rcpOtaReceivedLen);
 
         if (esp_rcp_ota_get_state(imageProcessor->mRcpOtaHandle) == ESP_RCP_OTA_STATE_FINISHED)
         {
@@ -369,9 +369,9 @@ 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->mRcpOtaHandle   = 0;
     imageProcessor->mBrFirmwareSize = 0;
-    imageProcessor->mRcpDone = false;
+    imageProcessor->mRcpDone        = false;
     if (esp_rcp_ota_begin(&imageProcessor->mRcpOtaHandle) != ESP_OK)
     {
         return;
@@ -424,9 +424,9 @@ void OTAImageProcessorImpl::HandleFinalize(intptr_t context)
 #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->mRcpOtaHandle   = 0;
     imageProcessor->mBrFirmwareSize = 0;
-    imageProcessor->mRcpDone = false;
+    imageProcessor->mRcpDone        = false;
 #else
     esp_err_t err = esp_ota_end(imageProcessor->mOTAUpdateHandle);
 #endif // CONFIG_ENABLE_DELTA_OTA
@@ -473,9 +473,9 @@ void OTAImageProcessorImpl::HandleAbort(intptr_t context)
     {
         ESP_LOGE(TAG, "ESP RCP OTA abort failed");
     }
-    imageProcessor->mRcpOtaHandle = 0;
+    imageProcessor->mRcpOtaHandle   = 0;
     imageProcessor->mBrFirmwareSize = 0;
-    imageProcessor->mRcpDone = false;
+    imageProcessor->mRcpDone        = false;
 #endif
 
     if (esp_ota_abort(imageProcessor->mOTAUpdateHandle) != ESP_OK)
@@ -541,9 +541,9 @@ 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(context, blockToWrite.data(), blockToWrite.size());
+    err                             = imageProcessor->ProcessRcpImage(context, blockToWrite.data(), blockToWrite.size());
 #else
-    err = esp_ota_write(imageProcessor->mOTAUpdateHandle, blockToWrite.data(), blockToWrite.size());
+    err           = esp_ota_write(imageProcessor->mOTAUpdateHandle, blockToWrite.data(), blockToWrite.size());
 #endif // CONFIG_ENABLE_DELTA_OTA
 
 #ifdef CONFIG_ENABLE_ENCRYPTED_OTA
diff --git a/src/platform/ESP32/OTAImageProcessorImpl.h b/src/platform/ESP32/OTAImageProcessorImpl.h
index 206b38d8067ab7..4d0ded9c222441 100644
--- a/src/platform/ESP32/OTAImageProcessorImpl.h
+++ b/src/platform/ESP32/OTAImageProcessorImpl.h
@@ -35,8 +35,8 @@
 
 #if defined(CONFIG_AUTO_UPDATE_RCP) && defined(CONFIG_OPENTHREAD_BORDER_ROUTER)
 #include "esp_check.h"
-#include "esp_rcp_update.h"
 #include "esp_rcp_ota.h"
+#include "esp_rcp_update.h"
 #endif
 
 namespace chip {

From 1a51dfe72fe61fb00a3f96e548b5cf97be7afbc2 Mon Sep 17 00:00:00 2001
From: liyashuai <liyashuai@espressif.com>
Date: Tue, 18 Mar 2025 14:16:08 +0800
Subject: [PATCH 4/6] add thread br ota file generate and fix some issue

---
 config/esp32/components/chip/CMakeLists.txt  | 25 ++++++++----
 examples/thread-br-app/esp32/README.md       | 12 ++----
 src/platform/ESP32/OTAImageProcessorImpl.cpp | 41 ++++++++++----------
 src/platform/ESP32/OTAImageProcessorImpl.h   |  4 +-
 4 files changed, 42 insertions(+), 40 deletions(-)

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/examples/thread-br-app/esp32/README.md b/examples/thread-br-app/esp32/README.md
index 4911db92f03987..138f18a13cab3c 100644
--- a/examples/thread-br-app/esp32/README.md
+++ b/examples/thread-br-app/esp32/README.md
@@ -97,12 +97,6 @@ the Thread network.
 
 ### Generate OTA Firmware For BR
 
-After enable the option `CONFIG_CREATE_OTA_IMAGE_WITH_RCP_FW` in menuconfig,
-will generate OTA image with rcp firmware in build process, named
-`ota_with_rcp_image` in build folder.
-
-Then can add a Matter OTA header for the ota_with_rcp_image file.
-
-```
-./ota_image_tool.py create -v 65521 -p 32768 --version 1 --version-str "v1.0" -da sha256 build/ota_with_rcp_image ota_with_rcp_image.ota
-```
+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/src/platform/ESP32/OTAImageProcessorImpl.cpp b/src/platform/ESP32/OTAImageProcessorImpl.cpp
index 656fe6d55f58ba..539dfb0def5216 100644
--- a/src/platform/ESP32/OTAImageProcessorImpl.cpp
+++ b/src/platform/ESP32/OTAImageProcessorImpl.cpp
@@ -281,26 +281,25 @@ 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(intptr_t context, const uint8_t * buffer, uint32_t bufLen)
+esp_err_t OTAImageProcessorImpl::ProcessRcpImage(const uint8_t * buffer, uint32_t bufLen)
 {
-    esp_err_t err         = ESP_OK;
-    auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
+    esp_err_t err = ESP_OK;
 
-    if (!imageProcessor->mRcpDone)
+    if (!this->mRcpFirmwareDownloaded)
     {
         size_t rcpOtaReceivedLen = 0;
-        err                      = esp_rcp_ota_receive(imageProcessor->mRcpOtaHandle, buffer, bufLen, &rcpOtaReceivedLen);
+        err                      = esp_rcp_ota_receive(this->mRcpOtaHandle, buffer, bufLen, &rcpOtaReceivedLen);
 
-        if (esp_rcp_ota_get_state(imageProcessor->mRcpOtaHandle) == ESP_RCP_OTA_STATE_FINISHED)
+        if (esp_rcp_ota_get_state(this->mRcpOtaHandle) == ESP_RCP_OTA_STATE_FINISHED)
         {
-            imageProcessor->mBrFirmwareSize = esp_rcp_ota_get_subfile_size(imageProcessor->mRcpOtaHandle, FILETAG_HOST_FIRMWARE);
-            err = esp_ota_write(imageProcessor->mOTAUpdateHandle, buffer + rcpOtaReceivedLen, bufLen - rcpOtaReceivedLen);
-            imageProcessor->mRcpDone = true;
+            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 (imageProcessor->mBrFirmwareSize > 0)
+    else if (this->mBrFirmwareSize > 0)
     {
-        err = esp_ota_write(imageProcessor->mOTAUpdateHandle, buffer, bufLen);
+        err = esp_ota_write(this->mOTAUpdateHandle, buffer, bufLen);
     }
     else
     {
@@ -369,9 +368,9 @@ 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->mRcpDone        = false;
+    imageProcessor->mRcpOtaHandle          = 0;
+    imageProcessor->mBrFirmwareSize        = 0;
+    imageProcessor->mRcpFirmwareDownloaded = false;
     if (esp_rcp_ota_begin(&imageProcessor->mRcpOtaHandle) != ESP_OK)
     {
         return;
@@ -424,9 +423,9 @@ void OTAImageProcessorImpl::HandleFinalize(intptr_t context)
 #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->mRcpDone        = false;
+    imageProcessor->mRcpOtaHandle          = 0;
+    imageProcessor->mBrFirmwareSize        = 0;
+    imageProcessor->mRcpFirmwareDownloaded = false;
 #else
     esp_err_t err = esp_ota_end(imageProcessor->mOTAUpdateHandle);
 #endif // CONFIG_ENABLE_DELTA_OTA
@@ -473,9 +472,9 @@ void OTAImageProcessorImpl::HandleAbort(intptr_t context)
     {
         ESP_LOGE(TAG, "ESP RCP OTA abort failed");
     }
-    imageProcessor->mRcpOtaHandle   = 0;
-    imageProcessor->mBrFirmwareSize = 0;
-    imageProcessor->mRcpDone        = false;
+    imageProcessor->mRcpOtaHandle          = 0;
+    imageProcessor->mBrFirmwareSize        = 0;
+    imageProcessor->mRcpFirmwareDownloaded = false;
 #endif
 
     if (esp_ota_abort(imageProcessor->mOTAUpdateHandle) != ESP_OK)
@@ -541,7 +540,7 @@ 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(context, blockToWrite.data(), blockToWrite.size());
+    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 4d0ded9c222441..ac607768e905d8 100644
--- a/src/platform/ESP32/OTAImageProcessorImpl.h
+++ b/src/platform/ESP32/OTAImageProcessorImpl.h
@@ -108,9 +108,9 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface
 
 #if defined(CONFIG_AUTO_UPDATE_RCP) && defined(CONFIG_OPENTHREAD_BORDER_ROUTER)
     esp_rcp_ota_handle_t mRcpOtaHandle;
-    bool mRcpDone;
+    bool mRcpFirmwareDownloaded;
     uint32_t mBrFirmwareSize;
-    esp_err_t ProcessRcpImage(intptr_t context, const uint8_t * buffer, uint32_t bufLen);
+    esp_err_t ProcessRcpImage(const uint8_t * buffer, uint32_t bufLen);
 #endif
 };
 

From c6a1c74d63cd3705a602e62387869c43588cf948 Mon Sep 17 00:00:00 2001
From: liyashuai <liyashuai@espressif.com>
Date: Wed, 19 Mar 2025 10:31:03 +0800
Subject: [PATCH 5/6] fix restyled error

---
 examples/thread-br-app/esp32/README.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/examples/thread-br-app/esp32/README.md b/examples/thread-br-app/esp32/README.md
index 138f18a13cab3c..3fdcfa5899659b 100644
--- a/examples/thread-br-app/esp32/README.md
+++ b/examples/thread-br-app/esp32/README.md
@@ -97,6 +97,6 @@ the Thread network.
 
 ### 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 
+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.

From 9ef3c3e63603c2c53c8413961a59e0168aaeb1b1 Mon Sep 17 00:00:00 2001
From: Jerry-ESP <107675966+Jerry-ESP@users.noreply.github.com>
Date: Thu, 20 Mar 2025 10:16:16 +0800
Subject: [PATCH 6/6] Update src/platform/ESP32/OTAImageProcessorImpl.cpp

Co-authored-by: Wang Qixiang <43193572+wqx6@users.noreply.github.com>
---
 src/platform/ESP32/OTAImageProcessorImpl.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/platform/ESP32/OTAImageProcessorImpl.cpp b/src/platform/ESP32/OTAImageProcessorImpl.cpp
index 539dfb0def5216..839b84134b6680 100644
--- a/src/platform/ESP32/OTAImageProcessorImpl.cpp
+++ b/src/platform/ESP32/OTAImageProcessorImpl.cpp
@@ -285,7 +285,7 @@ esp_err_t OTAImageProcessorImpl::ProcessRcpImage(const uint8_t * buffer, uint32_
 {
     esp_err_t err = ESP_OK;
 
-    if (!this->mRcpFirmwareDownloaded)
+    if (!mRcpFirmwareDownloaded)
     {
         size_t rcpOtaReceivedLen = 0;
         err                      = esp_rcp_ota_receive(this->mRcpOtaHandle, buffer, bufLen, &rcpOtaReceivedLen);