diff --git a/components/esp_phy/lib b/components/esp_phy/lib index 3d57415af6..ac744ff2c5 160000 --- a/components/esp_phy/lib +++ b/components/esp_phy/lib @@ -1 +1 @@ -Subproject commit 3d57415af6e4c92eff2c4c3463e20a51d7340aba +Subproject commit ac744ff2c5c39c63f8cdd503d4074905647fdbb6 diff --git a/components/hal/esp32c5/include/hal/ieee802154_ll.h b/components/hal/esp32c5/include/hal/ieee802154_ll.h index f480050ccd..853781acbd 100644 --- a/components/hal/esp32c5/include/hal/ieee802154_ll.h +++ b/components/hal/esp32c5/include/hal/ieee802154_ll.h @@ -9,8 +9,4 @@ #include #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 diff --git a/components/hal/esp32c6/include/hal/ieee802154_ll.h b/components/hal/esp32c6/include/hal/ieee802154_ll.h index 14e548a1d3..6272766511 100644 --- a/components/hal/esp32c6/include/hal/ieee802154_ll.h +++ b/components/hal/esp32c6/include/hal/ieee802154_ll.h @@ -9,8 +9,4 @@ #include #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 diff --git a/components/hal/esp32h2/include/hal/ieee802154_ll.h b/components/hal/esp32h2/include/hal/ieee802154_ll.h index 2795fc4896..ea0b6dafbc 100644 --- a/components/hal/esp32h2/include/hal/ieee802154_ll.h +++ b/components/hal/esp32h2/include/hal/ieee802154_ll.h @@ -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 diff --git a/components/ieee802154/driver/esp_ieee802154_ack.c b/components/ieee802154/driver/esp_ieee802154_ack.c index 60302a1dd1..ce15b44597 100644 --- a/components/ieee802154/driver/esp_ieee802154_ack.c +++ b/components/ieee802154/driver/esp_ieee802154_ack.c @@ -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); } diff --git a/components/ieee802154/driver/esp_ieee802154_debug.c b/components/ieee802154/driver/esp_ieee802154_debug.c index 8aa30f26cc..5979c0483f 100644 --- a/components/ieee802154/driver/esp_ieee802154_debug.c +++ b/components/ieee802154/driver/esp_ieee802154_debug.c @@ -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) { - s_rx_buffer_used_nums--; + 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, "+-------------------------+-------------------------+"); } diff --git a/components/ieee802154/driver/esp_ieee802154_dev.c b/components/ieee802154/driver/esp_ieee802154_dev.c index 9f497761db..7630e1b9ba 100644 --- a/components/ieee802154/driver/esp_ieee802154_dev.c +++ b/components/ieee802154/driver/esp_ieee802154_dev.c @@ -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_enter_critical(); - ieee802154_etm_set_event_task(IEEE802154_ETM_CHANNEL0, ETM_EVENT_TIMER0_OVERFLOW, ETM_TASK_ED_TRIG_TX); - 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); - } - 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(); } - + 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, cca ? ETM_TASK_ED_TRIG_TX : ETM_TASK_TX_START); + ieee802154_timer0_fire_at(tx_target_time); + ieee802154_exit_critical(); + 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); + } 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; } diff --git a/components/ieee802154/driver/esp_ieee802154_frame.c b/components/ieee802154/driver/esp_ieee802154_frame.c index 35e4eb5b84..4eda910637 100644 --- a/components/ieee802154/driver/esp_ieee802154_frame.c +++ b/components/ieee802154/driver/esp_ieee802154_frame.c @@ -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)) { diff --git a/components/ieee802154/driver/esp_ieee802154_pib.c b/components/ieee802154/driver/esp_ieee802154_pib.c index bcfc13d290..b8a95369db 100644 --- a/components/ieee802154/driver/esp_ieee802154_pib.c +++ b/components/ieee802154/driver/esp_ieee802154_pib.c @@ -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(); diff --git a/components/ieee802154/driver/esp_ieee802154_timer.c b/components/ieee802154/driver/esp_ieee802154_timer.c index d44249e529..f4c6eb2b79 100644 --- a/components/ieee802154/driver/esp_ieee802154_timer.c +++ b/components/ieee802154/driver/esp_ieee802154_timer.c @@ -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; } diff --git a/components/ieee802154/driver/esp_ieee802154_util.c b/components/ieee802154/driver/esp_ieee802154_util.c index 73f31d2b52..a37cf4b6d8 100644 --- a/components/ieee802154/driver/esp_ieee802154_util.c +++ b/components/ieee802154/driver/esp_ieee802154_util.c @@ -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; } diff --git a/components/ieee802154/esp_ieee802154.c b/components/ieee802154/esp_ieee802154.c index 6f6f4282fc..1947c73a52 100644 --- a/components/ieee802154/esp_ieee802154.c +++ b/components/ieee802154/esp_ieee802154.c @@ -8,6 +8,7 @@ #include #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; } @@ -251,7 +260,7 @@ esp_err_t esp_ieee802154_set_ack_timeout(uint32_t timeout) { // Divide by 16 and round it up. uint32_t target_reg_value = (timeout + 15) / 16; - if((timeout % 16) != 0) { + if ((timeout % 16) != 0) { ESP_LOGW(IEEE802154_TAG, "Ack timeout should be a multiple of 16, input %"PRIu32", will be replaced by %"PRIu32"", timeout, (target_reg_value * 16)); } ieee802154_ll_set_ack_timeout(target_reg_value); @@ -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; } diff --git a/components/ieee802154/include/esp_ieee802154.h b/components/ieee802154/include/esp_ieee802154.h index 63cab50d2d..56c45dbd16 100644 --- a/components/ieee802154/include/esp_ieee802154.h +++ b/components/ieee802154/include/esp_ieee802154.h @@ -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); diff --git a/components/ieee802154/include/esp_ieee802154_types.h b/components/ieee802154/include/esp_ieee802154_types.h index ce01937fb9..ddf5d792af 100644 --- a/components/ieee802154/include/esp_ieee802154_types.h +++ b/components/ieee802154/include/esp_ieee802154_types.h @@ -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 #include "esp_err.h" -#define US_PER_SYMBLE 16 +#define US_PER_SYMBOL 16 #ifdef __cplusplus extern "C" { @@ -61,8 +61,8 @@ typedef enum { } esp_ieee802154_pending_mode_t; /** -* @brief The four groups of mac filter interface index. -*/ + * @brief The four groups of mac filter interface index. + */ typedef enum { ESP_IEEE802154_MULTIPAN_0 = 0, ESP_IEEE802154_MULTIPAN_1 = 1, @@ -143,13 +143,13 @@ typedef esp_err_t (*esp_ieee802154_enh_ack_generator_cb_t)(uint8_t *frame, esp_i * */ typedef struct { - esp_ieee802154_receive_done_cb_t rx_done_cb; /*!= IEEE802154_OQPSK_2P4G_CHANNEL_MIN)); diff --git a/components/openthread/src/port/esp_openthread_radio.c b/components/openthread/src/port/esp_openthread_radio.c index c5d32fa09f..fee5c36093 100644 --- a/components/openthread/src/port/esp_openthread_radio.c +++ b/components/openthread/src/port/esp_openthread_radio.c @@ -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; }