Skip to content

Commit

Permalink
ieee802154: copy component from ESP-IDF
Browse files Browse the repository at this point in the history
Commit hash in ESP-IDF: a2f420a36ecf8cd19b443adde1d75e5eaecc6309

Signed-off-by: Martin Jäger <[email protected]>
  • Loading branch information
martinjaeger committed Dec 11, 2024
1 parent 8d35aa7 commit 3efa906
Show file tree
Hide file tree
Showing 28 changed files with 5,293 additions and 0 deletions.
39 changes: 39 additions & 0 deletions components/ieee802154/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
idf_build_get_property(target IDF_TARGET)

if(${target} STREQUAL "linux")
return() # This component is not supported by the POSIX/Linux simulator
endif()

set(srcs "")
set(include "include")
set(private_include "")

if(CONFIG_IEEE802154_ENABLED)
list(APPEND srcs "esp_ieee802154.c"
"driver/esp_ieee802154_ack.c"
"driver/esp_ieee802154_dev.c"
"driver/esp_ieee802154_frame.c"
"driver/esp_ieee802154_pib.c"
"driver/esp_ieee802154_util.c"
"driver/esp_ieee802154_sec.c"
"driver/esp_ieee802154_timer.c")
list(APPEND private_include "private_include")

if(CONFIG_IEEE802154_TEST)
list(REMOVE_ITEM private_include "private_include")
list(APPEND include "private_include")
endif()

endif()

if(CONFIG_IEEE802154_DEBUG)
list(APPEND srcs "driver/esp_ieee802154_debug.c")
endif()

idf_component_register(
SRCS "${srcs}"
INCLUDE_DIRS "${include}"
PRIV_INCLUDE_DIRS "${private_include}"
LDFRAGMENTS linker.lf
PRIV_REQUIRES esp_phy esp_timer esp_coex soc hal esp_pm
)
176 changes: 176 additions & 0 deletions components/ieee802154/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
menu "IEEE 802.15.4"
visible if SOC_IEEE802154_SUPPORTED

config IEEE802154_ENABLED
bool "IEEE802154 Enable"
default "y" if SOC_IEEE802154_SUPPORTED

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

choice IEEE802154_CCA_MODE
depends on IEEE802154_ENABLED
prompt "Clear Channel Assessment (CCA) mode"
default IEEE802154_CCA_ED
help
configure the CCA mode

config IEEE802154_CCA_CARRIER
bool "Carrier sense only"
help
configure the CCA mode to Energy above threshold

config IEEE802154_CCA_ED
bool "Energy above threshold"
help
configure the CCA mode to Energy above threshold

config IEEE802154_CCA_CARRIER_OR_ED
bool "Carrier sense OR energy above threshold"
help
configure the CCA mode to Carrier sense OR energy above threshold

config IEEE802154_CCA_CARRIER_AND_ED
bool "Carrier sense AND energy above threshold"
help
configure the CCA mode to Carrier sense AND energy above threshold
endchoice

config IEEE802154_CCA_MODE
depends on IEEE802154_ENABLED
int
default 0 if IEEE802154_CCA_CARRIER
default 1 if IEEE802154_CCA_ED
default 2 if IEEE802154_CCA_CARRIER_OR_ED
default 3 if IEEE802154_CCA_CARRIER_AND_ED

config IEEE802154_CCA_THRESHOLD
int "CCA detection threshold"
depends on IEEE802154_ENABLED
range -120 0
default -60
help
set the CCA threshold, in dB

config IEEE802154_PENDING_TABLE_SIZE
int "Pending table size"
depends on IEEE802154_ENABLED
range 1 100
default 20
help
set the pending table size

config IEEE802154_MULTI_PAN_ENABLE
bool "Enable multi-pan feature for frame filter"
depends on IEEE802154_ENABLED
default n
help
Enable IEEE802154 multi-pan

config IEEE802154_TIMING_OPTIMIZATION
bool "Enable throughput optimization"
depends on IEEE802154_ENABLED
default n
help
Enabling this option increases throughput by ~5% at the expense of ~2.1k
IRAM code size increase.

config IEEE802154_SLEEP_ENABLE
# Todo: Remove when support safe power-down of the power domain (IDF-7317)
bool "Enable IEEE802154 light sleep"
depends on PM_ENABLE && IEEE802154_ENABLED
default n
help
Enabling this option allows the IEEE802.15.4 module to be powered down during automatic light sleep,
which reduces current consumption.

