Skip to content

Commit

Permalink
Merge branch 'feature/public_ot_port' into 'master'
Browse files Browse the repository at this point in the history
openthread: open source openthread port layer

See merge request espressif/esp-idf!21803
  • Loading branch information
chshu committed Dec 31, 2022
2 parents c09cbfe + 094997a commit 0025915
Show file tree
Hide file tree
Showing 37 changed files with 3,733 additions and 92 deletions.
6 changes: 6 additions & 0 deletions components/ieee802154/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,10 @@ menu "IEEE 802.15.4"
bool
default "y" if SOC_IEEE802154_SUPPORTED

config IEEE802154_RX_BUFFER_SIZE
int "The number of 802.15.4 receive buffers"
depends on IEEE802154_ENABLED
default 20
range 2 100

endmenu # IEEE 802.15.4
69 changes: 18 additions & 51 deletions components/openthread/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ if(CONFIG_OPENTHREAD_ENABLED)
"private_include")

set(src_dirs
"port"
"openthread/examples/platforms/utils"
"openthread/src/core/api"
"openthread/src/core/common"
Expand All @@ -33,7 +34,6 @@ if(CONFIG_OPENTHREAD_ENABLED)

if(CONFIG_OPENTHREAD_FTD OR CONFIG_OPENTHREAD_MTD)
list(APPEND src_dirs
"src"
"openthread/src/core/backbone_router"
"openthread/src/core/coap"
"openthread/src/core/meshcop"
Expand Down Expand Up @@ -105,6 +105,15 @@ if(CONFIG_OPENTHREAD_ENABLED)
"openthread/src/core/utils/child_supervision.cpp")
endif()

if(CONFIG_OPENTHREAD_RADIO_NATIVE)
list(APPEND exclude_srcs
"port/esp_openthread_radio_uart.cpp"
"port/esp_uart_spinel_interface.cpp")
elseif(CONFIG_OPENTHREAD_RADIO_SPINEL_UART)
list(APPEND exclude_srcs
"port/esp_openthread_radio.c")
endif()

if(CONFIG_OPENTHREAD_BORDER_ROUTER)
list(APPEND src_dirs
"openthread/src/core/border_router")
Expand Down Expand Up @@ -148,7 +157,9 @@ idf_component_register(SRC_DIRS "${src_dirs}"
EXCLUDE_SRCS "${exclude_srcs}"
INCLUDE_DIRS "${public_include_dirs}"
PRIV_INCLUDE_DIRS "${private_include_dirs}"
REQUIRES esp_event mbedtls ieee802154 console lwip)
REQUIRES esp_netif lwip
PRIV_REQUIRES console driver esp_event esp_partition esp_timer
ieee802154 mbedtls spi_flash)

if(CONFIG_OPENTHREAD_ENABLED)
if(CONFIG_OPENTHREAD_RADIO)
Expand All @@ -168,64 +179,20 @@ if(CONFIG_OPENTHREAD_ENABLED)
"PACKAGE_VERSION=\"${IDF_VERSION_FOR_OPENTHREAD_PACKAGE}-${OPENTHREAD_VERSION}\""
"OPENTHREAD_BUILD_DATETIME=\"${OT_BUILD_TIMESTAMP}\""
)

if(CONFIG_OPENTHREAD_RADIO)
file(WRITE ${CMAKE_BINARY_DIR}/rcp_version ${OT_FULL_VERSION_STRING})
endif()

