Merge branch 'feat/use_ot_cmakelists_v5.3' into 'release/v5.3'

feat(openthread): use upstream CMakeLists.txt for radio build (v5.3)

See merge request espressif/esp-idf!46593
This commit is contained in:
Shu Chen
2026-03-25 04:08:51 +00:00
19 changed files with 582 additions and 261 deletions
+43 -235
View File
@@ -5,14 +5,12 @@ if(${idf_target} STREQUAL "linux")
endif()
if(CONFIG_OPENTHREAD_ENABLED OR CONFIG_IDF_DOC_BUILD OR CONFIG_OPENTHREAD_SPINEL_ONLY)
set(public_include_dirs
"include"
"openthread/include")
endif()
if(CONFIG_OPENTHREAD_ENABLED)
set(private_include_dirs
"openthread/examples/platforms"
"openthread/src"
@@ -24,239 +22,18 @@ if(CONFIG_OPENTHREAD_ENABLED)
"openthread/src/ncp"
"private_include")
set(src_dirs
"src"
"src/port"
"openthread/examples/platforms/utils"
"openthread/src/core/api"
"openthread/src/core/common"
"openthread/src/core/crypto"
"openthread/src/core/diags"
"openthread/src/core/instance"
"openthread/src/core/mac"
"openthread/src/core/radio"
"openthread/src/core/thread"
"openthread/src/core/utils"
"openthread/src/lib/hdlc"
"openthread/src/lib/spinel")
set(exclude_srcs
"openthread/examples/platforms/utils/logging_rtt.c"
"openthread/examples/platforms/utils/soft_source_match_table.c"
"openthread/src/core/instance/extension_example.cpp")
if(CONFIG_OPENTHREAD_FTD OR CONFIG_OPENTHREAD_MTD)
list(APPEND src_dirs
"openthread/src/core/backbone_router"
"openthread/src/core/coap"
"openthread/src/core/meshcop"
"openthread/src/core/net"
"openthread/src/lib/platform")
if(CONFIG_OPENTHREAD_CLI)
list(APPEND src_dirs
"openthread/examples/apps/cli"
"openthread/src/cli")
list(APPEND exclude_srcs
"openthread/examples/apps/cli/main.c")
endif()
elseif(CONFIG_OPENTHREAD_RADIO)
list(APPEND src_dirs
"openthread/src/ncp"
"openthread/examples/apps/ncp")
list(APPEND exclude_srcs
"src/port/esp_openthread_state.c"
"openthread/examples/apps/ncp/main.c"
"openthread/src/core/api/backbone_router_api.cpp"
"openthread/src/core/api/child_supervision_api.cpp"
"openthread/src/core/api/dataset_api.cpp"
"openthread/src/core/api/dns_api.cpp"
"openthread/src/core/api/entropy_api.cpp"
"openthread/src/core/api/heap_api.cpp"
"openthread/src/core/api/icmp6_api.cpp"
"openthread/src/core/api/ip6_api.cpp"
"openthread/src/core/api/link_api.cpp"
"openthread/src/core/api/link_metrics_api.cpp"
"openthread/src/core/api/message_api.cpp"
"openthread/src/core/api/nat64_api.cpp"
"openthread/src/core/api/netdata_api.cpp"
"openthread/src/core/api/netdiag_api.cpp"
"openthread/src/core/api/network_time_api.cpp"
"openthread/src/core/api/random_crypto_api.cpp"
"openthread/src/core/api/tcp_api.cpp"
"openthread/src/core/api/udp_api.cpp"
"openthread/src/core/common/heap.cpp"
"openthread/src/core/common/heap_string.cpp"
"openthread/src/core/common/notifier.cpp"
"openthread/src/core/common/settings.cpp"
"openthread/src/core/common/time_ticker.cpp"
"openthread/src/core/mac/channel_mask.cpp"
"openthread/src/core/mac/data_poll_handler.cpp"
"openthread/src/core/mac/data_poll_sender.cpp"
"openthread/src/core/mac/mac.cpp"
"openthread/src/core/mac/mac_filter.cpp"
"openthread/src/core/mac/mac_links.cpp"
"openthread/src/core/thread/announce_begin_server.cpp"
"openthread/src/core/thread/announce_sender.cpp"
"openthread/src/core/thread/address_resolver.cpp"
"openthread/src/core/thread/child.cpp"
"openthread/src/core/thread/child_supervision.cpp"
"openthread/src/core/thread/csl_tx_scheduler.cpp"
"openthread/src/core/thread/discover_scanner.cpp"
"openthread/src/core/thread/energy_scan_server.cpp"
"openthread/src/core/thread/indirect_sender.cpp"
"openthread/src/core/thread/key_manager.cpp"
"openthread/src/core/thread/link_metrics.cpp"
"openthread/src/core/thread/lowpan.cpp"
"openthread/src/core/thread/mesh_forwarder.cpp"
"openthread/src/core/thread/mesh_forwarder_ftd.cpp"
"openthread/src/core/thread/mesh_forwarder_mtd.cpp"
"openthread/src/core/thread/message_framer.cpp"
"openthread/src/core/thread/mle.cpp"
"openthread/src/core/thread/mle_ftd.cpp"
"openthread/src/core/thread/mle_p2p.cpp"
"openthread/src/core/thread/mle_router.cpp"
"openthread/src/core/thread/mle_types.cpp"
"openthread/src/core/thread/neighbor.cpp"
"openthread/src/core/thread/neighbor_table.cpp"
"openthread/src/core/thread/network_data.cpp"
"openthread/src/core/thread/network_data_leader.cpp"
"openthread/src/core/thread/network_data_leader_ftd.cpp"
"openthread/src/core/thread/network_data_types.cpp"
"openthread/src/core/thread/network_data_service.cpp"
"openthread/src/core/thread/network_diagnostic.cpp"
"openthread/src/core/thread/network_diagnostic_tlvs.cpp"
"openthread/src/core/thread/panid_query_server.cpp"
"openthread/src/core/thread/router.cpp"
"openthread/src/core/thread/thread_netif.cpp"
"openthread/src/core/thread/time_sync_service.cpp"
"openthread/src/core/thread/tmf.cpp"
"openthread/src/core/thread/topology.cpp"
"openthread/src/core/utils/child_supervision.cpp")
endif()
if(CONFIG_OPENTHREAD_RADIO_NATIVE)
list(APPEND exclude_srcs
"src/port/esp_openthread_radio_spinel.cpp"
"src/port/esp_spi_spinel_interface.cpp"
"src/port/esp_uart_spinel_interface.cpp"
)
elseif(CONFIG_OPENTHREAD_RADIO_SPINEL_UART OR CONFIG_OPENTHREAD_RADIO_SPINEL_SPI)
list(APPEND exclude_srcs
"src/port/esp_openthread_radio.c"
"src/port/esp_openthread_sleep.c")
elseif(CONFIG_OPENTHREAD_RADIO_154_NONE)
list(APPEND exclude_srcs
"src/port/esp_openthread_radio_spinel.cpp"
"src/port/esp_spi_spinel_interface.cpp"
"src/port/esp_uart_spinel_interface.cpp"
"src/port/esp_openthread_radio.c"
"src/port/esp_openthread_sleep.c"
)
endif()
if(NOT CONFIG_OPENTHREAD_RADIO_TREL)
list(APPEND exclude_srcs
"src/port/esp_openthread_trel.c")
endif()
if(CONFIG_OPENTHREAD_BORDER_ROUTER)
list(APPEND src_dirs
"openthread/src/core/border_router")
endif()
if(CONFIG_OPENTHREAD_FTD)
set_source_files_properties("openthread/src/core/net/srp_server.cpp"
PROPERTIES COMPILE_FLAGS
-Wno-maybe-uninitialized)
endif()
if(CONFIG_OPENTHREAD_NCP_VENDOR_HOOK)
list(APPEND src_dirs
"src/ncp")
if(CONFIG_OPENTHREAD_RCP_UART OR CONFIG_OPENTHREAD_RCP_USB_SERIAL_JTAG)
list(APPEND exclude_srcs
"src/ncp/esp_openthread_ncp_spi.cpp")
elseif(CONFIG_OPENTHREAD_RCP_SPI)
list(APPEND exclude_srcs
"src/ncp/esp_openthread_ncp_hdlc.cpp")
endif()
endif()
if(NOT CONFIG_OPENTHREAD_DNS64_CLIENT)
list(APPEND exclude_srcs
"src/esp_openthread_dns64.c")
endif()
if(NOT CONFIG_FREERTOS_USE_TICKLESS_IDLE)
list(APPEND exclude_srcs
"src/port/esp_openthread_sleep.c")
endif()
if(NOT CONFIG_OPENTHREAD_PLATFORM_MSGPOOL_MANAGEMENT)
list(APPEND exclude_srcs
"src/port/esp_openthread_messagepool.c")
endif()
if(NOT CONFIG_OPENTHREAD_RCP_SPINEL_CONSOLE)
list(APPEND exclude_srcs
"src/ncp/esp_openthread_ncp_console.cpp")
endif()
if(CONFIG_OPENTHREAD_FTD)
include(srcs_ftd_mtd.cmake)
set(device_type "OPENTHREAD_FTD=1")
elseif(CONFIG_OPENTHREAD_MTD)
include(srcs_ftd_mtd.cmake)
set(device_type "OPENTHREAD_MTD=1")
elseif(CONFIG_OPENTHREAD_RADIO)
include(srcs_radio.cmake)
set(device_type "OPENTHREAD_RADIO=1")
endif()
elseif(CONFIG_OPENTHREAD_SPINEL_ONLY)
set(src_dirs
"src/spinel"
"src/port"
"openthread/src/lib/spinel"
"openthread/src/lib/hdlc"
"openthread/src/lib/platform"
"openthread/src/core/api"
"openthread/src/core/common"
"openthread/src/core/mac")
set(private_include_dirs
"private_include"
"openthread/src"
"openthread/src/core"
"openthread/src/include"
"openthread/src/lib"
"openthread/src/lib/hdlc"
"openthread/src/lib/spinel")
file(GLOB_RECURSE exclude_srcs_list
"src/port/*"
"openthread/src/core/api/*.cpp"
"openthread/src/core/common/*"
"openthread/src/core/mac/*")
list(REMOVE_ITEM exclude_srcs_list
"${CMAKE_CURRENT_SOURCE_DIR}/src/port/esp_openthread_alarm.c"
"${CMAKE_CURRENT_SOURCE_DIR}/src/port/esp_openthread_logging.c"
"${CMAKE_CURRENT_SOURCE_DIR}/openthread/src/core/api/error_api.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/openthread/src/core/api/logging_api.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/openthread/src/core/common/error.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/openthread/src/core/common/error.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/openthread/src/core/common/log.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/openthread/src/core/common/log.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/openthread/src/core/common/logging.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/openthread/src/core/common/string.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/openthread/src/core/common/string.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/openthread/src/core/mac/mac_frame.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/openthread/src/core/mac/mac_frame.hpp")
list(APPEND exclude_srcs ${exclude_srcs_list})
include(srcs_spinel.cmake)
endif()
if(CONFIG_OPENTHREAD_HEADER_CUSTOM)
@@ -283,14 +60,45 @@ string(CONCAT OT_FULL_VERSION_STRING
"${IDF_VERSION_FOR_OPENTHREAD_PACKAGE}-${OPENTHREAD_VERSION}\; "
"${CONFIG_OPENTHREAD_PLATFORM_INFO}\; ${OT_BUILD_TIMESTAMP}")
idf_component_register(SRC_DIRS "${src_dirs}"
EXCLUDE_SRCS "${exclude_srcs}"
INCLUDE_DIRS "${public_include_dirs}"
PRIV_INCLUDE_DIRS "${private_include_dirs}"
REQUIRES esp_netif lwip esp_driver_uart driver
LDFRAGMENTS linker.lf
PRIV_REQUIRES console esp_coex esp_event esp_partition esp_timer
ieee802154 mbedtls nvs_flash)
# Register component based on mode
if(CONFIG_OPENTHREAD_FTD OR CONFIG_OPENTHREAD_MTD)
# FTD/MTD modes use directory-based collection from srcs_ftd_mtd.cmake
idf_component_register(SRC_DIRS "${src_dirs}"
EXCLUDE_SRCS "${exclude_srcs}"
INCLUDE_DIRS "${public_include_dirs}"
PRIV_INCLUDE_DIRS "${private_include_dirs}"
REQUIRES esp_netif lwip esp_driver_uart driver
LDFRAGMENTS linker.lf
PRIV_REQUIRES console esp_coex esp_event esp_partition esp_timer
ieee802154 mbedtls nvs_flash esp_psram)
elseif(CONFIG_OPENTHREAD_RADIO)
# RCP mode uses explicit source list from srcs_radio.cmake
idf_component_register(SRCS ${rcp_srcs}
INCLUDE_DIRS "${public_include_dirs}"
PRIV_INCLUDE_DIRS "${private_include_dirs}"
REQUIRES esp_netif lwip esp_driver_uart driver
LDFRAGMENTS linker.lf
PRIV_REQUIRES console esp_coex esp_event esp_partition esp_timer
ieee802154 mbedtls nvs_flash esp_psram)
elseif(CONFIG_OPENTHREAD_SPINEL_ONLY)
# SPINEL_ONLY mode uses explicit source list from srcs_spinel.cmake
idf_component_register(SRCS ${spinel_srcs}
INCLUDE_DIRS "${public_include_dirs}"
PRIV_INCLUDE_DIRS "${private_include_dirs}"
REQUIRES esp_netif lwip esp_driver_uart driver
LDFRAGMENTS linker.lf
PRIV_REQUIRES console esp_coex esp_event esp_partition esp_timer
ieee802154 mbedtls nvs_flash esp_psram)
else()
# This is not supposed to happen, but in older versions of IDF components couldn't be selectively
# enabled based on KConfig options so some examples just included openthread for all configs.
idf_component_register(INCLUDE_DIRS "${public_include_dirs}"
PRIV_INCLUDE_DIRS "${private_include_dirs}"
REQUIRES esp_netif lwip esp_driver_uart driver
LDFRAGMENTS linker.lf
PRIV_REQUIRES console esp_coex esp_event esp_partition esp_timer
ieee802154 mbedtls nvs_flash esp_psram)
endif()
if(CONFIG_OPENTHREAD_RADIO_TREL)
idf_component_optional_requires(PRIVATE espressif__mdns)
+23
View File
@@ -436,6 +436,7 @@ menu "OpenThread"
config OPENTHREAD_PLATFORM_MSGPOOL_MANAGEMENT
bool 'Allocate message pool buffer from PSRAM'
depends on OPENTHREAD_PLATFORM_MALLOC_CAP_SPIRAM
default y
help
If enabled, the message pool is managed by platform defined logic.
@@ -622,5 +623,27 @@ menu "OpenThread"
information whenever an OpenThread assert occurs. This can help developers
analyze unexpected failures by providing additional MAC layer context.
config OPENTHREAD_TASK_BLOCK_MONITOR
depends on OPENTHREAD_DEBUG
bool "Enable OpenThread Task Block Monitor"
default n
help
Enable monitoring of OpenThread tasks to detect if a task is blocked
and unable to continue its normal execution loop. Useful for debugging
issues where tasks stop progressing due to deadlocks or resource waits.
On RISC-V targets, in order to get meaningful backtraces when a task is
detected as blocked, ESP_SYSTEM_USE_EH_FRAME must be enabled in
ESP System Settings.
config OPENTHREAD_TASK_BLOCK_MONITOR_TIMEOUT
depends on OPENTHREAD_TASK_BLOCK_MONITOR
int "Task Block Monitor Timeout (seconds)"
range 1 60
default 20
help
Set the timeout (in seconds) for detecting a blocked task.
The timer is started at the beginning of each task main loop
and stopped at the end. If the timer expires, the task is considered blocked.
endmenu
+1 -1
View File
@@ -2,13 +2,13 @@
archive: libopenthread.a
entries:
if OPENTHREAD_TIMING_OPTIMIZATION = y:
link_metrics (noflash)
link_quality (noflash)
mac_frame (noflash)
radio (noflash)
sub_mac (noflash)
if OPENTHREAD_TIMING_OPTIMIZATION = y && OPENTHREAD_RADIO = n:
link_metrics (noflash)
mesh_forwarder (noflash)
csl_tx_scheduler (noflash)
mac (noflash)
@@ -0,0 +1,55 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <esp_err.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#ifdef __cplusplus
extern "C" {
#endif
#if CONFIG_OPENTHREAD_TASK_BLOCK_MONITOR
/**
* @brief This function creates the OpenThread task block monitor.
* The monitor task periodically checks whether the OpenThread mainloop
* has been blocked for more than `CONFIG_OPENTHREAD_TASK_BLOCK_MONITOR_TIMEOUT`
* seconds and prints backtraces when a block is detected.
*
* @return
* - ESP_OK on success
* - ESP_FAIL if the monitor task cannot be created
*
*/
esp_err_t esp_openthread_task_block_monitor_create(void);
/**
* @brief This function deletes the OpenThread task block monitor.
*
* @return
* - ESP_OK on success
*
*/
esp_err_t esp_openthread_task_block_monitor_delete(void);
/**
* @brief This function enables or disables the OpenThread task block monitor.
*
* @note When enabled, the latest mainloop activity timestamp is updated and the
* monitor task starts checking for blocking. When disabled, monitoring is
* temporarily stopped.
*
* @param[in] enable True to enable the monitor, false to disable it.
*
*/
void esp_openthread_task_block_monitor_set(bool enable);
#endif // CONFIG_OPENTHREAD_TASK_BLOCK_MONITOR
#ifdef __cplusplus
}
#endif
+16 -3
View File
@@ -18,6 +18,7 @@
#include "esp_openthread_platform.h"
#include "esp_openthread_sleep.h"
#include "esp_openthread_state.h"
#include "esp_openthread_debug.h"
#include "esp_openthread_task_queue.h"
#include "esp_openthread_types.h"
#include "freertos/FreeRTOS.h"
@@ -27,7 +28,6 @@
#include "openthread/netdata.h"
#include "openthread/tasklet.h"
#include "openthread/thread.h"
#include <cstddef>
#if CONFIG_OPENTHREAD_FTD
#include "openthread/dataset_ftd.h"
@@ -186,6 +186,10 @@ esp_err_t esp_openthread_launch_mainloop(void)
esp_err_t error = ESP_OK;
s_ot_mainloop_running = true;
#if CONFIG_OPENTHREAD_TASK_BLOCK_MONITOR
ESP_ERROR_CHECK(esp_openthread_task_block_monitor_create());
#endif
while (s_ot_mainloop_running) {
FD_ZERO(&mainloop.read_fds);
FD_ZERO(&mainloop.write_fds);
@@ -206,8 +210,14 @@ esp_err_t esp_openthread_launch_mainloop(void)
#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE && CONFIG_OPENTHREAD_RADIO_NATIVE */
esp_openthread_lock_release();
if (select(mainloop.max_fd + 1, &mainloop.read_fds, &mainloop.write_fds, &mainloop.error_fds,
&mainloop.timeout) >= 0) {
#if CONFIG_OPENTHREAD_TASK_BLOCK_MONITOR
esp_openthread_task_block_monitor_set(false);
#endif
int result = select(mainloop.max_fd + 1, &mainloop.read_fds, &mainloop.write_fds, &mainloop.error_fds, &mainloop.timeout);
#if CONFIG_OPENTHREAD_TASK_BLOCK_MONITOR
esp_openthread_task_block_monitor_set(true);
#endif
if (result >= 0) {
esp_openthread_lock_acquire(portMAX_DELAY);
error = esp_openthread_platform_process(instance, &mainloop);
while (otTaskletsArePending(instance)) {
@@ -224,6 +234,9 @@ esp_err_t esp_openthread_launch_mainloop(void)
break;
}
}
#if CONFIG_OPENTHREAD_TASK_BLOCK_MONITOR
ESP_ERROR_CHECK(esp_openthread_task_block_monitor_delete());
#endif
return error;
}
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -179,11 +179,21 @@ esp_err_t esp_openthread_platform_deinit(void)
esp_openthread_task_queue_deinit();
esp_openthread_radio_deinit();
if (get_host_connection_mode() == HOST_CONNECTION_MODE_RCP_SPI){
esp_openthread_host_connection_mode_t host_mode = get_host_connection_mode();
switch (host_mode) {
#if CONFIG_OPENTHREAD_RCP_SPI
case HOST_CONNECTION_MODE_RCP_SPI:
esp_openthread_spi_slave_deinit();
} else if (get_host_connection_mode() == HOST_CONNECTION_MODE_CLI_UART ||
get_host_connection_mode() == HOST_CONNECTION_MODE_RCP_UART) {
break;
#endif
#if CONFIG_OPENTHREAD_RCP_UART || CONFIG_OPENTHREAD_CONSOLE_TYPE_UART
case HOST_CONNECTION_MODE_RCP_UART:
case HOST_CONNECTION_MODE_CLI_UART:
esp_openthread_uart_deinit();
break;
#endif
default:
break;
}
esp_openthread_lock_deinit();
@@ -217,6 +227,6 @@ uint32_t esp_openthread_get_alloc_caps(void)
#if CONFIG_OPENTHREAD_PLATFORM_MALLOC_CAP_SPIRAM
(MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
#else
(MALLOC_CAP_DEFAULT | MALLOC_CAP_8BIT);
(MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
#endif
}
@@ -0,0 +1,131 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#include <stdatomic.h>
#include <stdbool.h>
#include <string.h>
#include "esp_check.h"
#include "esp_log.h"
#include "esp_timer.h"
#include "esp_debug_helpers.h"
#include "esp_openthread_debug.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#if CONFIG_OPENTHREAD_TASK_BLOCK_MONITOR
#include "esp_private/eh_frame_parser.h"
#include "esp_attr.h"
#include "esp_private/esp_cpu_internal.h"
#include "esp_private/panic_internal.h"
#include "esp_private/freertos_debug.h"
static const char *TAG = "OT_DEBUG";
static TaskHandle_t s_ot_task_block_monitor_task = NULL;
static atomic_llong s_ot_task_block_monitor_latest_time = 0;
static atomic_bool s_ot_task_block_monitor_active = false;
static const int64_t s_ot_task_block_monitor_timeout = CONFIG_OPENTHREAD_TASK_BLOCK_MONITOR_TIMEOUT * 1000000;
static bool is_backtrace_printed = false;
#if CONFIG_IDF_TARGET_ARCH_RISCV
static esp_err_t IRAM_ATTR esp_task_backtrace_print(TaskHandle_t target_task)
{
TaskSnapshot_t snapshot = {};
void *frame = NULL;
vTaskGetSnapshot(target_task, &snapshot);
frame = snapshot.pxTopOfStack;
char *name = pcTaskGetName(target_task);
ESP_LOGI(TAG, "Target Task Backtrace: %s", name ? name : "No Name");
#if CONFIG_ESP_SYSTEM_USE_EH_FRAME
esp_eh_frame_print_backtrace(frame);
#else
esp_cpu_frame_t backtrace_frame = {};
const int current_core = xPortGetCoreID();
memset(&backtrace_frame, 0, sizeof(esp_cpu_frame_t));
memcpy(&backtrace_frame, frame, sizeof(esp_cpu_frame_t));
panic_prepare_frame_from_ctx(&backtrace_frame);
panic_print_registers(&backtrace_frame, current_core);
esp_rom_printf("\r\n");
esp_rom_printf("Please enable CONFIG_ESP_SYSTEM_USE_EH_FRAME option to have a full backtrace.\r\n");
#endif
return ESP_OK;
}
#endif
static void ot_debug_monitor_task(void *arg)
{
(void)arg;
while (true) {
if (atomic_load(&s_ot_task_block_monitor_active)) {
int64_t elapsed = esp_timer_get_time() - atomic_load(&s_ot_task_block_monitor_latest_time);
if (elapsed > s_ot_task_block_monitor_timeout && !is_backtrace_printed) {
is_backtrace_printed = true;
ESP_LOGW(TAG,
"OpenThread mainloop blocked for more than %d seconds, printing all tasks backtrace",
CONFIG_OPENTHREAD_TASK_BLOCK_MONITOR_TIMEOUT);
#if CONFIG_IDF_TARGET_ARCH_XTENSA
esp_backtrace_print_all_tasks(10);
#elif CONFIG_IDF_TARGET_ARCH_RISCV
TaskHandle_t handle = xTaskGetHandle(CONFIG_OPENTHREAD_TASK_NAME);
if (handle) {
esp_task_backtrace_print(handle);
}
#endif
} else if (elapsed <= s_ot_task_block_monitor_timeout) {
is_backtrace_printed = false;
}
}
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
esp_err_t esp_openthread_task_block_monitor_create(void)
{
ESP_RETURN_ON_FALSE(s_ot_task_block_monitor_task == NULL, ESP_OK, TAG, "Task block monitor already created");
BaseType_t ret = xTaskCreate(ot_debug_monitor_task, "ot_task_monitor", 3072, NULL, CONFIG_OPENTHREAD_TASK_PRIORITY, &s_ot_task_block_monitor_task);
ESP_RETURN_ON_FALSE(ret == pdPASS, ESP_FAIL, TAG, "Failed to create OpenThread task block monitor");
ESP_LOGI(TAG, "OpenThread task block monitor created");
esp_openthread_task_block_monitor_set(true);
return ESP_OK;
}
esp_err_t esp_openthread_task_block_monitor_delete(void)
{
ESP_RETURN_ON_FALSE(s_ot_task_block_monitor_task != NULL, ESP_OK, TAG, "Task block monitor not created");
esp_openthread_task_block_monitor_set(false);
vTaskDelete(s_ot_task_block_monitor_task);
s_ot_task_block_monitor_task = NULL;
ESP_LOGI(TAG, "OpenThread task block monitor deleted");
return ESP_OK;
}
void esp_openthread_task_block_monitor_set(bool enable)
{
if (enable) {
atomic_store(&s_ot_task_block_monitor_latest_time, esp_timer_get_time());
atomic_store(&s_ot_task_block_monitor_active, true);
} else {
atomic_store(&s_ot_task_block_monitor_active, false);
}
}
#endif // CONFIG_OPENTHREAD_TASK_BLOCK_MONITOR
@@ -13,7 +13,7 @@
void *otPlatCAlloc(size_t num, size_t size)
{
return heap_caps_calloc(num, size, esp_openthread_get_alloc_caps());
return heap_caps_calloc_prefer(num, size, 3, esp_openthread_get_alloc_caps(), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
}
void otPlatFree(void *ptr)
@@ -1,35 +1,48 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "openthread-core-config.h"
#include "esp_openthread_common_macro.h"
#include "esp_openthread_platform.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_heap_caps.h"
#include "esp_psram.h"
#include "openthread/instance.h"
#include "openthread/platform/messagepool.h"
int s_buffer_pool_head = -1;
otMessageBuffer **s_buffer_pool_pointer = NULL;
otMessageBuffer *s_buffer_pool = NULL;
// Fallback buffer count at runtime for non-PSRAM targets (matches Kconfig default)
#define OT_MSGPOOL_NUM_BUFFERS_NO_PSRAM 65
static int s_buffer_pool_head = -1;
static otMessageBuffer **s_buffer_pool_pointer = NULL;
static otMessageBuffer *s_buffer_pool = NULL;
void otPlatMessagePoolInit(otInstance *aInstance, uint16_t aMinNumFreeBuffers, size_t aBufferSize)
{
otMessageBuffer *buffer_pool = (otMessageBuffer *)heap_caps_calloc(aMinNumFreeBuffers, aBufferSize, MALLOC_CAP_SPIRAM);
s_buffer_pool_pointer = (otMessageBuffer **)heap_caps_calloc(aMinNumFreeBuffers, sizeof(otMessageBuffer **), MALLOC_CAP_SPIRAM);
uint16_t num_buffers = aMinNumFreeBuffers;
if (!esp_psram_is_initialized() && num_buffers > OT_MSGPOOL_NUM_BUFFERS_NO_PSRAM) {
ESP_LOGW(OT_PLAT_LOG_TAG, "PSRAM not available, reducing message pool from %u to %u buffers",
num_buffers, OT_MSGPOOL_NUM_BUFFERS_NO_PSRAM);
num_buffers = OT_MSGPOOL_NUM_BUFFERS_NO_PSRAM;
}
otMessageBuffer *buffer_pool = (otMessageBuffer *)heap_caps_calloc_prefer(num_buffers, aBufferSize, 3, esp_openthread_get_alloc_caps(), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
s_buffer_pool_pointer = (otMessageBuffer **)heap_caps_calloc_prefer(num_buffers, sizeof(otMessageBuffer **), 3, esp_openthread_get_alloc_caps(), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
if (buffer_pool == NULL || s_buffer_pool_pointer == NULL) {
ESP_LOGE(OT_PLAT_LOG_TAG, "Failed to create message buffer pool");
assert(false);
}
for (uint16_t i = 0; i < aMinNumFreeBuffers; i++) {
for (uint16_t i = 0; i < num_buffers; i++) {
s_buffer_pool_pointer[i] = buffer_pool + i * aBufferSize / sizeof(otMessageBuffer);
}
s_buffer_pool_head = aMinNumFreeBuffers - 1;
s_buffer_pool_head = num_buffers - 1;
s_buffer_pool = buffer_pool;
ESP_LOGI(OT_PLAT_LOG_TAG, "Create message buffer pool successfully, size %d", aMinNumFreeBuffers*aBufferSize);
ESP_LOGI(OT_PLAT_LOG_TAG, "Create message buffer pool successfully, size %d", num_buffers * aBufferSize);
}
otMessageBuffer *otPlatMessagePoolNew(otInstance *aInstance)
+114
View File
@@ -0,0 +1,114 @@
# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
# Source files for FTD (Full Thread Device) and MTD (Minimal Thread Device) modes.
# Uses directory-based collection with exclusions.
set(src_dirs
"src"
"src/port"
"openthread/examples/platforms/utils"
"openthread/src/core/api"
"openthread/src/core/common"
"openthread/src/core/crypto"
"openthread/src/core/diags"
"openthread/src/core/instance"
"openthread/src/core/mac"
"openthread/src/core/radio"
"openthread/src/core/thread"
"openthread/src/core/utils"
"openthread/src/lib/hdlc"
"openthread/src/lib/spinel"
"openthread/src/core/backbone_router"
"openthread/src/core/coap"
"openthread/src/core/meshcop"
"openthread/src/core/net"
"openthread/src/lib/platform"
)
set(exclude_srcs
"openthread/examples/platforms/utils/logging_rtt.c"
"openthread/examples/platforms/utils/soft_source_match_table.c"
"openthread/src/core/instance/extension_example.cpp"
)
# CLI sources
if(CONFIG_OPENTHREAD_CLI)
list(APPEND src_dirs
"openthread/examples/apps/cli"
"openthread/src/cli")
list(APPEND exclude_srcs
"openthread/examples/apps/cli/main.c")
endif()
# Radio interface exclusions
if(CONFIG_OPENTHREAD_RADIO_NATIVE)
list(APPEND exclude_srcs
"src/port/esp_openthread_radio_spinel.cpp"
"src/port/esp_spi_spinel_interface.cpp"
"src/port/esp_uart_spinel_interface.cpp")
elseif(CONFIG_OPENTHREAD_RADIO_SPINEL_UART OR CONFIG_OPENTHREAD_RADIO_SPINEL_SPI)
list(APPEND exclude_srcs
"src/port/esp_openthread_radio.c"
"src/port/esp_openthread_sleep.c")
elseif(CONFIG_OPENTHREAD_RADIO_154_NONE)
list(APPEND exclude_srcs
"src/port/esp_openthread_radio_spinel.cpp"
"src/port/esp_spi_spinel_interface.cpp"
"src/port/esp_uart_spinel_interface.cpp"
"src/port/esp_openthread_radio.c"
"src/port/esp_openthread_sleep.c")
endif()
# TREL
if(NOT CONFIG_OPENTHREAD_RADIO_TREL)
list(APPEND exclude_srcs
"src/port/esp_openthread_trel.c")
endif()
# Border router
if(CONFIG_OPENTHREAD_BORDER_ROUTER)
list(APPEND src_dirs
"openthread/src/core/border_router")
endif()
# FTD-specific
if(CONFIG_OPENTHREAD_FTD)
set_source_files_properties("openthread/src/core/net/srp_server.cpp"
PROPERTIES COMPILE_FLAGS
-Wno-maybe-uninitialized)
endif()
# NCP vendor hook
if(CONFIG_OPENTHREAD_NCP_VENDOR_HOOK)
list(APPEND src_dirs
"src/ncp")
if(CONFIG_OPENTHREAD_RCP_UART OR CONFIG_OPENTHREAD_RCP_USB_SERIAL_JTAG)
list(APPEND exclude_srcs
"src/ncp/esp_openthread_ncp_spi.cpp")
elseif(CONFIG_OPENTHREAD_RCP_SPI)
list(APPEND exclude_srcs
"src/ncp/esp_openthread_ncp_hdlc.cpp")
endif()
endif()
# Optional features
if(NOT CONFIG_OPENTHREAD_DNS64_CLIENT)
list(APPEND exclude_srcs
"src/esp_openthread_dns64.c")
endif()
if(NOT CONFIG_FREERTOS_USE_TICKLESS_IDLE)
list(APPEND exclude_srcs
"src/port/esp_openthread_sleep.c")
endif()
if(NOT CONFIG_OPENTHREAD_PLATFORM_MSGPOOL_MANAGEMENT)
list(APPEND exclude_srcs
"src/port/esp_openthread_messagepool.c")
endif()
if(NOT CONFIG_OPENTHREAD_RCP_SPINEL_CONSOLE)
list(APPEND exclude_srcs
"src/ncp/esp_openthread_ncp_console.cpp")
endif()
+97
View File
@@ -0,0 +1,97 @@
# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
# Source files for RCP (Radio Co-Processor) mode.
# Uses explicit whitelist to avoid including non-RCP-compatible files.
# This prevents new OpenThread files from breaking RCP builds.
set(rcp_srcs
# OpenThread core - RADIO_COMMON_SOURCES from openthread/src/core/CMakeLists.txt
# No need for crypto/crypto_platform_mbedtls.cpp because we use esp-idf implementation
openthread/src/core/api/diags_api.cpp
openthread/src/core/api/error_api.cpp
openthread/src/core/api/instance_api.cpp
openthread/src/core/api/link_raw_api.cpp
openthread/src/core/api/logging_api.cpp
openthread/src/core/api/random_noncrypto_api.cpp
openthread/src/core/api/tasklet_api.cpp
openthread/src/core/common/binary_search.cpp
openthread/src/core/common/error.cpp
openthread/src/core/common/frame_builder.cpp
openthread/src/core/common/log.cpp
openthread/src/core/common/random.cpp
openthread/src/core/common/string.cpp
openthread/src/core/common/tasklet.cpp
openthread/src/core/common/timer.cpp
openthread/src/core/common/uptime.cpp
openthread/src/core/crypto/aes_ccm.cpp
openthread/src/core/crypto/aes_ecb.cpp
openthread/src/core/crypto/crypto_platform.cpp
openthread/src/core/crypto/storage.cpp
openthread/src/core/diags/factory_diags.cpp
openthread/src/core/instance/instance.cpp
openthread/src/core/mac/link_raw.cpp
openthread/src/core/mac/mac_frame.cpp
openthread/src/core/mac/mac_header_ie.cpp
openthread/src/core/mac/mac_types.cpp
openthread/src/core/mac/sub_mac.cpp
openthread/src/core/mac/sub_mac_callbacks.cpp
openthread/src/core/mac/sub_mac_csl_receiver.cpp
openthread/src/core/mac/sub_mac_wed.cpp
openthread/src/core/radio/radio.cpp
openthread/src/core/radio/radio_callbacks.cpp
openthread/src/core/radio/radio_platform.cpp
openthread/src/core/thread/link_quality.cpp
openthread/src/core/utils/otns.cpp
openthread/src/core/utils/parse_cmdline.cpp
openthread/src/core/utils/power_calibration.cpp
# Platform utils
openthread/examples/platforms/utils/mac_frame.cpp
# HDLC library
openthread/src/lib/hdlc/hdlc.cpp
# Spinel library
openthread/src/lib/spinel/spinel.c
openthread/src/lib/spinel/spinel_buffer.cpp
openthread/src/lib/spinel/spinel_decoder.cpp
openthread/src/lib/spinel/spinel_encoder.cpp
# NCP
openthread/src/ncp/changed_props_set.cpp
openthread/src/ncp/ncp_base.cpp
openthread/src/ncp/ncp_base_dispatcher.cpp
openthread/src/ncp/ncp_base_radio.cpp
openthread/examples/apps/ncp/ncp.c
# ESP port
src/port/esp_openthread_alarm.c
src/port/esp_openthread_logging.c
src/port/esp_openthread_misc.c
src/port/esp_openthread_radio.c
src/port/esp_openthread_settings.c
# ESP sources
src/esp_openthread.cpp
src/esp_openthread_lock.c
src/esp_openthread_platform.cpp
src/esp_openthread_task_queue.c
# ESP NCP
src/ncp/esp_openthread_ncp.cpp
)
# Conditional sources based on host connection mode
if(CONFIG_OPENTHREAD_RCP_UART OR CONFIG_OPENTHREAD_RCP_USB_SERIAL_JTAG)
list(APPEND rcp_srcs
openthread/src/ncp/ncp_hdlc.cpp
src/port/esp_openthread_uart.c)
if(CONFIG_OPENTHREAD_NCP_VENDOR_HOOK)
list(APPEND rcp_srcs src/ncp/esp_openthread_ncp_hdlc.cpp)
endif()
elseif(CONFIG_OPENTHREAD_RCP_SPI)
list(APPEND rcp_srcs
openthread/src/ncp/ncp_spi.cpp
src/port/esp_openthread_spi_slave.c)
if(CONFIG_OPENTHREAD_NCP_VENDOR_HOOK)
list(APPEND rcp_srcs src/ncp/esp_openthread_ncp_spi.cpp)
endif()
endif()
if(CONFIG_OPENTHREAD_NCP_VENDOR_HOOK AND CONFIG_OPENTHREAD_RCP_SPINEL_CONSOLE)
list(APPEND rcp_srcs src/ncp/esp_openthread_ncp_console.cpp)
endif()
+45
View File
@@ -0,0 +1,45 @@
# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
# Source files for SPINEL_ONLY mode.
# Minimal build for host-side spinel communication.
# Uses explicit whitelist for clarity.
set(private_include_dirs
"private_include"
"openthread/src"
"openthread/src/core"
"openthread/src/include"
"openthread/src/lib"
"openthread/src/lib/hdlc"
"openthread/src/lib/spinel"
)
set(spinel_srcs
# ESP spinel sources
src/spinel/esp_radio_spinel.cpp
src/spinel/esp_radio_spinel_uart_interface.cpp
# ESP port (minimal)
src/port/esp_openthread_alarm.c
src/port/esp_openthread_logging.c
# OpenThread spinel library
openthread/src/lib/spinel/spinel.c
openthread/src/lib/spinel/spinel_buffer.cpp
openthread/src/lib/spinel/spinel_decoder.cpp
openthread/src/lib/spinel/spinel_encoder.cpp
openthread/src/lib/spinel/spinel_helper.cpp
openthread/src/lib/spinel/radio_spinel.cpp
openthread/src/lib/spinel/spinel_driver.cpp
openthread/src/lib/spinel/logger.cpp
# OpenThread HDLC library
openthread/src/lib/hdlc/hdlc.cpp
# OpenThread platform library
openthread/src/lib/platform/exit_code.c
# OpenThread core (minimal)
openthread/src/core/api/error_api.cpp
openthread/src/core/api/logging_api.cpp
openthread/src/core/common/error.cpp
openthread/src/core/common/log.cpp
openthread/src/core/common/string.cpp
openthread/src/core/mac/mac_frame.cpp
)