Skip to content

Commit

Permalink
Merge branch 'feature/154_api_enhancement_for_mp_v5.1' into 'release/…
Browse files Browse the repository at this point in the history
…v5.1'

feat(802.15.4): support register isr callback (v5.1)

See merge request espressif/esp-idf!36201
  • Loading branch information
chshu committed Jan 8, 2025
2 parents 8c1e948 + 6d28fb7 commit 4a83e6b
Show file tree
Hide file tree
Showing 9 changed files with 326 additions and 21 deletions.
1 change: 1 addition & 0 deletions components/ieee802154/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ if(CONFIG_IEEE802154_ENABLED)
list(APPEND srcs "esp_ieee802154.c"
"driver/esp_ieee802154_ack.c"
"driver/esp_ieee802154_dev.c"
"driver/esp_ieee802154_event.c"
"driver/esp_ieee802154_frame.c"
"driver/esp_ieee802154_pib.c"
"driver/esp_ieee802154_util.c"
Expand Down
46 changes: 26 additions & 20 deletions components/ieee802154/driver/esp_ieee802154_dev.c
Original file line number Diff line number Diff line change
@@ -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
*/
Expand All @@ -18,6 +18,7 @@
#include "esp_timer.h"
#include "esp_ieee802154_ack.h"
#include "esp_ieee802154_dev.h"
#include "esp_ieee802154_event.h"
#include "esp_ieee802154_frame.h"
#include "esp_ieee802154_pib.h"
#include "esp_ieee802154_sec.h"
Expand Down Expand Up @@ -93,7 +94,7 @@ static void ieee802154_receive_done(uint8_t *data, esp_ieee802154_frame_info_t *
// Ignore bit8 for the frame length, due to the max frame length is 127 based 802.15.4 spec.
data[0] = data[0] & 0x7f;
frame_info->process = true;
esp_ieee802154_receive_done(data, frame_info);
ieee802154_inner_receive_done(data, frame_info);
}
}

Expand All @@ -102,13 +103,13 @@ static void ieee802154_transmit_done(const uint8_t *frame, const uint8_t *ack, e
if (ack && ack_frame_info) {
IEEE802154_RX_BUFFER_STAT_IS_FREE(false);
if (s_rx_index == CONFIG_IEEE802154_RX_BUFFER_SIZE) {
esp_ieee802154_transmit_failed(frame, ESP_IEEE802154_TX_ERR_NO_ACK);
ieee802154_inner_transmit_failed(frame, ESP_IEEE802154_TX_ERR_NO_ACK);
} else {
ack_frame_info->process = true;
esp_ieee802154_transmit_done(frame, ack, ack_frame_info);
ieee802154_inner_transmit_done(frame, ack, ack_frame_info);
}
} else {
esp_ieee802154_transmit_done(frame, ack, ack_frame_info);
ieee802154_inner_transmit_done(frame, ack, ack_frame_info);
}
}

Expand Down Expand Up @@ -240,7 +241,7 @@ IEEE802154_NOINLINE static bool stop_tx(void)
// if the tx is already done, and the frame is not ack request OR auto ack rx is disabled.
ieee802154_transmit_done(s_tx_frame, NULL, NULL);
} else {
esp_ieee802154_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_ABORT);
ieee802154_inner_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_ABORT);
}

ieee802154_ll_clear_events(IEEE802154_EVENT_TX_DONE | IEEE802154_EVENT_TX_ABORT | IEEE802154_EVENT_TX_SFD_DONE);
Expand Down Expand Up @@ -276,7 +277,7 @@ IEEE802154_NOINLINE static bool stop_rx_ack(void)
if (events & IEEE802154_EVENT_ACK_RX_DONE) {
ieee802154_transmit_done(s_tx_frame, (uint8_t *)&s_rx_frame[s_rx_index], &s_rx_frame_info[s_rx_index]);
} else {
esp_ieee802154_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_NO_ACK);
ieee802154_inner_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_NO_ACK);
}