if($ENV{OPENTHREAD_ESP_LIB_FROM_INTERNAL_SRC})
idf_component_get_property(openthread_port_lib openthread_port COMPONENT_LIB)
idf_component_get_property(lwip_lib lwip COMPONENT_LIB)
idf_component_get_property(esp_netif_lib esp_netif COMPONENT_LIB)
idf_component_get_property(esp_system_lib esp_system COMPONENT_LIB)
target_link_libraries(${COMPONENT_LIB} PUBLIC
$<TARGET_FILE:${openthread_port_lib}>
$<TARGET_FILE:${esp_system_lib}>)
target_link_libraries(${COMPONENT_LIB} PUBLIC
$<TARGET_FILE:${lwip_lib}>
$<TARGET_FILE:${esp_netif_lib}>
$<TARGET_FILE:${openthread_port_lib}>
$<TARGET_FILE:${esp_netif_lib}>
$<TARGET_FILE:${lwip_lib}>)
if(CONFIG_OPENTHREAD_BORDER_ROUTER)
if(CONFIG_OPENTHREAD_BORDER_ROUTER)
if($ENV{OPENTHREAD_ESP_BR_LIB_FROM_INTERNAL_SRC})
idf_component_get_property(openthread_br_lib openthread_br COMPONENT_LIB)
target_link_libraries(${COMPONENT_LIB} PUBLIC $<TARGET_FILE:${openthread_br_lib}>)
endif()

else()
if(IDF_TARGET STREQUAL "esp32h4")
if(CONFIG_IDF_TARGET_ESP32H4_BETA_VERSION_1)
add_prebuilt_library(openthread_port
"${CMAKE_CURRENT_SOURCE_DIR}/lib/${idf_target}/rev1/libopenthread_port.a"
REQUIRES openthread)
endif()
if(CONFIG_IDF_TARGET_ESP32H4_BETA_VERSION_2)
add_prebuilt_library(openthread_port
"${CMAKE_CURRENT_SOURCE_DIR}/lib/${idf_target}/rev2/libopenthread_port.a"
REQUIRES openthread)
endif()
elseif(IDF_TARGET STREQUAL "esp32c6")
if(CONFIG_OPENTHREAD_BORDER_ROUTER)
add_prebuilt_library(openthread_port
"${CMAKE_CURRENT_SOURCE_DIR}/lib/${idf_target}/br/libopenthread_port.a"
REQUIRES openthread)
else()
add_prebuilt_library(openthread_port
"${CMAKE_CURRENT_SOURCE_DIR}/lib/${idf_target}/cli/libopenthread_port.a"
REQUIRES openthread)
endif()
else()
add_prebuilt_library(openthread_port "${CMAKE_CURRENT_SOURCE_DIR}/lib/${idf_target}/libopenthread_port.a"
REQUIRES openthread)
endif()
add_prebuilt_library(openthread_br "${CMAKE_CURRENT_SOURCE_DIR}/lib/${idf_target}/libopenthread_br.a"
REQUIRES openthread)

target_link_libraries(${COMPONENT_LIB} INTERFACE openthread_port)

if(CONFIG_OPENTHREAD_BORDER_ROUTER)
add_prebuilt_library(openthread_br "${CMAKE_CURRENT_SOURCE_DIR}/lib/${idf_target}/libopenthread_br.a"
REQUIRES openthread)
target_link_libraries(${COMPONENT_LIB} INTERFACE openthread_br)
endif()

endif()

endif()
2 changes: 1 addition & 1 deletion components/openthread/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ menu "OpenThread"
config OPENTHREAD_SRP_CLIENT
bool "Enable SRP Client"
depends on OPENTHREAD_ENABLED
default n
default y
help
Select this option to enable SRP Client in OpenThread. This allows a device to register SRP services to SRP
Server.
Expand Down
4 changes: 3 additions & 1 deletion components/openthread/include/esp_openthread_lock.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,14 @@ void esp_openthread_lock_release(void);
*
* @note Please use esp_openthread_lock_acquire() for normal cases.
*
* @param[in] block_ticks The maxinum number of RTOS ticks to wait for the lock.
*
* @return
* - True on lock acquired
* - False on failing to acquire the lock with the timeout.
*
*/
bool esp_openthread_task_switching_lock_acquire(void);
bool esp_openthread_task_switching_lock_acquire(TickType_t block_ticks);

