diff --git a/components/openthread/CMakeLists.txt b/components/openthread/CMakeLists.txt index 87463f77fd..60f592890a 100644 --- a/components/openthread/CMakeLists.txt +++ b/components/openthread/CMakeLists.txt @@ -70,7 +70,7 @@ if(CONFIG_OPENTHREAD_FTD OR CONFIG_OPENTHREAD_MTD) REQUIRES esp_netif lwip driver LDFRAGMENTS linker.lf PRIV_REQUIRES console esp_coex esp_event esp_partition esp_timer - ieee802154 mbedtls nvs_flash) + 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} @@ -79,7 +79,7 @@ elseif(CONFIG_OPENTHREAD_RADIO) REQUIRES esp_netif lwip driver LDFRAGMENTS linker.lf PRIV_REQUIRES console esp_coex esp_event esp_partition esp_timer - ieee802154 mbedtls nvs_flash) + 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} @@ -88,7 +88,7 @@ elseif(CONFIG_OPENTHREAD_SPINEL_ONLY) REQUIRES esp_netif lwip driver LDFRAGMENTS linker.lf PRIV_REQUIRES console esp_coex esp_event esp_partition esp_timer - ieee802154 mbedtls nvs_flash) + 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. @@ -97,7 +97,7 @@ else() REQUIRES esp_netif lwip driver LDFRAGMENTS linker.lf PRIV_REQUIRES console esp_coex esp_event esp_partition esp_timer - ieee802154 mbedtls nvs_flash) + ieee802154 mbedtls nvs_flash esp_psram) endif() if(CONFIG_OPENTHREAD_RADIO_TREL) diff --git a/components/openthread/Kconfig b/components/openthread/Kconfig index 9460c2ec1a..f86e5d720a 100644 --- a/components/openthread/Kconfig +++ b/components/openthread/Kconfig @@ -430,6 +430,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. diff --git a/components/openthread/src/esp_openthread_platform.cpp b/components/openthread/src/esp_openthread_platform.cpp index 39a9bc86a3..9c0af3718e 100644 --- a/components/openthread/src/esp_openthread_platform.cpp +++ b/components/openthread/src/esp_openthread_platform.cpp @@ -221,6 +221,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 } diff --git a/components/openthread/src/port/esp_openthread_memory.c b/components/openthread/src/port/esp_openthread_memory.c index 67c3c6df45..6b5aba17f2 100644 --- a/components/openthread/src/port/esp_openthread_memory.c +++ b/components/openthread/src/port/esp_openthread_memory.c @@ -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) diff --git a/components/openthread/src/port/esp_openthread_messagepool.c b/components/openthread/src/port/esp_openthread_messagepool.c index 17761b5061..7996af3340 100644 --- a/components/openthread/src/port/esp_openthread_messagepool.c +++ b/components/openthread/src/port/esp_openthread_messagepool.c @@ -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)