ieee802154_ll_clear_events(IEEE802154_EVENT_ACK_RX_DONE | IEEE802154_EVENT_RX_SFD_DONE | IEEE802154_EVENT_TX_ABORT);
Expand Down Expand Up @@ -397,7 +398,7 @@ static void isr_handle_timer0_done(void)
{
#if !CONFIG_IEEE802154_TEST
if (s_ieee802154_state == IEEE802154_STATE_RX_ACK) {
esp_ieee802154_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_NO_ACK);
ieee802154_inner_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_NO_ACK);
NEEDS_NEXT_OPT(true);
}
#else
Expand Down Expand Up @@ -451,7 +452,7 @@ static IRAM_ATTR void isr_handle_rx_done(void)
&& ieee802154_ll_get_tx_enhance_ack()) {
s_rx_frame_info[s_rx_index].pending = ieee802154_ack_config_pending_bit(s_rx_frame[s_rx_index]);
// For 2015 enh-ack, SW should generate an enh-ack then send it manually
if (esp_ieee802154_enh_ack_generator(s_rx_frame[s_rx_index], &s_rx_frame_info[s_rx_index], s_enh_ack_frame) == ESP_OK) {
if (ieee802154_inner_enh_ack_generator(s_rx_frame[s_rx_index], &s_rx_frame_info[s_rx_index], s_enh_ack_frame) == ESP_OK) {
extcoex_tx_stage_start();
#if !CONFIG_IEEE802154_TEST
// Send the Enh-Ack frame if generator succeeds.
Expand Down Expand Up @@ -590,14 +591,14 @@ static IRAM_ATTR void isr_handle_tx_abort(ieee802154_ll_tx_abort_reason_t tx_abo
case IEEE802154_TX_ABORT_BY_RX_ACK_TYPE_NOT_ACK:
case IEEE802154_TX_ABORT_BY_RX_ACK_RESTART:
IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_RX_ACK);
esp_ieee802154_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_INVALID_ACK);
ieee802154_inner_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_INVALID_ACK);
NEEDS_NEXT_OPT(false);
break;
// The above events are only used in test mode.
case IEEE802154_TX_ABORT_BY_RX_ACK_TIMEOUT:
IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_RX_ACK);
ieee802154_ll_disable_events(IEEE802154_EVENT_TIMER0_OVERFLOW);
esp_ieee802154_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_NO_ACK);
ieee802154_inner_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_NO_ACK);
NEEDS_NEXT_OPT(true);
break;
case IEEE802154_TX_ABORT_BY_TX_COEX_BREAK:
Expand All @@ -606,22 +607,22 @@ static IRAM_ATTR void isr_handle_tx_abort(ieee802154_ll_tx_abort_reason_t tx_abo
#endif
IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_TX || s_ieee802154_state == IEEE802154_STATE_TX_CCA);
IEEE802154_TX_BREAK_COEX_NUMS_UPDATE();
esp_ieee802154_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_COEXIST);
ieee802154_inner_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_COEXIST);
NEEDS_NEXT_OPT(true);
break;
case IEEE802154_TX_ABORT_BY_TX_SECURITY_ERROR:
IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_TX || s_ieee802154_state == IEEE802154_STATE_TX_CCA);
esp_ieee802154_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_SECURITY);
ieee802154_inner_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_SECURITY);
NEEDS_NEXT_OPT(true);
break;
case IEEE802154_TX_ABORT_BY_CCA_FAILED:
IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_TX_CCA);
esp_ieee802154_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_ABORT);
ieee802154_inner_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_ABORT);
NEEDS_NEXT_OPT(true);
break;
case IEEE802154_TX_ABORT_BY_CCA_BUSY:
IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_TX_CCA);
esp_ieee802154_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_CCA_BUSY);
ieee802154_inner_transmit_failed(s_tx_frame, ESP_IEEE802154_TX_ERR_CCA_BUSY);
NEEDS_NEXT_OPT(true);
break;
default:
Expand All @@ -635,18 +636,18 @@ static IRAM_ATTR void isr_handle_ed_done(void)
if (s_ieee802154_state == IEEE802154_STATE_CCA) {
esp_ieee802154_cca_done(ieee802154_ll_is_cca_busy());
} else if (s_ieee802154_state == IEEE802154_STATE_ED) {
esp_ieee802154_energy_detect_done(ieee802154_ll_get_ed_rss());
ieee802154_inner_energy_detect_done(ieee802154_ll_get_ed_rss());
}

