fix(openthread): turn off rx for SSED running CSL during idle

This commit is contained in:
Tan Yan Quan
2024-12-25 21:05:08 +08:00
parent 5a0899e129
commit 68e9452871
12 changed files with 300 additions and 104 deletions

View File

@ -131,12 +131,24 @@ static IRAM_ATTR void event_end_process(void)
ieee802154_etm_channel_clear(IEEE802154_ETM_CHANNEL1); ieee802154_etm_channel_clear(IEEE802154_ETM_CHANNEL1);
ieee802154_ll_set_transmit_security(false); ieee802154_ll_set_transmit_security(false);
ieee802154_timer0_stop(); ieee802154_timer0_stop();
ieee802154_timer1_stop();
} }
#if !CONFIG_IEEE802154_TEST #if !CONFIG_IEEE802154_TEST
IEEE802154_NOINLINE static void ieee802154_rx_ack_timeout_callback(void* s_tx_frame)
{
IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_RX_ACK);
ieee802154_inner_transmit_failed((uint8_t*)s_tx_frame, ESP_IEEE802154_TX_ERR_NO_ACK);
NEEDS_NEXT_OPT(true);
}
static IRAM_ATTR void receive_ack_timeout_timer_start(uint32_t duration) static IRAM_ATTR void receive_ack_timeout_timer_start(uint32_t duration)
{ {
ieee802154_ll_enable_events(IEEE802154_EVENT_TIMER0_OVERFLOW); ieee802154_ll_enable_events(IEEE802154_EVENT_TIMER0_OVERFLOW);
uint32_t current_time = (uint32_t)esp_timer_get_time();
ieee802154_timer0_fire_at_with_callback(current_time + duration, ieee802154_rx_ack_timeout_callback, (void*)s_tx_frame);
ieee802154_timer0_set_threshold(duration); ieee802154_timer0_set_threshold(duration);
ieee802154_timer0_start(); ieee802154_timer0_start();
} }
@ -396,22 +408,16 @@ static IRAM_ATTR void next_operation(void)
static void isr_handle_timer0_done(void) static void isr_handle_timer0_done(void)
{ {
#if !CONFIG_IEEE802154_TEST ieee802154_timer0_execute_callback();
if (s_ieee802154_state == IEEE802154_STATE_RX_ACK) { #if CONFIG_IEEE802154_TEST
ieee802154_inner_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_NO_ACK); extern void esp_ieee802154_timer0_done(void);
NEEDS_NEXT_OPT(true);
}
#else
esp_ieee802154_timer0_done(); esp_ieee802154_timer0_done();
#endif #endif
} }
static void isr_handle_timer1_done(void) static void isr_handle_timer1_done(void)
{ {
// timer 1 is now unused. ieee802154_timer1_execute_callback();
#if CONFIG_IEEE802154_TEST
esp_ieee802154_timer1_done();
#endif
} }
static IRAM_ATTR void isr_handle_tx_done(void) static IRAM_ATTR void isr_handle_tx_done(void)
@ -501,7 +507,8 @@ static IRAM_ATTR void isr_handle_rx_phase_rx_abort(ieee802154_ll_rx_abort_reason
case IEEE802154_RX_ABORT_BY_TX_ACK_STOP: case IEEE802154_RX_ABORT_BY_TX_ACK_STOP:
case IEEE802154_RX_ABORT_BY_ED_STOP: case IEEE802154_RX_ABORT_BY_ED_STOP:
// do nothing // do nothing
break; NEEDS_NEXT_OPT(false);
return;
case IEEE802154_RX_ABORT_BY_SFD_TIMEOUT: case IEEE802154_RX_ABORT_BY_SFD_TIMEOUT:
case IEEE802154_RX_ABORT_BY_CRC_ERROR: case IEEE802154_RX_ABORT_BY_CRC_ERROR:
case IEEE802154_RX_ABORT_BY_INVALID_LEN: case IEEE802154_RX_ABORT_BY_INVALID_LEN:
@ -540,6 +547,8 @@ static IRAM_ATTR void isr_handle_tx_ack_phase_rx_abort(ieee802154_ll_rx_abort_re
case IEEE802154_RX_ABORT_BY_RX_STOP: case IEEE802154_RX_ABORT_BY_RX_STOP:
case IEEE802154_RX_ABORT_BY_TX_ACK_STOP: case IEEE802154_RX_ABORT_BY_TX_ACK_STOP:
case IEEE802154_RX_ABORT_BY_ED_STOP: case IEEE802154_RX_ABORT_BY_ED_STOP:
NEEDS_NEXT_OPT(false);
return;
case IEEE802154_RX_ABORT_BY_SFD_TIMEOUT: case IEEE802154_RX_ABORT_BY_SFD_TIMEOUT:
case IEEE802154_RX_ABORT_BY_CRC_ERROR: case IEEE802154_RX_ABORT_BY_CRC_ERROR:
case IEEE802154_RX_ABORT_BY_INVALID_LEN: case IEEE802154_RX_ABORT_BY_INVALID_LEN:
@ -789,7 +798,7 @@ esp_err_t ieee802154_mac_init(void)
ieee802154_ll_enable_events(IEEE802154_EVENT_MASK); ieee802154_ll_enable_events(IEEE802154_EVENT_MASK);
#if !CONFIG_IEEE802154_TEST #if !CONFIG_IEEE802154_TEST
ieee802154_ll_disable_events((IEEE802154_EVENT_TIMER0_OVERFLOW) | (IEEE802154_EVENT_TIMER1_OVERFLOW)); ieee802154_ll_disable_events(IEEE802154_EVENT_TIMER0_OVERFLOW);
#endif #endif
ieee802154_ll_enable_tx_abort_events(BIT(IEEE802154_TX_ABORT_BY_RX_ACK_TIMEOUT - 1) | BIT(IEEE802154_TX_ABORT_BY_TX_COEX_BREAK - 1) | BIT(IEEE802154_TX_ABORT_BY_TX_SECURITY_ERROR - 1) | BIT(IEEE802154_TX_ABORT_BY_CCA_FAILED - 1) | BIT(IEEE802154_TX_ABORT_BY_CCA_BUSY - 1)); ieee802154_ll_enable_tx_abort_events(BIT(IEEE802154_TX_ABORT_BY_RX_ACK_TIMEOUT - 1) | BIT(IEEE802154_TX_ABORT_BY_TX_COEX_BREAK - 1) | BIT(IEEE802154_TX_ABORT_BY_TX_SECURITY_ERROR - 1) | BIT(IEEE802154_TX_ABORT_BY_CCA_FAILED - 1) | BIT(IEEE802154_TX_ABORT_BY_CCA_BUSY - 1));
ieee802154_ll_enable_rx_abort_events(BIT(IEEE802154_RX_ABORT_BY_TX_ACK_TIMEOUT - 1) | BIT(IEEE802154_RX_ABORT_BY_TX_ACK_COEX_BREAK - 1)); ieee802154_ll_enable_rx_abort_events(BIT(IEEE802154_RX_ABORT_BY_TX_ACK_TIMEOUT - 1) | BIT(IEEE802154_RX_ABORT_BY_TX_ACK_COEX_BREAK - 1));
@ -902,16 +911,10 @@ esp_err_t ieee802154_transmit(const uint8_t *frame, bool cca)
return ieee802154_transmit_internal(frame, cca); return ieee802154_transmit_internal(frame, cca);
} }
IEEE802154_NOINLINE static bool is_target_time_expired(uint32_t target, uint32_t now)
{
return (((now - target) & (1 << 31)) == 0);
}
esp_err_t ieee802154_transmit_at(const uint8_t *frame, bool cca, uint32_t time) esp_err_t ieee802154_transmit_at(const uint8_t *frame, bool cca, uint32_t time)
{ {
ESP_RETURN_ON_FALSE(frame[0] <= 127, ESP_ERR_INVALID_ARG, IEEE802154_TAG, "Invalid frame length."); ESP_RETURN_ON_FALSE(frame[0] <= 127, ESP_ERR_INVALID_ARG, IEEE802154_TAG, "Invalid frame length.");
uint32_t tx_target_time; uint32_t tx_target_time;
uint32_t current_time;
IEEE802154_RF_ENABLE(); IEEE802154_RF_ENABLE();
tx_init(frame); tx_init(frame);
IEEE802154_SET_TXRX_PTI(IEEE802154_SCENE_TX_AT); IEEE802154_SET_TXRX_PTI(IEEE802154_SCENE_TX_AT);
@ -921,9 +924,7 @@ esp_err_t ieee802154_transmit_at(const uint8_t *frame, bool cca, uint32_t time)
ieee802154_set_state(IEEE802154_STATE_TX_CCA); ieee802154_set_state(IEEE802154_STATE_TX_CCA);
ieee802154_enter_critical(); ieee802154_enter_critical();
ieee802154_etm_set_event_task(IEEE802154_ETM_CHANNEL0, ETM_EVENT_TIMER0_OVERFLOW, ETM_TASK_ED_TRIG_TX); ieee802154_etm_set_event_task(IEEE802154_ETM_CHANNEL0, ETM_EVENT_TIMER0_OVERFLOW, ETM_TASK_ED_TRIG_TX);
current_time = (uint32_t)esp_timer_get_time(); ieee802154_timer0_fire_at(tx_target_time);
ieee802154_timer0_set_threshold((is_target_time_expired(tx_target_time, current_time) ? 0 : (tx_target_time - current_time))); //uint: 1us
ieee802154_timer0_start();
ieee802154_exit_critical(); ieee802154_exit_critical();
} else { } else {
tx_target_time = time - IEEE802154_TX_RAMPUP_TIME_US; tx_target_time = time - IEEE802154_TX_RAMPUP_TIME_US;
@ -934,9 +935,7 @@ esp_err_t ieee802154_transmit_at(const uint8_t *frame, bool cca, uint32_t time)
} }
ieee802154_enter_critical(); ieee802154_enter_critical();
ieee802154_etm_set_event_task(IEEE802154_ETM_CHANNEL0, ETM_EVENT_TIMER0_OVERFLOW, ETM_TASK_TX_START); ieee802154_etm_set_event_task(IEEE802154_ETM_CHANNEL0, ETM_EVENT_TIMER0_OVERFLOW, ETM_TASK_TX_START);
current_time = (uint32_t)esp_timer_get_time(); ieee802154_timer0_fire_at(tx_target_time);
ieee802154_timer0_set_threshold((is_target_time_expired(tx_target_time, current_time) ? 0 : (tx_target_time - current_time))); //uint: 1us
ieee802154_timer0_start();
ieee802154_exit_critical(); ieee802154_exit_critical();
} }
@ -964,20 +963,34 @@ esp_err_t ieee802154_receive(void)
return ESP_OK; return ESP_OK;
} }
esp_err_t ieee802154_receive_at(uint32_t time) IEEE802154_NOINLINE static void ieee802154_finish_receive_at(void* ctx)
{ {
uint32_t rx_target_time = time - IEEE802154_RX_RAMPUP_TIME_US; (void)ctx;
uint32_t current_time; stop_current_operation();
esp_ieee802154_receive_at_done();
}
IEEE802154_NOINLINE static void ieee802154_start_receive_at(void* ctx)
{
uint32_t rx_stop_time = (uint32_t)ctx;
ieee802154_timer1_fire_at_with_callback(rx_stop_time, ieee802154_finish_receive_at, NULL);
}
esp_err_t ieee802154_receive_at(uint32_t time, uint32_t duration)
{
// TODO: Light sleep current optimization, TZ-1613.
IEEE802154_RF_ENABLE(); IEEE802154_RF_ENABLE();
ieee802154_enter_critical(); ieee802154_enter_critical();
rx_init(); rx_init();
IEEE802154_SET_TXRX_PTI(IEEE802154_SCENE_RX_AT); IEEE802154_SET_TXRX_PTI(IEEE802154_SCENE_RX_AT);
set_next_rx_buffer(); set_next_rx_buffer();
ieee802154_set_state(IEEE802154_STATE_RX); ieee802154_set_state(IEEE802154_STATE_RX);
ieee802154_etm_set_event_task(IEEE802154_ETM_CHANNEL1, ETM_EVENT_TIMER0_OVERFLOW, ETM_TASK_RX_START); ieee802154_etm_set_event_task(IEEE802154_ETM_CHANNEL1, ETM_EVENT_TIMER1_OVERFLOW, ETM_TASK_RX_START);
current_time = (uint32_t)esp_timer_get_time(); if (duration) {
ieee802154_timer0_set_threshold((is_target_time_expired(rx_target_time, current_time) ? 0 : (rx_target_time - current_time))); //uint: 1us ieee802154_timer1_fire_at_with_callback(time - IEEE802154_RX_RAMPUP_TIME_US, ieee802154_start_receive_at, (void*)(time + duration));
ieee802154_timer0_start(); } else {
ieee802154_timer1_fire_at(time - IEEE802154_RX_RAMPUP_TIME_US);
}
ieee802154_exit_critical(); ieee802154_exit_critical();
return ESP_OK; return ESP_OK;
} }

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -9,6 +9,12 @@
#include "esp_check.h" #include "esp_check.h"
#include "esp_ieee802154_timer.h" #include "esp_ieee802154_timer.h"
#include "esp_ieee802154_util.h" #include "esp_ieee802154_util.h"
#include <stdbool.h>
static timer_callback_t s_timer0_callback = NULL;
static timer_callback_t s_timer1_callback = NULL;
static void* s_timer0_ctx = NULL;
static void* s_timer1_ctx = NULL;
void ieee802154_timer0_start(void) void ieee802154_timer0_start(void)
{ {
@ -17,6 +23,8 @@ void ieee802154_timer0_start(void)
void ieee802154_timer0_stop(void) void ieee802154_timer0_stop(void)
{ {
s_timer0_callback = NULL;
s_timer0_ctx = NULL;
ieee802154_ll_set_cmd(IEEE802154_CMD_TIMER0_STOP); ieee802154_ll_set_cmd(IEEE802154_CMD_TIMER0_STOP);
} }
@ -41,6 +49,8 @@ void ieee802154_timer1_start(void)
void ieee802154_timer1_stop(void) void ieee802154_timer1_stop(void)
{ {
s_timer1_callback = NULL;
s_timer1_ctx = NULL;
ieee802154_ll_set_cmd(IEEE802154_CMD_TIMER1_STOP); ieee802154_ll_set_cmd(IEEE802154_CMD_TIMER1_STOP);
} }
@ -57,3 +67,62 @@ uint32_t ieee802154_timer1_get_value(void)
{ {
return ieee802154_ll_timer1_get_value(); return ieee802154_ll_timer1_get_value();
} }
FORCE_INLINE_ATTR bool is_target_time_expired(uint32_t target, uint32_t now)
{
return (((now - target) & (1 << 31)) == 0);
}
void ieee802154_timer0_fire_at(uint32_t fire_time)
{
uint32_t current_time = (uint32_t)esp_timer_get_time();
ieee802154_timer0_set_threshold((is_target_time_expired(fire_time, current_time) ? 0 : (fire_time - current_time))); //uint: 1us
ieee802154_timer0_start();
}
void ieee802154_timer1_fire_at(uint32_t fire_time)
{
uint32_t current_time = (uint32_t)esp_timer_get_time();
ieee802154_timer1_set_threshold((is_target_time_expired(fire_time, current_time) ? 0 : (fire_time - current_time))); //uint: 1us
ieee802154_timer1_start();
}
void ieee802154_timer0_fire_at_with_callback(uint32_t fire_time, timer_callback_t timer0_cb, void *timer0_ctx)
{
s_timer0_callback = timer0_cb;
s_timer0_ctx = timer0_ctx;
ieee802154_timer0_fire_at(fire_time);
}
void ieee802154_timer1_fire_at_with_callback(uint32_t fire_time, timer_callback_t timer1_cb, void *timer1_ctx)
{
s_timer1_callback = timer1_cb;
s_timer1_ctx = timer1_ctx;
ieee802154_timer1_fire_at(fire_time);
}
void ieee802154_timer0_execute_callback(void)
{
timer_callback_t callback_tmp = s_timer0_callback; // tmp function used to allow new callback function to set a new callback without overwriting it
void* ctx_tmp = s_timer0_ctx;
s_timer0_callback = NULL;
s_timer0_ctx = NULL;
if (callback_tmp) {
callback_tmp(ctx_tmp);
}
}
void ieee802154_timer1_execute_callback(void)
{
timer_callback_t callback_tmp = s_timer1_callback; // tmp function used to allow new callback function to set a new callback without overwriting it
void* ctx_tmp = s_timer1_ctx;
s_timer1_callback = NULL;
s_timer1_ctx = NULL;
if (callback_tmp) {
callback_tmp(ctx_tmp);
}
}

View File

@ -66,7 +66,7 @@ void ieee802154_set_txrx_pti(ieee802154_txrx_scene_t txrx_scene)
// TZ-97: implement these two functions using ETM common interface // TZ-97: implement these two functions using ETM common interface
void ieee802154_etm_channel_clear(uint32_t channel) void ieee802154_etm_channel_clear(uint32_t channel)
{ {
if (!(REG_READ(ETM_CHEN_AD0_REG) & (1 << channel))) { if ((REG_READ(ETM_CHEN_AD0_REG) & (1 << channel))) {
REG_WRITE(ETM_CHENCLR_AD0_REG, (REG_READ(ETM_CHENCLR_AD0_REG)) | 1 << channel); REG_WRITE(ETM_CHENCLR_AD0_REG, (REG_READ(ETM_CHENCLR_AD0_REG)) | 1 << channel);
} }
} }

View File

@ -212,8 +212,7 @@ esp_err_t esp_ieee802154_set_multipan_enable(uint8_t mask)
ieee802154_ll_set_multipan_enable_mask(mask); ieee802154_ll_set_multipan_enable_mask(mask);
return ESP_OK; return ESP_OK;
} }
#endif // CONFIG_IEEE802154_MULTI_PAN_ENABLE
#else
esp_err_t esp_ieee802154_set_ack_timeout(uint32_t timeout) esp_err_t esp_ieee802154_set_ack_timeout(uint32_t timeout)
{ {
@ -265,8 +264,6 @@ esp_err_t esp_ieee802154_set_extended_address(const uint8_t *ext_addr)
return ESP_OK; return ESP_OK;
} }
#endif // CONFIG_IEEE802154_MULTI_PAN_ENABLE
esp_ieee802154_pending_mode_t esp_ieee802154_get_pending_mode(void) esp_ieee802154_pending_mode_t esp_ieee802154_get_pending_mode(void)
{ {
return ieee802154_pib_get_pending_mode(); return ieee802154_pib_get_pending_mode();
@ -309,9 +306,9 @@ esp_err_t esp_ieee802154_receive(void)
return ieee802154_receive(); return ieee802154_receive();
} }
esp_err_t esp_ieee802154_receive_at(uint32_t time) esp_err_t esp_ieee802154_receive_at(uint32_t time, uint32_t duration)
{ {
return ieee802154_receive_at(time); return ieee802154_receive_at(time, duration);
} }
esp_err_t esp_ieee802154_energy_detect(uint32_t duration) esp_err_t esp_ieee802154_energy_detect(uint32_t duration)
@ -338,6 +335,7 @@ esp_ieee802154_state_t esp_ieee802154_get_state(void)
case IEEE802154_STATE_RX: case IEEE802154_STATE_RX:
case IEEE802154_STATE_TX_ACK: case IEEE802154_STATE_TX_ACK:
case IEEE802154_STATE_TX_ENH_ACK:
case IEEE802154_STATE_ED: case IEEE802154_STATE_ED:
return ESP_IEEE802154_RADIO_RECEIVE; return ESP_IEEE802154_RADIO_RECEIVE;
@ -345,7 +343,6 @@ esp_ieee802154_state_t esp_ieee802154_get_state(void)
case IEEE802154_STATE_CCA: case IEEE802154_STATE_CCA:
case IEEE802154_STATE_TX: case IEEE802154_STATE_TX:
case IEEE802154_STATE_RX_ACK: case IEEE802154_STATE_RX_ACK:
case IEEE802154_STATE_TX_ENH_ACK:
return ESP_IEEE802154_RADIO_TRANSMIT; return ESP_IEEE802154_RADIO_TRANSMIT;
default: default:
@ -434,6 +431,10 @@ __attribute__((weak)) void esp_ieee802154_energy_detect_done(int8_t power)
__attribute__((weak)) void esp_ieee802154_ed_failed(uint16_t error) __attribute__((weak)) void esp_ieee802154_ed_failed(uint16_t error)
{ {
}
__attribute__((weak)) void esp_ieee802154_receive_at_done(void)
{
} }
__attribute__((weak)) esp_err_t esp_ieee802154_enh_ack_generator(uint8_t *frame, esp_ieee802154_frame_info_t *frame_info, uint8_t* enhack_frame) __attribute__((weak)) esp_err_t esp_ieee802154_enh_ack_generator(uint8_t *frame, esp_ieee802154_frame_info_t *frame_info, uint8_t* enhack_frame)
@ -442,16 +443,6 @@ __attribute__((weak)) esp_err_t esp_ieee802154_enh_ack_generator(uint8_t *frame,
return ESP_FAIL; return ESP_FAIL;
} }
__attribute__((weak)) void esp_ieee802154_timer0_done(void)
{
}
__attribute__((weak)) void esp_ieee802154_timer1_done(void)
{
}
#if CONFIG_IEEE802154_TXRX_STATISTIC #if CONFIG_IEEE802154_TXRX_STATISTIC
void esp_ieee802154_txrx_statistic_clear(void) void esp_ieee802154_txrx_statistic_clear(void)
{ {

View File

@ -588,18 +588,24 @@ extern void esp_ieee802154_transmit_sfd_done(uint8_t *frame);
extern void esp_ieee802154_energy_detect_done(int8_t power); extern void esp_ieee802154_energy_detect_done(int8_t power);
/** /**
* @brief Set the IEEE 802.15.4 Radio to receive state at a specific time. * @brief The receive window for receive_at has finished.
* *
* @note Radio will start receiving after the timestamp, and continue receiving until it receives a valid frame. */
* Refer to `esp_ieee802154_receive_done()`. extern void esp_ieee802154_receive_at_done(void);
/**
* @brief Set the IEEE 802.15.4 Radio to receive state at a specific time, for a specific duration.
* *
* @param[in] time A specific timestamp for starting receiving. * @note Radio will start receiving after the timestamp, and continue receiving for the specific duration.
*
* @param[in] time A specific timestamp for starting receiving.
* @param[in] duration A specific duration after which to stop receiving. Set duration = 0 to rx indefinitely.
* @return * @return
* - ESP_OK on success * - ESP_OK on success
* - ESP_FAIL on failure due to invalid state. * - ESP_FAIL on failure due to invalid state.
* *
*/ */
esp_err_t esp_ieee802154_receive_at(uint32_t time); esp_err_t esp_ieee802154_receive_at(uint32_t time, uint32_t duration);
/** /**
* @brief Transmit the given frame at a specific time. * @brief Transmit the given frame at a specific time.

View File

@ -4,30 +4,30 @@ entries:
if IEEE802154_ENABLED = y: if IEEE802154_ENABLED = y:
# When adding static functions here, add IEEE802154_NOINLINE attribute to them # When adding static functions here, add IEEE802154_NOINLINE attribute to them
esp_ieee802154_ack: ieee802154_ack_config_pending_bit (noflash) esp_ieee802154_ack: ieee802154_ack_config_pending_bit (noflash)
esp_ieee802154_dev: ieee802154_rx_frame_info_update (noflash)
esp_ieee802154_dev: ieee802154_isr (noflash) esp_ieee802154_dev: ieee802154_isr (noflash)
esp_ieee802154_dev: ieee802154_rx_frame_info_update (noflash)
esp_ieee802154_event: ieee802154_inner_energy_detect_done (noflash)
esp_ieee802154_event: ieee802154_inner_enh_ack_generator (noflash)
esp_ieee802154_event: ieee802154_inner_receive_done (noflash) esp_ieee802154_event: ieee802154_inner_receive_done (noflash)
esp_ieee802154_event: ieee802154_inner_receive_sfd_done (noflash) esp_ieee802154_event: ieee802154_inner_receive_sfd_done (noflash)
esp_ieee802154_event: ieee802154_inner_transmit_done (noflash) esp_ieee802154_event: ieee802154_inner_transmit_done (noflash)
esp_ieee802154_event: ieee802154_inner_transmit_failed (noflash) esp_ieee802154_event: ieee802154_inner_transmit_failed (noflash)
esp_ieee802154_event: ieee802154_inner_transmit_sfd_done (noflash) esp_ieee802154_event: ieee802154_inner_transmit_sfd_done (noflash)
esp_ieee802154_event: ieee802154_inner_energy_detect_done (noflash) esp_ieee802154_frame: ieee802154_frame_get_security_field_len (noflash)
esp_ieee802154_event: ieee802154_inner_enh_ack_generator (noflash) esp_ieee802154_frame: ieee802154_frame_get_security_payload_offset (noflash)
esp_ieee802154_frame: ieee802154_frame_get_src_addr (noflash)
esp_ieee802154_frame: ieee802154_frame_security_header_offset (noflash)
esp_ieee802154_frame: is_dst_panid_present (noflash) esp_ieee802154_frame: is_dst_panid_present (noflash)
esp_ieee802154_frame: is_src_panid_present (noflash) esp_ieee802154_frame: is_src_panid_present (noflash)
esp_ieee802154_frame: ieee802154_frame_security_header_offset (noflash)
esp_ieee802154_frame: ieee802154_frame_get_security_field_len (noflash)
esp_ieee802154_frame: ieee802154_frame_get_src_addr (noflash)
esp_ieee802154_frame: ieee802154_frame_get_security_payload_offset (noflash)
esp_ieee802154_pib: ieee802154_pib_get_pending_mode (noflash) esp_ieee802154_pib: ieee802154_pib_get_pending_mode (noflash)
esp_ieee802154_pib: ieee802154_pib_get_rx_when_idle (noflash) esp_ieee802154_pib: ieee802154_pib_get_rx_when_idle (noflash)
esp_ieee802154_sec: ieee802154_transmit_security_config (noflash)
esp_ieee802154_sec: ieee802154_sec_update (noflash) esp_ieee802154_sec: ieee802154_sec_update (noflash)
esp_ieee802154_sec: ieee802154_transmit_security_config (noflash)
esp_ieee802154_timer: ieee802154_timer0_set_threshold (noflash) esp_ieee802154_timer: ieee802154_timer0_set_threshold (noflash)
esp_ieee802154_timer: ieee802154_timer1_set_threshold (noflash)
esp_ieee802154_timer: ieee802154_timer0_start (noflash) esp_ieee802154_timer: ieee802154_timer0_start (noflash)
esp_ieee802154_timer: ieee802154_timer1_start (noflash)
esp_ieee802154_timer: ieee802154_timer0_stop (noflash) esp_ieee802154_timer: ieee802154_timer0_stop (noflash)
esp_ieee802154_timer: ieee802154_timer1_set_threshold (noflash)
esp_ieee802154_timer: ieee802154_timer1_start (noflash)
esp_ieee802154_timer: ieee802154_timer1_stop (noflash) esp_ieee802154_timer: ieee802154_timer1_stop (noflash)
esp_ieee802154_util: ieee802154_etm_channel_clear (noflash) esp_ieee802154_util: ieee802154_etm_channel_clear (noflash)
@ -35,35 +35,38 @@ entries:
esp_ieee802154_debug (noflash) esp_ieee802154_debug (noflash)
if IEEE802154_TIMING_OPTIMIZATION = y: if IEEE802154_TIMING_OPTIMIZATION = y:
esp_ieee802154_dev: set_next_rx_buffer (noflash)
esp_ieee802154_dev: stop_rx (noflash)
esp_ieee802154_dev: stop_tx_ack (noflash)
esp_ieee802154_dev: stop_tx (noflash)
esp_ieee802154_dev: stop_cca (noflash)
esp_ieee802154_dev: stop_tx_cca (noflash)
esp_ieee802154_dev: stop_rx_ack (noflash)
esp_ieee802154_dev: stop_ed (noflash)
esp_ieee802154_dev: stop_current_operation (noflash)
esp_ieee802154_dev: is_target_time_expired (noflash)
esp_ieee802154_dev: ieee802154_transmit_at (noflash)
esp_ieee802154_dev: ieee802154_receive_at (noflash)
esp_ieee802154_dev: ieee802154_transmit (noflash)
esp_ieee802154_dev: ieee802154_receive (noflash)
esp_ieee802154_pib: ieee802154_pib_update (noflash)
esp_ieee802154_pib: ieee802154_txpower_convert (noflash)
esp_ieee802154_util: ieee802154_channel_to_freq (noflash)
esp_ieee802154: esp_ieee802154_transmit_at (noflash)
esp_ieee802154: esp_ieee802154_receive_at (noflash)
esp_ieee802154: esp_ieee802154_transmit (noflash)
esp_ieee802154: esp_ieee802154_receive (noflash)
if OPENTHREAD_CSL_ENABLE = y || OPENTHREAD_LINK_METRICS = y:
esp_ieee802154: esp_ieee802154_enh_ack_generator (noflash) esp_ieee802154: esp_ieee802154_enh_ack_generator (noflash)
esp_ieee802154: esp_ieee802154_get_extended_address (noflash) esp_ieee802154: esp_ieee802154_get_extended_address (noflash)
esp_ieee802154: esp_ieee802154_set_transmit_security (noflash)
if OPENTHREAD_LINK_METRICS = y:
esp_ieee802154: esp_ieee802154_get_recent_lqi (noflash) esp_ieee802154: esp_ieee802154_get_recent_lqi (noflash)
esp_ieee802154: esp_ieee802154_get_recent_rssi (noflash) esp_ieee802154: esp_ieee802154_get_recent_rssi (noflash)
esp_ieee802154_dev: ieee802154_get_recent_rssi (noflash) esp_ieee802154: esp_ieee802154_receive (noflash)
esp_ieee802154: esp_ieee802154_receive_at (noflash)
esp_ieee802154: esp_ieee802154_set_transmit_security (noflash)
esp_ieee802154: esp_ieee802154_transmit (noflash)
esp_ieee802154: esp_ieee802154_transmit_at (noflash)
esp_ieee802154_dev: ieee802154_finish_receive_at (noflash)
esp_ieee802154_dev: ieee802154_get_recent_lqi (noflash) esp_ieee802154_dev: ieee802154_get_recent_lqi (noflash)
esp_ieee802154_dev: ieee802154_get_recent_rssi (noflash)
esp_ieee802154_dev: ieee802154_receive (noflash)
esp_ieee802154_dev: ieee802154_receive_at (noflash)
esp_ieee802154_dev: ieee802154_start_receive_at (noflash)
esp_ieee802154_dev: ieee802154_transmit (noflash)
esp_ieee802154_dev: ieee802154_transmit_at (noflash)
esp_ieee802154_dev: set_next_rx_buffer (noflash)
esp_ieee802154_dev: stop_cca (noflash)
esp_ieee802154_dev: stop_current_operation (noflash)
esp_ieee802154_dev: stop_ed (noflash)
esp_ieee802154_dev: stop_rx (noflash)
esp_ieee802154_dev: stop_rx_ack (noflash)
esp_ieee802154_dev: stop_tx (noflash)
esp_ieee802154_dev: stop_tx_ack (noflash)
esp_ieee802154_dev: stop_tx_cca (noflash)
esp_ieee802154_pib: ieee802154_pib_update (noflash)
esp_ieee802154_pib: ieee802154_txpower_convert (noflash)
esp_ieee802154_timer: ieee802154_timer0_execute_callback (noflash)
esp_ieee802154_timer: ieee802154_timer0_fire_at (noflash)
esp_ieee802154_timer: ieee802154_timer0_fire_at_with_callback (noflash)
esp_ieee802154_timer: ieee802154_timer1_execute_callback (noflash)
esp_ieee802154_timer: ieee802154_timer1_fire_at (noflash)
esp_ieee802154_timer: ieee802154_timer1_fire_at_with_callback (noflash)
esp_ieee802154_util: ieee802154_channel_to_freq (noflash)

View File

@ -141,10 +141,11 @@ esp_err_t ieee802154_receive_handle_done(const uint8_t* frame);
esp_err_t ieee802154_transmit_at(const uint8_t *frame, bool cca, uint32_t time); esp_err_t ieee802154_transmit_at(const uint8_t *frame, bool cca, uint32_t time);
/** /**
* @brief Set the IEEE 802.15.4 Radio to receive state at a specific time. * @brief Set the IEEE 802.15.4 Radio to receive state at a specific time, for a specific duration.
* *
* *
* @param[in] time A specific timestamp for starting receiving. * @param[in] time A specific timestamp for starting receiving.
* @param[in] duration A specific duration after which to stop receiving. Set duration = 0 to rx indefinitely.
* @return * @return
* - ESP_OK on success * - ESP_OK on success
* - ESP_FAIL on failure due to invalid state. * - ESP_FAIL on failure due to invalid state.
@ -153,7 +154,7 @@ esp_err_t ieee802154_transmit_at(const uint8_t *frame, bool cca, uint32_t time);
* Ref to esp_ieee802154_receive_done(). * Ref to esp_ieee802154_receive_done().
* *
*/ */
esp_err_t ieee802154_receive_at(uint32_t time); esp_err_t ieee802154_receive_at(uint32_t time, uint32_t duration);
/** /**
* @brief Set the IEEE 802.15.4 Radio to sleep state. * @brief Set the IEEE 802.15.4 Radio to sleep state.
@ -263,8 +264,6 @@ bool ieee802154_mac_is_inited(void);
#if CONFIG_IEEE802154_TEST #if CONFIG_IEEE802154_TEST
#define IEEE802154_STATIC #define IEEE802154_STATIC
#define IEEE802154_INLINE #define IEEE802154_INLINE
extern void esp_ieee802154_timer0_done(void);
extern void esp_ieee802154_timer1_done(void);
#else #else
#define IEEE802154_STATIC static #define IEEE802154_STATIC static
#define IEEE802154_INLINE inline #define IEEE802154_INLINE inline

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -79,6 +79,44 @@ esp_err_t ieee802154_timer1_set_threshold(uint32_t value);
*/ */
uint32_t ieee802154_timer1_get_value(void); uint32_t ieee802154_timer1_get_value(void);
/**
* @brief Set timer0 to fire at specific time.
*
*/
void ieee802154_timer0_fire_at(uint32_t fire_time);
/**
* @brief Set timer1 to fire at specific time.
*
*/
void ieee802154_timer1_fire_at(uint32_t fire_time);
typedef void (*timer_callback_t)(void* ctx);
/**
* @brief Set timer0 to fire at specific time with callback.
*
*/
void ieee802154_timer0_fire_at_with_callback(uint32_t fire_time, timer_callback_t timer0_callback, void *timer0_ctx);
/**
* @brief Set timer1 to fire at specific time with callback.
*
*/
void ieee802154_timer1_fire_at_with_callback(uint32_t fire_time, timer_callback_t timer1_callback, void *timer1_ctx);
/**
* @brief Execute timer0 callback.
*
*/
void ieee802154_timer0_execute_callback(void);
/**
* @brief Execute timer1 callback.
*
*/
void ieee802154_timer1_execute_callback(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -259,6 +259,7 @@ menu "OpenThread"
config OPENTHREAD_LINK_METRICS config OPENTHREAD_LINK_METRICS
bool "Enable link metrics feature" bool "Enable link metrics feature"
default n default n
select IEEE802154_TIMING_OPTIMIZATION if IEEE802154_ENABLED
help help
Select this option to enable link metrics feature Select this option to enable link metrics feature
@ -271,6 +272,7 @@ menu "OpenThread"
config OPENTHREAD_CSL_ENABLE config OPENTHREAD_CSL_ENABLE
bool "Enable CSL feature" bool "Enable CSL feature"
default n default n
select IEEE802154_TIMING_OPTIMIZATION if IEEE802154_ENABLED
help help
Select this option to enable CSL feature Select this option to enable CSL feature
menu "CSL Configurations" menu "CSL Configurations"
@ -278,13 +280,13 @@ menu "OpenThread"
config OPENTHREAD_CSL_ACCURACY config OPENTHREAD_CSL_ACCURACY
int "The current CSL rx/tx scheduling drift, in units of ± ppm" int "The current CSL rx/tx scheduling drift, in units of ± ppm"
default 1 default 20
help help
The current accuracy of the clock used for scheduling CSL operations The current accuracy of the clock used for scheduling CSL operations
config OPENTHREAD_CSL_UNCERTAIN config OPENTHREAD_CSL_UNCERTAIN
int "The CSL Uncertainty in units of 10 us." int "The CSL Uncertainty in units of 10 us."
default 1 default 0
help help
The fixed uncertainty of the Device for scheduling CSL Transmissions in units of 10 microseconds. The fixed uncertainty of the Device for scheduling CSL Transmissions in units of 10 microseconds.
@ -374,7 +376,7 @@ menu "OpenThread"
config OPENTHREAD_XTAL_ACCURACY config OPENTHREAD_XTAL_ACCURACY
int "The accuracy of the XTAL" int "The accuracy of the XTAL"
default 130 default 10
help help
The device's XTAL accuracy, in ppm. The device's XTAL accuracy, in ppm.

View File

@ -726,11 +726,21 @@
/** /**
* @def OPENTHREAD_CONFIG_MAC_CSL_REQUEST_AHEAD_US * @def OPENTHREAD_CONFIG_MAC_CSL_REQUEST_AHEAD_US
* *
* Define as 1 to set the ahead time for CSL transmit timing. * Define how many microseconds ahead should MAC deliver CSL frame to SubMac.
* *
*/ */
#ifndef OPENTHREAD_CONFIG_MAC_CSL_REQUEST_AHEAD_US #ifndef OPENTHREAD_CONFIG_MAC_CSL_REQUEST_AHEAD_US
#define OPENTHREAD_CONFIG_MAC_CSL_REQUEST_AHEAD_US 20000 #define OPENTHREAD_CONFIG_MAC_CSL_REQUEST_AHEAD_US (2 * 1000000 / CONFIG_FREERTOS_HZ)
#endif
/**
* @def OPENTHREAD_CONFIG_CSL_RECEIVE_TIME_AHEAD
*
* Reception scheduling and ramp up time needed for the CSL receiver to be ready, in units of microseconds.
*
*/
#ifndef OPENTHREAD_CONFIG_CSL_RECEIVE_TIME_AHEAD
#define OPENTHREAD_CONFIG_CSL_RECEIVE_TIME_AHEAD (OPENTHREAD_CONFIG_MAC_CSL_REQUEST_AHEAD_US + 320)
#endif #endif
/** /**

View File

@ -400,3 +400,52 @@
#ifndef OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_MARK_ECN_INTERVAL #ifndef OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_MARK_ECN_INTERVAL
#define OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_MARK_ECN_INTERVAL 1000 #define OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_MARK_ECN_INTERVAL 1000
#endif #endif
#ifdef OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
#error `OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE` is redefined.
#endif
#if CONFIG_OPENTHREAD_CSL_ENABLE
/**
* @def OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
*
* Define as 1 to support Thread 1.2 CSL feature.
*
*/
#define OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 1
/**
* @def OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE
*
* Define as 1 to enable support Thread 1.2 CSL debug.
*
*/
#ifdef OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE
#error `OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE` is redefined.
#endif
#define OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE CONFIG_OPENTHREAD_CSL_DEBUG_ENABLE
#else
#define OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 0
#endif // CONFIG_OPENTHREAD_CSL_ENABLE
/**
* @def OPENTHREAD_CONFIG_MAC_CSL_REQUEST_AHEAD_US
*
* Define how many microseconds ahead should MAC deliver CSL frame to SubMac.
*
*/
#ifndef OPENTHREAD_CONFIG_MAC_CSL_REQUEST_AHEAD_US
#define OPENTHREAD_CONFIG_MAC_CSL_REQUEST_AHEAD_US (2 * 1000000 / CONFIG_FREERTOS_HZ)
#endif
/**
* @def OPENTHREAD_CONFIG_CSL_RECEIVE_TIME_AHEAD
*
* Reception scheduling and ramp up time needed for the CSL receiver to be ready, in units of microseconds.
*
*/
#ifndef OPENTHREAD_CONFIG_CSL_RECEIVE_TIME_AHEAD
#define OPENTHREAD_CONFIG_CSL_RECEIVE_TIME_AHEAD (OPENTHREAD_CONFIG_MAC_CSL_REQUEST_AHEAD_US + 320)
#endif

View File

@ -47,6 +47,7 @@
#define EVENT_TX_FAILED (1 << 1) #define EVENT_TX_FAILED (1 << 1)
#define EVENT_RX_DONE (1 << 2) #define EVENT_RX_DONE (1 << 2)
#define EVENT_ENERGY_DETECT_DONE (1 << 3) #define EVENT_ENERGY_DETECT_DONE (1 << 3)
#define EVENT_SLEEP (1 << 4)
typedef struct { typedef struct {
uint8_t length; uint8_t length;
@ -241,6 +242,11 @@ esp_err_t esp_openthread_radio_process(otInstance *aInstance, const esp_openthre
} }
} }
if (get_event(EVENT_SLEEP)) {
clr_event(EVENT_SLEEP);
esp_ieee802154_sleep();
}
return ESP_OK; return ESP_OK;
} }
@ -312,7 +318,11 @@ otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame)
aFrame->mPsdu[-1] = aFrame->mLength; // length locates one byte before the psdu (esp_openthread_radio_tx_psdu); aFrame->mPsdu[-1] = aFrame->mLength; // length locates one byte before the psdu (esp_openthread_radio_tx_psdu);
if (otMacFrameIsSecurityEnabled(aFrame) && !aFrame->mInfo.mTxInfo.mIsSecurityProcessed) { if (otMacFrameIsSecurityEnabled(aFrame) && !aFrame->mInfo.mTxInfo.mIsSecurityProcessed) {
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
if (!s_transmit_frame.mInfo.mTxInfo.mIsARetx || s_csl_period > 0) {
#else
if (!s_transmit_frame.mInfo.mTxInfo.mIsARetx) { if (!s_transmit_frame.mInfo.mTxInfo.mIsARetx) {
#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
otMacFrameSetFrameCounter(aFrame, s_mac_frame_counter++); otMacFrameSetFrameCounter(aFrame, s_mac_frame_counter++);
} }
if (otMacFrameIsKeyIdMode1(aFrame)) { if (otMacFrameIsKeyIdMode1(aFrame)) {
@ -362,7 +372,8 @@ otRadioCaps otPlatRadioGetCaps(otInstance *aInstance)
otError otPlatRadioReceiveAt(otInstance *aInstance, uint8_t aChannel, uint32_t aStart, uint32_t aDuration) otError otPlatRadioReceiveAt(otInstance *aInstance, uint8_t aChannel, uint32_t aStart, uint32_t aDuration)
{ {
esp_ieee802154_receive_at((aStart + aDuration)); esp_ieee802154_set_channel(aChannel);
esp_ieee802154_receive_at(aStart, aDuration);
return OT_ERROR_NONE; return OT_ERROR_NONE;
} }
@ -826,3 +837,8 @@ esp_ieee802154_coex_config_t esp_openthread_get_coex_config(void)
return esp_ieee802154_get_coex_config(); return esp_ieee802154_get_coex_config();
} }
#endif #endif
void esp_ieee802154_receive_at_done(void)
{
set_event(EVENT_SLEEP);
}