menuconfig IEEE802154_DEBUG
bool "Enable IEEE802154 Debug"
depends on IEEE802154_ENABLED
default n
help
Enabling this option allows different kinds of IEEE802154 debug output.
All IEEE802154 debug features increase the size of the final binary.

config IEEE802154_ASSERT
bool "Enrich the assert information with IEEE802154 state and event"
depends on IEEE802154_DEBUG
default n
help
Enabling this option to add some probe codes in the driver, and these informations
will be printed when assert.

config IEEE802154_RECORD_EVENT
bool "Enable record event information for debugging"
depends on IEEE802154_DEBUG
default n
help
Enabling this option to record event, when assert, the recorded event will be printed.

config IEEE802154_RECORD_EVENT_SIZE
int "Record event table size"
depends on IEEE802154_RECORD_EVENT
range 1 50
default 30
help
set the record event table size

config IEEE802154_RECORD_STATE
bool "Enable record state information for debugging"
depends on IEEE802154_DEBUG
default n
help
Enabling this option to record state, when assert, the recorded state will be printed.

config IEEE802154_RECORD_STATE_SIZE
int "Record state table size"
depends on IEEE802154_RECORD_STATE
range 1 50
default 10
help
set the record state table size

config IEEE802154_RECORD_CMD
bool "Enable record command information for debugging"
depends on IEEE802154_DEBUG
default n
help
Enabling this option to record the command, when assert, the recorded
command will be printed.

config IEEE802154_RECORD_CMD_SIZE
int "Record command table size"
depends on IEEE802154_RECORD_CMD
range 1 50
default 10
help
set the record command table size

config IEEE802154_RECORD_ABORT
bool "Enable record abort information for debugging"
depends on IEEE802154_DEBUG
default n
help
Enabling this option to record the abort, when assert, the recorded
abort will be printed.

config IEEE802154_RECORD_ABORT_SIZE
int "Record abort table size"
depends on IEEE802154_RECORD_ABORT
range 1 50
default 10
help
set the record abort table size

config IEEE802154_TXRX_STATISTIC
bool "Enable record tx/rx packets information for debugging"
depends on IEEE802154_DEBUG
default n
help
Enabling this option to record the tx and rx
endmenu # IEEE 802.15.4
167 changes: 167 additions & 0 deletions components/ieee802154/driver/esp_ieee802154_ack.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <string.h>
#include "hal/ieee802154_ll.h"
#include "esp_attr.h"
#include "esp_err.h"
#include "esp_ieee802154_ack.h"
#include "esp_ieee802154_dev.h"
#include "esp_ieee802154_frame.h"
#include "esp_ieee802154_pib.h"
#include "esp_ieee802154_types.h"
#include "esp_ieee802154_util.h"

static ieee802154_pending_table_t ieee802154_pending_table;

#define GET_MASK_ITEM_FROM_TABLE(mask, pos) (mask[(pos) / IEEE802154_PENDING_TABLE_MASK_BITS])

#define BIT_SET(mask, pos) (GET_MASK_ITEM_FROM_TABLE(mask, pos) |= (1UL << (pos % IEEE802154_PENDING_TABLE_MASK_BITS)))
#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)
{
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) {
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) {
ret = true;
break;
}
}
}
return ret;
}

esp_err_t ieee802154_add_pending_addr(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)) {
// 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) {
// 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);
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)) {
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) {
// 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);
ret = ESP_OK;
}
}
return ret;
}

esp_err_t ieee802154_clear_pending_addr(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);
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);
ret = ESP_OK;
break;
}
}
}

return ret;
}

void ieee802154_reset_pending_table(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);
} else {
memset(ieee802154_pending_table.ext_addr_mask, 0, IEEE802154_PENDING_TABLE_MASK_SIZE);
}
}

bool ieee802154_ack_config_pending_bit(const uint8_t *frame)
{
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();

switch (pending_mode) {
case IEEE802154_AUTO_PENDING_DISABLE:
// HW will check whether the frame is data request or not
pending_bit = true;
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) {
if (ieee802154_addr_in_pending_table(addr, src_mode == IEEE802154_FRAME_SRC_MODE_SHORT)) {
pending_bit = true;
}
}
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;
}
break;
default:
IEEE802154_ASSERT(false);
}

if (set_to_hw) {
ieee802154_ll_set_pending_bit(pending_bit);
}

return pending_bit;
}
Loading

0 comments on commit 3efa906

Please sign in to comment.