NEEDS_NEXT_OPT(true);
}

IEEE802154_STATIC IRAM_ATTR void ieee802154_enter_critical(void)
IRAM_ATTR void ieee802154_enter_critical(void)
{
portENTER_CRITICAL(&s_ieee802154_spinlock);
}

IEEE802154_STATIC IRAM_ATTR void ieee802154_exit_critical(void)
IRAM_ATTR void ieee802154_exit_critical(void)
{
portEXIT_CRITICAL(&s_ieee802154_spinlock);
}
Expand All @@ -672,7 +673,7 @@ IEEE802154_NOINLINE static void ieee802154_isr(void *arg)
IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_RX || s_ieee802154_state == IEEE802154_STATE_RX_ACK || s_ieee802154_state == IEEE802154_STATE_TX || s_ieee802154_state == IEEE802154_STATE_TX_CCA || s_ieee802154_state == IEEE802154_STATE_TX_ENH_ACK);

s_rx_frame_info[s_rx_index].timestamp = esp_timer_get_time();
esp_ieee802154_receive_sfd_done();
ieee802154_inner_receive_sfd_done();

events &= (uint16_t)(~IEEE802154_EVENT_RX_SFD_DONE);
}
Expand All @@ -681,7 +682,7 @@ IEEE802154_NOINLINE static void ieee802154_isr(void *arg)
// ZB-81: IEEE802154_STATE_TX_ACK is also a possible state
IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_TX || s_ieee802154_state == IEEE802154_STATE_TX_CCA || s_ieee802154_state == IEEE802154_STATE_TEST_TX || s_ieee802154_state == IEEE802154_STATE_TX_ENH_ACK || s_ieee802154_state == IEEE802154_STATE_TX_ACK);

esp_ieee802154_transmit_sfd_done(s_tx_frame);
ieee802154_inner_transmit_sfd_done(s_tx_frame);

events &= (uint16_t)(~IEEE802154_EVENT_TX_SFD_DONE);
}
Expand Down Expand Up @@ -832,6 +833,11 @@ esp_err_t ieee802154_mac_deinit(void)
return ret;
}

bool ieee802154_mac_is_inited(void)
{
return s_ieee802154_isr_handle != NULL;
}

