Merge branch 'feat/multiple_instance_for_pending_table_v5.2' into 'release/v5.2'

Feat/multiple instance for pending table (v5.2)

See merge request espressif/esp-idf!45102
This commit is contained in:
Shu Chen
2026-01-29 07:24:17 +00:00
14 changed files with 342 additions and 70 deletions
@@ -414,6 +414,11 @@ static inline void ieee802154_ll_set_pending_mode(bool enable)
IEEE802154.conf.pending_enhance = enable;
}
static inline bool ieee802154_ll_get_pending_mode(void)
{
return IEEE802154.conf.pending_enhance;
}
FORCE_INLINE_ATTR void ieee802154_ll_set_pending_bit(bool pending)
{
IEEE802154.pending_cfg.pending = pending;
+10
View File
@@ -72,6 +72,16 @@ menu "IEEE 802.15.4"
help
Enable IEEE802154 multi-pan
config IEEE802154_INTERFACE_NUM
int "Number of IEEE802154 interfaces"
depends on IEEE802154_ENABLED
range 1 1 if !IEEE802154_MULTI_PAN_ENABLE
range 1 4 if IEEE802154_MULTI_PAN_ENABLE
default 1 if !IEEE802154_MULTI_PAN_ENABLE
default 2 if IEEE802154_MULTI_PAN_ENABLE
help
Number of IEEE802154 interfaces
config IEEE802154_TIMING_OPTIMIZATION
bool "Enable throughput optimization"
depends on IEEE802154_ENABLED
@@ -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
*/
@@ -15,7 +15,7 @@
#include "esp_ieee802154_types.h"
#include "esp_ieee802154_util.h"
static ieee802154_pending_table_t ieee802154_pending_table;
static ieee802154_pending_table_t ieee802154_pending_table[CONFIG_IEEE802154_INTERFACE_NUM];
#define GET_MASK_ITEM_FROM_TABLE(mask, pos) (mask[(pos) / IEEE802154_PENDING_TABLE_MASK_BITS])
@@ -23,21 +23,21 @@ static ieee802154_pending_table_t ieee802154_pending_table;
#define BIT_CLR(mask, pos) (GET_MASK_ITEM_FROM_TABLE(mask, pos) &= ~(1UL << (pos % IEEE802154_PENDING_TABLE_MASK_BITS)))
#define BIT_IST(mask, pos) (GET_MASK_ITEM_FROM_TABLE(mask, pos) & (1UL << (pos % IEEE802154_PENDING_TABLE_MASK_BITS)))
static IRAM_ATTR bool ieee802154_addr_in_pending_table(const uint8_t *addr, bool is_short)
static IRAM_ATTR bool ieee802154_addr_in_pending_table(esp_ieee802154_multipan_index_t inf_index, const uint8_t *addr, bool is_short)
{
bool ret = false;
if (is_short) {
for (uint8_t index = 0; index < CONFIG_IEEE802154_PENDING_TABLE_SIZE; index++) {
if (BIT_IST(ieee802154_pending_table.short_addr_mask, index) &&
memcmp(addr, ieee802154_pending_table.short_addr[index], IEEE802154_FRAME_SHORT_ADDR_SIZE) == 0) {
if (BIT_IST(ieee802154_pending_table[inf_index].short_addr_mask, index) &&
memcmp(addr, ieee802154_pending_table[inf_index].short_addr[index], IEEE802154_FRAME_SHORT_ADDR_SIZE) == 0) {
ret = true;
break;
}
}
} else {
for (uint8_t index = 0; index < CONFIG_IEEE802154_PENDING_TABLE_SIZE; index++) {
if (BIT_IST(ieee802154_pending_table.ext_addr_mask, index) &&
memcmp(addr, ieee802154_pending_table.ext_addr[index], IEEE802154_FRAME_EXT_ADDR_SIZE) == 0) {
if (BIT_IST(ieee802154_pending_table[inf_index].ext_addr_mask, index) &&
memcmp(addr, ieee802154_pending_table[inf_index].ext_addr[index], IEEE802154_FRAME_EXT_ADDR_SIZE) == 0) {
ret = true;
break;
}
@@ -46,63 +46,63 @@ static IRAM_ATTR bool ieee802154_addr_in_pending_table(const uint8_t *addr, bool
return ret;
}
esp_err_t ieee802154_add_pending_addr(const uint8_t *addr, bool is_short)
esp_err_t ieee802154_add_pending_addr(esp_ieee802154_multipan_index_t inf_index, const uint8_t *addr, bool is_short)
{
esp_err_t ret = ESP_FAIL;
int8_t first_empty_index = -1;
if (is_short) {
for (uint8_t index = 0; index < CONFIG_IEEE802154_PENDING_TABLE_SIZE; index++) {
if (!BIT_IST(ieee802154_pending_table.short_addr_mask, index)) {
if (!BIT_IST(ieee802154_pending_table[inf_index].short_addr_mask, index)) {
// record the first empty index
first_empty_index = (first_empty_index == -1 ? index : first_empty_index);
} else if (memcmp(addr, ieee802154_pending_table.short_addr[index], IEEE802154_FRAME_SHORT_ADDR_SIZE) == 0) {
} else if (memcmp(addr, ieee802154_pending_table[inf_index].short_addr[index], IEEE802154_FRAME_SHORT_ADDR_SIZE) == 0) {
// The address is in the table already.
ret = ESP_OK;
return ret;
}
}
if (first_empty_index != -1) {
memcpy(ieee802154_pending_table.short_addr[first_empty_index], addr, IEEE802154_FRAME_SHORT_ADDR_SIZE);
BIT_SET(ieee802154_pending_table.short_addr_mask, first_empty_index);
memcpy(ieee802154_pending_table[inf_index].short_addr[first_empty_index], addr, IEEE802154_FRAME_SHORT_ADDR_SIZE);
BIT_SET(ieee802154_pending_table[inf_index].short_addr_mask, first_empty_index);
ret = ESP_OK;
}
} else {
for (uint8_t index = 0; index < CONFIG_IEEE802154_PENDING_TABLE_SIZE; index++) {
if (!BIT_IST(ieee802154_pending_table.ext_addr_mask, index)) {
if (!BIT_IST(ieee802154_pending_table[inf_index].ext_addr_mask, index)) {
first_empty_index = (first_empty_index == -1 ? index : first_empty_index);
} else if (memcmp(addr, ieee802154_pending_table.ext_addr[index], IEEE802154_FRAME_EXT_ADDR_SIZE) == 0) {
} else if (memcmp(addr, ieee802154_pending_table[inf_index].ext_addr[index], IEEE802154_FRAME_EXT_ADDR_SIZE) == 0) {
// The address is already in the pending table.
ret = ESP_OK;
return ret;
}
}
if (first_empty_index != -1) {
memcpy(ieee802154_pending_table.ext_addr[first_empty_index], addr, IEEE802154_FRAME_EXT_ADDR_SIZE);
BIT_SET(ieee802154_pending_table.ext_addr_mask, first_empty_index);
memcpy(ieee802154_pending_table[inf_index].ext_addr[first_empty_index], addr, IEEE802154_FRAME_EXT_ADDR_SIZE);
BIT_SET(ieee802154_pending_table[inf_index].ext_addr_mask, first_empty_index);
ret = ESP_OK;
}
}
return ret;
}
esp_err_t ieee802154_clear_pending_addr(const uint8_t *addr, bool is_short)
esp_err_t ieee802154_clear_pending_addr(esp_ieee802154_multipan_index_t inf_index, const uint8_t *addr, bool is_short)
{
esp_err_t ret = ESP_FAIL;
// Consider this function may be called in ISR, only clear the mask bits for finishing the process quickly.
if (is_short) {
for (uint8_t index = 0; index < CONFIG_IEEE802154_PENDING_TABLE_SIZE; index++) {
if (BIT_IST(ieee802154_pending_table.short_addr_mask, index) &&
memcmp(addr, ieee802154_pending_table.short_addr[index], IEEE802154_FRAME_SHORT_ADDR_SIZE) == 0) {
BIT_CLR(ieee802154_pending_table.short_addr_mask, index);
if (BIT_IST(ieee802154_pending_table[inf_index].short_addr_mask, index) &&
memcmp(addr, ieee802154_pending_table[inf_index].short_addr[index], IEEE802154_FRAME_SHORT_ADDR_SIZE) == 0) {
BIT_CLR(ieee802154_pending_table[inf_index].short_addr_mask, index);
ret = ESP_OK;
break;
}
}
} else {
for (uint8_t index = 0; index < CONFIG_IEEE802154_PENDING_TABLE_SIZE; index++) {
if (BIT_IST(ieee802154_pending_table.ext_addr_mask, index) &&
memcmp(addr, ieee802154_pending_table.ext_addr[index], IEEE802154_FRAME_EXT_ADDR_SIZE) == 0) {
BIT_CLR(ieee802154_pending_table.ext_addr_mask, index);
if (BIT_IST(ieee802154_pending_table[inf_index].ext_addr_mask, index) &&
memcmp(addr, ieee802154_pending_table[inf_index].ext_addr[index], IEEE802154_FRAME_EXT_ADDR_SIZE) == 0) {
BIT_CLR(ieee802154_pending_table[inf_index].ext_addr_mask, index);
ret = ESP_OK;
break;
}
@@ -112,25 +112,39 @@ esp_err_t ieee802154_clear_pending_addr(const uint8_t *addr, bool is_short)
return ret;
}
void ieee802154_reset_pending_table(bool is_short)
void ieee802154_reset_pending_table(esp_ieee802154_multipan_index_t inf_index, bool is_short)
{
// Consider this function may be called in ISR, only clear the mask bits for finishing the process quickly.
if (is_short) {
memset(ieee802154_pending_table.short_addr_mask, 0, IEEE802154_PENDING_TABLE_MASK_SIZE);
memset(ieee802154_pending_table[inf_index].short_addr_mask, 0, IEEE802154_PENDING_TABLE_MASK_SIZE);
} else {
memset(ieee802154_pending_table.ext_addr_mask, 0, IEEE802154_PENDING_TABLE_MASK_SIZE);
memset(ieee802154_pending_table[inf_index].ext_addr_mask, 0, IEEE802154_PENDING_TABLE_MASK_SIZE);
}
}
bool ieee802154_ack_config_pending_bit(const uint8_t *frame)
bool ieee802154_ack_config_pending_bit(const uint8_t *frame, const esp_ieee802154_frame_info_t *frame_info)
{
esp_ieee802154_multipan_index_t inf_index = 0;
#if CONFIG_IEEE802154_MULTI_PAN_ENABLE
inf_index = frame_info->mpf_index;
if (inf_index >= ESP_IEEE802154_MULTIPAN_MAX || inf_index < ESP_IEEE802154_MULTIPAN_0) {
return false;
}
#endif
bool pending_bit = false;
uint8_t addr[IEEE802154_FRAME_EXT_ADDR_SIZE] = {0};
uint8_t src_mode = 0;
// 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);
ieee802154_ll_pending_mode_t pending_mode = ieee802154_pib_get_pending_mode();
// 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) {
pending_bit = ieee802154_is_data_request(frame);
}
ieee802154_ll_pending_mode_t pending_mode = ieee802154_pib_get_pending_mode(inf_index);
switch (pending_mode) {
case IEEE802154_AUTO_PENDING_DISABLE:
@@ -140,20 +154,14 @@ bool ieee802154_ack_config_pending_bit(const uint8_t *frame)
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) {
if (ieee802154_addr_in_pending_table(addr, src_mode == IEEE802154_FRAME_SRC_MODE_SHORT)) {
pending_bit = true;
}
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 = true;
if (src_mode == IEEE802154_FRAME_SRC_MODE_SHORT && ieee802154_addr_in_pending_table(addr, src_mode == IEEE802154_FRAME_SRC_MODE_SHORT)) {
pending_bit = false;
}
pending_bit = !(src_mode == IEEE802154_FRAME_SRC_MODE_SHORT && ieee802154_addr_in_pending_table(inf_index, addr, src_mode == IEEE802154_FRAME_SRC_MODE_SHORT));
break;
default:
IEEE802154_ASSERT(false);
@@ -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
*/
@@ -144,12 +144,93 @@ static IRAM_ATTR void receive_ack_timeout_timer_start(uint32_t duration)
}
#endif
#if CONFIG_IEEE802154_MULTI_PAN_ENABLE
IEEE802154_STATIC IEEE802154_NOINLINE bool is_broadcast_panid(uint8_t *target_panid)
{
if (target_panid[0] == 0xff && target_panid[1] == 0xff) {
return true;
}
return false;
}
static IEEE802154_NOINLINE bool is_broadcast_addr(uint8_t *dest_addr, uint8_t addr_mode)
{
uint8_t target[IEEE802154_FRAME_EXT_ADDR_SIZE] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
if (addr_mode == IEEE802154_FRAME_DST_MODE_NONE) {
return false;
}
size_t addr_size = (addr_mode == IEEE802154_FRAME_DST_MODE_SHORT) ? IEEE802154_FRAME_SHORT_ADDR_SIZE : IEEE802154_FRAME_EXT_ADDR_SIZE;
if (memcmp(dest_addr, target, addr_size) == 0) {
return true;
}
return false;
}
IEEE802154_STATIC IEEE802154_NOINLINE void update_mpf_index(void)
{
uint8_t *frame = s_rx_frame[s_rx_index];
uint8_t frame_type = ieee802154_frame_get_type(frame);
s_rx_frame_info[s_rx_index].mpf_index = ESP_IEEE802154_MULTIPAN_MAX;
bool is_target_panid_present = false;
uint8_t dest_addr_mode = IEEE802154_FRAME_DST_MODE_NONE;
uint8_t dest_addr[IEEE802154_FRAME_EXT_ADDR_SIZE] = {0};
uint8_t target_panid[IEEE802154_FRAME_PANID_SIZE] = {0};
// Get dest addr and panid from the raw packet.
if (frame_type == IEEE802154_FRAME_TYPE_BEACON) {
is_target_panid_present = (ieee802154_frame_get_src_panid(frame, target_panid) == ESP_OK) ? true : false;
} else {
is_target_panid_present = (ieee802154_frame_get_dest_panid(frame, target_panid) == ESP_OK) ? true : false;
}
dest_addr_mode = ieee802154_frame_get_dst_addr(frame, dest_addr);
// Check is this packet is Broadcast
if (is_broadcast_addr(dest_addr, dest_addr_mode) || (is_target_panid_present && is_broadcast_panid(target_panid))) {
return;
}
for (esp_ieee802154_multipan_index_t index = 0; index < CONFIG_IEEE802154_INTERFACE_NUM; index++) {
if (is_target_panid_present == true) {
uint16_t panid = target_panid[1];
panid = (panid << 8) | target_panid[0];
if (panid != esp_ieee802154_get_multipan_panid(index)) {
continue;
}
}
if (dest_addr_mode == IEEE802154_FRAME_DST_MODE_SHORT) {
uint16_t short_addr = dest_addr[1];
short_addr = (short_addr << 8) | dest_addr[0];
if (short_addr != esp_ieee802154_get_multipan_short_address(index)) {
continue;
} else {
s_rx_frame_info[s_rx_index].mpf_index = index;
return;
}
} else if (dest_addr_mode == IEEE802154_FRAME_DST_MODE_EXT) {
uint8_t ext_addr[IEEE802154_FRAME_EXT_ADDR_SIZE] = {0};
esp_ieee802154_get_multipan_extended_address(index, ext_addr);
if (memcmp(dest_addr, ext_addr, IEEE802154_FRAME_EXT_ADDR_SIZE) != 0) {
continue;
} else {
s_rx_frame_info[s_rx_index].mpf_index = index;
return;
}
}
}
}
#endif
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];
#if CONFIG_IEEE802154_MULTI_PAN_ENABLE
update_mpf_index();
#endif
s_rx_frame_info[s_rx_index].channel = ieee802154_freq_to_channel(ieee802154_ll_get_freq());
s_rx_frame_info[s_rx_index].rssi = rssi + IEEE802154_RSSI_COMPENSATION_VALUE;
s_rx_frame_info[s_rx_index].lqi = lqi;
@@ -436,12 +517,12 @@ static IRAM_ATTR void isr_handle_rx_done(void)
&& ieee802154_ll_get_tx_auto_ack()) {
extcoex_tx_stage_start();
// auto tx ack only works for the frame with version 0b00 and 0b01
s_rx_frame_info[s_rx_index].pending = ieee802154_ack_config_pending_bit(s_rx_frame[s_rx_index]);
s_rx_frame_info[s_rx_index].pending = ieee802154_ack_config_pending_bit(s_rx_frame[s_rx_index], &s_rx_frame_info[s_rx_index]);
ieee802154_set_state(IEEE802154_STATE_TX_ACK);
NEEDS_NEXT_OPT(false);
} else if (ieee802154_frame_is_ack_required(s_rx_frame[s_rx_index]) && ieee802154_frame_get_version(s_rx_frame[s_rx_index]) == IEEE802154_FRAME_VERSION_2
&& 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]);
s_rx_frame_info[s_rx_index].pending = ieee802154_ack_config_pending_bit(s_rx_frame[s_rx_index], &s_rx_frame_info[s_rx_index]);
// For 2015 enh-ack, SW should generate an enh-ack then send it manually
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();
@@ -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
*/
@@ -290,6 +290,28 @@ IEEE802154_STATIC IRAM_ATTR uint8_t ieee802154_frame_payload_offset(const uint8_
return offset - 1;
}
bool ieee802154_is_data_request(const uint8_t *frame)
{
if (ieee802154_frame_get_type(frame) != IEEE802154_FRAME_TYPE_COMMAND) {
return false;
}
uint8_t offset = ieee802154_frame_security_header_offset(frame);
if (ieee802154_frame_is_security_enabled(frame)) {
// skip security field.
offset += ieee802154_frame_get_security_field_len(frame);
}
if (ieee802154_frame_get_version(frame) == IEEE802154_FRAME_VERSION_2 && is_ie_present(frame)) {
// skip IE fields.
offset += ieee802154_frame_get_ie_field_len(frame);
}
if (frame[offset] == IEEE802154_CMD_DATA_REQ) {
return true;
}
return false;
}
uint8_t IEEE802154_INLINE ieee802154_frame_get_type(const uint8_t *frame)
{
return frame[IEEE802154_FRAME_TYPE_OFFSET] & IEEE802154_FRAME_TYPE_MASK;
@@ -311,6 +333,9 @@ uint8_t ieee802154_frame_get_dst_addr(const uint8_t *frame, uint8_t *addr)
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");
@@ -335,6 +360,10 @@ uint8_t ieee802154_frame_get_src_addr(const uint8_t *frame, uint8_t *addr)
uint8_t src_mode = src_addr_mode(frame);
uint8_t addr_size;
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");
addr_size = (src_mode == IEEE802154_FRAME_SRC_MODE_SHORT) ? IEEE802154_FRAME_SHORT_ADDR_SIZE : IEEE802154_FRAME_EXT_ADDR_SIZE;
@@ -1,11 +1,12 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <string.h>
#include "sdkconfig.h"
#include "hal/ieee802154_ll.h"
#include "esp_check.h"
#include "esp_ieee802154_pib.h"
@@ -74,7 +75,14 @@ void ieee802154_pib_update(void)
ieee802154_ll_set_coordinator(s_ieee802154_pib.coordinator);
ieee802154_ll_set_promiscuous(s_ieee802154_pib.promiscuous);
ieee802154_ll_set_pending_mode(s_ieee802154_pib.pending_mode == IEEE802154_AUTO_PENDING_ENHANCED);
bool target_mode = false;
for (int i = 0; i < CONFIG_IEEE802154_INTERFACE_NUM; i++) {
if (s_ieee802154_pib.pending_mode[i] == IEEE802154_AUTO_PENDING_ENHANCED || s_ieee802154_pib.pending_mode[i] == IEEE802154_AUTO_PENDING_ZIGBEE) {
target_mode = true;
break;
}
}
ieee802154_ll_set_pending_mode(target_mode);
clr_pending();
}
@@ -231,15 +239,15 @@ void ieee802154_pib_set_coordinator(bool enable)
}
}
ieee802154_ll_pending_mode_t ieee802154_pib_get_pending_mode(void)
ieee802154_ll_pending_mode_t ieee802154_pib_get_pending_mode(esp_ieee802154_multipan_index_t inf_index)
{
return s_ieee802154_pib.pending_mode;
return s_ieee802154_pib.pending_mode[inf_index];
}
void ieee802154_pib_set_pending_mode(ieee802154_ll_pending_mode_t pending_mode)
void ieee802154_pib_set_pending_mode(esp_ieee802154_multipan_index_t inf_index, ieee802154_ll_pending_mode_t pending_mode)
{
if (s_ieee802154_pib.pending_mode != pending_mode) {
s_ieee802154_pib.pending_mode = pending_mode;
if (s_ieee802154_pib.pending_mode[inf_index] != pending_mode) {
s_ieee802154_pib.pending_mode[inf_index] = pending_mode;
set_pending();
}
}
+45 -12
View File
@@ -163,40 +163,40 @@ esp_err_t esp_ieee802154_set_coordinator(bool enable)
uint16_t esp_ieee802154_get_multipan_panid(esp_ieee802154_multipan_index_t index)
{
assert(index < ESP_IEEE802154_MULTIPAN_MAX);
assert(index < CONFIG_IEEE802154_INTERFACE_NUM);
return ieee802154_ll_get_multipan_panid(index);
}
esp_err_t esp_ieee802154_set_multipan_panid(esp_ieee802154_multipan_index_t index, uint16_t panid)
{
assert(index < ESP_IEEE802154_MULTIPAN_MAX);
assert(index < CONFIG_IEEE802154_INTERFACE_NUM);
ieee802154_ll_set_multipan_panid(index, panid);
return ESP_OK;
}
uint16_t esp_ieee802154_get_multipan_short_address(esp_ieee802154_multipan_index_t index)
{
assert(index < ESP_IEEE802154_MULTIPAN_MAX);
assert(index < CONFIG_IEEE802154_INTERFACE_NUM);
return ieee802154_ll_get_multipan_short_addr(index);
}
esp_err_t esp_ieee802154_set_multipan_short_address(esp_ieee802154_multipan_index_t index, uint16_t short_address)
{
assert(index < ESP_IEEE802154_MULTIPAN_MAX);
assert(index < CONFIG_IEEE802154_INTERFACE_NUM);
ieee802154_ll_set_multipan_short_addr(index, short_address);
return ESP_OK;
}
esp_err_t esp_ieee802154_get_multipan_extended_address(esp_ieee802154_multipan_index_t index, uint8_t *ext_addr)
{
assert(index < ESP_IEEE802154_MULTIPAN_MAX);
assert(index < CONFIG_IEEE802154_INTERFACE_NUM);
ieee802154_ll_get_multipan_ext_addr(index, ext_addr);
return ESP_OK;
}
esp_err_t esp_ieee802154_set_multipan_extended_address(esp_ieee802154_multipan_index_t index, const uint8_t *ext_addr)
{
assert(index < ESP_IEEE802154_MULTIPAN_MAX);
assert(index < CONFIG_IEEE802154_INTERFACE_NUM);
ieee802154_ll_set_multipan_ext_addr(index, ext_addr);
return ESP_OK;
}
@@ -208,10 +208,43 @@ uint8_t esp_ieee802154_get_multipan_enable(void)
esp_err_t esp_ieee802154_set_multipan_enable(uint8_t mask)
{
assert(mask < (1 << ESP_IEEE802154_MULTIPAN_MAX));
assert(mask < (1 << CONFIG_IEEE802154_INTERFACE_NUM));
ieee802154_ll_set_multipan_enable_mask(mask);
return ESP_OK;
}
esp_ieee802154_pending_mode_t esp_ieee802154_multipan_get_pending_mode(esp_ieee802154_multipan_index_t index)
{
assert(index < CONFIG_IEEE802154_INTERFACE_NUM);
return ieee802154_pib_get_pending_mode(index);
}
esp_err_t esp_ieee802154_multipan_set_pending_mode(esp_ieee802154_multipan_index_t inf_index, esp_ieee802154_pending_mode_t pending_mode)
{
assert(inf_index < CONFIG_IEEE802154_INTERFACE_NUM);
ieee802154_pib_set_pending_mode(inf_index, pending_mode);
return ESP_OK;
}
esp_err_t esp_ieee802154_multipan_add_pending_addr(esp_ieee802154_multipan_index_t inf_index, const uint8_t *addr, bool is_short)
{
assert(inf_index < CONFIG_IEEE802154_INTERFACE_NUM);
return ieee802154_add_pending_addr(inf_index, addr, is_short);
}
esp_err_t esp_ieee802154_multipan_clear_pending_addr(esp_ieee802154_multipan_index_t inf_index, const uint8_t *addr, bool is_short)
{
assert(inf_index < CONFIG_IEEE802154_INTERFACE_NUM);
return ieee802154_clear_pending_addr(inf_index, addr, is_short);
}
esp_err_t esp_ieee802154_multipan_reset_pending_table(esp_ieee802154_multipan_index_t inf_index, bool is_short)
{
assert(inf_index < CONFIG_IEEE802154_INTERFACE_NUM);
ieee802154_reset_pending_table(inf_index, is_short);
return ESP_OK;
}
#endif // CONFIG_IEEE802154_MULTI_PAN_ENABLE
esp_err_t esp_ieee802154_set_ack_timeout(uint32_t timeout)
@@ -266,12 +299,12 @@ esp_err_t esp_ieee802154_set_extended_address(const uint8_t *ext_addr)
esp_ieee802154_pending_mode_t esp_ieee802154_get_pending_mode(void)
{
return ieee802154_pib_get_pending_mode();
return ieee802154_pib_get_pending_mode(ESP_IEEE802154_MULTIPAN_0);
}
esp_err_t esp_ieee802154_set_pending_mode(esp_ieee802154_pending_mode_t pending_mode)
{
ieee802154_pib_set_pending_mode(pending_mode);
ieee802154_pib_set_pending_mode(ESP_IEEE802154_MULTIPAN_0, pending_mode);
return ESP_OK;
}
@@ -359,17 +392,17 @@ esp_err_t esp_ieee802154_set_transmit_security(uint8_t *frame, uint8_t *key, uin
esp_err_t esp_ieee802154_add_pending_addr(const uint8_t *addr, bool is_short)
{
return ieee802154_add_pending_addr(addr, is_short);
return ieee802154_add_pending_addr(0, addr, is_short);
}
esp_err_t esp_ieee802154_clear_pending_addr(const uint8_t *addr, bool is_short)
{
return ieee802154_clear_pending_addr(addr, is_short);
return ieee802154_clear_pending_addr(0, addr, is_short);
}
esp_err_t esp_ieee802154_reset_pending_table(bool is_short)
{
ieee802154_reset_pending_table(is_short);
ieee802154_reset_pending_table(0, is_short);
return ESP_OK;
}
+75 -1
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -756,6 +756,80 @@ esp_err_t esp_ieee802154_event_callback_list_register(esp_ieee802154_event_cb_li
*/
esp_err_t esp_ieee802154_event_callback_list_unregister(void);
/**
* @brief Add a pending address to the multipan table for the specified interface.
*
* @note This API should be called only when the IEEE 802.15.4 subsystem is enabled.
*
* @param inf_index Index of the interface.
* @param addr Pointer to the address to add.
* @param is_short True if the address is a short address, false if extended.
*
* @return
* - ESP_OK on success.
* - ESP_FAIL on failure.
*/
esp_err_t esp_ieee802154_multipan_add_pending_addr(esp_ieee802154_multipan_index_t inf_index, const uint8_t *addr, bool is_short);
/**
* @brief Remove a pending address from the multipan table for the specified interface.
*
* @note This API should be called only when the IEEE 802.15.4 subsystem is enabled.
*
* @param inf_index Index of the interface.
* @param addr Pointer to the address to remove.
* @param is_short True if the address is a short address, false if extended.
*
* @return
* - ESP_OK on success.
* - ESP_FAIL on failure.
*/
esp_err_t esp_ieee802154_multipan_clear_pending_addr(esp_ieee802154_multipan_index_t inf_index, const uint8_t *addr, bool is_short);
/**
* @brief Reset the pending address table for the specified interface.
*
* @note This API clears all pending addresses of the specified type (short or extended) for the interface.
*
* @param inf_index Index of the interface.
* @param is_short True to reset short addresses, false to reset extended addresses.
*
* @return
* - ESP_OK on success.
* - ESP_FAIL on failure.
*/
esp_err_t esp_ieee802154_multipan_reset_pending_table(esp_ieee802154_multipan_index_t inf_index, bool is_short);
/**
* @brief Get the auto frame pending mode of the specified multipan interface.
*
* @note This API returns the logical pending mode configured for a given multipan
* interface. The value is used by the ACK generation logic together with the
* per-interface pending address table.
*
* @param inf_index Index of the multipan interface.
*
* @return
* - The auto frame pending mode, refer to esp_ieee802154_pending_mode_t.
*/
esp_ieee802154_pending_mode_t esp_ieee802154_multipan_get_pending_mode(esp_ieee802154_multipan_index_t inf_index);
/**
* @brief Set the auto frame pending mode of the specified multipan interface.
*
* @note This API configures the logical pending mode for a given multipan interface.
* The configured mode is used by the ACK generation logic together with the
* per-interface pending address table.
*
* @param inf_index Index of the multipan interface.
* @param pending_mode Pending mode to set for this interface.
*
* @return
* - ESP_OK on success.
* - ESP_FAIL on failure.
*/
esp_err_t esp_ieee802154_multipan_set_pending_mode(esp_ieee802154_multipan_index_t inf_index, esp_ieee802154_pending_mode_t pending_mode);
#ifdef __cplusplus
}
#endif
@@ -82,6 +82,7 @@ typedef struct {
int8_t rssi; /*!< RSSI */
uint8_t lqi; /*!< LQI */
uint64_t timestamp; /*!< The timestamp when the frame's SFD field was received */
esp_ieee802154_multipan_index_t mpf_index; /*!< Multipan interface that matches the frame, ESP_IEEE802154_MULTIPAN_MAX if none */
} esp_ieee802154_frame_info_t;
/**
+12
View File
@@ -17,7 +17,11 @@ entries:
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: ieee802154_frame_get_dest_panid (noflash)
esp_ieee802154_frame: ieee802154_frame_get_dst_addr (noflash)
esp_ieee802154_frame: ieee802154_frame_get_src_panid (noflash)
esp_ieee802154_frame: ieee802154_frame_is_security_enabled(noflash)
esp_ieee802154_frame: ieee802154_is_data_request (noflash)
esp_ieee802154_frame: is_dst_panid_present (noflash)
esp_ieee802154_frame: is_src_panid_present (noflash)
esp_ieee802154_pib: ieee802154_pib_get_pending_mode (noflash)
@@ -73,3 +77,11 @@ entries:
esp_ieee802154_timer: isr_handle_timer0_done (noflash)
esp_ieee802154_timer: isr_handle_timer1_done (noflash)
esp_ieee802154_util: ieee802154_channel_to_freq (noflash)
if IEEE802154_MULTI_PAN_ENABLE = y:
esp_ieee802154: esp_ieee802154_get_multipan_extended_address (noflash)
esp_ieee802154: esp_ieee802154_get_multipan_panid (noflash)
esp_ieee802154: esp_ieee802154_get_multipan_short_address (noflash)
esp_ieee802154_dev: is_broadcast_addr (noflash)
esp_ieee802154_dev: is_broadcast_panid (noflash)
esp_ieee802154_dev: update_mpf_index (noflash)
@@ -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
*/
@@ -10,6 +10,7 @@
#include <stdbool.h>
#include "sdkconfig.h"
#include "esp_err.h"
#include "esp_ieee802154_types.h"
#include "esp_ieee802154_frame.h"
#ifdef __cplusplus
@@ -40,7 +41,7 @@ typedef struct {
* - ESP_FAIL on failure due to the table is full.
*
*/
esp_err_t ieee802154_add_pending_addr(const uint8_t *addr, bool is_short);
esp_err_t ieee802154_add_pending_addr(esp_ieee802154_multipan_index_t inf_index, const uint8_t *addr, bool is_short);
/**
* @brief Remove an address in pending table.
@@ -53,7 +54,7 @@ esp_err_t ieee802154_add_pending_addr(const uint8_t *addr, bool is_short);
* - ESP_FAIL on failure if the given address is not present in the pending table.
*
*/
esp_err_t ieee802154_clear_pending_addr(const uint8_t *addr, bool is_short);
esp_err_t ieee802154_clear_pending_addr(esp_ieee802154_multipan_index_t inf_index, const uint8_t *addr, bool is_short);
/**
* @brief Reset the pending table, only clear the mask bits for finishing the process quickly.
@@ -61,7 +62,7 @@ esp_err_t ieee802154_clear_pending_addr(const uint8_t *addr, bool is_short);
* @param[in] is_short The type of address, true for resetting short address table, false for extended.
*
*/
void ieee802154_reset_pending_table(bool is_short);
void ieee802154_reset_pending_table(esp_ieee802154_multipan_index_t inf_index, bool is_short);
/**
* @brief Check whether the pending bit should be set or not in the ack frame.
@@ -72,7 +73,7 @@ void ieee802154_reset_pending_table(bool is_short);
* - True The pending bit should be set, otherwise False.
*
*/
bool ieee802154_ack_config_pending_bit(const uint8_t *frame);
bool ieee802154_ack_config_pending_bit(const uint8_t *frame, const esp_ieee802154_frame_info_t *frame_info);
#ifdef __cplusplus
}
@@ -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
*/
@@ -213,6 +213,15 @@ esp_err_t ieee802154_frame_get_dest_panid(const uint8_t *frame, uint8_t *panid);
*
*/
esp_err_t ieee802154_frame_get_src_panid(const uint8_t *frame, uint8_t *panid);
/**
* @brief Check whether the given frame is a MAC Data Request command.
*
* @param[in] frame Pointer to the raw MAC frame buffer.
*
* @return true if the frame is a Data Request command, false otherwise.
*/
bool ieee802154_is_data_request(const uint8_t *frame);
#ifdef __cplusplus
}
#endif
@@ -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
*/
@@ -8,6 +8,7 @@
#include <stdbool.h>
#include <stdint.h>
#include "sdkconfig.h"
#include "hal/ieee802154_ll.h"
#include "esp_ieee802154_frame.h"
#include "esp_ieee802154_types.h"
@@ -28,7 +29,7 @@ typedef struct {
bool rx_when_idle; /*!< A flag indicates the device is rx on when idle or not */
esp_ieee802154_txpower_table_t power_table; /*!< The power table configuration */
uint8_t channel; /*!< Channel configuration */
ieee802154_ll_pending_mode_t pending_mode; /*!< Pending mode configuration */
ieee802154_ll_pending_mode_t pending_mode[CONFIG_IEEE802154_INTERFACE_NUM]; /*!< Pending mode configuration */
int8_t cca_threshold; /*!< CCA threshold */
ieee802154_ll_cca_mode_t cca_mode; /*!< CCA mode */
} ieee802154_pib_t;
@@ -248,7 +249,7 @@ bool ieee802154_pib_get_coordinator(void);
* @param[in] pending_mode The pending mode.
*
*/
void ieee802154_pib_set_pending_mode(ieee802154_ll_pending_mode_t pending_mode);
void ieee802154_pib_set_pending_mode(esp_ieee802154_multipan_index_t inf_index, ieee802154_ll_pending_mode_t pending_mode);
/**
* @brief Get the pending mode from the PIB.
@@ -256,7 +257,7 @@ void ieee802154_pib_set_pending_mode(ieee802154_ll_pending_mode_t pending_mode);
* @return
* - The pending mode has been set in the PIB.
*/
ieee802154_ll_pending_mode_t ieee802154_pib_get_pending_mode(void);
ieee802154_ll_pending_mode_t ieee802154_pib_get_pending_mode(esp_ieee802154_multipan_index_t inf_index);
/**
* @brief Configure the radio mode when the radio is going to enter idle to the PIB.