/**
* @brief This function releases the OpenThread API task switching lock.
Expand Down
91 changes: 91 additions & 0 deletions components/openthread/port/esp_openthread.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#include "esp_openthread.h"
#include "esp_check.h"
#include "esp_openthread_border_router.h"
#include "esp_openthread_common_macro.h"
#include "esp_openthread_lock.h"
#include "esp_openthread_platform.h"
#include "esp_openthread_task_queue.h"
#include "esp_openthread_types.h"
#include "freertos/FreeRTOS.h"
#include "lwip/dns.h"
#include "openthread/instance.h"
#include "openthread/netdata.h"
#include "openthread/tasklet.h"

esp_err_t esp_openthread_init(const esp_openthread_platform_config_t *config)
{
ESP_RETURN_ON_ERROR(esp_openthread_platform_init(config), OT_PLAT_LOG_TAG,
"Failed to initialize OpenThread platform driver");
esp_openthread_lock_acquire(portMAX_DELAY);
ESP_RETURN_ON_FALSE(otInstanceInitSingle() != NULL, ESP_FAIL, OT_PLAT_LOG_TAG,
"Failed to initialize OpenThread instance");
esp_openthread_lock_release();

return ESP_OK;
}

esp_err_t esp_openthread_launch_mainloop(void)
{
esp_openthread_mainloop_context_t mainloop;
otInstance *instance = esp_openthread_get_instance();
esp_err_t error = ESP_OK;

while (true) {
FD_ZERO(&mainloop.read_fds);
FD_ZERO(&mainloop.write_fds);
FD_ZERO(&mainloop.error_fds);

mainloop.max_fd = -1;
mainloop.timeout.tv_sec = 10;
mainloop.timeout.tv_usec = 0;

esp_openthread_lock_acquire(portMAX_DELAY);
esp_openthread_platform_update(&mainloop);
if (otTaskletsArePending(instance)) {
mainloop.timeout.tv_sec = 0;
mainloop.timeout.tv_usec = 0;
}
esp_openthread_lock_release();

if (select(mainloop.max_fd + 1, &mainloop.read_fds, &mainloop.write_fds, &mainloop.error_fds,
&mainloop.timeout) >= 0) {
esp_openthread_lock_acquire(portMAX_DELAY);
error = esp_openthread_platform_process(instance, &mainloop);
while (otTaskletsArePending(instance)) {
otTaskletsProcess(instance);
}
esp_openthread_lock_release();
if (error != ESP_OK) {
ESP_LOGE(OT_PLAT_LOG_TAG, "esp_openthread_platform_process failed");
break;
}
} else {
error = ESP_FAIL;
ESP_LOGE(OT_PLAT_LOG_TAG, "OpenThread system polling failed");
break;
}
}
return error;
}

esp_err_t esp_openthread_deinit(void)
{
otInstanceFinalize(esp_openthread_get_instance());
return esp_openthread_platform_deinit();
}

static void stub_task(void *context)
{
// this is a empty function used for ot-task signal pending
}

void otTaskletsSignalPending(otInstance *aInstance)
{
esp_openthread_task_queue_post(stub_task, NULL);
}
149 changes: 149 additions & 0 deletions components/openthread/port/esp_openthread_alarm.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#include "esp_openthread_alarm.h"

#include <stdbool.h>
#include <stdint.h>
#include <sys/time.h>

#include "esp_log.h"
#include "esp_openthread_common_macro.h"
#include "esp_openthread_platform.h"
#include "esp_timer.h"
#include "openthread-core-config.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "openthread/platform/alarm-micro.h"
#include "openthread/platform/alarm-milli.h"
#include "openthread/platform/diag.h"
#include "openthread/platform/radio.h"
#include "openthread/platform/time.h"

static uint64_t s_alarm_ms_t0 = 0;
static uint64_t s_alarm_ms_dt = 0;
static bool s_is_ms_running = false;
static uint64_t s_alarm_us_t0 = 0;
static uint64_t s_alarm_us_dt = 0;
static bool s_is_us_running = false;
static const char *alarm_workflow = "alarm";

uint64_t otPlatTimeGet(void)
{
struct timeval tv_now;

int err = gettimeofday(&tv_now, NULL);
assert(err == 0);

return (uint64_t)tv_now.tv_sec * US_PER_S + tv_now.tv_usec;
}

void otPlatAlarmMilliStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt)
{
OT_UNUSED_VARIABLE(aInstance);

s_alarm_ms_t0 = aT0;
s_alarm_ms_dt = aDt;
s_is_ms_running = true;

ESP_LOGD(OT_PLAT_LOG_TAG, "Millisecond timer alarm start running, t0=%llu, dt=%llu", s_alarm_ms_t0, s_alarm_ms_dt);
}

void otPlatAlarmMilliStop(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);

s_is_ms_running = false;
}

uint32_t otPlatAlarmMilliGetNow(void)
{
return esp_timer_get_time() / US_PER_MS;
}

void otPlatAlarmMicroStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt)
{
OT_UNUSED_VARIABLE(aInstance);

s_alarm_us_t0 = aT0;
s_alarm_us_dt = aDt;
s_is_us_running = true;

ESP_LOGD(OT_PLAT_LOG_TAG, "Microsecond timer alarm start running, t0=%llu, dt=%llu", s_alarm_us_t0, s_alarm_us_dt);
}

void otPlatAlarmMicroStop(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
s_is_us_running = false;
}

uint32_t otPlatAlarmMicroGetNow(void)
{
return esp_timer_get_time();
}

esp_err_t esp_openthread_alarm_init(void)
{
return esp_openthread_platform_workflow_register(&esp_openthread_alarm_update, &esp_openthread_alarm_process,
alarm_workflow);
}

void esp_openthread_alarm_deinit(void)
{
esp_openthread_platform_workflow_unregister(alarm_workflow);
}

void esp_openthread_alarm_update(esp_openthread_mainloop_context_t *mainloop)
{
struct timeval *timeout = &mainloop->timeout;
uint64_t now = esp_timer_get_time();
int64_t remain_min_time_us = INT64_MAX;
int64_t remaining_us = 0;
if (s_is_ms_running) {
remaining_us = (s_alarm_ms_dt + s_alarm_ms_t0) * US_PER_MS - now;
if (remain_min_time_us > remaining_us) {
remain_min_time_us = remaining_us;
}
}
if (s_is_us_running) {
remaining_us = s_alarm_us_dt + s_alarm_us_t0 - now;
if (remain_min_time_us > remaining_us) {
remain_min_time_us = remaining_us;
}
}
if (remain_min_time_us > 0) {
timeout->tv_sec = remain_min_time_us / US_PER_S;
timeout->tv_usec = remain_min_time_us % US_PER_S;
} else {
timeout->tv_sec = 0;
timeout->tv_usec = 0;
}
}

esp_err_t esp_openthread_alarm_process(otInstance *aInstance, const esp_openthread_mainloop_context_t *mainloop)
{
if (s_is_ms_running && s_alarm_ms_t0 + s_alarm_ms_dt <= otPlatAlarmMilliGetNow()) {
s_is_ms_running = false;

#if OPENTHREAD_CONFIG_DIAG_ENABLE
if (otPlatDiagModeGet()) {
otPlatDiagAlarmFired(aInstance);
} else
#endif
{
otPlatAlarmMilliFired(aInstance);
}

ESP_LOGD(OT_PLAT_LOG_TAG, "Millisecond timer alarm fired");
}
if (s_is_us_running && s_alarm_us_t0 + s_alarm_us_dt <= esp_timer_get_time()) {
s_is_us_running = false;
otPlatAlarmMicroFired(aInstance);
ESP_LOGD(OT_PLAT_LOG_TAG, "Microsecond timer alarm fired");
}
return ESP_OK;
}
Loading

0 comments on commit 0025915

Please sign in to comment.