Skip to content

Commit 984b633

Browse files
committed
Merge branch 'feat/add_ot_rcp_update_component' into 'main'
feat(rcp_update): add new APIs for openthread rcp update See merge request espressif/esp-thread-br!195
2 parents fc2aa19 + 4c1b767 commit 984b633

File tree

5 files changed

+152
-55
lines changed

5 files changed

+152
-55
lines changed

components/esp_rcp_update/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,20 @@ if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "5.3")
44
else()
55
set (priv_requires "driver")
66
endif()
7+
8+
if(CONFIG_OPENTHREAD_ENABLED AND CONFIG_AUTO_UPDATE_RCP)
9+
list(APPEND srcs "src/esp_ot_rcp_update.c")
10+
endif()
11+
712
idf_component_register(SRC_DIRS src
813
INCLUDE_DIRS include
914
REQUIRES esp-serial-flasher nvs_flash
1015
PRIV_REQUIRES ${priv_requires})
1116

17+
if(CONFIG_OPENTHREAD_ENABLED)
18+
idf_component_optional_requires(PRIVATE openthread)
19+
endif()
20+
1221
idf_build_get_property(python PYTHON)
1322
if(CONFIG_AUTO_UPDATE_RCP)
1423
add_custom_target(rcp_image_generation ALL

components/esp_rcp_update/idf_component.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version: "1.5.1"
1+
version: "1.5.2"
22
description: Espressif RCP Update Component for Thread Border Router and Zigbee Gateway
33
url: https://github.com/espressif/esp-thread-br/tree/main/components/esp_rcp_update
44
dependencies:
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: CC0-1.0
5+
*
6+
* OpenThread Command Line Example
7+
*
8+
* This example code is in the Public Domain (or CC0 licensed, at your option.)
9+
*
10+
* Unless required by applicable law or agreed to in writing, this
11+
* software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12+
* CONDITIONS OF ANY KIND, either express or implied.
13+
*/
14+
15+
#ifndef ESP_OT_RCP_UPDATE_H
16+
#define ESP_OT_RCP_UPDATE_H
17+
18+
#ifdef __cplusplus
19+
extern "C" {
20+
#endif
21+
22+
/**
23+
* @brief Attempts to update the RCP.
24+
*
25+
* @note If @p running_rcp_version is not NULL, the stored version will be
26+
* compared with the running version to determine whether an update
27+
* is required. If it is NULL, the stored version will be used to
28+
* force an update.
29+
*
30+
* @note This function must be called after esp_rcp_update_init.
31+
* This function may call esp_restart() if an update is performed.
32+
*
33+
* @param[in] running_rcp_version The currently running RCP version.
34+
*/
35+
void esp_ot_try_update_rcp(const char *running_rcp_version);
36+
37+
/**
38+
* @brief Registers the handlers used to process RCP-related errors.
39+
*
40+
* @note The registered handlers rely on esp_rcp_update_init, and therefore
41+
* esp_rcp_update_init must be called before any handler is triggered.
42+
* However, the registration itself does not require a specific call order.
43+
*/
44+
void esp_ot_register_rcp_handler(void);
45+
46+
/**
47+
* @brief Triggers an RCP update if the running RCP version does not match
48+
* the version stored in flash.
49+
*
50+
* @note This function must be called after esp_rcp_update_init.
51+
*/
52+
void esp_ot_update_rcp_if_different(void);
53+
54+
#ifdef __cplusplus
55+
}
56+
#endif
57+
58+
#endif // ESP_OT_RCP_UPDATE_H
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: CC0-1.0
5+
*
6+
* OpenThread Command Line Example
7+
*
8+
* This example code is in the Public Domain (or CC0 licensed, at your option.)
9+
*
10+
* Unless required by applicable law or agreed to in writing, this
11+
* software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12+
* CONDITIONS OF ANY KIND, either express or implied.
13+
*/
14+
#include "esp_ot_rcp_update.h"
15+
#include "esp_log.h"
16+
#include "esp_openthread.h"
17+
#include "esp_openthread_lock.h"
18+
#include "esp_openthread_spinel.h"
19+
#include "esp_rcp_update.h"
20+
#include "openthread/platform/radio.h"
21+
22+
#define TAG "ot_rcp_update"
23+
#define ESP_RCP_VERSION_MAX_SIZE 100
24+
25+
void esp_ot_try_update_rcp(const char *running_rcp_version)
26+
{
27+
char internal_rcp_version[ESP_RCP_VERSION_MAX_SIZE];
28+
if (running_rcp_version) {
29+
ESP_LOGI(TAG, "Running RCP Version: %s", running_rcp_version);
30+
}
31+
if (esp_rcp_load_version_in_storage(internal_rcp_version, sizeof(internal_rcp_version)) == ESP_OK) {
32+
ESP_LOGI(TAG, "Internal RCP Version: %s", internal_rcp_version);
33+
if (running_rcp_version && strcmp(internal_rcp_version, running_rcp_version) == 0) {
34+
esp_rcp_mark_image_verified(true);
35+
} else {
36+
esp_openthread_rcp_deinit();
37+
if (esp_rcp_update() == ESP_OK) {
38+
esp_rcp_mark_image_verified(true);
39+
} else {
40+
esp_rcp_mark_image_verified(false);
41+
}
42+
esp_restart();
43+
}
44+
} else {
45+
ESP_LOGI(TAG, "RCP firmware not found in storage");
46+
esp_rcp_mark_image_verified(false);
47+
esp_restart();
48+
}
49+
}
50+
51+
static void rcp_hardware_reset_handler(void)
52+
{
53+
esp_rcp_reset();
54+
}
55+
56+
static void rcp_compatibility_error_handler(void)
57+
{
58+
esp_ot_try_update_rcp(NULL);
59+
}
60+
61+
static void rcp_failure_handler(void)
62+
{
63+
esp_ot_try_update_rcp(NULL);
64+
}
65+
66+
void esp_ot_register_rcp_handler(void)
67+
{
68+
esp_openthread_register_rcp_failure_handler(rcp_hardware_reset_handler);
69+
esp_openthread_set_compatibility_error_callback(rcp_compatibility_error_handler);
70+
esp_openthread_set_coprocessor_reset_failure_callback(rcp_failure_handler);
71+
}
72+
73+
void esp_ot_update_rcp_if_different(void)
74+
{
75+
esp_openthread_lock_acquire(portMAX_DELAY);
76+
const char *running_rcp_version = otPlatRadioGetVersionString(esp_openthread_get_instance());
77+
esp_openthread_lock_release();
78+
esp_ot_try_update_rcp(running_rcp_version);
79+
}

examples/common/thread_border_router/src/border_router_launch.c

Lines changed: 5 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "esp_openthread_netif_glue.h"
2222
#include "esp_openthread_types.h"
2323
#include "esp_ot_cli_extension.h"
24+
#include "esp_ot_rcp_update.h"
2425
#include "esp_rcp_update.h"
2526
#include "esp_vfs_eventfd.h"
2627
#include "freertos/FreeRTOS.h"
@@ -48,60 +49,9 @@
4849
#endif
4950

5051
#define TAG "esp_ot_br"
51-
#define RCP_VERSION_MAX_SIZE 100
5252

5353
static esp_openthread_platform_config_t s_openthread_platform_config;
5454

55-
#if CONFIG_AUTO_UPDATE_RCP
56-
static void update_rcp(void)
57-
{
58-
// Deinit uart to transfer UART to the serial loader
59-
esp_openthread_rcp_deinit();
60-
if (esp_rcp_update() == ESP_OK) {
61-
esp_rcp_mark_image_verified(true);
62-
} else {
63-
esp_rcp_mark_image_verified(false);
64-
}
65-
esp_restart();
66-
}
67-
68-
static void try_update_ot_rcp(const esp_openthread_platform_config_t *config)
69-
{
70-
char internal_rcp_version[RCP_VERSION_MAX_SIZE];
71-
const char *running_rcp_version = otPlatRadioGetVersionString(esp_openthread_get_instance());
72-
73-
if (esp_rcp_load_version_in_storage(internal_rcp_version, sizeof(internal_rcp_version)) == ESP_OK) {
74-
ESP_LOGI(TAG, "Internal RCP Version: %s", internal_rcp_version);
75-
ESP_LOGI(TAG, "Running RCP Version: %s", running_rcp_version);
76-
if (strcmp(internal_rcp_version, running_rcp_version) == 0) {
77-
esp_rcp_mark_image_verified(true);
78-
} else {
79-
update_rcp();
80-
}
81-
} else {
82-
ESP_LOGI(TAG, "RCP firmware not found in storage, will reboot to try next image");
83-
esp_rcp_mark_image_verified(false);
84-
esp_restart();
85-
}
86-
}
87-
#endif // CONFIG_AUTO_UPDATE_RCP
88-
89-
static void rcp_failure_handler(void)
90-
{
91-
#if CONFIG_AUTO_UPDATE_RCP
92-
esp_rcp_mark_image_unusable();
93-
char internal_rcp_version[RCP_VERSION_MAX_SIZE];
94-
if (esp_rcp_load_version_in_storage(internal_rcp_version, sizeof(internal_rcp_version)) == ESP_OK) {
95-
ESP_LOGI(TAG, "Internal RCP Version: %s", internal_rcp_version);
96-
update_rcp();
97-
} else {
98-
ESP_LOGI(TAG, "RCP firmware not found in storage, will reboot to try next image");
99-
esp_rcp_mark_image_verified(false);
100-
esp_restart();
101-
}
102-
#endif
103-
}
104-
10555
static void ot_br_init(void *ctx)
10656
{
10757
#if CONFIG_OPENTHREAD_BR_AUTO_START
@@ -157,11 +107,12 @@ static void ot_task_worker(void *ctx)
157107
assert(openthread_netif != NULL);
158108

159109
// Initialize the OpenThread stack
160-
esp_openthread_register_rcp_failure_handler(rcp_failure_handler);
161-
esp_openthread_set_compatibility_error_callback(rcp_failure_handler);
110+
#if CONFIG_AUTO_UPDATE_RCP
111+
esp_ot_register_rcp_handler();
112+
#endif
162113
ESP_ERROR_CHECK(esp_openthread_init(&s_openthread_platform_config));
163114
#if CONFIG_AUTO_UPDATE_RCP
164-
try_update_ot_rcp(&s_openthread_platform_config);
115+
esp_ot_update_rcp_if_different();
165116
#endif
166117
// Initialize border routing features
167118
esp_openthread_lock_acquire(portMAX_DELAY);

0 commit comments

Comments
 (0)