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

feat(802.15.4): ensure 154 txpower index changes linearly (v5.3)

See merge request espressif/esp-idf!46143
This commit is contained in:
Shu Chen
2026-03-25 04:07:58 +00:00
19 changed files with 354 additions and 182 deletions
@@ -9,8 +9,4 @@
#include <stdbool.h>
#include "hal/ieee802154_common_ll.h"
#define IEEE802154_TXPOWER_VALUE_MAX 20
#define IEEE802154_TXPOWER_VALUE_MIN -15
#define IEEE802154_TXPOWER_INDEX_MIN 3
#define IEEE802154_RSSI_COMPENSATION_VALUE 0
@@ -9,8 +9,4 @@
#include <stdbool.h>
#include "hal/ieee802154_common_ll.h"
#define IEEE802154_TXPOWER_VALUE_MAX 20
#define IEEE802154_TXPOWER_VALUE_MIN -15
#define IEEE802154_TXPOWER_INDEX_MIN 3
#define IEEE802154_RSSI_COMPENSATION_VALUE 0
@@ -15,10 +15,6 @@ extern "C" {
extern uint32_t bt_bb_get_rssi_comp(void);
#define IEEE802154_TXPOWER_VALUE_MAX 20
#define IEEE802154_TXPOWER_VALUE_MIN -24
#define IEEE802154_TXPOWER_INDEX_MIN 0
#define IEEE802154_RSSI_COMPENSATION_VALUE bt_bb_get_rssi_comp()
#ifdef __cplusplus
@@ -137,15 +137,17 @@ bool ieee802154_ack_config_pending_bit(const uint8_t *frame, const esp_ieee80215
// Only set the HW pending bit for the frames with version 0b00 or 0b01.
bool set_to_hw = (ieee802154_frame_get_version(frame) <= IEEE802154_FRAME_VERSION_1);
// Check SW should check whether the frame is data request or not.
bool sw_check_data_req = ieee802154_ll_get_pending_mode();
if (sw_check_data_req) {
// Check whether the frame is a Data Request.
if (ieee802154_ll_get_pending_mode()) {
pending_bit = ieee802154_is_data_request(frame);
}
ieee802154_ll_pending_mode_t pending_mode = ieee802154_pib_get_pending_mode(inf_index);
src_mode = ieee802154_frame_get_src_addr(frame, addr);
if (src_mode == IEEE802154_FRAME_INVALID_VALUE) {
goto exit;
}
switch (pending_mode) {
case IEEE802154_AUTO_PENDING_DISABLE:
// HW will check whether the frame is data request or not
@@ -153,20 +155,22 @@ bool ieee802154_ack_config_pending_bit(const uint8_t *frame, const esp_ieee80215
break;
case IEEE802154_AUTO_PENDING_ENABLE:
case IEEE802154_AUTO_PENDING_ENHANCED:
src_mode = ieee802154_frame_get_src_addr(frame, addr);
if (src_mode == IEEE802154_FRAME_SRC_MODE_SHORT || src_mode == IEEE802154_FRAME_SRC_MODE_EXT) {
pending_bit = ieee802154_addr_in_pending_table(inf_index, addr, src_mode == IEEE802154_FRAME_SRC_MODE_SHORT);
}
break;
case IEEE802154_AUTO_PENDING_ZIGBEE:
// If the address type is short and in pending table, set 'pending_bit' false, otherwise set true.
src_mode = ieee802154_frame_get_src_addr(frame, addr);
pending_bit = !(src_mode == IEEE802154_FRAME_SRC_MODE_SHORT && ieee802154_addr_in_pending_table(inf_index, addr, src_mode == IEEE802154_FRAME_SRC_MODE_SHORT));
pending_bit = true;
if (src_mode == IEEE802154_FRAME_SRC_MODE_SHORT && ieee802154_addr_in_pending_table(inf_index, addr, src_mode == IEEE802154_FRAME_SRC_MODE_SHORT)) {
pending_bit = false;
}
break;
default:
IEEE802154_ASSERT(false);
}
exit:
if (set_to_hw) {
ieee802154_ll_set_pending_bit(pending_bit);
}
@@ -77,6 +77,16 @@ static char *ieee802154_state_string[] = {
"ED",
"CCA",
};
static char *ieee802154_state_to_string(ieee802154_state_t state)
{
char *state_string = "INVALID";
if (state < sizeof(ieee802154_state_string) / sizeof(ieee802154_state_string[0])) {
state_string = ieee802154_state_string[state];
}
return state_string;
}
#endif // CONFIG_IEEE802154_RECORD_STATE
#if CONFIG_IEEE802154_RECORD_CMD
@@ -126,7 +136,7 @@ static char *ieee802154_get_cmd_string(ieee802154_ll_cmd_t cmd)
#endif // CONFIG_IEEE802154_RECORD_CMD
#if CONFIG_IEEE802154_RECORD_EVENT || CONFIG_IEEE802154_RECORD_ABORT
static char *ieee80154_rx_abort_reason_string[] = {
static char *ieee802154_rx_abort_reason_string[] = {
"RSVD", // = 0,
"RX_STOP", // = 1,
"SFD_TIMEOUT", // = 2,
@@ -148,7 +158,7 @@ static char *ieee80154_rx_abort_reason_string[] = {
"ED_COEX_REJECT", // = 26,
};
static char *ieee80154_tx_abort_reason_string[] = {
static char *ieee802154_tx_abort_reason_string[] = {
"RSVD", // = 0,
"RX_ACK_STOP", // = 1,
"RX_ACK_SFD_TIMEOUT", // = 2,
@@ -169,17 +179,47 @@ static char *ieee80154_tx_abort_reason_string[] = {
"CCA_BUSY", // = 25,
};
static char *ieee802154_abort_reason_to_string(ieee802154_ll_rx_abort_reason_t reason, bool is_tx_abort)
{
char *abort_reason_string = "UNKNOWN";
if (is_tx_abort) {
if (reason < sizeof(ieee802154_tx_abort_reason_string) / sizeof(ieee802154_tx_abort_reason_string[0])) {
abort_reason_string = ieee802154_tx_abort_reason_string[reason];
}
} else {
if (reason < sizeof(ieee802154_rx_abort_reason_string) / sizeof(ieee802154_rx_abort_reason_string[0])) {
abort_reason_string = ieee802154_rx_abort_reason_string[reason];
}
}
return abort_reason_string;
}
#endif // CONFIG_IEEE802154_RECORD_EVENT
#if CONFIG_IEEE802154_RECORD
#if CONFIG_IEEE802154_RECORD_TXRX_FRAME
static void ieee802154_dump_frame_print(const uint8_t *frame)
{
if (frame == NULL) {
ESP_EARLY_LOGW(IEEE802154_TAG, "Invalid frame, frame is NULL");
return;
}
if (frame[0] < IEEE802154_FRAME_MIN_LEN) {
ESP_EARLY_LOGW(IEEE802154_TAG, "Invalid frame, frame length is %d", frame[0]);
return;
}
for (uint8_t i = 1; i < frame[0]; i+=8) {
uint8_t end = (i + 7 < frame[0]) ? i + 7 : frame[0] - 1;
ESP_EARLY_LOGW(IEEE802154_TAG, "frag(%03d:%03d~%03d): %02x %02x %02x %02x %02x %02x %02x %02x",
frame[0], i, i+7,
frame[i], frame[i+1], frame[i+2], frame[i+3],
frame[i+4], frame[i+5], frame[i+6], frame[i+7]);
frame[0], i, end,
frame[i],
(i+1 < frame[0]) ? frame[i+1] : 0,
(i+2 < frame[0]) ? frame[i+2] : 0,
(i+3 < frame[0]) ? frame[i+3] : 0,
(i+4 < frame[0]) ? frame[i+4] : 0,
(i+5 < frame[0]) ? frame[i+5] : 0,
(i+6 < frame[0]) ? frame[i+6] : 0,
(i+7 < frame[0]) ? frame[i+7] : 0);
}
}
#endif // CONFIG_IEEE802154_RECORD_TXRX_FRAME
@@ -193,14 +233,14 @@ void ieee802154_record_print(void)
char abort_log[100] = { 0 };
snprintf(event_log, 200,"index %2d: event: 0x%4x, %15s, state:%10s, timestamp: %lld", i, g_ieee802154_probe.event[i].event,
ieee802154_get_event_string(g_ieee802154_probe.event[i].event),
ieee802154_state_string[g_ieee802154_probe.event[i].state],
ieee802154_state_to_string(g_ieee802154_probe.event[i].state),
g_ieee802154_probe.event[i].timestamp);
if (g_ieee802154_probe.event[i].event == IEEE802154_EVENT_RX_ABORT) {
snprintf(abort_log, 100, "rx abort reason: %4x, %20s", g_ieee802154_probe.event[i].abort_reason.rx,
ieee80154_rx_abort_reason_string[g_ieee802154_probe.event[i].abort_reason.rx]);
ieee802154_abort_reason_to_string(g_ieee802154_probe.event[i].abort_reason.rx, false));
} else if (g_ieee802154_probe.event[i].event == IEEE802154_EVENT_TX_ABORT) {
snprintf(abort_log, 100, "tx abort reason: %4x, %20s", g_ieee802154_probe.event[i].abort_reason.tx,
ieee80154_tx_abort_reason_string[g_ieee802154_probe.event[i].abort_reason.tx]);
ieee802154_abort_reason_to_string(g_ieee802154_probe.event[i].abort_reason.tx, true));
}
ESP_EARLY_LOGW(IEEE802154_TAG, "%s %s", event_log, abort_log);
}
@@ -212,7 +252,7 @@ void ieee802154_record_print(void)
for (uint8_t i = 0; i < IEEE802154_ASSERT_RECORD_STATE_SIZE; i++) {
ESP_EARLY_LOGW(IEEE802154_TAG, "index %2d: line:%5lu, state:%10s, timestamp: %lld",
i, g_ieee802154_probe.state[i].line,
ieee802154_state_string[g_ieee802154_probe.state[i].state],
ieee802154_state_to_string(g_ieee802154_probe.state[i].state),
g_ieee802154_probe.state[i].timestamp);
}
ESP_EARLY_LOGW(IEEE802154_TAG,"Print the record state done.");
@@ -235,12 +275,12 @@ void ieee802154_record_print(void)
if (g_ieee802154_probe.abort[i].is_tx_abort) {
ESP_EARLY_LOGW(IEEE802154_TAG, "index %2d: tx abort: %4x, %15s, timestamp: %lld",
i, g_ieee802154_probe.abort[i].abort_reason.tx,
ieee80154_tx_abort_reason_string[g_ieee802154_probe.abort[i].abort_reason.tx],
ieee802154_abort_reason_to_string(g_ieee802154_probe.abort[i].abort_reason.tx, true),
g_ieee802154_probe.abort[i].timestamp);
} else {
ESP_EARLY_LOGW(IEEE802154_TAG, "index %2d: rx abort: %4x, %15s, timestamp: %lld",
i, g_ieee802154_probe.abort[i].abort_reason.rx,
ieee80154_rx_abort_reason_string[g_ieee802154_probe.abort[i].abort_reason.rx],
ieee802154_abort_reason_to_string(g_ieee802154_probe.abort[i].abort_reason.rx, false),
g_ieee802154_probe.abort[i].timestamp);
}
}
@@ -418,14 +458,19 @@ static uint64_t s_rx_buffer_used_water_level[IEEE802154_RX_BUFFER_USED_TOTAL_LEV
void ieee802154_rx_buffer_statistic_is_free(bool is_free)
{
if (is_free) {
if (s_rx_buffer_used_nums > 0) {
s_rx_buffer_used_nums--;
}
} else {
s_rx_buffer_used_nums++;
// (CONFIG_IEEE802154_RX_BUFFER_SIZE + 1) means buffer full.
if (s_rx_buffer_used_nums > (CONFIG_IEEE802154_RX_BUFFER_SIZE + 1)) {
s_rx_buffer_used_nums = CONFIG_IEEE802154_RX_BUFFER_SIZE + 1;
}
s_rx_buffer_used_water_level[IEEE802154_RX_BUFFER_GET_USED_LEVEL(s_rx_buffer_used_nums)]++;
uint8_t level = IEEE802154_RX_BUFFER_GET_USED_LEVEL(s_rx_buffer_used_nums);
if (level <= IEEE802154_RX_BUFFER_USED_TOTAL_LEVEL) {
s_rx_buffer_used_water_level[level]++;
}
}
}
@@ -437,6 +482,7 @@ void ieee802154_rx_buffer_statistic_clear(void)
void ieee802154_rx_buffer_statistic_print(void)
{
uint64_t total_times = 0;
float percentage = 0.0f;
for (uint8_t i = 0; i < (IEEE802154_RX_BUFFER_USED_TOTAL_LEVEL + 1); i++) {
total_times += s_rx_buffer_used_water_level[i];
}
@@ -445,9 +491,15 @@ void ieee802154_rx_buffer_statistic_print(void)
ESP_LOGW(IEEE802154_TAG, "|%25s|%-25llu|", "buffer alloc times:", total_times);
ESP_LOGW(IEEE802154_TAG, "+-------------------------+-------------------------+");
for (uint8_t i = 0; i < (IEEE802154_RX_BUFFER_USED_TOTAL_LEVEL); i++) {
ESP_LOGW(IEEE802154_TAG, "|%4d%%%5s%4d%%%10s|%-15llu%9.2f%%|", ((i) * 100 / IEEE802154_RX_BUFFER_USED_TOTAL_LEVEL), "~", ((i + 1) * 100 / IEEE802154_RX_BUFFER_USED_TOTAL_LEVEL), " used:", s_rx_buffer_used_water_level[i], ((float)s_rx_buffer_used_water_level[i] / (float)total_times)*100);
percentage = (total_times > 0) ? ((float)s_rx_buffer_used_water_level[i] / (float)total_times) * 100 : 0.0f;
ESP_LOGW(IEEE802154_TAG, "|%4d%%%5s%4d%%%10s|%-15llu%9.2f%%|",
((i) * 100 / IEEE802154_RX_BUFFER_USED_TOTAL_LEVEL), "~",
((i + 1) * 100 / IEEE802154_RX_BUFFER_USED_TOTAL_LEVEL), " used:",
s_rx_buffer_used_water_level[i], percentage);
}
ESP_LOGW(IEEE802154_TAG, "|%25s|%-15llu%9.2f%%|", "full used:", s_rx_buffer_used_water_level[IEEE802154_RX_BUFFER_USED_TOTAL_LEVEL], ((float)s_rx_buffer_used_water_level[IEEE802154_RX_BUFFER_USED_TOTAL_LEVEL] / (float)total_times)*100);
percentage = (total_times > 0) ? ((float)s_rx_buffer_used_water_level[IEEE802154_RX_BUFFER_USED_TOTAL_LEVEL] / (float)total_times) * 100 : 0.0f;
ESP_LOGW(IEEE802154_TAG, "|%25s|%-15llu%9.2f%%|", "full used:",
s_rx_buffer_used_water_level[IEEE802154_RX_BUFFER_USED_TOTAL_LEVEL], percentage);
ESP_LOGW(IEEE802154_TAG, "+-------------------------+-------------------------+");
}
@@ -48,7 +48,12 @@ extern uint32_t bt_bb_get_cur_rx_info(void);
IEEE802154_STATIC volatile ieee802154_state_t s_ieee802154_state;
static uint8_t *s_tx_frame = NULL;
#if CONFIG_IEEE802154_TEST
#define IEEE802154_RX_FRAME_SIZE (127 + 1 + 1) // +1: len, +1: for dma test
#else
#define IEEE802154_RX_FRAME_SIZE (127 + 1) // +1: len
#endif // CONFIG_IEEE802154_TEST
// +1: for the stub buffer when the valid buffers are full.
//
@@ -224,9 +229,18 @@ IEEE802154_STATIC IEEE802154_NOINLINE void update_mpf_index(void)
static IEEE802154_NOINLINE void ieee802154_rx_frame_info_update(void)
{
uint8_t len = s_rx_frame[s_rx_index][0];
int8_t rssi = s_rx_frame[s_rx_index][len - 1]; // crc is not written to rx buffer
uint8_t lqi = s_rx_frame[s_rx_index][len];
uint8_t len = s_rx_frame[s_rx_index][0] & 0x7f;
int8_t rssi = 0;
uint8_t lqi = 0;
if (len < IEEE802154_FRAME_MIN_LEN) {
s_rx_frame_info[s_rx_index].channel = 0;
s_rx_frame_info[s_rx_index].rssi = 0;
s_rx_frame_info[s_rx_index].lqi = 0;
return;
}
rssi = s_rx_frame[s_rx_index][len - 1]; // crc is not written to rx buffer
lqi = s_rx_frame[s_rx_index][len];
#if CONFIG_IEEE802154_MULTI_PAN_ENABLE
update_mpf_index();
@@ -977,7 +991,6 @@ static inline esp_err_t ieee802154_transmit_internal(const uint8_t *frame, bool
esp_err_t ieee802154_transmit(const uint8_t *frame, bool cca)
{
ESP_RETURN_ON_FALSE(frame[0] <= 127, ESP_ERR_INVALID_ARG, IEEE802154_TAG, "Invalid frame length.");
#if !CONFIG_IEEE802154_TEST
ieee802154_enter_critical();
if ((s_ieee802154_state == IEEE802154_STATE_RX && ieee802154_ll_is_current_rx_frame())
@@ -999,32 +1012,23 @@ esp_err_t ieee802154_transmit(const uint8_t *frame, bool cca)
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.");
uint32_t tx_target_time;
uint32_t rampup_time = cca ? IEEE802154_ED_TRIG_TX_RAMPUP_TIME_US : IEEE802154_TX_RAMPUP_TIME_US;
uint32_t tx_target_time = (time >= rampup_time) ? time - rampup_time : 0;
IEEE802154_RF_ENABLE();
tx_init(frame);
IEEE802154_SET_TXRX_PTI(IEEE802154_SCENE_TX_AT);
if (cca) {
ieee802154_ll_set_ed_duration(CCA_DETECTION_TIME);
tx_target_time = time - IEEE802154_ED_TRIG_TX_RAMPUP_TIME_US;
ieee802154_set_state(IEEE802154_STATE_TX_CCA);
}
ieee802154_set_state(cca ? IEEE802154_STATE_TX_CCA : IEEE802154_STATE_TX);
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, cca ? ETM_TASK_ED_TRIG_TX : ETM_TASK_TX_START);
ieee802154_timer0_fire_at(tx_target_time);
ieee802154_exit_critical();
} else {
tx_target_time = time - IEEE802154_TX_RAMPUP_TIME_US;
if (ieee802154_frame_get_type(frame) == IEEE802154_FRAME_TYPE_ACK && ieee802154_frame_get_version(frame) == IEEE802154_FRAME_VERSION_2) {
ieee802154_set_state(IEEE802154_STATE_TX_ENH_ACK);
} else {
ieee802154_set_state(IEEE802154_STATE_TX);
if (time < rampup_time) {
// First start the transmit at and then print some logs.
ESP_EARLY_LOGE(IEEE802154_TAG, "Time should be longer than %d us to account for the TX ramp-up", rampup_time);
}
ieee802154_enter_critical();
ieee802154_etm_set_event_task(IEEE802154_ETM_CHANNEL0, ETM_EVENT_TIMER0_OVERFLOW, ETM_TASK_TX_START);
ieee802154_timer0_fire_at(tx_target_time);
ieee802154_exit_critical();
}
return ESP_OK;
}
@@ -1072,6 +1076,7 @@ IEEE802154_NOINLINE static void ieee802154_start_receive_at(void* ctx)
esp_err_t ieee802154_receive_at(uint32_t time, uint32_t duration)
{
// TODO: Light sleep current optimization, TZ-1613.
uint32_t target_time = (time >= IEEE802154_RX_RAMPUP_TIME_US) ? time - IEEE802154_RX_RAMPUP_TIME_US : 0;
IEEE802154_RF_ENABLE();
ieee802154_enter_critical();
rx_init();
@@ -1080,11 +1085,15 @@ esp_err_t ieee802154_receive_at(uint32_t time, uint32_t duration)
ieee802154_set_state(IEEE802154_STATE_RX);
ieee802154_etm_set_event_task(IEEE802154_ETM_CHANNEL1, ETM_EVENT_TIMER1_OVERFLOW, ETM_TASK_RX_START);
if (duration) {
ieee802154_timer1_fire_at_with_callback(time - IEEE802154_RX_RAMPUP_TIME_US, ieee802154_start_receive_at, (void*)(time + duration));
ieee802154_timer1_fire_at_with_callback(target_time, ieee802154_start_receive_at, (void*)(time + duration));
} else {
ieee802154_timer1_fire_at(time - IEEE802154_RX_RAMPUP_TIME_US);
ieee802154_timer1_fire_at(target_time);
}
ieee802154_exit_critical();
if (time < IEEE802154_RX_RAMPUP_TIME_US) {
// First start the receive at and then print some logs.
ESP_EARLY_LOGE(IEEE802154_TAG, "Time should be longer than %d us to account for the RX ramp-up", IEEE802154_RX_RAMPUP_TIME_US);
}
return ESP_OK;
}
@@ -10,6 +10,7 @@
#include "esp_ieee802154_dev.h"
#include "esp_ieee802154_frame.h"
#include "esp_ieee802154_util.h"
#include "esp_rom_sys.h"
bool ieee802154_frame_is_security_enabled(const uint8_t *frame)
{
@@ -42,14 +43,29 @@ IEEE802154_STATIC IEEE802154_INLINE bool is_panid_compression(const uint8_t *fra
return frame[IEEE802154_FRAME_PANID_COMP_OFFSET] & IEEE802154_FRAME_PANID_COMP_BIT;
}
IEEE802154_STATIC IEEE802154_INLINE bool is_valid_dst_mode(uint8_t dst_mode)
{
return (dst_mode == IEEE802154_FRAME_DST_MODE_NONE ||
dst_mode == IEEE802154_FRAME_DST_MODE_SHORT ||
dst_mode == IEEE802154_FRAME_DST_MODE_EXT);
}
IEEE802154_STATIC IEEE802154_INLINE bool is_valid_src_mode(uint8_t src_mode)
{
return (src_mode == IEEE802154_FRAME_SRC_MODE_NONE ||
src_mode == IEEE802154_FRAME_SRC_MODE_SHORT ||
src_mode == IEEE802154_FRAME_SRC_MODE_EXT);
}
IEEE802154_STATIC IEEE802154_NOINLINE bool is_dst_panid_present(const uint8_t *frame)
{
uint8_t dst_mode = dst_addr_mode(frame);
uint8_t src_mode = src_addr_mode(frame);
bool dst_panid_present = false;
bool panid_compression = is_panid_compression(frame);
IEEE802154_RETURN_ON_FALSE_SILENTLY(is_valid_dst_mode(dst_mode) && is_valid_src_mode(src_mode), false);
if (ieee802154_frame_get_version(frame) == IEEE802154_FRAME_VERSION_2) {
uint8_t src_mode = src_addr_mode(frame);
bool panid_compression = is_panid_compression(frame);
if (dst_mode != IEEE802154_FRAME_DST_MODE_NONE) { // dest address is present/short/extended
if ((src_mode == IEEE802154_FRAME_SRC_MODE_NONE && panid_compression) ||
@@ -74,13 +90,13 @@ IEEE802154_STATIC IEEE802154_NOINLINE bool is_dst_panid_present(const uint8_t *f
IEEE802154_STATIC IEEE802154_NOINLINE bool is_src_panid_present(const uint8_t *frame)
{
uint8_t dst_mode = dst_addr_mode(frame);
uint8_t src_mode = src_addr_mode(frame);
bool panid_compression = is_panid_compression(frame);
bool src_panid_present = false;
bool panid_compression = is_panid_compression(frame);
IEEE802154_RETURN_ON_FALSE_SILENTLY(is_valid_dst_mode(dst_mode) && is_valid_src_mode(src_mode), false);
if (ieee802154_frame_get_version(frame) == IEEE802154_FRAME_VERSION_2) {
uint8_t dst_mode = dst_addr_mode(frame);
if (src_mode != IEEE802154_FRAME_SRC_MODE_NONE) {
if (dst_mode == IEEE802154_FRAME_DST_MODE_EXT && src_mode == IEEE802154_FRAME_SRC_MODE_EXT && !panid_compression) {
src_panid_present = false;
@@ -101,6 +117,16 @@ IEEE802154_STATIC IEEE802154_NOINLINE bool is_src_panid_present(const uint8_t *f
return src_panid_present;
}
uint8_t IEEE802154_INLINE ieee802154_frame_get_type(const uint8_t *frame)
{
return frame[IEEE802154_FRAME_TYPE_OFFSET] & IEEE802154_FRAME_TYPE_MASK;
}
uint8_t IEEE802154_INLINE ieee802154_frame_get_version(const uint8_t *frame)
{
return frame[IEEE802154_FRAME_VERSION_OFFSET] & IEEE802154_FRAME_VERSION_MASK;
}
IEEE802154_STATIC uint8_t IEEE802154_INLINE ieee802154_frame_address_offset(const uint8_t *frame)
{
return IEEE802154_FRAME_PHR_SIZE + IEEE802154_FRAME_FCF_SIZE + (is_dsn_present(frame) ? IEEE802154_FRAME_DSN_SIZE : 0);
@@ -109,12 +135,17 @@ IEEE802154_STATIC uint8_t IEEE802154_INLINE ieee802154_frame_address_offset(cons
IEEE802154_STATIC IRAM_ATTR uint8_t ieee802154_frame_address_size(const uint8_t *frame)
{
uint8_t address_size = 0;
uint8_t dst_mode = dst_addr_mode(frame);
uint8_t src_mode = src_addr_mode(frame);
ESP_RETURN_ON_FALSE_ISR(is_valid_src_mode(src_mode) && is_valid_dst_mode(dst_mode), IEEE802154_FRAME_INVALID_VALUE, IEEE802154_TAG, "invalid address mode");
if (is_dst_panid_present(frame)) {
address_size += IEEE802154_FRAME_PANID_SIZE;
}
switch (dst_addr_mode(frame)) {
switch (dst_mode) {
case IEEE802154_FRAME_DST_MODE_NONE:
break;
@@ -127,14 +158,14 @@ IEEE802154_STATIC IRAM_ATTR uint8_t ieee802154_frame_address_size(const uint8_t
break;
default:
return IEEE802154_FRAME_INVALID_OFFSET;
break;
}
if (is_src_panid_present(frame)) {
address_size += IEEE802154_FRAME_PANID_SIZE;
}
switch (src_addr_mode(frame)) {
switch (src_mode) {
case IEEE802154_FRAME_SRC_MODE_NONE:
break;
@@ -147,7 +178,7 @@ IEEE802154_STATIC IRAM_ATTR uint8_t ieee802154_frame_address_size(const uint8_t
break;
default:
return IEEE802154_FRAME_INVALID_OFFSET;
break;
}
return address_size;
@@ -155,12 +186,11 @@ IEEE802154_STATIC IRAM_ATTR uint8_t ieee802154_frame_address_size(const uint8_t
IEEE802154_STATIC IEEE802154_NOINLINE uint8_t ieee802154_frame_security_header_offset(const uint8_t *frame)
{
ESP_RETURN_ON_FALSE_ISR(ieee802154_is_supported_frame_type(ieee802154_frame_get_type(frame)), IEEE802154_FRAME_INVALID_ADDR_MODE, IEEE802154_TAG, "invalid frame type");
IEEE802154_RETURN_ON_FALSE_SILENTLY(ieee802154_is_supported_frame_type(ieee802154_frame_get_type(frame)), IEEE802154_FRAME_INVALID_VALUE);
uint8_t offset = ieee802154_frame_address_offset(frame);
IEEE802154_RETURN_ON_FALSE_SILENTLY(offset != IEEE802154_FRAME_INVALID_VALUE, IEEE802154_FRAME_INVALID_VALUE);
uint8_t address_size = ieee802154_frame_address_size(frame);
ESP_RETURN_ON_FALSE_ISR(offset != IEEE802154_FRAME_INVALID_OFFSET, IEEE802154_FRAME_INVALID_OFFSET, IEEE802154_TAG, "invalid offset");
ESP_RETURN_ON_FALSE_ISR(address_size != IEEE802154_FRAME_INVALID_OFFSET, IEEE802154_FRAME_INVALID_OFFSET, IEEE802154_TAG, "invalid offset");
IEEE802154_RETURN_ON_FALSE_SILENTLY(address_size != IEEE802154_FRAME_INVALID_VALUE, IEEE802154_FRAME_INVALID_VALUE);
offset += address_size;
@@ -169,12 +199,12 @@ IEEE802154_STATIC IEEE802154_NOINLINE uint8_t ieee802154_frame_security_header_o
IEEE802154_STATIC IEEE802154_NOINLINE uint8_t ieee802154_frame_get_security_field_len(const uint8_t *frame)
{
ESP_RETURN_ON_FALSE_ISR(ieee802154_is_supported_frame_type(ieee802154_frame_get_type(frame)), IEEE802154_FRAME_INVALID_OFFSET, IEEE802154_TAG, "invalid frame type");
ESP_RETURN_ON_FALSE_ISR(ieee802154_is_supported_frame_type(ieee802154_frame_get_type(frame)), IEEE802154_FRAME_INVALID_VALUE, IEEE802154_TAG, "invalid frame type");
uint8_t security_field_len = 0;
uint8_t offset = ieee802154_frame_security_header_offset(frame);
ESP_RETURN_ON_FALSE_ISR(offset != IEEE802154_FRAME_INVALID_OFFSET, IEEE802154_FRAME_INVALID_OFFSET, IEEE802154_TAG, "invalid offset");
ESP_RETURN_ON_FALSE_ISR(offset != IEEE802154_FRAME_INVALID_VALUE, IEEE802154_FRAME_INVALID_VALUE, IEEE802154_TAG, "invalid offset");
security_field_len += IEEE802154_FRAME_SE_HEAD_SIZE;
uint8_t security_header = frame[offset];
@@ -206,7 +236,9 @@ IEEE802154_STATIC IEEE802154_NOINLINE uint8_t ieee802154_frame_get_security_fiel
IEEE802154_STATIC uint8_t ieee802154_frame_ie_header_offset(const uint8_t *frame)
{
uint8_t offset = ieee802154_frame_security_header_offset(frame);
IEEE802154_RETURN_ON_FALSE_SILENTLY(offset != IEEE802154_FRAME_INVALID_VALUE, IEEE802154_FRAME_INVALID_VALUE);
uint8_t security_field_len = ieee802154_frame_get_security_field_len(frame);
IEEE802154_RETURN_ON_FALSE_SILENTLY(security_field_len != IEEE802154_FRAME_INVALID_VALUE, IEEE802154_FRAME_INVALID_VALUE);
offset += security_field_len;
@@ -216,6 +248,7 @@ IEEE802154_STATIC uint8_t ieee802154_frame_ie_header_offset(const uint8_t *frame
IEEE802154_STATIC uint8_t ieee802154_frame_get_mic_len(const uint8_t *frame)
{
uint8_t offset = ieee802154_frame_security_header_offset(frame);
IEEE802154_RETURN_ON_FALSE_SILENTLY(offset != IEEE802154_FRAME_INVALID_VALUE, 0);
uint8_t mic_len = 0;
uint8_t security_header = frame[offset];
@@ -242,8 +275,10 @@ IEEE802154_STATIC uint8_t ieee802154_frame_get_mic_len(const uint8_t *frame)
IEEE802154_STATIC uint8_t ieee802154_frame_get_ie_field_len(const uint8_t *frame)
{
uint8_t offset = ieee802154_frame_ie_header_offset(frame);
IEEE802154_RETURN_ON_FALSE_SILENTLY(offset != IEEE802154_FRAME_INVALID_VALUE, IEEE802154_FRAME_INVALID_VALUE);
uint8_t ie_field_len = 0;
uint8_t frame_footer_len = ieee802154_frame_get_mic_len(frame) + IEEE802154_FRAME_FCS_SIZE;
uint8_t frame_len = frame[0];
/* If the `offset + frame_footer_len == frame_len`, we exit the `while()`
loop. This covers the case where frame contains one or more Header IEs
@@ -253,6 +288,9 @@ IEEE802154_STATIC uint8_t ieee802154_frame_get_ie_field_len(const uint8_t *frame
footer length. (for details, please reference 2015 - spec table 7 - 6 in page 169) */
while (frame[0] > offset + ie_field_len + frame_footer_len) {
if (offset + ie_field_len + 1 >= frame_len) {
break;
}
uint16_t ie_header = frame[offset + ie_field_len + 1] << 8 | frame[offset + ie_field_len];
// Header Termination IE 2 is used in to signal end of the MHR and beginning of the MAC Payload.
if ((ie_header & IEEE802154_FRAME_IE_HEAD_ID_MASK) == IEEE802154_IE_TYPE_HT2) {
@@ -269,9 +307,12 @@ IEEE802154_STATIC uint8_t ieee802154_frame_get_ie_field_len(const uint8_t *frame
IEEE802154_STATIC IRAM_ATTR uint8_t ieee802154_frame_payload_offset(const uint8_t *frame)
{
uint8_t offset = ieee802154_frame_security_header_offset(frame);
IEEE802154_RETURN_ON_FALSE_SILENTLY(offset != IEEE802154_FRAME_INVALID_VALUE, IEEE802154_FRAME_INVALID_VALUE);
if (ieee802154_frame_is_security_enabled(frame)) {
// skip security field.
offset += ieee802154_frame_get_security_field_len(frame);
uint8_t security_field_len = ieee802154_frame_get_security_field_len(frame);
IEEE802154_RETURN_ON_FALSE_SILENTLY(security_field_len != IEEE802154_FRAME_INVALID_VALUE, IEEE802154_FRAME_INVALID_VALUE);
offset += security_field_len;
}
if (ieee802154_frame_get_version(frame) == IEEE802154_FRAME_VERSION_2 && is_ie_present(frame)) {
@@ -312,34 +353,22 @@ bool ieee802154_is_data_request(const uint8_t *frame)
return false;
}
uint8_t IEEE802154_INLINE ieee802154_frame_get_type(const uint8_t *frame)
{
return frame[IEEE802154_FRAME_TYPE_OFFSET] & IEEE802154_FRAME_TYPE_MASK;
}
uint8_t IEEE802154_INLINE ieee802154_frame_get_version(const uint8_t *frame)
{
return frame[IEEE802154_FRAME_VERSION_OFFSET] & IEEE802154_FRAME_VERSION_MASK;
}
bool IEEE802154_INLINE ieee802154_frame_is_ack_required(const uint8_t *frame)
{
return (ieee802154_is_supported_frame_type(ieee802154_frame_get_type(frame))) && (frame[IEEE802154_FRAME_AR_OFFSET] & IEEE802154_FRAME_AR_BIT);
IEEE802154_RETURN_ON_FALSE_SILENTLY(ieee802154_is_supported_frame_type(ieee802154_frame_get_type(frame)), false);
return (frame[IEEE802154_FRAME_AR_OFFSET] & IEEE802154_FRAME_AR_BIT);
}
uint8_t ieee802154_frame_get_dst_addr(const uint8_t *frame, uint8_t *addr)
{
ESP_RETURN_ON_FALSE_ISR(ieee802154_is_supported_frame_type(ieee802154_frame_get_type(frame)), IEEE802154_FRAME_INVALID_ADDR_MODE, IEEE802154_TAG, "invalid frame type");
ESP_RETURN_ON_FALSE_ISR(ieee802154_is_supported_frame_type(ieee802154_frame_get_type(frame)), IEEE802154_FRAME_INVALID_VALUE, IEEE802154_TAG, "invalid frame type");
uint8_t offset = ieee802154_frame_address_offset(frame);
uint8_t dst_mode = dst_addr_mode(frame);
if (dst_mode == IEEE802154_FRAME_DST_MODE_NONE) {
return dst_mode;
}
uint8_t addr_size;
ESP_RETURN_ON_FALSE_ISR(dst_mode == IEEE802154_FRAME_DST_MODE_SHORT || dst_mode == IEEE802154_FRAME_DST_MODE_EXT, dst_mode, IEEE802154_TAG, "invalid address mode");
uint8_t addr_size = 0;
ESP_RETURN_ON_FALSE_ISR(is_valid_dst_mode(dst_mode), IEEE802154_FRAME_INVALID_VALUE, IEEE802154_TAG, "invalid destination address mode");
IEEE802154_RETURN_ON_FALSE_SILENTLY(dst_mode != IEEE802154_FRAME_DST_MODE_NONE, IEEE802154_FRAME_DST_MODE_NONE);
addr_size = (dst_mode == IEEE802154_FRAME_DST_MODE_SHORT) ? IEEE802154_FRAME_SHORT_ADDR_SIZE : IEEE802154_FRAME_EXT_ADDR_SIZE;
if (is_dst_panid_present(frame)) {
@@ -353,19 +382,16 @@ uint8_t ieee802154_frame_get_dst_addr(const uint8_t *frame, uint8_t *addr)
uint8_t ieee802154_frame_get_src_addr(const uint8_t *frame, uint8_t *addr)
{
ESP_RETURN_ON_FALSE_ISR(ieee802154_is_supported_frame_type(ieee802154_frame_get_type(frame)), IEEE802154_FRAME_INVALID_ADDR_MODE, IEEE802154_TAG, "invalid frame type");
ESP_RETURN_ON_FALSE_ISR(ieee802154_is_supported_frame_type(ieee802154_frame_get_type(frame)), IEEE802154_FRAME_INVALID_VALUE, IEEE802154_TAG, "invalid frame type");
uint8_t offset = ieee802154_frame_address_offset(frame);
uint8_t dst_mode = dst_addr_mode(frame);
uint8_t src_mode = src_addr_mode(frame);
uint8_t addr_size;
uint8_t addr_size = 0;
if (src_mode == IEEE802154_FRAME_SRC_MODE_NONE) {
return src_mode;
}
ESP_RETURN_ON_FALSE_ISR(src_mode == IEEE802154_FRAME_SRC_MODE_SHORT || src_mode == IEEE802154_FRAME_SRC_MODE_EXT, src_mode, IEEE802154_TAG, "invalid address mode");
ESP_RETURN_ON_FALSE_ISR(is_valid_src_mode(src_mode) && is_valid_dst_mode(dst_mode), IEEE802154_FRAME_INVALID_VALUE, IEEE802154_TAG, "invalid address mode");
IEEE802154_RETURN_ON_FALSE_SILENTLY(src_mode != IEEE802154_FRAME_SRC_MODE_NONE, IEEE802154_FRAME_SRC_MODE_NONE);
addr_size = (src_mode == IEEE802154_FRAME_SRC_MODE_SHORT) ? IEEE802154_FRAME_SHORT_ADDR_SIZE : IEEE802154_FRAME_EXT_ADDR_SIZE;
if (is_dst_panid_present(frame)) {
@@ -396,7 +422,9 @@ uint8_t ieee802154_frame_get_src_addr(const uint8_t *frame, uint8_t *addr)
uint8_t ieee802154_frame_get_security_payload_offset(uint8_t *frame)
{
return ieee802154_frame_payload_offset(frame);
uint8_t offset = ieee802154_frame_payload_offset(frame);
ESP_RETURN_ON_FALSE_ISR(offset != IEEE802154_FRAME_INVALID_VALUE, IEEE802154_FRAME_INVALID_VALUE, IEEE802154_TAG, "invalid offset");
return offset;
}
esp_err_t ieee802154_frame_get_dest_panid(const uint8_t *frame, uint8_t *panid)
@@ -414,6 +442,7 @@ esp_err_t ieee802154_frame_get_src_panid(const uint8_t *frame, uint8_t *panid)
{
uint8_t offset = ieee802154_frame_address_offset(frame);
uint8_t dst_mode = dst_addr_mode(frame);
IEEE802154_RETURN_ON_FALSE_SILENTLY(is_valid_dst_mode(dst_mode), ESP_FAIL);
if (is_src_panid_present(frame)) {
if (is_dst_panid_present(frame)) {
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -15,6 +15,30 @@
static ieee802154_pib_t s_ieee802154_pib;
static bool is_pending = false;
extern const int8_t* bt_bb_get_tx_pwr_table(uint8_t *length);
static inline int8_t IEEE802154_TXPOWER_VALUE_MAX(void)
{
uint8_t length = 0;
const int8_t *tx_pwr_table = bt_bb_get_tx_pwr_table(&length);
if (!tx_pwr_table || length == 0) {
ESP_LOGE(IEEE802154_TAG, "Failed to get tx power table");
return 0;
}
return tx_pwr_table[length - 1];
}
static inline int8_t IEEE802154_TXPOWER_VALUE_MIN(void)
{
uint8_t length = 0;
const int8_t *tx_pwr_table = bt_bb_get_tx_pwr_table(&length);
if (!tx_pwr_table || length == 0) {
ESP_LOGE(IEEE802154_TAG, "Failed to get tx power table");
return 0;
}
return tx_pwr_table[0];
}
static inline void set_pending(void)
{
is_pending = true;
@@ -25,7 +49,7 @@ static inline void clr_pending(void)
is_pending = false;
}
bool inline ieee802154_pib_is_pending(void)
inline bool ieee802154_pib_is_pending(void)
{
return is_pending;
}
@@ -42,22 +66,38 @@ void ieee802154_pib_init(void)
s_ieee802154_pib.channel = 11;
s_ieee802154_pib.cca_threshold = CONFIG_IEEE802154_CCA_THRESHOLD;
s_ieee802154_pib.cca_mode = CONFIG_IEEE802154_CCA_MODE;
memset(&s_ieee802154_pib.power_table, IEEE802154_TXPOWER_VALUE_MAX, sizeof(s_ieee802154_pib.power_table));
for (int i = 0; i < 16; i++) {
s_ieee802154_pib.power_table.channel[i] = IEEE802154_TXPOWER_VALUE_MAX();
}
set_pending();
}
IEEE802154_NOINLINE static uint8_t ieee802154_txpower_convert(int8_t txpower)
{
uint8_t ieee820154_txpower_index = 0;
if (txpower >= IEEE802154_TXPOWER_VALUE_MAX) {
ieee820154_txpower_index = 15;
} else if (txpower <= IEEE802154_TXPOWER_VALUE_MIN) {
ieee820154_txpower_index = IEEE802154_TXPOWER_INDEX_MIN;
} else {
ieee820154_txpower_index = (uint8_t)((txpower - IEEE802154_TXPOWER_VALUE_MIN) / 3) + IEEE802154_TXPOWER_INDEX_MIN;
uint8_t ieee802154_txpower_index = 0;
uint8_t length = 0;
const int8_t *tx_pwr_table = bt_bb_get_tx_pwr_table(&length);
if (!tx_pwr_table || length == 0) {
ESP_LOGE(IEEE802154_TAG, "Failed to get tx power table");
return 0;
}
return ieee820154_txpower_index;
if (txpower <= tx_pwr_table[0]) {
ieee802154_txpower_index = 0;
} else if (txpower >= tx_pwr_table[length - 1]) {
ieee802154_txpower_index = length - 1;
} else {
uint8_t i = 0;
for (i = length-1; i != 0; i--) {
if (tx_pwr_table[i] <= txpower) {
break;
}
}
ieee802154_txpower_index = i;
}
return ieee802154_txpower_index;
}
void ieee802154_pib_update(void)
@@ -95,7 +135,7 @@ uint8_t ieee802154_pib_get_channel(void)
void ieee802154_pib_set_channel(uint8_t channel)
{
ESP_RETURN_ON_FALSE(ieee802154_is_valid_channel(channel), , IEEE802154_TAG, "Failed to set channel, reason: Invalid channel: %d", channel);
ESP_RETURN_VOID_ON_FALSE(ieee802154_is_valid_channel(channel), IEEE802154_TAG, "Failed to set channel, reason: Invalid channel: %d", channel);
if (s_ieee802154_pib.channel != channel) {
s_ieee802154_pib.channel = channel;
set_pending();
@@ -30,10 +30,7 @@ void ieee802154_timer0_stop(void)
esp_err_t ieee802154_timer0_set_threshold(uint32_t value)
{
ESP_RETURN_ON_FALSE((value < IEEE802154_TIMER0_THRESHOLD), ESP_ERR_INVALID_ARG, IEEE802154_TAG, "invalid timer0 threshold");
ieee802154_ll_timer0_set_threshold(value);
return ESP_OK;
}
@@ -56,10 +53,7 @@ void ieee802154_timer1_stop(void)
esp_err_t ieee802154_timer1_set_threshold(uint32_t value)
{
ESP_RETURN_ON_FALSE((value < IEEE802154_TIMER1_THRESHOLD), ESP_ERR_INVALID_ARG, IEEE802154_TAG, "invalid timer1 threshold");
ieee802154_ll_timer1_set_threshold(value);
return ESP_OK;
}
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -8,16 +8,21 @@
#include "soc/soc.h"
#include "soc/periph_defs.h"
#include "hal/ieee802154_ll.h"
#include "esp_check.h"
#include "esp_coex_i154.h"
#include "esp_ieee802154_util.h"
uint8_t ieee802154_freq_to_channel(uint8_t freq)
{
return (freq - 3) / 5 + IEEE802154_OQPSK_2P4G_CHANNEL_MIN;
assert(((freq - 3) % 5) == 0);
uint8_t channel = (freq - 3) / 5 + IEEE802154_OQPSK_2P4G_CHANNEL_MIN;
assert(ieee802154_is_valid_channel(channel));
return channel;
}
uint8_t ieee802154_channel_to_freq(uint8_t channel)
{
assert(ieee802154_is_valid_channel(channel));
return (channel - IEEE802154_OQPSK_2P4G_CHANNEL_MIN) * 5 + 3;
}
@@ -43,7 +48,6 @@ esp_ieee802154_coex_config_t ieee802154_get_coex_config(void)
void ieee802154_set_txrx_pti(ieee802154_txrx_scene_t txrx_scene)
{
switch (txrx_scene) {
case IEEE802154_SCENE_IDLE:
esp_coex_ieee802154_txrx_pti_set(s_coex_config.idle);
@@ -66,8 +70,9 @@ void ieee802154_set_txrx_pti(ieee802154_txrx_scene_t txrx_scene)
// TZ-97: implement these two functions using ETM common interface
void ieee802154_etm_channel_clear(uint32_t channel)
{
assert(channel < 16);
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));
}
}
@@ -78,5 +83,11 @@ void ieee802154_etm_set_event_task(uint32_t channel, uint32_t event, uint32_t ta
REG_WRITE((ETM_CH0_EVT_ID_REG + ETM_CH_OFFSET * channel), event);
REG_WRITE((ETM_CH0_TASK_ID_REG + ETM_CH_OFFSET * channel), task);
REG_WRITE(ETM_CHENSET_AD0_REG, (REG_READ(ETM_CHENSET_AD0_REG) | 1 << channel));
REG_WRITE(ETM_CHENSET_AD0_REG, (REG_READ(ETM_CHENSET_AD0_REG) | (1 << channel)));
}
__attribute__((weak)) const int8_t* bt_bb_get_tx_pwr_table(uint8_t *length)
{
ESP_LOGE(IEEE802154_TAG, "bt_bb_get_tx_pwr_table is not implemented");
return NULL;
}
+28 -5
View File
@@ -8,6 +8,7 @@
#include <string.h>
#include "sdkconfig.h"
#include "esp_ieee802154.h"
#include "esp_check.h"
#include "esp_err.h"
#include "esp_phy_init.h"
#include "esp_ieee802154_ack.h"
@@ -26,6 +27,7 @@ esp_err_t esp_ieee802154_event_callback_list_register(esp_ieee802154_event_cb_li
{
return ieee802154_event_callback_list_register(cb_list);
}
esp_err_t esp_ieee802154_event_callback_list_unregister(void)
{
return ieee802154_event_callback_list_unregister();
@@ -54,6 +56,7 @@ uint8_t esp_ieee802154_get_channel(void)
esp_err_t esp_ieee802154_set_channel(uint8_t channel)
{
assert(ieee802154_is_valid_channel(channel));
ieee802154_pib_set_channel(channel);
return ESP_OK;
}
@@ -66,7 +69,9 @@ int8_t esp_ieee802154_get_txpower(void)
esp_err_t esp_ieee802154_set_txpower(int8_t power)
{
esp_ieee802154_txpower_table_t power_table;
memset(&power_table, power, sizeof(power_table));
for (int i = 0; i < 16; i++) {
power_table.channel[i] = power;
}
return ieee802154_pib_set_power_table(power_table);
}
@@ -77,6 +82,7 @@ esp_err_t esp_ieee802154_set_power_table(esp_ieee802154_txpower_table_t power_ta
esp_err_t esp_ieee802154_get_power_table(esp_ieee802154_txpower_table_t *out_power_table)
{
assert(out_power_table != NULL);
return ieee802154_pib_get_power_table(out_power_table);
}
@@ -87,6 +93,7 @@ esp_err_t esp_ieee802154_set_power_with_channel(uint8_t channel, int8_t power)
esp_err_t esp_ieee802154_get_power_with_channel(uint8_t channel, int8_t *out_power)
{
assert(out_power != NULL);
return ieee802154_pib_get_power_with_channel(channel, out_power);
}
@@ -190,6 +197,7 @@ esp_err_t esp_ieee802154_set_multipan_short_address(esp_ieee802154_multipan_inde
esp_err_t esp_ieee802154_get_multipan_extended_address(esp_ieee802154_multipan_index_t index, uint8_t *ext_addr)
{
assert(index < CONFIG_IEEE802154_INTERFACE_NUM);
assert(ext_addr != NULL);
ieee802154_ll_get_multipan_ext_addr(index, ext_addr);
return ESP_OK;
}
@@ -197,6 +205,7 @@ esp_err_t esp_ieee802154_get_multipan_extended_address(esp_ieee802154_multipan_i
esp_err_t esp_ieee802154_set_multipan_extended_address(esp_ieee802154_multipan_index_t index, const uint8_t *ext_addr)
{
assert(index < CONFIG_IEEE802154_INTERFACE_NUM);
assert(ext_addr != NULL);
ieee802154_ll_set_multipan_ext_addr(index, ext_addr);
return ESP_OK;
}
@@ -287,12 +296,14 @@ esp_err_t esp_ieee802154_set_short_address(uint16_t short_address)
esp_err_t esp_ieee802154_get_extended_address(uint8_t *ext_addr)
{
assert(ext_addr != NULL);
ieee802154_ll_get_multipan_ext_addr(ESP_IEEE802154_MULTIPAN_0, ext_addr);
return ESP_OK;
}
esp_err_t esp_ieee802154_set_extended_address(const uint8_t *ext_addr)
{
assert(ext_addr != NULL);
ieee802154_ll_set_multipan_ext_addr(ESP_IEEE802154_MULTIPAN_0, ext_addr);
return ESP_OK;
}
@@ -321,11 +332,15 @@ bool esp_ieee802154_get_rx_when_idle(void)
esp_err_t esp_ieee802154_transmit(const uint8_t *frame, bool cca)
{
assert(frame != NULL);
assert(frame[0] <= 127);
return ieee802154_transmit(frame, cca);
}
esp_err_t esp_ieee802154_transmit_at(const uint8_t *frame, bool cca, uint32_t time)
{
assert(frame != NULL);
assert(frame[0] <= 127);
return ieee802154_transmit_at(frame, cca, time);
}
@@ -375,10 +390,12 @@ esp_ieee802154_state_t esp_ieee802154_get_state(void)
case IEEE802154_STATE_TX_CCA:
case IEEE802154_STATE_CCA:
case IEEE802154_STATE_TX:
case IEEE802154_STATE_TEST_TX:
case IEEE802154_STATE_RX_ACK:
return ESP_IEEE802154_RADIO_TRANSMIT;
default:
ESP_LOGE(IEEE802154_TAG, "Invalid state: %d", ieee802154_get_state());
assert(false);
return ESP_IEEE802154_RADIO_DISABLE;
}
@@ -386,23 +403,28 @@ esp_ieee802154_state_t esp_ieee802154_get_state(void)
esp_err_t esp_ieee802154_set_transmit_security(uint8_t *frame, uint8_t *key, uint8_t *addr)
{
assert(frame != NULL);
assert(key != NULL);
assert(addr != NULL);
ieee802154_transmit_security_config(frame, key, addr);
return ESP_OK;
}
esp_err_t esp_ieee802154_add_pending_addr(const uint8_t *addr, bool is_short)
{
return ieee802154_add_pending_addr(0, addr, is_short);
assert(addr != NULL);
return ieee802154_add_pending_addr(ESP_IEEE802154_MULTIPAN_0, addr, is_short);
}
esp_err_t esp_ieee802154_clear_pending_addr(const uint8_t *addr, bool is_short)
{
return ieee802154_clear_pending_addr(0, addr, is_short);
assert(addr != NULL);
return ieee802154_clear_pending_addr(ESP_IEEE802154_MULTIPAN_0, addr, is_short);
}
esp_err_t esp_ieee802154_reset_pending_table(bool is_short)
{
ieee802154_reset_pending_table(0, is_short);
ieee802154_reset_pending_table(ESP_IEEE802154_MULTIPAN_0, is_short);
return ESP_OK;
}
@@ -465,6 +487,7 @@ __attribute__((weak)) void esp_ieee802154_ed_failed(uint16_t error)
{
}
__attribute__((weak)) void esp_ieee802154_receive_at_done(void)
{
@@ -472,7 +495,7 @@ __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)
{
ESP_EARLY_LOGE(IEEE802154_TAG, "Not implement for the enh-ack generating handler");
ESP_EARLY_LOGE(IEEE802154_TAG, "Not implemented for the enh-ack generating handler");
return ESP_FAIL;
}
+23 -10
View File
@@ -257,10 +257,11 @@ esp_err_t esp_ieee802154_set_short_address(uint16_t short_address);
/**
* @brief Get the device extended address.
*
* @param[out] ext_addr The pointer to the device extended address.
* @param[out] ext_addr The pointer to the device extended address. Must not be NULL.
*
* @return
* - ESP_OK on success.
* - ESP_ERR_INVALID_ARG if ext_addr is NULL.
* - ESP_FAIL on failure.
*/
esp_err_t esp_ieee802154_get_extended_address(uint8_t *ext_addr);
@@ -268,10 +269,11 @@ esp_err_t esp_ieee802154_get_extended_address(uint8_t *ext_addr);
/**
* @brief Set the device extended address.
*
* @param[in] ext_addr The pointer to the device extended address.
* @param[in] ext_addr The pointer to the device extended address. Must not be NULL.
*
* @return
* - ESP_OK on success.
* - ESP_ERR_INVALID_ARG if ext_addr is NULL.
* - ESP_FAIL on failure.
*/
esp_err_t esp_ieee802154_set_extended_address(const uint8_t *ext_addr);
@@ -324,10 +326,11 @@ esp_err_t esp_ieee802154_set_multipan_short_address(esp_ieee802154_multipan_inde
* @brief Get the device extended address for specific interface.
*
* @param[in] index The interface index.
* @param[out] ext_addr The pointer to the device extended address.
* @param[out] ext_addr The pointer to the device extended address. Must not be NULL.
*
* @return
* - ESP_OK on success.
* - ESP_ERR_INVALID_ARG if ext_addr is NULL.
* - ESP_FAIL on failure.
*/
esp_err_t esp_ieee802154_get_multipan_extended_address(esp_ieee802154_multipan_index_t index, uint8_t *ext_addr);
@@ -336,10 +339,11 @@ esp_err_t esp_ieee802154_get_multipan_extended_address(esp_ieee802154_multipan_i
* @brief Set the device extended address for specific interface.
*
* @param[in] index The interface index.
* @param[in] ext_addr The pointer to the device extended address.
* @param[in] ext_addr The pointer to the device extended address. Must not be NULL.
*
* @return
* - ESP_OK on success.
* - ESP_ERR_INVALID_ARG if addr is NULL.
* - ESP_FAIL on failure.
*/
esp_err_t esp_ieee802154_set_multipan_extended_address(esp_ieee802154_multipan_index_t index, const uint8_t *ext_addr);
@@ -409,12 +413,13 @@ esp_err_t esp_ieee802154_set_pending_mode(esp_ieee802154_pending_mode_t pending_
/**
* @brief Add address to the source matching table.
*
* @param[in] addr The pointer to the address.
* @param[in] addr The pointer to the address. Must not be NULL.
* @param[in] is_short Short address or Extended address.
*
* @return
* - ESP_OK on success.
* - ESP_ERR_NO_MEM if the pending table is full.
* - ESP_ERR_INVALID_ARG if addr is NULL.
*
*/
esp_err_t esp_ieee802154_add_pending_addr(const uint8_t *addr, bool is_short);
@@ -422,12 +427,13 @@ esp_err_t esp_ieee802154_add_pending_addr(const uint8_t *addr, bool is_short);
/**
* @brief Remove address from the source matching table.
*
* @param[in] addr The pointer to the address.
* @param[in] addr The pointer to the address. Must not be NULL.
* @param[in] is_short Short address or Extended address.
*
* @return
* - ESP_OK on success.
* - ESP_ERR_NOT_FOUND if the address was not found from the source matching table.
* - ESP_ERR_INVALID_ARG if addr is NULL.
*
*/
esp_err_t esp_ieee802154_clear_pending_addr(const uint8_t *addr, bool is_short);
@@ -440,6 +446,7 @@ esp_err_t esp_ieee802154_clear_pending_addr(const uint8_t *addr, bool is_short);
* @return
* - ESP_OK on success.
* - ESP_FAIL on failure.
*
*/
esp_err_t esp_ieee802154_reset_pending_table(bool is_short);
@@ -459,6 +466,7 @@ int8_t esp_ieee802154_get_cca_threshold(void);
* @return
* - ESP_OK on success.
* - ESP_FAIL on failure.
*
*/
esp_err_t esp_ieee802154_set_cca_threshold(int8_t cca_threshold);
@@ -478,6 +486,7 @@ esp_ieee802154_cca_mode_t esp_ieee802154_get_cca_mode(void);
* @return
* - ESP_OK on success.
* - ESP_FAIL on failure.
*
*/
esp_err_t esp_ieee802154_set_cca_mode(esp_ieee802154_cca_mode_t cca_mode);
@@ -489,6 +498,7 @@ esp_err_t esp_ieee802154_set_cca_mode(esp_ieee802154_cca_mode_t cca_mode);
* @return
* - ESP_OK on success.
* - ESP_FAIL on failure.
*
*/
esp_err_t esp_ieee802154_set_rx_when_idle(bool enable);
@@ -643,12 +653,13 @@ uint8_t esp_ieee802154_get_recent_lqi(void);
/**
* @brief Set the key and addr for a frame needs to be encrypted by HW.
*
* @param[in] frame A frame needs to be encrypted. Refer to `esp_ieee802154_transmit()`.
* @param[in] key A 16-bytes key for encryption.
* @param[in] addr An 8-bytes addr for HW to generate nonce, in general, is the device extended address.
* @param[in] frame A frame needs to be encrypted. Refer to `esp_ieee802154_transmit()`. Must not be NULL.
* @param[in] key A 16-bytes key for encryption. Must not be NULL.
* @param[in] addr An 8-bytes addr for HW to generate nonce, in general, is the device extended address. Must not be NULL.
*
* @return
* - ESP_OK on success.
* - ESP_ERR_INVALID_ARG if frame, key, or addr is NULL.
* - ESP_FAIL on failure.
*/
esp_err_t esp_ieee802154_set_transmit_security(uint8_t *frame, uint8_t *key, uint8_t *addr);
@@ -657,7 +668,7 @@ esp_err_t esp_ieee802154_set_transmit_security(uint8_t *frame, uint8_t *key, uin
* @brief This function will be called when a received frame needs to be acked with Enh-Ack, the upper
* layer should generate the Enh-Ack frame in this callback function.
*
* @param[in] frame The received frame.
* @param[in] frame The received frame. Must not be NULL.
* @param[in] frame_info The frame information. Refer to `esp_ieee802154_frame_info_t`.
* @param[out] enhack_frame The Enh-ack frame need to be generated via this function, HW will send it back after AIFS.
*
@@ -741,6 +752,7 @@ esp_ieee802154_coex_config_t esp_ieee802154_get_coex_config(void);
* @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);
@@ -753,6 +765,7 @@ esp_err_t esp_ieee802154_event_callback_list_register(esp_ieee802154_event_cb_li
* @return
* - ESP_OK on success.
* - ESP_FAIL on failure.
*
*/
esp_err_t esp_ieee802154_event_callback_list_unregister(void);
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -10,7 +10,7 @@
#include <stdbool.h>
#include "esp_err.h"
#define US_PER_SYMBLE 16
#define US_PER_SYMBOL 16
#ifdef __cplusplus
extern "C" {
@@ -149,7 +149,7 @@ typedef struct {
esp_ieee802154_transmit_failed_cb_t tx_failed_cb; /*!< The callback to process Tx Failed event */
esp_ieee802154_transmit_sfd_done_cb_t tx_sfd_done_cb; /*!< The callback to process Tx SFD Done event */
esp_ieee802154_energy_detect_done_cb_t ed_done_cb; /*!< The callback to process ED Done event */
esp_ieee802154_enh_ack_generator_cb_t enh_ack_generator_cb; /*!<The callback to process enh-ack generating */
esp_ieee802154_enh_ack_generator_cb_t enh_ack_generator_cb; /*!< The callback to process Enh-ack generating */
} esp_ieee802154_event_cb_list_t;
#ifdef __cplusplus
@@ -26,19 +26,20 @@ extern "C" {
typedef struct {
uint8_t short_addr[CONFIG_IEEE802154_PENDING_TABLE_SIZE][IEEE802154_FRAME_SHORT_ADDR_SIZE]; /*!< Short address table */
uint8_t ext_addr[CONFIG_IEEE802154_PENDING_TABLE_SIZE][IEEE802154_FRAME_EXT_ADDR_SIZE]; /*!< Extend address table */
uint8_t short_addr_mask[IEEE802154_PENDING_TABLE_MASK_SIZE]; /*!< The mask which the index of short address table is used */
uint8_t ext_addr_mask[IEEE802154_PENDING_TABLE_MASK_SIZE]; /*!< The mask which the index of extended address table is used */
uint8_t short_addr_mask[IEEE802154_PENDING_TABLE_MASK_SIZE]; /*!< Bit mask to track which indices of the short address table are used */
uint8_t ext_addr_mask[IEEE802154_PENDING_TABLE_MASK_SIZE]; /*!< Bit mask to track which indices of the extended address table are used */
} ieee802154_pending_table_t;
/**
* @brief Add an address to the pending table.
*
* @param[in] addr The pointer to the address needs to be added.
* @param[in] addr The pointer to the address needs to be added. Must not be NULL.
* @param[in] is_short The type of address, true for short address, false for extended.
*
* @return
* - ESP_OK on success.
* - ESP_FAIL on failure due to the table is full.
* - ESP_ERR_INVALID_ARG if addr is NULL.
*
*/
esp_err_t ieee802154_add_pending_addr(esp_ieee802154_multipan_index_t inf_index, const uint8_t *addr, bool is_short);
@@ -46,12 +47,13 @@ esp_err_t ieee802154_add_pending_addr(esp_ieee802154_multipan_index_t inf_index,
/**
* @brief Remove an address in pending table.
*
* @param[in] addr The pointer to the address needs to be cleared.
* @param[in] addr The pointer to the address needs to be cleared. Must not be NULL.
* @param[in] is_short The type of address, true for short address, false for extended.
*
* @return
* - ESP_OK on success.
* - ESP_FAIL on failure if the given address is not present in the pending table.
* - ESP_ERR_INVALID_ARG if addr is NULL.
*
*/
esp_err_t ieee802154_clear_pending_addr(esp_ieee802154_multipan_index_t inf_index, const uint8_t *addr, bool is_short);
@@ -67,10 +69,10 @@ void ieee802154_reset_pending_table(esp_ieee802154_multipan_index_t inf_index, b
/**
* @brief Check whether the pending bit should be set or not in the ack frame.
*
* @param[in] frame The pointer to the received frame.
* @param[in] frame The pointer to the received frame. Must not be NULL.
*
* @return
* - True The pending bit should be set, otherwise False.
* - True if the pending bit should be set, otherwise false.
*
*/
bool ieee802154_ack_config_pending_bit(const uint8_t *frame, const esp_ieee802154_frame_info_t *frame_info);
@@ -15,9 +15,9 @@ extern "C" {
#endif
#define IEEE802154_FRAME_MAX_LEN 127
#define IEEE802154_FRAME_MIN_LEN 3
#define IEEE802154_FRAME_INVALID_OFFSET 0xff
#define IEEE802154_FRAME_INVALID_ADDR_MODE 0xff
#define IEEE802154_FRAME_INVALID_VALUE 0xff
#define IEEE802154_FRAME_TYPE_OFFSET 1
#define IEEE802154_FRAME_TYPE_MASK 0x07
@@ -111,7 +111,7 @@ static inline bool ieee802154_is_supported_frame_type(uint8_t frame_type)
/**
* @brief Get the frame type.
*
* @param[in] frame The pointer to the frame.
* @param[in] frame The pointer to the frame. Must not be NULL.
*
* @return
* - The type of the frame.
@@ -122,7 +122,7 @@ uint8_t ieee802154_frame_get_type(const uint8_t *frame);
/**
* @brief Get the frame version.
*
* @param[in] frame The pointer to the frame.
* @param[in] frame The pointer to the frame. Must not be NULL.
*
* @return
* - The version of the frame.
@@ -133,7 +133,7 @@ uint8_t ieee802154_frame_get_version(const uint8_t *frame);
/**
* @brief Is the frame ack required.
*
* @param[in] frame The pointer to the frame.
* @param[in] frame The pointer to the frame. Must not be NULL.
*
* @return
* - True if the frame is ack required, otherwise false.
@@ -154,13 +154,14 @@ bool ieee802154_frame_is_security_enabled(const uint8_t *frame);
/**
* @brief Get the destination address of the frame.
*
* @param[in] frame The pointer to the frame.
* @param[out] addr The pointer to the address.
* @param[in] frame The pointer to the frame. Must not be NULL.
* @param[out] addr The pointer to the address. Must not be NULL.
*
* @return
* - IEEE802154_FRAME_DST_MODE_NONE if destination address mode is none.
* - IEEE802154_FRAME_DST_MODE_SHORT if destination address mode is short.
* - IEEE802154_FRAME_DST_MODE_EXT if destination address mode is extended.
* - IEEE802154_FRAME_INVALID_VALUE if frame is NULL, addr is NULL, or frame type is invalid.
*
*/
uint8_t ieee802154_frame_get_dst_addr(const uint8_t *frame, uint8_t *addr);
@@ -168,49 +169,49 @@ uint8_t ieee802154_frame_get_dst_addr(const uint8_t *frame, uint8_t *addr);
/**
* @brief Get the source address of the frame.
*
* @param[in] frame The pointer to the frame.
* @param[out] addr The pointer to the address.
* @param[in] frame The pointer to the frame. Must not be NULL.
* @param[out] addr The pointer to the address. Must not be NULL.
*
* @return
* - IEEE802154_FRAME_SRC_MODE_NONE if source address mode is none.
* - IEEE802154_FRAME_SRC_MODE_SHORT if source address mode is short.
* - IEEE802154_FRAME_SRC_MODE_EXT if source address mode is extended.
*
* - IEEE802154_FRAME_INVALID_VALUE if frame is NULL, addr is NULL, or frame type is invalid.
*/
uint8_t ieee802154_frame_get_src_addr(const uint8_t *frame, uint8_t *addr);
/**
* @brief Get the offset of the private payload.
*
* @param[in] frame The pointer to the frame.
* @param[in] frame The pointer to the frame. Must not be NULL.
*
* @return
* - The offset of the private payload
*
* - IEEE802154_FRAME_INVALID_VALUE if frame is NULL, or frame type is invalid.
*/
uint8_t ieee802154_frame_get_security_payload_offset(uint8_t *frame);
/**
* @brief Get the destination PAN ID of the frame.
*
* @param[in] frame The pointer to the frame.
* @param[out] panid The pointer to the destination PAN ID.
* @param[in] frame The pointer to the frame. Must not be NULL.
* @param[out] panid The pointer to the destination PAN ID. Must not be NULL.
*
* @return
* - ESP_OK if destination PAN ID is present, otherwise ESP_FAIL.
*
* - ESP_FAIL if frame is NULL, panid is NULL, or frame type is invalid.
*/
esp_err_t ieee802154_frame_get_dest_panid(const uint8_t *frame, uint8_t *panid);
/**
* @brief Get the source PAN ID of the frame.
*
* @param[in] frame The pointer to the frame.
* @param[out] panid The pointer to the source PAN ID.
* @param[in] frame The pointer to the frame. Must not be NULL.
* @param[out] panid The pointer to the source PAN ID. Must not be NULL.
*
* @return
* - ESP_OK if source PAN ID is present, otherwise ESP_FAIL.
*
* - ESP_FAIL if frame is NULL, panid is NULL, or frame type is invalid.
*/
esp_err_t ieee802154_frame_get_src_panid(const uint8_t *frame, uint8_t *panid);
@@ -262,16 +262,16 @@ ieee802154_ll_pending_mode_t ieee802154_pib_get_pending_mode(esp_ieee802154_mult
/**
* @brief Configure the radio mode when the radio is going to enter idle to the PIB.
*
* @param[in] enable True for continuing to receive when the radio is going to enter ilde, otherwise false.
* @param[in] enable True for continuing to receive when the radio is going to enter idle, otherwise false.
*
*/
void ieee802154_pib_set_rx_when_idle(bool enable);
/**
* @brief Get the radio mode when the radio is going to enter ilde to the PIB.
* @brief Get the radio mode when the radio is going to enter idle to the PIB.
*
* @return
* - True for continuing to receive when the radio is going to enter ilde, otherwise false.
* - True for continuing to receive when the radio is going to enter idle, otherwise false.
*
*/
bool ieee802154_pib_get_rx_when_idle(void);
@@ -23,6 +23,12 @@ extern "C" {
#define IEEE802154_OQPSK_2P4G_CHANNEL_MIN 11
#define IEEE802154_OQPSK_2P4G_CHANNEL_MAX 26
#define IEEE802154_RETURN_ON_FALSE_SILENTLY(a, ret) do { \
if (unlikely(!(a))) { \
return ret; \
} \
} while(0)
static inline bool ieee802154_is_valid_channel(uint8_t channel)
{
return ((channel <= IEEE802154_OQPSK_2P4G_CHANNEL_MAX) && (channel >= IEEE802154_OQPSK_2P4G_CHANNEL_MIN));
@@ -401,7 +401,7 @@ void otPlatRadioClearSrcMatchExtEntries(otInstance *aInstance)
otError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel, uint16_t aScanDuration)
{
esp_ieee802154_set_channel(aScanChannel);
esp_ieee802154_energy_detect(aScanDuration * US_PER_MS / US_PER_SYMBLE);
esp_ieee802154_energy_detect(aScanDuration * US_PER_MS / US_PER_SYMBOL);
return OT_ERROR_NONE;
}