IEEE802154_STATIC void start_ed(uint32_t duration)
{
ieee802154_ll_enable_events(IEEE802154_EVENT_ED_DONE);
Expand Down
94 changes: 94 additions & 0 deletions components/ieee802154/driver/esp_ieee802154_event.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <string.h>
#include "esp_check.h"
#include "esp_ieee802154_dev.h"
#include "esp_ieee802154_event.h"
#include "esp_ieee802154_types.h"
#include "esp_ieee802154_util.h"

static esp_ieee802154_event_cb_list_t s_event_cb_list;

esp_err_t ieee802154_event_callback_list_register(esp_ieee802154_event_cb_list_t cb_list)
{
ESP_RETURN_ON_FALSE(!ieee802154_mac_is_inited(), ESP_FAIL, IEEE802154_TAG,
"The event callback register function should be called when the IEEE 802.15.4 subsystem is disabled");
memcpy((void*)(&s_event_cb_list), (void*)(&cb_list), sizeof(esp_ieee802154_event_cb_list_t));
return ESP_OK;
}
esp_err_t ieee802154_event_callback_list_unregister(void)
{
ESP_RETURN_ON_FALSE(!ieee802154_mac_is_inited(), ESP_FAIL, IEEE802154_TAG,
"The event callback unregister function should be called when the IEEE 802.15.4 subsystem is disabled");
memset((void*)(&s_event_cb_list), 0, sizeof(esp_ieee802154_event_cb_list_t));
return ESP_OK;
}

void ieee802154_inner_receive_done(uint8_t *data, esp_ieee802154_frame_info_t *frame_info)
{
if (s_event_cb_list.rx_done_cb) {
s_event_cb_list.rx_done_cb(data, frame_info);
} else {
esp_ieee802154_receive_done(data, frame_info);
}
}

void ieee802154_inner_receive_sfd_done(void)
{
if (s_event_cb_list.rx_sfd_done_cb) {
s_event_cb_list.rx_sfd_done_cb();
} else {
esp_ieee802154_receive_sfd_done();
}
}

void ieee802154_inner_transmit_done(const uint8_t *frame, const uint8_t *ack, esp_ieee802154_frame_info_t *ack_frame_info)
{
if (s_event_cb_list.tx_done_cb) {
s_event_cb_list.tx_done_cb(frame, ack, ack_frame_info);
} else {
esp_ieee802154_transmit_done(frame, ack, ack_frame_info);
}
}

void ieee802154_inner_transmit_failed(const uint8_t *frame, esp_ieee802154_tx_error_t error)
{
if (s_event_cb_list.tx_failed_cb) {
s_event_cb_list.tx_failed_cb(frame, error);
} else {
esp_ieee802154_transmit_failed(frame, error);
}
}

void ieee802154_inner_transmit_sfd_done(uint8_t *frame)
{
if (s_event_cb_list.tx_sfd_done_cb) {
s_event_cb_list.tx_sfd_done_cb(frame);
} else {
esp_ieee802154_transmit_sfd_done(frame);
}
}

void ieee802154_inner_energy_detect_done(int8_t power)
{
if (s_event_cb_list.ed_done_cb) {
s_event_cb_list.ed_done_cb(power);
} else {
esp_ieee802154_energy_detect_done(power);
}
}

esp_err_t ieee802154_inner_enh_ack_generator(uint8_t *frame, esp_ieee802154_frame_info_t *frame_info, uint8_t* enhack_frame)
{
esp_err_t err = ESP_FAIL;
if (s_event_cb_list.enh_ack_generator_cb) {
err = s_event_cb_list.enh_ack_generator_cb(frame, frame_info, enhack_frame);
} else {
err = esp_ieee802154_enh_ack_generator(frame, frame_info, enhack_frame);
}
return err;
}
10 changes: 10 additions & 0 deletions components/ieee802154/esp_ieee802154.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "esp_phy_init.h"
#include "esp_ieee802154_ack.h"
#include "esp_ieee802154_dev.h"
#include "esp_ieee802154_event.h"
#include "esp_ieee802154_frame.h"
#include "esp_ieee802154_pib.h"
#include "esp_ieee802154_sec.h"
Expand All @@ -21,6 +22,15 @@
#include "hal/ieee802154_ll.h"
#include "hal/ieee802154_common_ll.h"

esp_err_t esp_ieee802154_event_callback_list_register(esp_ieee802154_event_cb_list_t cb_list)
{
return ieee802154_event_callback_list_register(cb_list);
}
esp_err_t esp_ieee802154_event_callback_list_unregister(void)
{
return ieee802154_event_callback_list_unregister();
}

esp_err_t esp_ieee802154_enable(void)
{
ieee802154_enable();
Expand Down
26 changes: 26 additions & 0 deletions components/ieee802154/include/esp_ieee802154.h
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,32 @@ void esp_ieee802154_set_coex_config(esp_ieee802154_coex_config_t config);
esp_ieee802154_coex_config_t esp_ieee802154_get_coex_config(void);
#endif

/**
* @brief Register process callbacks for events generated by the IEEE 802.15.4 subsystem.
*
* @param[in] cb_list The event process callback list, please refer to `esp_ieee802154_event_cb_list_t`.
*
* @note This API should be called only when IEEE 802.15.4 subsystem is not enabled
* or after IEEE 802.15.4 subsystem is disabled (refer to `esp_ieee802154_disable`).
*
* @return
* - ESP_OK on success.
* - ESP_FAIL on failure.
*/
esp_err_t esp_ieee802154_event_callback_list_register(esp_ieee802154_event_cb_list_t cb_list);

/**
* @brief Unregister process callbacks for events generated by the IEEE 802.15.4 subsystem.
*
* @note This API should be called only when IEEE 802.15.4 subsystem is not enabled
* or after IEEE 802.15.4 subsystem is disabled (refer to `esp_ieee802154_disable`).
*
* @return
* - ESP_OK on success.
* - ESP_FAIL on failure.
*/
esp_err_t esp_ieee802154_event_callback_list_unregister(void);

#ifdef __cplusplus
}
#endif
Loading

0 comments on commit 4a83e6b

Please sign in to comment.