drivers: nrf_802154: Update the IEEE 802.15.4 component

This commit updates the nRF 802.15.4 radio driver to feature the latest
changes.

sdk-nrf-802154 commit: e9eca1e61abc07f34604fa8154ca2eaca6f3c922

Signed-off-by: Jędrzej Ciupis <jedrzej.ciupis@nordicsemi.no>
This commit is contained in:
Jędrzej Ciupis 2023-03-06 14:04:29 +01:00 committed by Robert Lubos
parent 6c9f23498e
commit 609d4b41fe
38 changed files with 1060 additions and 758 deletions

View File

@ -39,3 +39,7 @@ add_subdirectory(driver)
add_subdirectory(sl)
add_subdirectory(serialization)
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/internal/CMakeLists.txt)
add_subdirectory(internal)
endif ()

View File

@ -106,6 +106,12 @@ if (SL_OPENSOURCE)
)
endif()
target_compile_definitions(nrf-802154-driver-interface
INTERFACE
# Disable total times measurement
NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED=0
)
if (NRF_802154_PROJECT_CONFIG)
target_compile_definitions(nrf-802154-driver-interface
INTERFACE

View File

@ -1775,6 +1775,13 @@ nrf_802154_capabilities_t nrf_802154_capabilities_get(void);
*/
void nrf_802154_security_global_frame_counter_set(uint32_t frame_counter);
/**
* @brief Sets nRF 802.15.4 Radio Driver MAC Global Frame Counter if the value passed is larger than current.
*
* @param[in] frame_counter Frame counter to set.
*/
void nrf_802154_security_global_frame_counter_set_if_larger(uint32_t frame_counter);
/**
* @brief Store the 802.15.4 MAC Security Key inside the nRF 802.15.4 Radio Driver.
*

View File

@ -41,6 +41,10 @@
#include <nrfx.h>
#if NRF_802154_USE_INTERNAL_INCLUDES
#include "nrf_802154_config_internal.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -198,21 +202,6 @@ extern "C" {
#define NRF_802154_RX_BUFFERS 16
#endif
/**
* @def NRF_802154_DISABLE_BCC_MATCHING
*
* Setting this flag disables NRF_RADIO_EVENT_BCMATCH handling, and therefore the address filtering
* during the frame reception. With this flag set to 1, the address filtering is done after
* receiving a frame, during NRF_RADIO_EVENT_END handling.
*
* @note This option is incompatible with antenna diversity. If set to 1, antenna diversity
* must not be used.
*
*/
#ifndef NRF_802154_DISABLE_BCC_MATCHING
#define NRF_802154_DISABLE_BCC_MATCHING 0
#endif
/**
* @def NRF_802154_NOTIFY_CRCERROR
*
@ -245,12 +234,11 @@ extern "C" {
*
* If measurement of total time spent in certain states is to be calculated.
*
* This option can be enabled when @ref NRF_802154_FRAME_TIMESTAMP_ENABLED is 1
* and @ref NRF_802154_DISABLE_BCC_MATCHING is 0.
* This option can be enabled when @ref NRF_802154_FRAME_TIMESTAMP_ENABLED is 1.
*/
#ifndef NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED
#define NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED \
(1 && NRF_802154_FRAME_TIMESTAMP_ENABLED && !NRF_802154_DISABLE_BCC_MATCHING)
(1 && NRF_802154_FRAME_TIMESTAMP_ENABLED)
#endif
/**
@ -430,22 +418,6 @@ extern "C" {
* @{
*/
/**
* @def NRF_802154_TX_STARTED_NOTIFY_ENABLED
*
* Indicates whether the notifications of the started transmissions are to be enabled in the driver.
*
* @note This feature is enabled by default if the ACK timeout feature or CSMA-CA is enabled.
* These features depend on the notifications of the transmission start.
*/
#ifndef NRF_802154_TX_STARTED_NOTIFY_ENABLED
#if NRF_802154_ACK_TIMEOUT_ENABLED || NRF_802154_CSMA_CA_ENABLED
#define NRF_802154_TX_STARTED_NOTIFY_ENABLED 1
#else
#define NRF_802154_TX_STARTED_NOTIFY_ENABLED 0
#endif
#endif // NRF_802154_TX_STARTED_NOTIFY_ENABLED
/**
* @}
* @defgroup nrf_802154_config_coex WiFi coexistence feature configuration

View File

@ -474,13 +474,11 @@ static bool encryption_prepare(const nrf_802154_frame_parser_data_t * p_ack_data
* @section Enhanced ACK generation
**************************************************************************************************/
static void fcf_process(const nrf_802154_frame_parser_data_t * p_frame_data,
uint8_t * p_bytes_written)
static void fcf_process(const nrf_802154_frame_parser_data_t * p_frame_data)
{
// Set Frame Control field bits.
// Some of them might require correction when higher parse level is available
*p_bytes_written = frame_control_set(p_frame_data, false);
m_ack[PHR_OFFSET] += *p_bytes_written;
m_ack[PHR_OFFSET] += frame_control_set(p_frame_data, false);
bool result = nrf_802154_frame_parser_valid_data_extend(&m_ack_data,
m_ack[PHR_OFFSET] + PHR_SIZE,
@ -490,27 +488,13 @@ static void fcf_process(const nrf_802154_frame_parser_data_t * p_frame_data,
(void)result;
}
static void dst_addr_process(const nrf_802154_frame_parser_data_t * p_frame_data,
uint8_t * p_bytes_written)
{
// Set valid sequence number in ACK frame.
*p_bytes_written = sequence_number_set(p_frame_data);
m_ack[PHR_OFFSET] += *p_bytes_written;
// Set destination address and PAN ID.
*p_bytes_written = destination_set(p_frame_data, &m_ack_data);
m_ack[PHR_OFFSET] += *p_bytes_written;
bool result = nrf_802154_frame_parser_valid_data_extend(&m_ack_data,
m_ack[PHR_OFFSET] + PHR_SIZE,
PARSE_LEVEL_DST_ADDRESSING_END);
assert(result);
(void)result;
}
static void addr_end_process(const nrf_802154_frame_parser_data_t * p_frame_data)
{
// Set valid sequence number in ACK frame.
m_ack[PHR_OFFSET] += sequence_number_set(p_frame_data);
// Set destination address and PAN ID.
m_ack[PHR_OFFSET] += destination_set(p_frame_data, &m_ack_data);
// Set source address and PAN ID.
source_set();
@ -532,15 +516,16 @@ static void addr_end_process(const nrf_802154_frame_parser_data_t * p_frame_data
(void)result;
}
static bool aux_sec_hdr_process(const nrf_802154_frame_parser_data_t * p_frame_data,
uint8_t * p_bytes_written)
static bool aux_sec_hdr_process(const nrf_802154_frame_parser_data_t * p_frame_data)
{
if (security_header_set(p_frame_data, &m_ack_data, p_bytes_written) == false)
uint8_t bytes_written;
if (security_header_set(p_frame_data, &m_ack_data, &bytes_written) == false)
{
return false;
}
m_ack[PHR_OFFSET] += *p_bytes_written;
m_ack[PHR_OFFSET] += bytes_written;
bool result = nrf_802154_frame_parser_valid_data_extend(&m_ack_data,
m_ack[PHR_OFFSET] + PHR_SIZE,
@ -552,16 +537,14 @@ static bool aux_sec_hdr_process(const nrf_802154_frame_parser_data_t * p_frame_d
return true;
}
static void ie_process(const nrf_802154_frame_parser_data_t * p_frame_data,
uint8_t * p_bytes_written)
static void ie_process(const nrf_802154_frame_parser_data_t * p_frame_data)
{
// Set IE header.
ie_header_set(mp_ie_data, m_ie_data_len, &m_ack_data);
m_ack[PHR_OFFSET] += m_ie_data_len;
// Terminate the IE header if needed.
*p_bytes_written = ie_header_terminate(mp_ie_data, m_ie_data_len, &m_ack_data);
m_ack[PHR_OFFSET] += *p_bytes_written + FCS_SIZE;
m_ack[PHR_OFFSET] += ie_header_terminate(mp_ie_data, m_ie_data_len, &m_ack_data) + FCS_SIZE;
bool result = nrf_802154_frame_parser_valid_data_extend(&m_ack_data,
m_ack[PHR_OFFSET] + PHR_SIZE,
@ -580,8 +563,6 @@ static uint8_t * ack_process(
const nrf_802154_frame_parser_data_t * p_frame_data,
bool * p_processing_done)
{
uint8_t bytes_written = 0U;
nrf_802154_frame_parser_level_t frame_parse_level = nrf_802154_frame_parser_parse_level_get(
p_frame_data);
nrf_802154_frame_parser_level_t ack_parse_level = nrf_802154_frame_parser_parse_level_get(
@ -592,13 +573,7 @@ static uint8_t * ack_process(
if ((frame_parse_level >= PARSE_LEVEL_FCF_OFFSETS) &&
(ack_parse_level < PARSE_LEVEL_FCF_OFFSETS))
{
fcf_process(p_frame_data, &bytes_written);
}
if ((frame_parse_level >= PARSE_LEVEL_DST_ADDRESSING_END) &&
(ack_parse_level < PARSE_LEVEL_DST_ADDRESSING_END))
{
dst_addr_process(p_frame_data, &bytes_written);
fcf_process(p_frame_data);
}
if ((frame_parse_level >= PARSE_LEVEL_ADDRESSING_END) &&
@ -610,14 +585,14 @@ static uint8_t * ack_process(
if ((frame_parse_level >= PARSE_LEVEL_AUX_SEC_HDR_END) &&
(ack_parse_level < PARSE_LEVEL_AUX_SEC_HDR_END))
{
if (!aux_sec_hdr_process(p_frame_data, &bytes_written))
if (!aux_sec_hdr_process(p_frame_data))
{
// Failure to set auxiliary security header, the ACK cannot be created. Exit immediately
*p_processing_done = true;
return NULL;
}
ie_process(p_frame_data, &bytes_written);
ie_process(p_frame_data);
}
if (frame_parse_level == PARSE_LEVEL_FULL)

View File

@ -271,6 +271,7 @@ static void random_backoff_start(void)
rsch_dly_ts_param_t backoff_ts_param =
{
.trigger_time = nrf_802154_sl_timer_current_time_get() + backoff_us,
.ppi_trigger_en = false,
.op = RSCH_DLY_TS_OP_CSMACA,
.type = RSCH_DLY_TS_TYPE_RELAXED,
.started_callback = frame_transmit,

View File

@ -62,14 +62,19 @@
#include "nrf_802154_sl_utils.h"
#include "nrf_802154_sl_atomics.h"
#ifdef NRF_802154_USE_INTERNAL_INCLUDES
#include "nrf_802154_delayed_trx_internal.h"
#endif
#if NRF_802154_DELAYED_TRX_ENABLED
/* The following time is the sum of 70us RTC_IRQHandler processing time, 40us of time that elapses
* from the moment a board starts transmission to the moment other boards (e.g. sniffer) are able
* to detect that frame and in case of TX - 93us that accounts for a delay of yet unknown origin.
*/
#define TX_SETUP_TIME 203u ///< Time needed to prepare TX procedure [us]. It does not include TX ramp-up time.
#define RX_SETUP_TIME 110u ///< Time needed to prepare RX procedure [us]. It does not include RX ramp-up time.
#if defined(NRF52_SERIES)
#define TX_SETUP_TIME_MAX 270u ///< Maximum time needed to prepare TX procedure [us]. It does not include TX ramp-up time.
#define RX_SETUP_TIME_MAX 270u ///< Maximum time needed to prepare RX procedure [us]. It does not include RX ramp-up time.
#elif defined(NRF53_SERIES)
#define TX_SETUP_TIME_MAX 360u ///< Maximum time needed to prepare TX procedure [us]. It does not include TX ramp-up time.
#define RX_SETUP_TIME_MAX 290u ///< Maximum time needed to prepare RX procedure [us]. It does not include RX ramp-up time.
#endif
/**
* @brief States of delayed operations.
@ -768,7 +773,7 @@ bool nrf_802154_delayed_trx_transmit(uint8_t * p
if (p_dly_tx_data != NULL)
{
tx_time -= TX_SETUP_TIME;
tx_time -= TX_SETUP_TIME_MAX;
tx_time -= TX_RAMP_UP_TIME;
if (p_metadata->cca)
@ -791,6 +796,8 @@ bool nrf_802154_delayed_trx_transmit(uint8_t * p
rsch_dly_ts_param_t dly_ts_param =
{
.trigger_time = tx_time,
.ppi_trigger_en = true,
.ppi_trigger_dly = TX_SETUP_TIME_MAX,
.prio = RSCH_PRIO_TX,
.op = RSCH_DLY_TS_OP_DTX,
.type = RSCH_DLY_TS_TYPE_PRECISE,
@ -814,12 +821,13 @@ bool nrf_802154_delayed_trx_receive(uint64_t rx_time,
if (p_dly_rx_data != NULL)
{
rx_time -= RX_SETUP_TIME;
rx_time -= RX_SETUP_TIME_MAX;
rx_time -= RX_RAMP_UP_TIME;
p_dly_rx_data->op = RSCH_DLY_TS_OP_DRX;
p_dly_rx_data->rx.timeout_length = timeout + RX_RAMP_UP_TIME;
p_dly_rx_data->rx.timeout_length = timeout + RX_RAMP_UP_TIME +
RX_SETUP_TIME_MAX;
p_dly_rx_data->rx.timeout_timer.action.callback.callback = notify_rx_timeout;
p_dly_rx_data->rx.channel = channel;
@ -828,6 +836,8 @@ bool nrf_802154_delayed_trx_receive(uint64_t rx_time,
rsch_dly_ts_param_t dly_ts_param =
{
.trigger_time = rx_time,
.ppi_trigger_en = true,
.ppi_trigger_dly = RX_SETUP_TIME_MAX,
.prio = RSCH_PRIO_IDLE_LISTENING,
.op = RSCH_DLY_TS_OP_DRX,
.type = RSCH_DLY_TS_TYPE_PRECISE,
@ -938,6 +948,7 @@ bool nrf_802154_delayed_trx_nearest_drx_time_to_midpoint_get(uint32_t * p_drx_ti
uint32_t min_time_to_start = 0xffffffff;
uint64_t drx_time_to_start = UINT64_C(0xffffffff);
uint32_t drx_time_to_midpoint;
uint32_t drx_window_duration_time;
for (int i = 0; i < sizeof(m_dly_rx_data) / sizeof(m_dly_rx_data[0]); i++)
{
@ -948,13 +959,15 @@ bool nrf_802154_delayed_trx_nearest_drx_time_to_midpoint_get(uint32_t * p_drx_ti
result = nrf_802154_rsch_delayed_timeslot_time_to_start_get(m_dly_rx_data[i].id,
&drx_time_to_start);
drx_time_to_start += RX_SETUP_TIME + RX_RAMP_UP_TIME;
drx_time_to_start += RX_SETUP_TIME_MAX + RX_RAMP_UP_TIME;
if (result)
{
min_time_to_start = drx_time_to_start < min_time_to_start ?
(uint32_t)drx_time_to_start : min_time_to_start;
drx_time_to_midpoint = min_time_to_start + m_dly_rx_data[i].rx.timeout_length / 2;
drx_window_duration_time = m_dly_rx_data[i].rx.timeout_length -
(RX_SETUP_TIME_MAX + RX_RAMP_UP_TIME);
drx_time_to_midpoint = min_time_to_start + drx_window_duration_time / 2;
}
}

View File

@ -132,7 +132,7 @@ static bool dst_addressing_may_be_present(uint8_t frame_type)
}
/**
* @brief Get offset of end of addressing fields for given frame assuming its version is 2006.
* @brief Verify if destination addressing bits in the FCF field are correct assuming its version is 2006.
*
* If given frame contains errors that prevent getting offset, this function returns
* NRF_802154_RX_ERROR_INVALID_FRAME. If there are no destination address fields in given frame,
@ -140,11 +140,9 @@ static bool dst_addressing_may_be_present(uint8_t frame_type)
* beacon.
* If both of those conditions are not met, the function returns
* NRF_802154_RX_ERROR_INVALID_DEST_ADDR.
* Otherwise, this function returns NRF_802154_RX_ERROR_NONE and inserts offset of addressing
* fields end to @p p_num_bytes.
* Otherwise, this function returns NRF_802154_RX_ERROR_NONE.
*
* @param[in] p_frame_data Pointer to the frame parser data.
* @param[out] p_num_bytes Offset of addressing fields end.
* @param[in] frame_type Type of incoming frame.
*
* @retval NRF_802154_RX_ERROR_NONE No errors in given frame were detected - it may be
@ -153,9 +151,8 @@ static bool dst_addressing_may_be_present(uint8_t frame_type)
* @retval NRF_802154_RX_ERROR_INVALID_FRAME Detected an error in given frame - it should be
* discarded.
*/
static nrf_802154_rx_error_t dst_addressing_end_offset_get_2006(
static nrf_802154_rx_error_t dst_addressing_fcf_check_2006(
const nrf_802154_frame_parser_data_t * p_frame_data,
uint8_t * p_num_bytes,
uint8_t frame_type)
{
nrf_802154_rx_error_t result;
@ -163,13 +160,11 @@ static nrf_802154_rx_error_t dst_addressing_end_offset_get_2006(
switch (nrf_802154_frame_parser_dst_addr_type_get(p_frame_data))
{
case DEST_ADDR_TYPE_SHORT:
*p_num_bytes = SHORT_ADDR_CHECK_OFFSET;
result = NRF_802154_RX_ERROR_NONE;
result = NRF_802154_RX_ERROR_NONE;
break;
case DEST_ADDR_TYPE_EXTENDED:
*p_num_bytes = EXTENDED_ADDR_CHECK_OFFSET;
result = NRF_802154_RX_ERROR_NONE;
result = NRF_802154_RX_ERROR_NONE;
break;
case DEST_ADDR_TYPE_NONE:
@ -179,8 +174,7 @@ static nrf_802154_rx_error_t dst_addressing_end_offset_get_2006(
{
case SRC_ADDR_TYPE_SHORT:
case SRC_ADDR_TYPE_EXTENDED:
*p_num_bytes = PANID_CHECK_OFFSET;
result = NRF_802154_RX_ERROR_NONE;
result = NRF_802154_RX_ERROR_NONE;
break;
default:
@ -202,15 +196,13 @@ static nrf_802154_rx_error_t dst_addressing_end_offset_get_2006(
}
/**
* @brief Get offset of end of addressing fields for given frame assuming its version is 2015.
* @brief Verify if destination addressing bits in the FCF field are correct assuming its version is 2015.
*
* If given frame contains errors that prevent getting offset, this function returns
* NRF_802154_RX_ERROR_INVALID_FRAME.
* Otherwise, this function returns NRF_802154_RX_ERROR_NONE and inserts offset of addressing
* fields end to @p p_num_bytes.
* Otherwise, this function returns NRF_802154_RX_ERROR_NONE.
*
* @param[in] p_frame_data Pointer to the frame parser data.
* @param[out] p_num_bytes Offset of addressing fields end.
* @param[in] frame_type Type of incoming frame.
*
* @retval NRF_802154_RX_ERROR_NONE No errors in given frame were detected - it may be
@ -218,9 +210,8 @@ static nrf_802154_rx_error_t dst_addressing_end_offset_get_2006(
* @retval NRF_802154_RX_ERROR_INVALID_FRAME Detected an error in given frame - it should be
* discarded.
*/
static nrf_802154_rx_error_t dst_addressing_end_offset_get_2015(
static nrf_802154_rx_error_t dst_addressing_fcf_check_2015(
const nrf_802154_frame_parser_data_t * p_frame_data,
uint8_t * p_num_bytes,
uint8_t frame_type)
{
nrf_802154_rx_error_t result;
@ -241,8 +232,7 @@ static nrf_802154_rx_error_t dst_addressing_end_offset_get_2015(
}
else
{
*p_num_bytes = end_offset;
result = NRF_802154_RX_ERROR_NONE;
result = NRF_802154_RX_ERROR_NONE;
}
}
break;
@ -266,13 +256,12 @@ static nrf_802154_rx_error_t dst_addressing_end_offset_get_2015(
}
/**
* @brief Get offset of end of addressing fields for given frame.
* @brief Verify if destination addressing bits in the FCF field are correct.
*
* This function relays its arguments to either @ref dst_addressing_end_offset_get_2006
* or @ref dst_addressing_end_offset_get_2015 depending on the frame version.
*
* @param[in] p_frame_data Pointer to the frame parser data.
* @param[out] p_num_bytes Offset of addressing fields end.
* @param[in] frame_type Type of incoming frame.
* @param[in] frame_version Version of the incoming frame.
*
@ -282,9 +271,8 @@ static nrf_802154_rx_error_t dst_addressing_end_offset_get_2015(
* @retval NRF_802154_RX_ERROR_INVALID_FRAME Detected an error in given frame - it should be
* discarded.
*/
static nrf_802154_rx_error_t dst_addressing_end_offset_get(
static nrf_802154_rx_error_t dst_addressing_fcf_check(
const nrf_802154_frame_parser_data_t * p_frame_data,
uint8_t * p_num_bytes,
uint8_t frame_type,
uint8_t frame_version)
{
@ -294,11 +282,11 @@ static nrf_802154_rx_error_t dst_addressing_end_offset_get(
{
case FRAME_VERSION_0:
case FRAME_VERSION_1:
result = dst_addressing_end_offset_get_2006(p_frame_data, p_num_bytes, frame_type);
result = dst_addressing_fcf_check_2006(p_frame_data, frame_type);
break;
case FRAME_VERSION_2:
result = dst_addressing_end_offset_get_2015(p_frame_data, p_num_bytes, frame_type);
result = dst_addressing_fcf_check_2015(p_frame_data, frame_type);
break;
default:
@ -441,60 +429,50 @@ static nrf_802154_rx_error_t dst_addr_check(const nrf_802154_frame_parser_data_t
}
nrf_802154_rx_error_t nrf_802154_filter_frame_part(
nrf_802154_frame_parser_data_t * p_frame_data,
uint8_t * p_num_bytes)
const nrf_802154_frame_parser_data_t * p_frame_data,
nrf_802154_filter_mode_t filter_mode)
{
nrf_802154_rx_error_t result = NRF_802154_RX_ERROR_INVALID_FRAME;
uint8_t frame_type = nrf_802154_frame_parser_frame_type_get(p_frame_data);
uint8_t frame_version = nrf_802154_frame_parser_frame_version_get(p_frame_data);
uint8_t psdu_length = nrf_802154_frame_parser_frame_length_get(p_frame_data);
nrf_802154_rx_error_t result = NRF_802154_RX_ERROR_NONE;
uint8_t frame_type = nrf_802154_frame_parser_frame_type_get(
p_frame_data);
uint8_t frame_version = nrf_802154_frame_parser_frame_version_get(
p_frame_data);
uint8_t psdu_length = nrf_802154_frame_parser_frame_length_get(
p_frame_data);
switch (*p_num_bytes)
if (filter_mode & NRF_802154_FILTER_MODE_FCF)
{
case FCF_CHECK_OFFSET:
if ((psdu_length < IMM_ACK_LENGTH) || (psdu_length > MAX_PACKET_SIZE))
{
result = NRF_802154_RX_ERROR_INVALID_LENGTH;
break;
}
assert(nrf_802154_frame_parser_parse_level_get(p_frame_data) >= PARSE_LEVEL_FCF_OFFSETS);
if (!nrf_802154_frame_parser_valid_data_extend(p_frame_data,
*p_num_bytes,
PARSE_LEVEL_FCF_OFFSETS))
{
result = NRF_802154_RX_ERROR_INVALID_FRAME;
break;
}
if ((psdu_length < IMM_ACK_LENGTH) || (psdu_length > MAX_PACKET_SIZE))
{
return NRF_802154_RX_ERROR_INVALID_LENGTH;
}
if (!frame_type_and_version_filter(frame_type, frame_version))
{
result = NRF_802154_RX_ERROR_INVALID_FRAME;
break;
}
if (!frame_type_and_version_filter(frame_type, frame_version))
{
return NRF_802154_RX_ERROR_INVALID_FRAME;
}
if (!dst_addressing_may_be_present(frame_type))
{
result = NRF_802154_RX_ERROR_NONE;
break;
}
if (dst_addressing_may_be_present(frame_type))
{
result = dst_addressing_fcf_check(p_frame_data,
frame_type,
frame_version);
}
}
result = dst_addressing_end_offset_get(p_frame_data,
p_num_bytes,
frame_type,
frame_version);
break;
if (result != NRF_802154_RX_ERROR_NONE)
{
return result;
}
default:
if (!nrf_802154_frame_parser_valid_data_extend(p_frame_data,
*p_num_bytes,
PARSE_LEVEL_DST_ADDRESSING_END))
{
result = NRF_802154_RX_ERROR_INVALID_FRAME;
break;
}
if (filter_mode & NRF_802154_FILTER_MODE_DST_ADDR)
{
assert(nrf_802154_frame_parser_parse_level_get(
p_frame_data) >= PARSE_LEVEL_DST_ADDRESSING_END);
result = dst_addr_check(p_frame_data);
break;
result = dst_addr_check(p_frame_data);
}
return result;

View File

@ -53,26 +53,42 @@
* @brief Procedures used to discard the incoming frames that contain unexpected data in PHR or MHR.
*/
/**@brief Type representing the scope of frame filtering.
*
* Possible values:
* @ref NRF_802154_FILTER_MODE_FCF
* @ref NRF_802154_FILTER_MODE_DST_ADDR
*/
typedef uint32_t nrf_802154_filter_mode_t;
/**@brief Filter the frame based on the content of the FCF field. */
#define NRF_802154_FILTER_MODE_FCF (1UL << 0)
/**@brief Filter the frame based on the content of the destination addressing fields. */
#define NRF_802154_FILTER_MODE_DST_ADDR (1UL << 1)
/**@brief Perform all filtering tests. */
#define NRF_802154_FILTER_MODE_ALL (NRF_802154_FILTER_MODE_FCF | \
NRF_802154_FILTER_MODE_DST_ADDR)
/**
* @brief Verifies if the given part of the frame is valid.
*
* This function is called a few times for each received frame. The first call is after the FCF
* is received (PSDU length is 2 and @p p_num_bytes value is 3). The subsequent calls are performed
* when the number of bytes requested by the previous call is available. The iteration ends
* when the function does not request any more bytes to check.
* If the verified part of the function is correct, this function returns true and sets
* @p p_num_bytes to the number of bytes that should be available in PSDU during the next iteration.
* If the frame is correct and there is nothing more to check, this function returns true
* and does not modify the @p p_num_bytes value. If the verified frame is incorrect, this function
* returns false and the @p p_num_bytes value is undefined.
* This function filters the given frame within the scope specified by @p filter_mode argument.
* In the @c NRF_802154_FILTER_MODE_FCF filter mode the function will reject all frames that do
* not satisfy requirements that can be determined by parsing the FCF field, such as unsupported
* frame versions, unsupported frame types, or when destination addressing is not present in the
* frame and the node is not a coordinator.
* In the @c NRF_802154_FILTER_MODE_DST_ADDR filter mode the function will only check if the
* destination address matches the address of the current node. If the incoming frame has no address
* and the node is a coordinator the frame will be accepted. No validation of FCF is performend.
*
* @param[inout] p_frame_data Pointer to a frame parser data of the frame to be filtered.
* The frame filter may increase the frame parse level to either
* PARSE_LEVEL_FCF_OFFSETS or PARSE_LEVEL_DST_ADDRESSING_END.
* @param[inout] p_num_bytes Number of bytes available in @p p_data buffer. This value is either
* set to the requested number of bytes for the next iteration or remains
* unchanged if no more iterations are to be performed during
* the filtering of the given frame.
* To perform a full filtering procedure it is necessary to call this function on the incoming frame
* with both @c NRF_802154_FILTER_MODE_FCF and @c NRF_802154_FILTER_MODE_DST_ADDR scopes in
* two iterations, or both at once using @c NRF_802154_FILTER_MODE_ALL.
*
* @param[in] p_frame_data Pointer to a frame parser data of the frame to be filtered.
* @param[in] filter_mode The filtering scope that should be performed by the function.
*
* @retval NRF_802154_RX_ERROR_NONE Verified part of the incoming frame is valid.
* @retval NRF_802154_RX_ERROR_INVALID_FRAME Verified part of the incoming frame is invalid.
@ -80,8 +96,8 @@
* mismatches the address of this node.
*/
nrf_802154_rx_error_t nrf_802154_filter_frame_part(
nrf_802154_frame_parser_data_t * p_frame_data,
uint8_t * p_num_bytes);
const nrf_802154_frame_parser_data_t * p_frame_data,
nrf_802154_filter_mode_t filter_mode);
/**
*@}

View File

@ -103,6 +103,13 @@ nrf_802154_security_error_t nrf_802154_security_pib_key_use(nrf_802154_key_id_t
*/
void nrf_802154_security_pib_global_frame_counter_set(uint32_t frame_counter);
/**
* @brief Sets nRF 802.15.4 Radio Driver MAC Global Frame Counter if the value passed is larger than current.
*
* @param[in] frame_counter Frame counter to set.
*/
void nrf_802154_security_pib_global_frame_counter_set_if_larger(uint32_t frame_counter);
/**
* @brief Get the next 802.15.4 global frame counter.
*

View File

@ -36,6 +36,7 @@
#include "nrf_802154_config.h"
#include "nrf_802154_const.h"
#include "nrf_802154_sl_atomics.h"
#include <string.h>
#include <stdbool.h>
@ -222,6 +223,23 @@ void nrf_802154_security_pib_global_frame_counter_set(uint32_t frame_counter)
m_global_frame_counter = frame_counter;
}
void nrf_802154_security_pib_global_frame_counter_set_if_larger(uint32_t frame_counter)
{
uint32_t fc;
do
{
fc = m_global_frame_counter;
if (fc >= frame_counter)
{
break;
}
}
while (!nrf_802154_sl_atomic_cas_u32(&m_global_frame_counter, &fc, frame_counter));
}
nrf_802154_security_error_t nrf_802154_security_pib_frame_counter_get_next(
uint32_t * p_frame_counter,
nrf_802154_key_id_t * p_id)

View File

@ -1066,6 +1066,11 @@ void nrf_802154_security_global_frame_counter_set(uint32_t frame_counter)
nrf_802154_security_pib_global_frame_counter_set(frame_counter);
}
void nrf_802154_security_global_frame_counter_set_if_larger(uint32_t frame_counter)
{
nrf_802154_security_pib_global_frame_counter_set_if_larger(frame_counter);
}
nrf_802154_security_error_t nrf_802154_security_key_store(nrf_802154_key_t * p_key)
{
return nrf_802154_security_pib_key_store(p_key);

View File

@ -158,9 +158,6 @@ static uint32_t m_rx_window_id;
#if !NRF_802154_FRAME_TIMESTAMP_ENABLED
#error NRF_802154_FRAME_TIMESTAMP_ENABLED == 0 when NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED != 0
#endif
#if NRF_802154_DISABLE_BCC_MATCHING
#error NRF_802154_DISABLE_BCC_MATCHING != 0 when NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED != 0
#endif
#endif // NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED
#if NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED
@ -197,6 +194,19 @@ static void state_set(radio_state_t state)
request_preconditions_for_state(state);
}
/** Specifies what ramp up trigger mode to use when handling RX or TX operation request.
*
* It is assumed that the DELAYED_TRX module always requests HW mode both RX and TX,
* while in all other cases SW mode is required.
*
* @param[in] request_orig Module that originates the request.
*/
static nrf_802154_trx_ramp_up_trigger_mode_t ramp_up_mode_choose(req_originator_t request_orig)
{
return (request_orig == REQ_ORIG_DELAYED_TRX) ?
TRX_RAMP_UP_HW_TRIGGER : TRX_RAMP_UP_SW_TRIGGER;
}
/** Clear RX frame data. */
static void rx_data_clear(void)
{
@ -337,7 +347,6 @@ static void transmit_ack_started_notify()
nrf_802154_tx_ack_started(mp_ack);
}
#if !NRF_802154_DISABLE_BCC_MATCHING
/** Notify that reception of a frame has started. */
static void receive_started_notify(void)
{
@ -346,8 +355,6 @@ static void receive_started_notify(void)
nrf_802154_core_hooks_rx_started(p_frame);
}
#endif
/** Notify MAC layer that a frame was transmitted. */
static void transmitted_frame_notify(uint8_t * p_ack, int8_t power, uint8_t lqi)
{
@ -1001,8 +1008,19 @@ static nrf_802154_trx_transmit_notifications_t make_trx_frame_transmit_notificat
return result;
}
/** Initialize RX operation. */
static void rx_init(void)
/**
* @brief Initializes RX operation
*
* @param[in] ru_tr_mode Desired trigger mode for radio ramp up.
* @param[out] p_abort_shall_follow It is set to `true` when initialization fails and the trx
* module needs to be reset. When obtaining `true` here, the user
* is then obliged to call @ref nrf_802154_trx_abort. Such a case
* can only happen when @p ru_tr_mode = TRX_RAMP_UP_HW_TRIGGER.
* In all other cases, the value is not modified at all, so it
* should be initialized to `false` before calling the function.
* Can be NULL if @p ru_tr_mode is not TRX_RAMP_UP_HW_TRIGGER.
*/
static void rx_init(nrf_802154_trx_ramp_up_trigger_mode_t ru_tr_mode, bool * p_abort_shall_follow)
{
bool free_buffer;
@ -1029,11 +1047,31 @@ static void rx_init(void)
(void)nrf_802154_tx_power_split_pib_power_get(&split_power);
nrf_802154_trx_receive_frame(BCC_INIT / 8U,
ru_tr_mode,
m_trx_receive_frame_notifications_mask,
&split_power);
if (ru_tr_mode == TRX_RAMP_UP_HW_TRIGGER)
{
uint32_t ppi_ch = nrf_802154_trx_ramp_up_ppi_channel_get();
if (!nrf_802154_rsch_delayed_timeslot_ppi_update(ppi_ch))
{
/**
* The trigger has occurred. This has happened too early so there is a high risk
* that the radio will not ramp up. It is necessary to abort the operation.
*/
assert(p_abort_shall_follow);
*p_abort_shall_follow = true;
}
}
#if NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED
m_listening_start_hp_timestamp = nrf_802154_hp_timer_current_time_get();
// The introduction of TRX_RAMP_UP_HW_TRIGGER broke the measurement method used here.
// Obtained timestamp is no more related to the moment when listening starts.
// TODO: Remove TOTAL_TIMES_MEASUREMENT feature, as it has been verified that it is
// not needed.
#endif
#if (NRF_802154_FRAME_TIMESTAMP_ENABLED)
@ -1061,7 +1099,9 @@ static void rx_init(void)
}
/** Initialize TX operation. */
static bool tx_init(const uint8_t * p_data, bool cca)
static bool tx_init(const uint8_t * p_data,
nrf_802154_trx_ramp_up_trigger_mode_t rampup_trigg_mode,
bool cca)
{
if (!timeslot_is_granted() || !nrf_802154_rsch_timeslot_request(
nrf_802154_tx_duration_get(p_data[0], cca, ack_is_requested(p_data))))
@ -1091,10 +1131,26 @@ static bool tx_init(const uint8_t * p_data, bool cca)
m_flags.tx_with_cca = cca;
nrf_802154_trx_transmit_frame(nrf_802154_tx_work_buffer_get(p_data),
rampup_trigg_mode,
cca,
&m_tx_power,
m_trx_transmit_frame_notifications_mask);
if (rampup_trigg_mode == TRX_RAMP_UP_HW_TRIGGER)
{
uint32_t ppi_ch = nrf_802154_trx_ramp_up_ppi_channel_get();
if (!nrf_802154_rsch_delayed_timeslot_ppi_update(ppi_ch))
{
/**
* The trigger has occurred. This has happened too early so there is a high risk
* that the radio will not ramp up. It is necessary to abort the operation.
*/
nrf_802154_trx_abort();
return false;
}
}
return true;
}
@ -1345,15 +1401,15 @@ static void on_preconditions_approved(radio_state_t state)
break;
case RADIO_STATE_RX:
rx_init();
rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
break;
case RADIO_STATE_CCA_TX:
(void)tx_init(mp_tx_data, true);
(void)tx_init(mp_tx_data, TRX_RAMP_UP_SW_TRIGGER, true);
break;
case RADIO_STATE_TX:
(void)tx_init(mp_tx_data, false);
(void)tx_init(mp_tx_data, TRX_RAMP_UP_SW_TRIGGER, false);
break;
case RADIO_STATE_ED:
@ -1659,122 +1715,129 @@ void nrf_802154_trx_receive_frame_started(void)
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
}
#if !NRF_802154_DISABLE_BCC_MATCHING
uint8_t nrf_802154_trx_receive_frame_bcmatched(uint8_t bcc)
{
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
uint8_t prev_num_data_bytes;
uint8_t num_data_bytes;
nrf_802154_rx_error_t filter_result;
bool frame_accepted = true;
uint8_t next_bcc;
nrf_802154_filter_mode_t filter_mode;
bool parse_result;
bool should_filter = false;
nrf_802154_rx_error_t filter_result = NRF_802154_RX_ERROR_NONE;
nrf_802154_frame_parser_level_t parse_level = PARSE_LEVEL_NONE;
nrf_802154_frame_parser_level_t prev_level =
nrf_802154_frame_parser_parse_level_get(&m_current_rx_frame_data);
num_data_bytes = bcc;
prev_num_data_bytes = num_data_bytes;
assert(num_data_bytes >= PHR_SIZE + FCF_SIZE);
assert(m_state == RADIO_STATE_RX);
if (!m_flags.frame_filtered)
switch (prev_level)
{
filter_result = nrf_802154_filter_frame_part(&m_current_rx_frame_data,
&num_data_bytes);
case PARSE_LEVEL_NONE:
parse_level = PARSE_LEVEL_FCF_OFFSETS;
filter_mode = NRF_802154_FILTER_MODE_FCF;
should_filter = true;
break;
if (filter_result == NRF_802154_RX_ERROR_NONE)
{
if (num_data_bytes != prev_num_data_bytes)
{
bcc = num_data_bytes;
}
else
{
m_flags.frame_filtered = true;
case PARSE_LEVEL_FCF_OFFSETS:
parse_level = PARSE_LEVEL_DST_ADDRESSING_END;
filter_mode = NRF_802154_FILTER_MODE_DST_ADDR;
should_filter = true;
break;
/* Request boosted preconditions */
nrf_802154_rsch_crit_sect_prio_request(RSCH_PRIO_RX);
case PARSE_LEVEL_DST_ADDRESSING_END:
parse_level = PARSE_LEVEL_SEC_CTRL_OFFSETS;
break;
/* Request next bcc match event to occur when basic data necessary for Ack
* generation is received. */
m_flags.frame_parsed = false;
nrf_802154_ack_generator_reset();
case PARSE_LEVEL_SEC_CTRL_OFFSETS:
parse_level = PARSE_LEVEL_AUX_SEC_HDR_END;
break;
bcc = PHR_SIZE +
nrf_802154_frame_parser_addressing_end_offset_get(&m_current_rx_frame_data) +
SECURITY_CONTROL_SIZE;
}
}
else if ((filter_result == NRF_802154_RX_ERROR_INVALID_LENGTH) ||
(!nrf_802154_pib_promiscuous_get()))
{
trx_abort();
rx_init();
frame_accepted = false;
/* Release boosted preconditions */
request_preconditions_for_state(m_state);
if ((mp_current_rx_buffer->data[FRAME_TYPE_OFFSET] & FRAME_TYPE_MASK) !=
FRAME_TYPE_ACK)
{
receive_failed_notify(filter_result);
}
}
else
{
// Promiscuous mode, allow incorrect frames. Nothing to do here.
}
}
else if (!m_flags.frame_parsed)
{
if (nrf_802154_frame_parser_security_enabled_bit_is_set(&m_current_rx_frame_data))
{
if (nrf_802154_frame_parser_valid_data_extend(
&m_current_rx_frame_data,
num_data_bytes,
PARSE_LEVEL_AUX_SEC_HDR_END))
{
// All security fields have been received.
m_flags.frame_parsed = true;
}
else if (nrf_802154_frame_parser_valid_data_extend(
&m_current_rx_frame_data,
num_data_bytes,
PARSE_LEVEL_SEC_CTRL_OFFSETS))
{
// All addressing fields and Security Control byte have been received.
// With the Security Control field, length of Auxiliary Security Header can be
// determined. Set BCC there
bcc = PHR_SIZE +
nrf_802154_frame_parser_aux_sec_hdr_end_offset_get(&m_current_rx_frame_data);
}
else
{
// This code should be unreachable.
}
}
else if (nrf_802154_frame_parser_valid_data_extend(
&m_current_rx_frame_data,
num_data_bytes,
PARSE_LEVEL_ADDRESSING_END))
{
m_flags.frame_parsed = true;
}
else
{
// This code should be unreachable.
}
}
else
{
// Nothing to do
default:
/* Parsing completed. Nothing more to be done. */
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
return 0;
}
if ((!m_flags.rx_timeslot_requested) && (frame_accepted))
parse_result = nrf_802154_frame_parser_valid_data_extend(&m_current_rx_frame_data,
bcc,
parse_level);
if (!parse_result)
{
if (nrf_802154_rsch_timeslot_request(nrf_802154_rx_duration_get(
mp_current_rx_buffer->data[0],
ack_is_requested(mp_current_rx_buffer->data))))
should_filter = false;
filter_result = NRF_802154_RX_ERROR_INVALID_FRAME;
}
if (should_filter)
{
filter_result = nrf_802154_filter_frame_part(&m_current_rx_frame_data, filter_mode);
if ((filter_result == NRF_802154_RX_ERROR_NONE) &&
(filter_mode == NRF_802154_FILTER_MODE_DST_ADDR))
{
m_flags.frame_filtered = true;
nrf_802154_rsch_crit_sect_prio_request(RSCH_PRIO_RX);
nrf_802154_ack_generator_reset();
}
if (nrf_802154_pib_promiscuous_get())
{
/*
* In promiscuous mode all filtering should be ignored unless the frame has
* invalid length.
*/
filter_result = filter_result == NRF_802154_RX_ERROR_INVALID_LENGTH ?
filter_result : NRF_802154_RX_ERROR_NONE;
}
}
if (filter_result != NRF_802154_RX_ERROR_NONE)
{
trx_abort();
rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
/* Release boosted preconditions */
request_preconditions_for_state(m_state);
if (nrf_802154_frame_parser_frame_type_get(&m_current_rx_frame_data) != FRAME_TYPE_ACK)
{
receive_failed_notify(filter_result);
}
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
return 0;
}
switch (parse_level)
{
case PARSE_LEVEL_FCF_OFFSETS:
next_bcc = PHR_SIZE + nrf_802154_frame_parser_dst_addressing_end_offset_get(
&m_current_rx_frame_data);
break;
case PARSE_LEVEL_DST_ADDRESSING_END:
next_bcc = PHR_SIZE + nrf_802154_frame_parser_addressing_end_offset_get(
&m_current_rx_frame_data) + SECURITY_CONTROL_SIZE;
break;
case PARSE_LEVEL_SEC_CTRL_OFFSETS:
next_bcc = PHR_SIZE + nrf_802154_frame_parser_aux_sec_hdr_end_offset_get(
&m_current_rx_frame_data);
break;
default:
next_bcc = 0;
break;
}
if (!m_flags.rx_timeslot_requested)
{
uint16_t duration = nrf_802154_rx_duration_get(
mp_current_rx_buffer->data[0],
nrf_802154_frame_parser_ar_bit_is_set(&m_current_rx_frame_data));
if (nrf_802154_rsch_timeslot_request(duration))
{
m_flags.rx_timeslot_requested = true;
@ -1788,7 +1851,7 @@ uint8_t nrf_802154_trx_receive_frame_bcmatched(uint8_t bcc)
// We should not leave trx in temporary state, let's receive then.
// We avoid hard reset of radio during TX ACK phase due to timeslot end,
// which could result in spurious RF emission.
rx_init();
rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
// Don't care about the result - if the notification cannot be performed
// no impact on the device's operation is expected
@ -1799,7 +1862,6 @@ uint8_t nrf_802154_trx_receive_frame_bcmatched(uint8_t bcc)
}
if (m_flags.frame_filtered &&
m_flags.frame_parsed &&
nrf_802154_frame_parser_ar_bit_is_set(&m_current_rx_frame_data) &&
nrf_802154_pib_auto_ack_get())
{
@ -1808,11 +1870,9 @@ uint8_t nrf_802154_trx_receive_frame_bcmatched(uint8_t bcc)
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
return bcc;
return next_bcc;
}
#endif
void nrf_802154_trx_go_idle_finished(void)
{
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
@ -1905,7 +1965,6 @@ void nrf_802154_trx_receive_frame_crcerror(void)
rx_data_clear();
// We don't change receive buffer, receive will go to the same that was already used
#if !NRF_802154_DISABLE_BCC_MATCHING
request_preconditions_for_state(m_state);
nrf_802154_fal_tx_power_split_t split_power = {0};
@ -1913,6 +1972,7 @@ void nrf_802154_trx_receive_frame_crcerror(void)
(void)nrf_802154_tx_power_split_pib_power_get(&split_power);
nrf_802154_trx_receive_frame(BCC_INIT / 8U,
TRX_RAMP_UP_SW_TRIGGER,
m_trx_receive_frame_notifications_mask,
&split_power);
@ -1924,10 +1984,6 @@ void nrf_802154_trx_receive_frame_crcerror(void)
nrf_802154_timer_coord_timestamp_prepare(nrf_802154_trx_radio_end_event_handle_get());
#endif
#else
// With BCC matching disabled trx module will re-arm automatically
#endif
#if NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED
update_total_times_on_receive_end(listening_start_hp_timestamp,
receive_end_hp_timestamp,
@ -1965,7 +2021,8 @@ void nrf_802154_trx_receive_frame_received(void)
{
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
uint8_t * p_received_data = mp_current_rx_buffer->data;
uint8_t * p_received_data = mp_current_rx_buffer->data;
nrf_802154_rx_error_t filter_result = NRF_802154_RX_ERROR_RUNTIME;
// Latch RSSI and LQI values before sending ACK
m_last_rssi = rssi_last_measurement_get();
@ -1980,57 +2037,35 @@ void nrf_802154_trx_receive_frame_received(void)
mp_current_rx_buffer->data[PHR_OFFSET]);
#endif
#if NRF_802154_DISABLE_BCC_MATCHING
uint8_t num_data_bytes = PHR_SIZE + FCF_SIZE;
uint8_t prev_num_data_bytes = 0;
nrf_802154_rx_error_t filter_result;
bool parse_result = nrf_802154_frame_parser_valid_data_extend(
&m_current_rx_frame_data,
PHR_SIZE + nrf_802154_frame_parser_frame_length_get(&m_current_rx_frame_data),
PARSE_LEVEL_FULL);
// Frame filtering
while (num_data_bytes != prev_num_data_bytes)
if (parse_result && !m_flags.frame_filtered)
{
prev_num_data_bytes = num_data_bytes;
// Keep checking consecutive parts of the frame header.
filter_result = nrf_802154_filter_frame_part(&m_current_rx_frame_data, &num_data_bytes);
filter_result = nrf_802154_filter_frame_part(&m_current_rx_frame_data,
NRF_802154_FILTER_MODE_ALL);
if (filter_result == NRF_802154_RX_ERROR_NONE)
{
if (num_data_bytes == prev_num_data_bytes)
uint16_t duration = nrf_802154_ack_duration_with_turnaround_get();
if (nrf_802154_rsch_timeslot_request(duration))
{
m_flags.frame_filtered = true;
m_flags.frame_filtered = true;
m_flags.rx_timeslot_requested = true;
nrf_802154_ack_generator_reset();
receive_started_notify();
}
else
{
filter_result = NRF_802154_RX_ERROR_TIMESLOT_ENDED;
}
}
else
{
break;
}
}
// Timeslot request
if (m_flags.frame_filtered &&
nrf_802154_frame_parser_ar_bit_is_set(&m_current_rx_frame_data) &&
!nrf_802154_rsch_timeslot_request(nrf_802154_rx_duration_get(0, true)))
{
// Frame is destined to this node but there is no timeslot to transmit ACK.
// Just disable receiver and wait for a new timeslot.
nrf_802154_trx_abort();
rx_flags_clear();
rx_data_clear();
// Filter out received ACK frame if promiscuous mode is disabled.
if (((p_received_data[FRAME_TYPE_OFFSET] & FRAME_TYPE_MASK) != FRAME_TYPE_ACK) ||
nrf_802154_pib_promiscuous_get())
{
mp_current_rx_buffer->free = false;
received_frame_notify_and_nesting_allow(p_received_data);
}
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
return;
}
#endif // NRF_802154_DISABLE_BCC_MATCHING
if (m_flags.frame_filtered || nrf_802154_pib_promiscuous_get())
{
nrf_802154_stat_counter_increment(received_frames);
@ -2043,11 +2078,7 @@ void nrf_802154_trx_receive_frame_received(void)
nrf_802154_sl_ant_div_rx_frame_received_notify();
bool send_ack = false;
bool parse_result = nrf_802154_frame_parser_valid_data_extend(
&m_current_rx_frame_data,
PHR_SIZE + nrf_802154_frame_parser_frame_length_get(&m_current_rx_frame_data),
PARSE_LEVEL_FULL);
bool send_ack = false;
if (m_flags.frame_filtered &&
parse_result &&
@ -2074,7 +2105,7 @@ void nrf_802154_trx_receive_frame_received(void)
mp_current_rx_buffer->free = false;
state_set(RADIO_STATE_RX);
rx_init();
rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
received_frame_notify_and_nesting_allow(p_received_data);
}
@ -2090,7 +2121,7 @@ void nrf_802154_trx_receive_frame_received(void)
mp_current_rx_buffer->free = false;
state_set(RADIO_STATE_RX);
rx_init();
rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
received_frame_notify_and_nesting_allow(p_received_data);
}
@ -2108,14 +2139,14 @@ void nrf_802154_trx_receive_frame_received(void)
// Find new buffer
rx_buffer_in_use_set(nrf_802154_rx_buffer_free_find());
rx_init();
rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
received_frame_notify_and_nesting_allow(p_received_data);
}
else
{
// Receive to the same buffer
rx_init();
rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
}
}
}
@ -2125,16 +2156,9 @@ void nrf_802154_trx_receive_frame_received(void)
// or problem due to software latency (i.e. handled BCMATCH, CRCERROR, CRCOK from two
// consecutively received frames).
request_preconditions_for_state(m_state);
rx_init();
rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
#if NRF_802154_DISABLE_BCC_MATCHING
if ((p_received_data[FRAME_TYPE_OFFSET] & FRAME_TYPE_MASK) != FRAME_TYPE_ACK)
{
receive_failed_notify(filter_result);
}
#else // NRF_802154_DISABLE_BCC_MATCHING
receive_failed_notify(NRF_802154_RX_ERROR_RUNTIME);
#endif // NRF_802154_DISABLE_BCC_MATCHING
receive_failed_notify(filter_result);
}
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
@ -2181,7 +2205,7 @@ void nrf_802154_trx_transmit_ack_transmitted(void)
state_set(RADIO_STATE_RX);
rx_init();
rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
received_frame_notify_and_nesting_allow(p_received_data);
@ -2273,7 +2297,7 @@ void nrf_802154_trx_transmit_frame_transmitted(void)
{
state_set(RADIO_STATE_RX);
rx_init();
rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
transmitted_frame_notify(NULL, 0, 0);
}
@ -2389,7 +2413,7 @@ static void on_bad_ack(void)
// We received either a frame with incorrect CRC or not an ACK frame or not matching ACK
state_set(RADIO_STATE_RX);
rx_init();
rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
nrf_802154_transmit_done_metadata_t metadata = {};
@ -2428,7 +2452,7 @@ void nrf_802154_trx_receive_ack_received(void)
mp_current_rx_buffer->free = false;
state_set(RADIO_STATE_RX);
rx_init();
rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
transmitted_frame_notify(p_ack_buffer->data, // phr + psdu
rssi_last_measurement_get(), // rssi
@ -2447,7 +2471,7 @@ void nrf_802154_trx_standalone_cca_finished(bool channel_was_idle)
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
state_set(RADIO_STATE_RX);
rx_init();
rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
cca_notify(channel_was_idle);
@ -2500,7 +2524,7 @@ void nrf_802154_trx_transmit_frame_ccabusy(void)
#endif
state_set(RADIO_STATE_RX);
rx_init();
rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
nrf_802154_transmit_done_metadata_t metadata = {};
@ -2543,7 +2567,7 @@ void nrf_802154_trx_energy_detection_finished(uint8_t ed_sample)
nrf_802154_trx_channel_set(nrf_802154_pib_channel_get());
state_set(RADIO_STATE_RX);
rx_init();
rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
energy_detected_notify(nrf_802154_rssi_ed_sample_convert(m_ed_result));
@ -2579,8 +2603,8 @@ void nrf_802154_core_deinit(void)
mpsl_fem_cleanup();
nrf_802154_irq_disable(RADIO_IRQn);
nrf_802154_irq_clear_pending(RADIO_IRQn);
nrf_802154_irq_disable(nrfx_get_irq_number(NRF_RADIO));
nrf_802154_irq_clear_pending(nrfx_get_irq_number(NRF_RADIO));
nrf_802154_sl_timer_deinit(&m_rx_prestarted_timer);
@ -2650,9 +2674,22 @@ bool nrf_802154_core_receive(nrf_802154_term_t term_lvl,
{
m_trx_receive_frame_notifications_mask =
make_trx_frame_receive_notification_mask();
m_rx_window_id = id;
state_set(RADIO_STATE_RX);
rx_init();
bool abort_shall_follow = false;
rx_init(ramp_up_mode_choose(req_orig), &abort_shall_follow);
if (abort_shall_follow)
{
nrf_802154_trx_abort();
// HW triggering failed, fallback is SW trigger.
// (fallback immunizes against the rare case of spurious lptimer firing)
rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
}
}
}
else
@ -2716,13 +2753,14 @@ bool nrf_802154_core_transmit(nrf_802154_term_t term_lvl,
m_tx_power = p_params->tx_power;
// coverity[check_return]
result = tx_init(p_data, p_params->cca);
result = tx_init(p_data, ramp_up_mode_choose(req_orig), p_params->cca);
if (p_params->immediate)
{
if (!result)
{
state_set(RADIO_STATE_RX);
rx_init();
rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
}
}
else
@ -2908,7 +2946,7 @@ bool nrf_802154_core_channel_update(req_originator_t req_orig)
case RADIO_STATE_RX:
if (current_operation_terminate(NRF_802154_TERM_802154, req_orig, true))
{
rx_init();
rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
}
break;

View File

@ -74,7 +74,7 @@ static void radio_critical_section_enter(void)
{
if (nrf_802154_rsch_prec_is_approved(RSCH_PREC_RAAL, RSCH_PRIO_MIN_APPROVED))
{
nrf_802154_irq_disable(RADIO_IRQn);
nrf_802154_irq_disable(nrfx_get_irq_number(NRF_RADIO));
}
}
@ -87,7 +87,7 @@ static void radio_critical_section_exit(void)
{
if (nrf_802154_rsch_prec_is_approved(RSCH_PREC_RAAL, RSCH_PRIO_MIN_APPROVED))
{
nrf_802154_irq_enable(RADIO_IRQn);
nrf_802154_irq_enable(nrfx_get_irq_number(NRF_RADIO));
}
}
@ -264,10 +264,11 @@ uint32_t nrf_802154_critical_section_active_vector_priority_get(void)
return UINT32_MAX;
}
assert(active_vector_id >= CMSIS_IRQ_NUM_VECTACTIVE_DIFF);
irq_number = (IRQn_Type)((int32_t)active_vector_id - CMSIS_IRQ_NUM_VECTACTIVE_DIFF);
irq_number = (IRQn_Type)(active_vector_id - CMSIS_IRQ_NUM_VECTACTIVE_DIFF);
active_priority = nrf_802154_irq_priority_get(irq_number);
assert(irq_number >= SVCall_IRQn);
active_priority = NVIC_GetPriority(irq_number);
return active_priority;
}

View File

@ -301,7 +301,8 @@ bool nrf_802154_encrypt_ack_prepare(const nrf_802154_frame_parser_data_t * p_ack
nrf_802154_aes_ccm_data_t aes_ccm_data;
bool success = false;
if (!nrf_802154_frame_parser_security_enabled_bit_is_set(p_ack_data))
if (!nrf_802154_frame_parser_security_enabled_bit_is_set(p_ack_data) ||
(nrf_802154_frame_parser_sec_ctrl_sec_lvl_get(p_ack_data) == SECURITY_LEVEL_NONE))
{
success = true;
}
@ -347,7 +348,8 @@ bool nrf_802154_encrypt_tx_setup(
assert(success);
(void)success;
if (!nrf_802154_frame_parser_security_enabled_bit_is_set(&frame_data))
if (!nrf_802154_frame_parser_security_enabled_bit_is_set(&frame_data) ||
(nrf_802154_frame_parser_sec_ctrl_sec_lvl_get(&frame_data) == SECURITY_LEVEL_NONE))
{
success = true;
}

View File

@ -38,20 +38,18 @@
#include "nrfx.h"
#include "nrf_802154_const.h"
/* The usage of ED_RSSISCALE is described inprecisely in the nRF product specifications. The meaning of
/* The usage of ED_RSSISCALE is described imprecisely in the nRF product specifications. The meaning of
this constant is the following: If we calculate ed_scaled = EDSAMPLE * ED_RSSISCALE, then
it is guaranteed that in the range 0-255 ed_scaled maps linearly to the ED power in dBm. This means,
that the maximum value in EDSAMPLE which can be reported in compliance with the 802.15.4 specification is
255/ED_RSSISCALE. */
#if defined (NRF52840_XXAA)
#define ED_RSSIOFFS (-92) ///< dBm value corresponding to value 0 in the EDSAMPLE register.
#define ED_RSSISCALE 4 ///< Factor needed to calculate the ED result based on the data from the RADIO peripheral.
#elif defined (NRF52833_XXAA) || defined(NRF5340_XXAA)
#define ED_RSSIOFFS (-93) ///< dBm value corresponding to value 0 in the EDSAMPLE register.
#define ED_RSSISCALE 5 ///< Factor needed to calculate the ED result based on the data from the RADIO peripheral.
#if defined (NRF52833_XXAA) || defined(NRF5340_XXAA)
#define ED_RSSIOFFS (-93) ///< dBm value corresponding to value 0 in the EDSAMPLE register.
#define ED_RSSISCALE 5 ///< Factor needed to calculate the ED result based on the data from the RADIO peripheral.
#else
#error "Selected chip is not supported."
#define ED_RSSIOFFS (-92) ///< dBm value corresponding to value 0 in the EDSAMPLE register.
#define ED_RSSISCALE 4 ///< Factor needed to calculate the ED result based on the data from the RADIO peripheral.
#endif
#define EDSAMPLE_MIN_REPORTED_VALUE (PHY_MIN_RECEIVER_SENSITIVITY - ED_RSSIOFFS + 10) ///< Minimal reported EDSAMPLE value (reported as 0)

View File

@ -49,8 +49,10 @@
#include "nrf_802154_peripherals_nrf52.h"
#elif defined(NRF5340_XXAA)
#include "nrf_802154_peripherals_nrf53.h"
#else
#error Unsupported chip family
#endif
#ifdef NRF_802154_USE_INTERNAL_INCLUDES
#include "nrf_802154_peripherals_internal.h"
#endif
#ifdef __cplusplus
@ -95,27 +97,6 @@ extern "C" {
#define NRF_802154_TIMER_INSTANCE \
NRFX_CONCAT_2(NRF_TIMER, NRF_802154_TIMER_INSTANCE_NO)
/**
* @def NRF_802154_COUNTER_TIMER_INSTANCE_NO
*
* Number of the timer instance used for detecting when PSDU is being received.
*
*/
#ifndef NRF_802154_COUNTER_TIMER_INSTANCE_NO
#define NRF_802154_COUNTER_TIMER_INSTANCE_NO 2
#endif
/**
* @def NRF_802154_COUNTER_TIMER_INSTANCE
*
* The timer instance used by the driver for detecting when PSDU is being received.
*
* @note This configuration is used only when the NRF_RADIO_EVENT_BCMATCH event handling is disabled
* (see @ref NRF_802154_DISABLE_BCC_MATCHING).
*/
#define NRF_802154_COUNTER_TIMER_INSTANCE \
NRFX_CONCAT_2(NRF_TIMER, NRF_802154_COUNTER_TIMER_INSTANCE_NO)
/**
* @def NRF_802154_RTC_INSTANCE
*
@ -156,8 +137,7 @@ extern "C" {
*/
#ifndef NRF_802154_TIMERS_USED_MASK
#define NRF_802154_TIMERS_USED_MASK ((1 << NRF_802154_HIGH_PRECISION_TIMER_INSTANCE_NO) | \
(1 << NRF_802154_TIMER_INSTANCE_NO) | \
(1 << NRF_802154_COUNTER_TIMER_INSTANCE_NO))
(1 << NRF_802154_TIMER_INSTANCE_NO))
#endif // NRF_802154_TIMERS_USED_MASK
/**

View File

@ -51,10 +51,10 @@
#include "mpsl.h"
#endif
#if defined(NRF52_SERIES)
#if defined(PPI_PRESENT)
#define NRF_802154_PPI_CH_USED_MSK NRF_802154_PPI_CHANNELS_USED_MASK
#define NRF_802154_PPI_GR_USED_MSK NRF_802154_PPI_GROUPS_USED_MASK
#elif defined(NRF53_SERIES)
#elif defined(DPPI_PRESENT)
#define NRF_802154_PPI_CH_USED_MSK NRF_802154_DPPI_CHANNELS_USED_MASK
#define NRF_802154_PPI_GR_USED_MSK NRF_802154_DPPI_GROUPS_USED_MASK
#else

View File

@ -111,12 +111,30 @@ extern "C" {
#endif // NRF_802154_RTC_INSTANCE_NO
/**
* @def NRF_802154_PPI_RADIO_RAMP_UP_TRIGG
*
* The PPI channel that connects ramp up triggering event to EGU task.
*
* @note The peripheral is shared with @ref NRF_802154_PPI_RADIO_DISABLED_TO_EGU in such a way
* that a receive or transmit request causes that ppi to be configured for ramp up
* triggering purpose, while in the EVENT_READY isr the ppi is reconfigured to follow the
* @ref NRF_802154_PPI_RADIO_DISABLED_TO_EGU description.
*
* @note This option is used regardless of the driver configuration.
*
*/
#ifndef NRF_802154_PPI_RADIO_RAMP_UP_TRIGG
#define NRF_802154_PPI_RADIO_RAMP_UP_TRIGG NRF_PPI_CHANNEL6
#endif
/**
* @def NRF_802154_PPI_RADIO_DISABLED_TO_EGU
*
* The PPI channel that connects RADIO_DISABLED event to EGU task.
*
* @note This option is used by the core module regardless of the driver configuration.
* The peripheral is shared with @ref NRF_802154_PPI_RADIO_RAMP_UP_TRIGG.
*
*/
#ifndef NRF_802154_PPI_RADIO_DISABLED_TO_EGU
@ -201,55 +219,12 @@ extern "C" {
#define NRF_802154_PPI_RADIO_CRCOK_TO_PPI_GRP_DISABLE NRF_PPI_CHANNEL10
#endif
#if NRF_802154_DISABLE_BCC_MATCHING
/**
* @def NRF_802154_PPI_RADIO_ADDR_TO_COUNTER_COUNT
*
* The PPI channel that connects RADIO_ADDRESS event to TIMER_COUNT task.
*
* @note This configuration is used only when the NRF_RADIO_EVENT_BCMATCH event handling is disabled
* (see @ref NRF_802154_DISABLE_BCC_MATCHING).
*
*/
#ifndef NRF_802154_PPI_RADIO_ADDR_TO_COUNTER_COUNT
#define NRF_802154_PPI_RADIO_ADDR_TO_COUNTER_COUNT NRF_PPI_CHANNEL11
#endif
/**
* @def NRF_802154_PPI_RADIO_CRCERROR_TO_COUNTER_CLEAR
*
* The PPI channel that connects RADIO_CRCERROR event to TIMER_CLEAR task.
*
* @note This option is used only when the NRF_RADIO_EVENT_BCMATCH event handling is disabled
* (see @ref NRF_802154_DISABLE_BCC_MATCHING).
*
*/
#ifndef NRF_802154_PPI_RADIO_CRCERROR_COUNTER_CLEAR
#define NRF_802154_PPI_RADIO_CRCERROR_COUNTER_CLEAR NRF_PPI_CHANNEL12
#endif
/**
* @def NRF_802154_DISABLE_BCC_MATCHING_PPI_CHANNELS_USED_MASK
*
* Helper bit mask of PPI channels used additionally by the 802.15.4 driver when the BCC matching
* is disabled.
*/
#define NRF_802154_DISABLE_BCC_MATCHING_PPI_CHANNELS_USED_MASK \
((1 << NRF_802154_PPI_RADIO_ADDR_TO_COUNTER_COUNT) | \
(1 << NRF_802154_PPI_RADIO_CRCERROR_COUNTER_CLEAR))
#else // NRF_802154_DISABLE_BCC_MATCHING
/**
* @def NRF_802154_PPI_RADIO_SYNC_TO_EGU_SYNC
*
* The PPI channel that connects RADIO_SYNC event to EGU_SYNC task.
* EGU_SYNC task belongs to one of EGU channels
*
* @note This configuration is used only when the NRF_RADIO_EVENT_BCMATCH event handling is enabled
* (see @ref NRF_802154_DISABLE_BCC_MATCHING).
*
*/
#ifndef NRF_802154_PPI_RADIO_SYNC_TO_EGU_SYNC
#define NRF_802154_PPI_RADIO_SYNC_TO_EGU_SYNC NRF_PPI_CHANNEL11
@ -258,8 +233,6 @@ extern "C" {
#define NRF_802154_DISABLE_BCC_MATCHING_PPI_CHANNELS_USED_MASK \
(1 << NRF_802154_PPI_RADIO_SYNC_TO_EGU_SYNC)
#endif // NRF_802154_DISABLE_BCC_MATCHING
#ifdef NRF_802154_FRAME_TIMESTAMP_ENABLED
/**
@ -341,6 +314,7 @@ extern "C" {
*/
#ifndef NRF_802154_PPI_CHANNELS_USED_MASK
#define NRF_802154_PPI_CHANNELS_USED_MASK ((1 << NRF_802154_PPI_RADIO_DISABLED_TO_EGU) | \
(1 << NRF_802154_PPI_RADIO_RAMP_UP_TRIGG) | \
(1 << NRF_802154_PPI_EGU_TO_RADIO_RAMP_UP) | \
(1 << NRF_802154_PPI_EGU_TO_TIMER_START) | \
(1 << NRF_802154_PPI_RADIO_CRCERROR_TO_TIMER_CLEAR) | \

View File

@ -93,6 +93,20 @@ extern "C" {
#define NRF_802154_EGU_IRQN \
NRFX_CONCAT_3(EGU, NRF_802154_EGU_INSTANCE_NO, _IRQn)
/**
* @def NRF_802154_EGU_RAMP_UP_EVENT
*
* The EGU event used by the driver to trigger radio ramp-up.
*/
#define NRF_802154_EGU_RAMP_UP_EVENT NRF_EGU_EVENT_TRIGGERED15
/**
* @def NRF_802154_EGU_RAMP_UP_TASK
*
* The EGU task used by the driver to trigger radio ramp-up.
*/
#define NRF_802154_EGU_RAMP_UP_TASK NRF_EGU_TASK_TRIGGER15
/**
* @def NRF_802154_EGU_USED_MASK
*
@ -112,6 +126,14 @@ extern "C" {
#define NRF_802154_RTC_INSTANCE_NO 2
#endif
/**
* @def NRF_802154_DPPIC_INSTANCE
*
* The DPPIC instance used by the driver to connect peripherals to radio.
*
*/
#define NRF_802154_DPPIC_INSTANCE NRF_DPPIC
/**
* @def NRF_802154_DPPI_RADIO_DISABLED
*
@ -239,6 +261,15 @@ extern "C" {
#define NRF_802154_DPPI_RADIO_TEST_MODE_USED_MASK 0U
#endif // NRF_802154_TEST_MODES_ENABLED
/**
* @def NRF_802154_DPPI_RADIO_CCABUSY
*
* The DPPI channel that triggers radio
*/
#ifndef NRF_802154_DPPI_RADIO_HW_TRIGGER
#define NRF_802154_DPPI_RADIO_HW_TRIGGER 15U
#endif
/**
* @def NRF_802154_DPPI_TIMESTAMPS_USED_MASK
*
@ -268,6 +299,7 @@ extern "C" {
(1UL << NRF_802154_DPPI_TIMER_COMPARE_TO_RADIO_TXEN) | \
(1UL << NRF_802154_DPPI_RADIO_SYNC_TO_EGU_SYNC) | \
(1UL << NRF_802154_DPPI_RADIO_CCAIDLE) | \
(1UL << NRF_802154_DPPI_RADIO_HW_TRIGGER) | \
NRF_802154_DPPI_RADIO_TEST_MODE_USED_MASK | \
NRF_802154_DPPI_TIMESTAMPS_USED_MASK)
#endif // NRF_802154_DPPI_CHANNELS_USED_MASK

View File

@ -160,13 +160,11 @@ static bool coex_rx_request_mode_is_supported(nrf_802154_coex_rx_request_mode_t
switch (mode)
{
#if !NRF_802154_DISABLE_BCC_MATCHING && defined(RADIO_INTENSET_SYNC_Msk)
#if defined(RADIO_INTENSET_SYNC_Msk)
case NRF_802154_COEX_RX_REQUEST_MODE_ENERGY_DETECTION:
#endif
case NRF_802154_COEX_RX_REQUEST_MODE_PREAMBLE:
#if !NRF_802154_DISABLE_BCC_MATCHING
case NRF_802154_COEX_RX_REQUEST_MODE_DESTINED:
#endif
result = true;
break;
@ -194,11 +192,7 @@ void nrf_802154_pib_init(void)
m_data.cca.corr_threshold = NRF_802154_CCA_CORR_THRESHOLD_DEFAULT;
m_data.cca.corr_limit = NRF_802154_CCA_CORR_LIMIT_DEFAULT;
#if NRF_802154_DISABLE_BCC_MATCHING
m_data.coex.rx_request_mode = NRF_802154_COEX_RX_REQUEST_MODE_PREAMBLE;
#else
m_data.coex.rx_request_mode = NRF_802154_COEX_RX_REQUEST_MODE_DESTINED;
#endif
m_data.coex.tx_request_mode = NRF_802154_COEX_TX_REQUEST_MODE_ON_CCA_TOGGLE;
#if NRF_802154_CSMA_CA_ENABLED

View File

@ -138,6 +138,15 @@ __STATIC_INLINE uint16_t nrf_802154_cca_before_tx_duration_get(void)
return us_time;
}
/**@brief Get the duration of the Ack frame along with turnaround in microseconds. */
__STATIC_INLINE uint16_t nrf_802154_ack_duration_with_turnaround_get(void)
{
// aTurnaroundTime + ACK frame duration
return PHY_US_TIME_FROM_SYMBOLS(A_TURNAROUND_TIME_SYMBOLS +
PHY_SHR_SYMBOLS +
PHY_SYMBOLS_FROM_OCTETS(IMM_ACK_LENGTH + PHR_SIZE));
}
__STATIC_INLINE uint16_t nrf_802154_rx_duration_get(uint8_t psdu_length, bool ack_requested)
{
// SHR + PHR + PSDU
@ -146,9 +155,7 @@ __STATIC_INLINE uint16_t nrf_802154_rx_duration_get(uint8_t psdu_length, bool ac
if (ack_requested)
{
us_time += PHY_US_TIME_FROM_SYMBOLS(A_TURNAROUND_TIME_SYMBOLS +
PHY_SHR_SYMBOLS +
PHY_SYMBOLS_FROM_OCTETS(IMM_ACK_LENGTH + PHR_SIZE));
us_time += nrf_802154_ack_duration_with_turnaround_get();
}
return us_time;

View File

@ -99,7 +99,7 @@ int8_t nrf_802154_rssi_sample_temp_corr_value_get(uint8_t rssi_sample)
return result;
}
#elif defined(NRF5340_XXAA)
#else
/** Macro for calculating x raised to the power of 2. */
#define POW_2(x) ((x) * (x))
@ -154,8 +154,6 @@ int8_t nrf_802154_rssi_sample_temp_corr_value_get(uint8_t rssi_sample)
return compensated_rssi - (int8_t)rssi_sample;
}
#else
#error Unsupported chip family
#endif
uint8_t nrf_802154_rssi_sample_corrected_get(uint8_t rssi_sample)

View File

@ -63,26 +63,26 @@
#include "nrf_802154_sl_ant_div.h"
#define EGU_SYNC_EVENT NRF_EGU_EVENT_TRIGGERED3
#define EGU_SYNC_TASK NRF_EGU_TASK_TRIGGER3
#define EGU_SYNC_INTMASK NRF_EGU_INT_TRIGGERED3
#ifdef NRF_802154_USE_INTERNAL_INCLUDES
#include "nrf_802154_trx_internal.h"
#endif
#define EGU_SYNC_EVENT NRF_EGU_EVENT_TRIGGERED3
#define EGU_SYNC_TASK NRF_EGU_TASK_TRIGGER3
#define EGU_SYNC_INTMASK NRF_EGU_INT_TRIGGERED3
#if defined(NRF52840_XXAA) || \
defined(NRF52833_XXAA)
#define PPI_CCAIDLE_FEM NRF_802154_PPI_RADIO_CCAIDLE_TO_FEM_GPIOTE ///< PPI that connects RADIO CCAIDLE event with GPIOTE tasks used by FEM
#define PPI_CHGRP_ABORT NRF_802154_PPI_ABORT_GROUP ///< PPI group used to disable PPIs when async event aborting radio operation is propagated through the system
#define RADIO_BASE NRF_RADIO_BASE
#define PPI_CCAIDLE_FEM NRF_802154_PPI_RADIO_CCAIDLE_TO_FEM_GPIOTE ///< PPI that connects RADIO CCAIDLE event with GPIOTE tasks used by FEM
#define PPI_CHGRP_ABORT NRF_802154_PPI_ABORT_GROUP ///< PPI group used to disable PPIs when async event aborting radio operation is propagated through the system
#define RADIO_BASE NRF_RADIO_BASE
#elif defined(NRF5340_XXAA)
#define PPI_CCAIDLE_FEM 0
#define RADIO_BASE NRF_RADIO_NS_BASE
#define FICR_BASE NRF_FICR_NS_BASE
#define PPI_CCAIDLE_FEM 0
#define RADIO_BASE NRF_RADIO_NS_BASE
#define FICR_BASE NRF_FICR_NS_BASE
#endif
#if NRF_802154_DISABLE_BCC_MATCHING
#define SHORT_ADDRESS_BCSTART 0UL
#else // NRF_802154_DISABLE_BCC_MATCHING
#define SHORT_ADDRESS_BCSTART NRF_RADIO_SHORT_ADDRESS_BCSTART_MASK
#endif // NRF_802154_DISABLE_BCC_MATCHING
/// Value set to SHORTS register when no shorts should be enabled.
#define SHORTS_IDLE 0
@ -130,6 +130,26 @@
void nrf_802154_radio_irq_handler(void); ///< Prototype required by internal RADIO IRQ handler
#endif // NRF_802154_INTERNAL_RADIO_IRQ_HANDLING
#ifndef NRF_802154_TRX_ENABLE_INTERNAL
#define NRF_802154_TRX_ENABLE_INTERNAL() \
do \
{ \
} \
while (0)
#endif
#ifndef NRF_802154_TRX_RADIO_RESET_INTERNAL
#define NRF_802154_TRX_RADIO_RESET_INTERNAL() \
do \
{ \
} \
while (0)
#endif
#ifndef NRF_802154_TRX_TEST_MODE_ALLOW_LATE_TX_ACK
#define NRF_802154_TRX_TEST_MODE_ALLOW_LATE_TX_ACK 0
#endif
/// Common parameters for the FEM handling.
static const mpsl_fem_event_t m_activate_rx_cc0 =
{
@ -176,20 +196,12 @@ static volatile trx_state_t m_trx_state;
typedef struct
{
#if !NRF_802154_DISABLE_BCC_MATCHING
bool psdu_being_received; ///< If PSDU is currently being received.
#endif
bool missing_receive_buffer; ///!< If trx entered receive state without receive buffer
#if NRF_802154_TX_STARTED_NOTIFY_ENABLED
bool tx_started; ///< If the requested transmission has started.
#endif // NRF_802154_TX_STARTED_NOTIFY_ENABLED
bool psdu_being_received; ///< If PSDU is currently being received.
bool missing_receive_buffer; ///!< If trx entered receive state without receive buffer
bool rxstarted_notif_en;
bool ccastarted_notif_en;
bool tx_started; ///< If the requested transmission has started.
bool rssi_started;
volatile bool rssi_settled;
} nrf_802154_flags_t;
@ -199,6 +211,8 @@ static nrf_802154_flags_t m_flags; ///< Flags used to store the current driver s
static volatile uint32_t m_timer_value_on_radio_end_event;
static volatile bool m_transmit_with_cca;
static void timer_frequency_set_1mhz(void);
static void rxframe_finish_disable_ppis(void);
static void rxack_finish_disable_ppis(void);
static void txframe_finish_disable_ppis(bool cca);
@ -221,9 +235,7 @@ static void energy_detection_abort(void);
void rx_flags_clear(void)
{
m_flags.missing_receive_buffer = false;
#if !NRF_802154_DISABLE_BCC_MATCHING
m_flags.psdu_being_received = false;
#endif // !NRF_802154_DISABLE_BCC_MATCHING
m_flags.psdu_being_received = false;
}
static void * volatile mp_receive_buffer;
@ -250,13 +262,7 @@ void nrf_timer_init(void)
nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_SHUTDOWN);
nrf_timer_mode_set(NRF_802154_TIMER_INSTANCE, NRF_TIMER_MODE_TIMER);
nrf_timer_bit_width_set(NRF_802154_TIMER_INSTANCE, NRF_TIMER_BIT_WIDTH_32);
nrf_timer_prescaler_set(NRF_802154_TIMER_INSTANCE, NRF_TIMER_FREQ_1MHz);
#if NRF_802154_DISABLE_BCC_MATCHING
// Setup timer for detecting PSDU reception.
nrf_timer_mode_set(NRF_802154_COUNTER_TIMER_INSTANCE, NRF_TIMER_MODE_COUNTER);
nrf_timer_bit_width_set(NRF_802154_COUNTER_TIMER_INSTANCE, NRF_TIMER_BIT_WIDTH_8);
#endif
timer_frequency_set_1mhz();
}
#if defined(NRF53_SERIES)
@ -290,13 +296,26 @@ static void yopan_158_workaround(void)
#endif /* NRF53_SERIES */
/** Sets the frequency of 1 MHz for NRF_802154_TIMER_INSTANCE. */
static void timer_frequency_set_1mhz(void)
{
uint32_t base_frequency = NRF_TIMER_BASE_FREQUENCY_GET(NRF_802154_TIMER_INSTANCE);
uint32_t prescaler = 31 - NRF_CLZ(base_frequency / 1000000);
nrf_timer_prescaler_set(NRF_802154_TIMER_INSTANCE, prescaler);
}
/** Reset radio peripheral. */
static void nrf_radio_reset(void)
{
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
#if defined(RADIO_POWER_POWER_Msk)
nrf_radio_power_set(NRF_RADIO, false);
nrf_radio_power_set(NRF_RADIO, true);
#endif
NRF_802154_TRX_RADIO_RESET_INTERNAL();
#if defined(NRF53_SERIES)
yopan_158_workaround();
@ -332,9 +351,11 @@ static void cca_configuration_update(void)
static void irq_init(void)
{
#if NRF_802154_INTERNAL_RADIO_IRQ_HANDLING
nrf_802154_irq_init(RADIO_IRQn, NRF_802154_IRQ_PRIORITY, nrf_802154_radio_irq_handler);
nrf_802154_irq_init(nrfx_get_irq_number(NRF_RADIO),
NRF_802154_IRQ_PRIORITY,
nrf_802154_radio_irq_handler);
#endif
nrf_802154_irq_enable(RADIO_IRQn);
nrf_802154_irq_enable(nrfx_get_irq_number(NRF_RADIO));
}
static void trigger_disable_to_start_rampup(void)
@ -342,6 +363,7 @@ static void trigger_disable_to_start_rampup(void)
if (!nrf_802154_trx_ppi_for_ramp_up_was_triggered())
{
nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_DISABLE);
nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_DISABLED);
}
}
@ -513,6 +535,32 @@ static void errata_117_apply(void)
#endif
static inline void wait_until_radio_is_disabled(void)
{
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
bool radio_is_disabled = false;
// RADIO should enter DISABLED state after no longer than RX ramp-down time, which is equal
// approximately 0.5us. Taking a bold assumption that a single iteration of the loop takes
// one cycle to complete, 32 iterations would amount to exactly 0.5 us of execution time.
// Please note that this approach ignores software latency completely, i.e. RADIO should
// have changed state already before entering this function due to ISR processing delays.
for (uint32_t i = 0; i < MAX_RXRAMPDOWN_CYCLES; i++)
{
if (nrf_radio_state_get(NRF_RADIO) == NRF_RADIO_STATE_DISABLED)
{
radio_is_disabled = true;
break;
}
}
assert(radio_is_disabled);
(void)radio_is_disabled;
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
}
void nrf_802154_trx_module_reset(void)
{
m_trx_state = TRX_STATE_DISABLED;
@ -570,7 +618,11 @@ void nrf_802154_trx_enable(void)
packet_conf.maxlen = MAX_PACKET_SIZE;
nrf_radio_packet_configure(NRF_RADIO, &packet_conf);
NRF_802154_TRX_ENABLE_INTERNAL();
#if defined(RADIO_MODECNF0_RU_Msk)
nrf_radio_modecnf0_set(NRF_RADIO, true, 0);
#endif
// Configure CRC
nrf_radio_crc_configure(NRF_RADIO, CRC_LENGTH, NRF_RADIO_CRC_ADDR_IEEE802154, CRC_POLYNOMIAL);
@ -677,13 +729,21 @@ void nrf_802154_trx_disable(void)
if (m_trx_state != TRX_STATE_DISABLED)
{
#if defined(RADIO_POWER_POWER_Msk)
nrf_radio_power_set(NRF_RADIO, false);
nrf_802154_irq_clear_pending(RADIO_IRQn);
#endif
nrf_802154_irq_clear_pending(nrfx_get_irq_number(NRF_RADIO));
/* While the RADIO is powered off deconfigure any PPIs used directly by trx module */
ppi_all_clear();
#if !NRF_802154_DISABLE_BCC_MATCHING && defined(RADIO_INTENSET_SYNC_Msk)
#if !defined(RADIO_POWER_POWER_Msk)
nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_DISABLE);
wait_until_radio_is_disabled();
nrf_radio_reset();
#endif
#if defined(RADIO_INTENSET_SYNC_Msk)
nrf_egu_int_disable(NRF_802154_EGU_INSTANCE, EGU_SYNC_INTMASK);
nrf_egu_event_clear(NRF_802154_EGU_INSTANCE, EGU_SYNC_EVENT);
#endif
@ -694,7 +754,9 @@ void nrf_802154_trx_disable(void)
NRF_TIMER_SHORT_COMPARE1_STOP_MASK);
nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_SHUTDOWN);
#if defined(RADIO_POWER_POWER_Msk)
nrf_radio_power_set(NRF_RADIO, true);
#endif
mpsl_fem_lna_configuration_clear();
mpsl_fem_pa_configuration_clear();
@ -705,19 +767,10 @@ void nrf_802154_trx_disable(void)
fem_power_down_now();
}
#if NRF_802154_DISABLE_BCC_MATCHING
// Anomaly 78: use SHUTDOWN instead of STOP and CLEAR.
nrf_timer_task_trigger(NRF_802154_COUNTER_TIMER_INSTANCE, NRF_TIMER_TASK_SHUTDOWN);
nrf_timer_shorts_disable(NRF_802154_COUNTER_TIMER_INSTANCE,
NRF_TIMER_SHORT_COMPARE1_STOP_MASK);
#else
m_flags.psdu_being_received = false;
#endif
m_flags.psdu_being_received = false;
m_flags.missing_receive_buffer = false;
m_flags.rssi_started = false;
#if NRF_802154_TX_STARTED_NOTIFY_ENABLED
m_flags.tx_started = false;
#endif
m_flags.tx_started = false;
m_trx_state = TRX_STATE_DISABLED;
@ -879,17 +932,7 @@ void nrf_802154_trx_cca_configuration_update(void)
*/
bool nrf_802154_trx_psdu_is_being_received(void)
{
#if NRF_802154_DISABLE_BCC_MATCHING
nrf_timer_task_trigger(NRF_802154_COUNTER_TIMER_INSTANCE,
nrf_timer_capture_task_get(NRF_TIMER_CC_CHANNEL0));
uint32_t counter = nrf_timer_cc_get(NRF_802154_COUNTER_TIMER_INSTANCE, NRF_TIMER_CC_CHANNEL0);
assert(counter <= 1);
return counter > 0;
#else // NRF_802154_DISABLE_BCC_MATCHING
return m_flags.psdu_being_received;
#endif // NRF_802154_DISABLE_BCC_MATCHING
}
bool nrf_802154_trx_receive_is_buffer_missing(void)
@ -961,6 +1004,7 @@ bool nrf_802154_trx_receive_buffer_set(void * p_receive_buffer)
}
void nrf_802154_trx_receive_frame(uint8_t bcc,
nrf_802154_trx_ramp_up_trigger_mode_t rampup_trigg_mode,
nrf_802154_trx_receive_notifications_t notifications_mask,
const nrf_802154_fal_tx_power_split_t * p_ack_tx_power)
{
@ -976,6 +1020,9 @@ void nrf_802154_trx_receive_frame(uint8_t bcc,
// Clear filtering flag
rx_flags_clear();
m_flags.rxstarted_notif_en = (notifications_mask & TRX_RECEIVE_NOTIFICATION_STARTED) != 0U;
// Clear the RSSI measurement flag.
m_flags.rssi_started = false;
@ -998,30 +1045,23 @@ void nrf_802154_trx_receive_frame(uint8_t bcc,
nrf_radio_shorts_set(NRF_RADIO, shorts);
// Set BCC
#if !NRF_802154_DISABLE_BCC_MATCHING
assert(bcc != 0U);
nrf_radio_bcc_set(NRF_RADIO, bcc * 8U);
#else
assert(bcc == 0U);
(void)bcc;
#endif // !NRF_802154_DISABLE_BCC_MATCHING
// Enable IRQs
#if !NRF_802154_DISABLE_BCC_MATCHING || NRF_802154_NOTIFY_CRCERROR
nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_CRCERROR);
ints_to_enable |= NRF_RADIO_INT_CRCERROR_MASK;
#endif // !NRF_802154_DISABLE_BCC_MATCHING ||NRF_802154_NOTIFY_CRCERROR
#if !NRF_802154_DISABLE_BCC_MATCHING
nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_BCMATCH);
ints_to_enable |= NRF_RADIO_INT_BCMATCH_MASK;
#endif // !NRF_802154_DISABLE_BCC_MATCHING
nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_CRCOK);
ints_to_enable |= NRF_RADIO_INT_CRCOK_MASK;
nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_ADDRESS);
ints_to_enable |= NRF_RADIO_INT_ADDRESS_MASK;
if ((notifications_mask & TRX_RECEIVE_NOTIFICATION_STARTED) != 0U)
if (rampup_trigg_mode == TRX_RAMP_UP_HW_TRIGGER)
{
nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_ADDRESS);
ints_to_enable |= NRF_RADIO_INT_ADDRESS_MASK;
nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_READY);
ints_to_enable |= NRF_RADIO_INT_READY_MASK;
}
bool allow_sync_swi = false;
@ -1037,7 +1077,7 @@ void nrf_802154_trx_receive_frame(uint8_t bcc,
if (allow_sync_swi)
{
#if (NRF_802154_DISABLE_BCC_MATCHING || !defined(RADIO_INTENSET_SYNC_Msk))
#if !defined(RADIO_INTENSET_SYNC_Msk)
assert(false);
#else
// The RADIO can't generate interrupt on EVENT_SYNC. Path to generate interrupt:
@ -1079,18 +1119,13 @@ void nrf_802154_trx_receive_frame(uint8_t bcc,
nrf_timer_shorts_enable(NRF_802154_TIMER_INSTANCE,
NRF_TIMER_SHORT_COMPARE0_STOP_MASK);
#if NRF_802154_DISABLE_BCC_MATCHING
nrf_timer_shorts_enable(NRF_802154_COUNTER_TIMER_INSTANCE, NRF_TIMER_SHORT_COMPARE1_STOP_MASK);
nrf_timer_cc_set(NRF_802154_COUNTER_TIMER_INSTANCE, NRF_TIMER_CC_CHANNEL1, 1);
#endif // NRF_802154_DISABLE_BCC_MATCHING
// Set PPIs
#if NRF_802154_DISABLE_BCC_MATCHING
#error Configuration unsupported anymore
#endif // NRF_802154_DISABLE_BCC_MATCHING
nrf_802154_trx_ppi_for_ramp_up_set(NRF_RADIO_TASK_RXEN, true);
nrf_802154_trx_ppi_for_ramp_up_set(NRF_RADIO_TASK_RXEN, rampup_trigg_mode, true);
trigger_disable_to_start_rampup();
if (rampup_trigg_mode == TRX_RAMP_UP_SW_TRIGGER)
{
trigger_disable_to_start_rampup();
}
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
}
@ -1128,7 +1163,7 @@ void nrf_802154_trx_receive_ack(void)
fem_for_lna_set();
nrf_802154_trx_antenna_update();
nrf_802154_trx_ppi_for_ramp_up_set(NRF_RADIO_TASK_RXEN, false);
nrf_802154_trx_ppi_for_ramp_up_set(NRF_RADIO_TASK_RXEN, TRX_RAMP_UP_SW_TRIGGER, false);
trigger_disable_to_start_rampup();
@ -1159,7 +1194,9 @@ bool nrf_802154_trx_rssi_measure(void)
m_flags.rssi_settled = true;
}
#if defined(RADIO_EVENTS_RSSIEND_EVENTS_RSSIEND_Msk)
nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_RSSIEND);
#endif
nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_RSSISTART);
m_flags.rssi_started = true;
@ -1191,10 +1228,15 @@ uint8_t nrf_802154_trx_rssi_last_sample_get(void)
bool nrf_802154_trx_rssi_sample_is_available(void)
{
#if defined(RADIO_EVENTS_RSSIEND_EVENTS_RSSIEND_Msk)
return nrf_radio_event_check(NRF_RADIO, NRF_RADIO_EVENT_RSSIEND);
#else
return true;
#endif
}
void nrf_802154_trx_transmit_frame(const void * p_transmit_buffer,
nrf_802154_trx_ramp_up_trigger_mode_t rampup_trigg_mode,
bool cca,
const nrf_802154_fal_tx_power_split_t * p_tx_power,
nrf_802154_trx_transmit_notifications_t notifications_mask)
@ -1209,6 +1251,8 @@ void nrf_802154_trx_transmit_frame(const void * p_tra
m_trx_state = TRX_STATE_TXFRAME;
m_transmit_with_cca = cca;
m_flags.ccastarted_notif_en = false;
txpower_set(p_tx_power->radio_tx_power);
nrf_radio_packetptr_set(NRF_RADIO, p_transmit_buffer);
@ -1227,6 +1271,12 @@ void nrf_802154_trx_transmit_frame(const void * p_tra
nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_PHYEND);
ints_to_enable |= NRF_RADIO_INT_PHYEND_MASK;
if (rampup_trigg_mode == TRX_RAMP_UP_HW_TRIGGER)
{
nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_READY);
ints_to_enable |= NRF_RADIO_INT_READY_MASK;
}
if (cca)
{
nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_CCABUSY);
@ -1242,23 +1292,27 @@ void nrf_802154_trx_transmit_frame(const void * p_tra
if ((notifications_mask & TRX_TRANSMIT_NOTIFICATION_CCASTARTED) != 0U)
{
nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_READY);
ints_to_enable |= NRF_RADIO_INT_READY_MASK;
ints_to_enable |= NRF_RADIO_INT_READY_MASK;
m_flags.ccastarted_notif_en = true;
}
}
nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_ADDRESS);
#if NRF_802154_TX_STARTED_NOTIFY_ENABLED
ints_to_enable |= NRF_RADIO_INT_ADDRESS_MASK;
m_flags.tx_started = false;
#endif // NRF_802154_TX_STARTED_NOTIFY_ENABLED
nrf_radio_int_enable(NRF_RADIO, ints_to_enable);
fem_for_tx_set(cca, &p_tx_power->fem);
nrf_802154_trx_antenna_update();
nrf_802154_trx_ppi_for_ramp_up_set(cca ? NRF_RADIO_TASK_RXEN : NRF_RADIO_TASK_TXEN, false);
nrf_802154_trx_ppi_for_ramp_up_set(cca ? NRF_RADIO_TASK_RXEN : NRF_RADIO_TASK_TXEN,
rampup_trigg_mode,
false);
trigger_disable_to_start_rampup();
if (rampup_trigg_mode == TRX_RAMP_UP_SW_TRIGGER)
{
trigger_disable_to_start_rampup();
}
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
}
@ -1330,9 +1384,7 @@ bool nrf_802154_trx_transmit_ack(const void * p_transmit_buffer, uint32_t delay_
nrf_802154_trx_antenna_update();
nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_PHYEND);
#if NRF_802154_TX_STARTED_NOTIFY_ENABLED
nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_ADDRESS);
#endif
// Set PPIs
nrf_802154_trx_ppi_for_ack_tx_set();
@ -1376,16 +1428,13 @@ bool nrf_802154_trx_transmit_ack(const void * p_transmit_buffer, uint32_t delay_
if (result)
{
uint32_t ints_to_enable = NRF_RADIO_INT_PHYEND_MASK;
#if NRF_802154_TX_STARTED_NOTIFY_ENABLED
ints_to_enable |= NRF_RADIO_INT_ADDRESS_MASK;
#endif // NRF_802154_TX_STARTED_NOTIFY_ENABLED
uint32_t ints_to_enable = NRF_RADIO_INT_PHYEND_MASK | NRF_RADIO_INT_ADDRESS_MASK;
nrf_radio_int_enable(NRF_RADIO, ints_to_enable);
}
else
{
#if !NRF_802154_TRX_TEST_MODE_ALLOW_LATE_TX_ACK
/* We were to late with setting up PPI_TIMER_ACK, ack transmission was not triggered and
* will not be triggered in future.
*/
@ -1400,6 +1449,15 @@ bool nrf_802154_trx_transmit_ack(const void * p_transmit_buffer, uint32_t delay_
nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_SHUTDOWN);
/* No callbacks will be called */
#else // !NRF_802154_TRX_TEST_MODE_ALLOW_LATE_TX_ACK
uint32_t ints_to_enable = NRF_RADIO_INT_PHYEND_MASK | NRF_RADIO_INT_ADDRESS_MASK;
nrf_radio_int_enable(NRF_RADIO, ints_to_enable);
nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_TXEN);
result = true;
#endif // !NRF_802154_TRX_TEST_MODE_ALLOW_LATE_TX_ACK
}
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
@ -1407,32 +1465,6 @@ bool nrf_802154_trx_transmit_ack(const void * p_transmit_buffer, uint32_t delay_
return result;
}
static inline void wait_until_radio_is_disabled(void)
{
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
bool radio_is_disabled = false;
// RADIO should enter DISABLED state after no longer than RX ramp-down time, which is equal
// approximately 0.5us. Taking a bold assumption that a single iteration of the loop takes
// one cycle to complete, 32 iterations would amount to exactly 0.5 us of execution time.
// Please note that this approach ignores software latency completely, i.e. RADIO should
// have changed state already before entering this function due to ISR processing delays.
for (uint32_t i = 0; i < MAX_RXRAMPDOWN_CYCLES; i++)
{
if (nrf_radio_state_get(NRF_RADIO) == NRF_RADIO_STATE_DISABLED)
{
radio_is_disabled = true;
break;
}
}
assert(radio_is_disabled);
(void)radio_is_disabled;
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
}
static void rxframe_finish_disable_ppis(void)
{
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
@ -1462,17 +1494,15 @@ static void rxframe_finish_disable_ints(void)
{
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
uint32_t ints_to_disable = NRF_RADIO_INT_CRCOK_MASK | NRF_RADIO_INT_ADDRESS_MASK;
uint32_t ints_to_disable = NRF_RADIO_INT_READY_MASK |
NRF_RADIO_INT_ADDRESS_MASK |
NRF_RADIO_INT_CRCOK_MASK;
#if !NRF_802154_DISABLE_BCC_MATCHING || NRF_802154_NOTIFY_CRCERROR
ints_to_disable |= NRF_RADIO_INT_CRCERROR_MASK;
#endif // !NRF_802154_DISABLE_BCC_MATCHING || NRF_802154_NOTIFY_CRCERROR
#if !NRF_802154_DISABLE_BCC_MATCHING
ints_to_disable |= NRF_RADIO_INT_BCMATCH_MASK;
#endif // !NRF_802154_DISABLE_BCC_MATCHING
nrf_radio_int_disable(NRF_RADIO, ints_to_disable);
#if !NRF_802154_DISABLE_BCC_MATCHING && defined(RADIO_INTENSET_SYNC_Msk)
#if defined(RADIO_INTENSET_SYNC_Msk)
nrf_egu_int_disable(NRF_802154_EGU_INSTANCE, EGU_SYNC_INTMASK);
#endif
@ -1481,13 +1511,7 @@ static void rxframe_finish_disable_ints(void)
static void rxframe_finish_psdu_is_not_being_received(void)
{
#if NRF_802154_DISABLE_BCC_MATCHING
// Anomaly 78: use SHUTDOWN instead of STOP and CLEAR.
nrf_timer_task_trigger(NRF_802154_COUNTER_TIMER_INSTANCE, NRF_TIMER_TASK_SHUTDOWN);
nrf_timer_shorts_disable(NRF_802154_COUNTER_TIMER_INSTANCE, NRF_TIMER_SHORT_COMPARE1_STOP_MASK);
#else
m_flags.psdu_being_received = false;
#endif // NRF_802154_DISABLE_BCC_MATCHING
}
static void rxframe_finish(void)
@ -1604,6 +1628,11 @@ trx_state_t nrf_802154_trx_state_get(void)
return m_trx_state;
}
uint32_t nrf_802154_trx_ramp_up_ppi_channel_get(void)
{
return nrf_802154_trx_ppi_for_ramp_up_channel_id_get();
}
static void go_idle_from_state_finished(void)
{
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
@ -1788,7 +1817,7 @@ void nrf_802154_trx_standalone_cca(void)
nrf_802154_trx_antenna_update();
// Set PPIs
nrf_802154_trx_ppi_for_ramp_up_set(NRF_RADIO_TASK_RXEN, false);
nrf_802154_trx_ppi_for_ramp_up_set(NRF_RADIO_TASK_RXEN, TRX_RAMP_UP_SW_TRIGGER, false);
trigger_disable_to_start_rampup();
@ -1844,7 +1873,7 @@ void nrf_802154_trx_continuous_carrier(const nrf_802154_fal_tx_power_split_t * p
nrf_802154_trx_antenna_update();
// Set PPIs
nrf_802154_trx_ppi_for_ramp_up_set(NRF_RADIO_TASK_TXEN, false);
nrf_802154_trx_ppi_for_ramp_up_set(NRF_RADIO_TASK_TXEN, TRX_RAMP_UP_SW_TRIGGER, false);
trigger_disable_to_start_rampup();
@ -1907,7 +1936,7 @@ void nrf_802154_trx_modulated_carrier(const void * p_
nrf_802154_trx_antenna_update();
// Set PPIs
nrf_802154_trx_ppi_for_ramp_up_set(NRF_RADIO_TASK_TXEN, false);
nrf_802154_trx_ppi_for_ramp_up_set(NRF_RADIO_TASK_TXEN, TRX_RAMP_UP_SW_TRIGGER, false);
trigger_disable_to_start_rampup();
@ -1958,7 +1987,9 @@ void nrf_802154_trx_energy_detection(uint32_t ed_count)
ed_count--;
/* Check that vd_count will fit into defined bits of register */
#if defined(RADIO_EDCNT_EDCNT_Msk)
assert( (ed_count & (~RADIO_EDCNT_EDCNT_Msk)) == 0U);
#endif
nrf_radio_ed_loop_count_set(NRF_RADIO, ed_count);
@ -1976,7 +2007,7 @@ void nrf_802154_trx_energy_detection(uint32_t ed_count)
nrf_802154_trx_antenna_update();
// Set PPIs
nrf_802154_trx_ppi_for_ramp_up_set(NRF_RADIO_TASK_RXEN, false);
nrf_802154_trx_ppi_for_ramp_up_set(NRF_RADIO_TASK_RXEN, TRX_RAMP_UP_SW_TRIGGER, false);
trigger_disable_to_start_rampup();
@ -2013,44 +2044,61 @@ static void irq_handler_ready(void)
{
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
assert(m_trx_state == TRX_STATE_TXFRAME);
nrf_radio_int_disable(NRF_RADIO, NRF_RADIO_INT_READY_MASK);
nrf_802154_trx_transmit_frame_ccastarted();
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
}
static void irq_handler_address(void)
{
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
nrf_802154_trx_ppi_for_ramp_up_reconfigure();
switch (m_trx_state)
{
case TRX_STATE_RXFRAME:
nrf_802154_trx_receive_frame_started();
break;
case TRX_STATE_RXACK:
m_flags.rssi_started = true;
nrf_802154_trx_receive_ack_started();
break;
#if NRF_802154_TX_STARTED_NOTIFY_ENABLED
case TRX_STATE_TXFRAME:
nrf_radio_int_disable(NRF_RADIO, NRF_RADIO_INT_ADDRESS_MASK);
m_flags.tx_started = true;
nrf_802154_trx_transmit_frame_started();
if (m_flags.ccastarted_notif_en)
{
nrf_802154_trx_transmit_frame_ccastarted();
}
break;
#endif // NRF_802154_TX_STARTED_NOTIFY_ENABLED
#if NRF_802154_TX_STARTED_NOTIFY_ENABLED
case TRX_STATE_TXACK:
nrf_radio_int_disable(NRF_RADIO, NRF_RADIO_INT_ADDRESS_MASK);
nrf_802154_trx_transmit_ack_started();
case TRX_STATE_RXFRAME:
break;
default:
assert(false);
}
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
}
static void irq_handler_address(void)
{
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
// NRF_RADIO_TASK_DISABLE may have been triggered by (D)PPI, therefore event reg
// cleanup is required. It's done here
nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_DISABLED);
switch (m_trx_state)
{
case TRX_STATE_RXFRAME:
if (m_flags.rxstarted_notif_en)
{
nrf_802154_trx_receive_frame_started();
}
break;
case TRX_STATE_RXACK:
m_flags.rssi_started = true;
nrf_802154_trx_receive_ack_started();
break;
case TRX_STATE_TXFRAME:
nrf_radio_int_disable(NRF_RADIO, NRF_RADIO_INT_ADDRESS_MASK);
m_flags.tx_started = true;
nrf_802154_trx_transmit_frame_started();
break;
case TRX_STATE_TXACK:
nrf_radio_int_disable(NRF_RADIO, NRF_RADIO_INT_ADDRESS_MASK);
nrf_802154_trx_transmit_ack_started();
break;
#endif
default:
assert(false);
@ -2059,7 +2107,6 @@ static void irq_handler_address(void)
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
}
#if !NRF_802154_DISABLE_BCC_MATCHING
static void irq_handler_bcmatch(void)
{
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
@ -2095,9 +2142,6 @@ static void irq_handler_bcmatch(void)
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
}
#endif
#if !NRF_802154_DISABLE_BCC_MATCHING || NRF_802154_NOTIFY_CRCERROR
static void irq_handler_crcerror(void)
{
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
@ -2105,17 +2149,10 @@ static void irq_handler_crcerror(void)
switch (m_trx_state)
{
case TRX_STATE_RXFRAME:
#if NRF_802154_DISABLE_BCC_MATCHING
/* The hardware restarts receive at the moment.
* The TIMER is being shutdown and restarted by the hardware see
* PPI_CRCERROR_CLEAR in nrf_802154_trx_receive_frame
*/
#else
rxframe_finish();
/* On crc error TIMER is not needed, no ACK may be sent */
nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_SHUTDOWN);
m_trx_state = TRX_STATE_FINISHED;
#endif
nrf_802154_trx_receive_frame_crcerror();
break;
@ -2132,8 +2169,6 @@ static void irq_handler_crcerror(void)
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
}
#endif
static void irq_handler_crcok(void)
{
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
@ -2207,9 +2242,8 @@ static void txframe_finish(void)
txframe_finish_disable_ints();
nrf_radio_shorts_set(NRF_RADIO, SHORTS_IDLE);
#if NRF_802154_TX_STARTED_NOTIFY_ENABLED
m_flags.tx_started = false;
#endif
m_flags.tx_started = false;
m_flags.missing_receive_buffer = false;
/* Current state of peripherals
@ -2233,9 +2267,8 @@ static void transmit_frame_abort(void)
fem_for_tx_reset(m_transmit_with_cca);
txframe_finish_disable_ints();
#if NRF_802154_TX_STARTED_NOTIFY_ENABLED
m_flags.tx_started = false;
#endif
m_flags.tx_started = false;
m_flags.missing_receive_buffer = false;
nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_CCASTOP);
@ -2489,7 +2522,6 @@ void nrf_802154_radio_irq_handler(void)
irq_handler_address();
}
#if !NRF_802154_DISABLE_BCC_MATCHING
// Check MAC frame header.
if (nrf_radio_int_enable_check(NRF_RADIO, NRF_RADIO_INT_BCMATCH_MASK) &&
nrf_radio_event_check(NRF_RADIO, NRF_RADIO_EVENT_BCMATCH))
@ -2499,9 +2531,6 @@ void nrf_802154_radio_irq_handler(void)
irq_handler_bcmatch();
}
#endif // !NRF_802154_DISABLE_BCC_MATCHING
#if !NRF_802154_DISABLE_BCC_MATCHING || NRF_802154_NOTIFY_CRCERROR
if (nrf_radio_int_enable_check(NRF_RADIO, NRF_RADIO_INT_CRCERROR_MASK) &&
nrf_radio_event_check(NRF_RADIO, NRF_RADIO_EVENT_CRCERROR))
{
@ -2509,7 +2538,6 @@ void nrf_802154_radio_irq_handler(void)
irq_handler_crcerror();
}
#endif // !NRF_802154_DISABLE_BCC_MATCHING || NRF_802154_NOTIFY_CRCERROR
if (nrf_radio_int_enable_check(NRF_RADIO, NRF_RADIO_INT_CRCOK_MASK) &&
nrf_radio_event_check(NRF_RADIO, NRF_RADIO_EVENT_CRCOK))
@ -2597,7 +2625,7 @@ void nrf_802154_trx_swi_irq_handler(void)
// Following will make it pending, and processing of RADIO_IRQ will start
// when critical section is left.
nrf_802154_irq_set_pending(RADIO_IRQn);
nrf_802154_irq_set_pending(nrfx_get_irq_number(NRF_RADIO));
}
nrf_802154_mcu_critical_exit(mcu_crit_state);

View File

@ -86,6 +86,13 @@ typedef enum
TRX_STATE_FINISHED
} trx_state_t;
/**@brief Radio ramp up procedure triggering modes. */
typedef enum
{
TRX_RAMP_UP_SW_TRIGGER, ///< Triggering by RADIO_DISABLED, which is a software generated event.
TRX_RAMP_UP_HW_TRIGGER ///< Triggering by some other event that needs to publish to a dedicated (D)PPI channel.
} nrf_802154_trx_ramp_up_trigger_mode_t;
/**@brief Notifications that can be enabled for @ref nrf_802154_trx_receive_frame operation. */
typedef enum
{
@ -176,7 +183,6 @@ void nrf_802154_trx_cca_configuration_update(void);
*
* The frame will be received into buffer set by @ref nrf_802154_trx_receive_buffer_set.
*
* When NRF_802154_DISABLE_BCC_MATCHING == 0
* - during receive @ref nrf_802154_trx_receive_frame_started handler is called when
* SHR field of a frame being received is received (only when @p notifications_mask contained @ref TRX_RECEIVE_NOTIFICATION_STARTED flag)
* - during receive @ref nrf_802154_trx_receive_frame_bcmatched handler is called when
@ -184,34 +190,25 @@ void nrf_802154_trx_cca_configuration_update(void);
* - when a frame is received with correct crc, @ref nrf_802154_trx_receive_frame_received is called
* - when a frame is received with incorrect crc, @ref nrf_802154_trx_receive_frame_crcerror is called
*
* When NRF_802154_DISABLE_BCC_MATCHING != 0
* - @ref nrf_802154_trx_receive_frame_prestarted handler is called when the RADIO initially syncs on received frame.
* This handler is called when @p notifications_mask contains @ref TRX_RECEIVE_NOTIFICATION_PRESTARTED.
* - @ref nrf_802154_trx_receive_frame_started handler is called when
* SHR field of a frame being received is received (only when @p notifications_mask contained @ref TRX_RECEIVE_NOTIFICATION_STARTED flag)
* - after the frame is received with correct crc, @ref nrf_802154_trx_receive_frame_received is called
* - after the frame is received with incorrect crc:
* - when NRF_802154_NOTIFY_CRCERROR == 0:
* - the hardware restarts receive automatically
* - no handler is called
* - when NRF_802154_NOTIFY_CRCERROR != 0:
* - the hardware restarts receive automatically
* - @ref nrf_802154_trx_receive_frame_crcerror is called
*
* When in @ref nrf_802154_trx_receive_frame_received, the TIMER is running allowing sending response (e.g. ACK frame)
* in time regime by a call to nrf_802154_trx_transmit_after_frame_received.
*
* @note To receive ACK use @ref nrf_802154_trx_receive_ack
*
* @param[in] bcc Number of received bytes after which @ref nrf_802154_trx_receive_frame_bcmatched will be called.
* This must not be zero if @ref NRF_802154_DISABLE_BCC_MATCHING == 0.
* When @ref NRF_802154_DISABLE_BCC_MATCHING != 0, this value must be zero.
* @param[in] rampup_trigg_mode Radio ramp up triggering mode to be used.
* If @ref TRX_RAMP_UP_SW_TRIGGER is selected, this function will trigger radio ramp up in a software manner
* and the caller is guaranteed that ramp up is ongoing when the function ends.
* If @ref TRX_RAMP_UP_HW_TRIGGER is selected, this function will prepare the operation but it will end
* without starting radio ramp up. In this case, it is assumed that the trigger will be generated
* on the (D)PPI channel specified by @ref nrf_802154_trx_ramp_up_ppi_channel_get. It is the user's
* responsibility to prepare the stimulation of this (D)PPI.
* @param[in] notifications_mask Selects additional notifications generated during a frame reception.
* It is bitwise combination of @ref nrf_802154_trx_receive_notifications_t values.
* When NRF_802154_DISABLE_BCC_MATCHING != 0, flag @ref TRX_RECEIVE_NOTIFICATION_PRESTARTED is forbidden.
* @param[in] p_ack_tx_power Selects the power which should be used to transmitted an ACK if required.
*/
void nrf_802154_trx_receive_frame(uint8_t bcc,
nrf_802154_trx_ramp_up_trigger_mode_t rampup_trigg_mode,
nrf_802154_trx_receive_notifications_t notifications_mask,
const nrf_802154_fal_tx_power_split_t * p_ack_tx_power);
@ -313,8 +310,6 @@ bool nrf_802154_trx_receive_buffer_set(void * p_receive_buffer);
* - The RADIO starts ramp up in transmit mode.
* - The RADIO starts sending synchronization header (SHR).
* - @ref nrf_802154_trx_transmit_frame_started handler is called from an ISR just after SHR is sent
* (only when @ref NRF_802154_TX_STARTED_NOTIFY_ENABLED == 1).
* - @ref nrf_802154_trx_transmit_frame_transmitted handler is called from an ISR after full frame is sent on air.
*
* When cca==true:
* - The radio starts ramp up in receive mode, then it starts cca procedure.
@ -327,8 +322,6 @@ bool nrf_802154_trx_receive_buffer_set(void * p_receive_buffer);
* - If @ref TRX_TRANSMIT_NOTIFICATION_CCAIDLE was present in notifications_mask,
* the @ref nrf_802154_trx_transmit_frame_ccaidle is called.
* - @ref nrf_802154_trx_transmit_frame_started handler is called from an ISR just after SHR is sent
* (only when @ref NRF_802154_TX_STARTED_NOTIFY_ENABLED == 1).
* - @ref nrf_802154_trx_transmit_frame_transmitted handler is called from an ISR after full frame is sent on air.
* - If cca failed (channel was busy):
* - The RADIO disables receive mode
* - @ref nrf_802154_trx_transmit_frame_ccabusy from an ISR handler is called
@ -338,6 +331,16 @@ bool nrf_802154_trx_receive_buffer_set(void * p_receive_buffer);
* bytes following p_transmit_buffer[0] to send.
* The number of bytes pointed by p_transmit buffer must
* be at least 1 and not less than p_transmit_buffer[0] + 1.
* @param rampup_trigg_mode Radio ramp up triggering mode to be used.
* If @ref TRX_RAMP_UP_SW_TRIGGER is selected, this function
* will trigger radio ramp up in a software manner.
* If @ref TRX_RAMP_UP_HW_TRIGGER is selected, this function
* will prepare the operation but it will end without starting
* radio ramp up. In this case, it is assumed that the trigger
* will be generated on the (D)PPI channel specified by
* @ref nrf_802154_trx_ramp_up_ppi_channel_get.
* It is the user's responsibility to prepare the stimulation
* of this (D)PPI.
* @param cca Selects if CCA procedure should be performed prior to
* real transmission. If false no cca will be performed.
* If true, cca will be performed.
@ -347,6 +350,7 @@ bool nrf_802154_trx_receive_buffer_set(void * p_receive_buffer);
* @note To transmit ack after frame is received use @ref nrf_802154_trx_transmit_ack.
*/
void nrf_802154_trx_transmit_frame(const void * p_transmit_buffer,
nrf_802154_trx_ramp_up_trigger_mode_t rampup_trigg_mode,
bool cca,
const nrf_802154_fal_tx_power_split_t * p_tx_power,
nrf_802154_trx_transmit_notifications_t notifications_mask);
@ -361,8 +365,7 @@ void nrf_802154_trx_transmit_frame(const void * p_tra
* @param[in] delay_us Delay (in microseconds)
*
* @retval true If the function was called in time and ACK frame is scheduled for transmission.
* When transmission starts and @ref NRF_802154_TX_STARTED_NOTIFY_ENABLED != 0
* the function @ref nrf_802154_trx_transmit_ack_started will be called.
* When transmission starts the function @ref nrf_802154_trx_transmit_ack_started will be called.
* When transmission is finished the function @ref nrf_802154_trx_transmit_ack_transmitted
* will be called.
* @retval false If the function was called too late and given delay_us time gap
@ -447,6 +450,11 @@ void nrf_802154_trx_abort(void);
* @return Current state of the TRX module.*/
trx_state_t nrf_802154_trx_state_get(void);
/**
* @brief Gets (D)PPI channel used to trigger ramp up procedure start.
*/
uint32_t nrf_802154_trx_ramp_up_ppi_channel_get(void);
/**@brief Handler called at the beginning of a ACK reception.
*
* This handler is called from an ISR when receive of an ack has been started, and
@ -538,7 +546,6 @@ extern void nrf_802154_trx_receive_frame_received(void);
* - receive operation has been started with a call to @ref nrf_802154_trx_receive_frame
* - the RADIO received a frame on air with incorrect crc
*
* If NRF_802154_DISABLE_BCC_MATCHING == 0:
* When this handler is called following holds:
* - the RADIO peripheral started ramping down (or it ramped down already)
* - trx module is in @c FINISHED state.
@ -550,9 +557,6 @@ extern void nrf_802154_trx_receive_frame_received(void);
* - @ref nrf_802154_trx_go_idle,
* - @ref nrf_802154_trx_disable.
*
* If NRF_802154_DISABLE_BCC_MATCHING != 0:
* - the RADIO peripheral is restarted automatically (by hardware) in receive mode
* - trx module stays in @c RXFRAME state
* Implementation of @ref nrf_802154_trx_receive_frame_crcerror should not call
* @ref nrf_802154_trx_receive_frame as receive is restarted automatically by the hardware.
* If the implementation wishes to change state it should call
@ -649,7 +653,6 @@ extern void nrf_802154_trx_transmit_frame_ccabusy(void);
/**@brief Handler called when frame transmission has just started.
*
* This handler is called from an ISR when:
* - @ref NRF_802154_TX_STARTED_NOTIFY_ENABLED == 1 (see nrf_802154_config.h)
* - transmit operation was started by a call to @ref nrf_802154_trx_transmit_frame.
* - the RADIO peripheral sent synchronization header
*
@ -683,7 +686,6 @@ extern void nrf_802154_trx_transmit_frame_transmitted(void);
/**@brief Handler called when ack transmission has just been started.
*
* This handler is called from an ISR when:
* - @ref NRF_802154_TX_STARTED_NOTIFY_ENABLED == 1 (see nrf_802154_config.h)
* - transmit operation was started by a call to @ref nrf_802154_trx_transmit_ack.
* - the RADIO peripheral sent synchronization header
*

View File

@ -36,7 +36,7 @@
#include "nrfx.h"
#ifdef NRF53_SERIES
#if defined(DPPI_PRESENT)
#include "nrf_802154_trx_ppi_api.h"
@ -48,9 +48,6 @@
#include "hal/nrf_radio.h"
#include "hal/nrf_timer.h"
#define EGU_EVENT NRF_EGU_EVENT_TRIGGERED15
#define EGU_TASK NRF_EGU_TASK_TRIGGER15
#define DPPI_CHGRP_RAMP_UP NRF_DPPI_CHANNEL_GROUP0 ///< PPI group used to disable self-disabling PPIs
#define DPPI_CHGRP_RAMP_UP_DIS_TASK NRF_DPPI_TASK_CHG0_DIS ///< PPI task used to disable self-disabling PPIs
@ -70,32 +67,46 @@ void nrf_802154_trx_ppi_for_enable(void)
#if NRF_802154_TEST_MODES_ENABLED
nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_CCABUSY, NRF_802154_DPPI_RADIO_CCABUSY);
#endif // NRF_802154_TEST_MODES_ENABLED
#if defined(NRF_802154_DPPI_RADIO_TXREADY)
nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_TXREADY, NRF_802154_DPPI_RADIO_TXREADY);
#endif
nrf_dppi_channels_enable(NRF_DPPIC,
nrf_dppi_channels_enable(NRF_802154_DPPIC_INSTANCE,
#if NRF_802154_TEST_MODES_ENABLED
(1UL << NRF_802154_DPPI_RADIO_CCABUSY) |
#endif // NRF_802154_TEST_MODES_ENABLED
(1UL << PPI_DISABLED_EGU) |
(1UL << NRF_802154_DPPI_RADIO_READY) |
#if defined(NRF_802154_DPPI_RADIO_TXREADY)
(1UL << NRF_802154_DPPI_RADIO_TXREADY) |
#endif
(1UL << NRF_802154_DPPI_RADIO_ADDRESS) |
(1UL << NRF_802154_DPPI_RADIO_END) |
(1UL << NRF_802154_DPPI_RADIO_PHYEND) |
(1UL << NRF_802154_DPPI_RADIO_CCAIDLE));
(1UL << NRF_802154_DPPI_RADIO_CCAIDLE) |
(1UL << NRF_802154_DPPI_RADIO_HW_TRIGGER));
}
void nrf_802154_trx_ppi_for_disable(void)
{
nrf_dppi_channels_disable(NRF_DPPIC,
nrf_dppi_channels_disable(NRF_802154_DPPIC_INSTANCE,
#if NRF_802154_TEST_MODES_ENABLED
(1UL << NRF_802154_DPPI_RADIO_CCABUSY) |
#endif // NRF_802154_TEST_MODES_ENABLED
(1UL << PPI_DISABLED_EGU) |
(1UL << NRF_802154_DPPI_RADIO_READY) |
#if defined(NRF_802154_DPPI_RADIO_TXREADY)
(1UL << NRF_802154_DPPI_RADIO_TXREADY) |
#endif
(1UL << NRF_802154_DPPI_RADIO_ADDRESS) |
(1UL << NRF_802154_DPPI_RADIO_END) |
(1UL << NRF_802154_DPPI_RADIO_PHYEND) |
(1UL << NRF_802154_DPPI_RADIO_CCAIDLE));
(1UL << NRF_802154_DPPI_RADIO_CCAIDLE) |
(1UL << NRF_802154_DPPI_RADIO_HW_TRIGGER));
#if defined(NRF_802154_DPPI_RADIO_TXREADY)
nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_TXREADY);
#endif
#if NRF_802154_TEST_MODES_ENABLED
nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_CCABUSY);
#endif // NRF_802154_TEST_MODES_ENABLED
@ -107,49 +118,75 @@ void nrf_802154_trx_ppi_for_disable(void)
nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_DISABLED);
}
void nrf_802154_trx_ppi_for_ramp_up_set(nrf_radio_task_t ramp_up_task, bool start_timer)
uint8_t nrf_802154_trx_ppi_for_ramp_up_channel_id_get(void)
{
return NRF_802154_DPPI_RADIO_HW_TRIGGER;
}
void nrf_802154_trx_ppi_for_ramp_up_set(nrf_radio_task_t ramp_up_task,
nrf_802154_trx_ramp_up_trigger_mode_t trigg_mode,
bool start_timer)
{
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
// Clr event EGU (needed for nrf_802154_trx_ppi_for_ramp_up_was_triggered)
nrf_egu_event_clear(NRF_802154_EGU_INSTANCE, EGU_EVENT);
nrf_egu_event_clear(NRF_802154_EGU_INSTANCE, NRF_802154_EGU_RAMP_UP_EVENT);
nrf_dppi_channels_include_in_group(NRF_802154_DPPIC_INSTANCE,
1UL << PPI_EGU_RAMP_UP,
DPPI_CHGRP_RAMP_UP);
nrf_dppi_channels_include_in_group(NRF_DPPIC, 1UL << PPI_EGU_RAMP_UP, DPPI_CHGRP_RAMP_UP);
nrf_egu_publish_set(NRF_802154_EGU_INSTANCE, EGU_EVENT, PPI_EGU_RAMP_UP);
nrf_radio_subscribe_set(NRF_RADIO, ramp_up_task, PPI_EGU_RAMP_UP);
nrf_dppi_subscribe_set(NRF_DPPIC, DPPI_CHGRP_RAMP_UP_DIS_TASK, PPI_EGU_RAMP_UP);
nrf_dppi_subscribe_set(NRF_802154_DPPIC_INSTANCE, DPPI_CHGRP_RAMP_UP_DIS_TASK, PPI_EGU_RAMP_UP);
if (start_timer)
{
nrf_timer_subscribe_set(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_START, PPI_DISABLED_EGU);
}
nrf_egu_subscribe_set(NRF_802154_EGU_INSTANCE, EGU_TASK, PPI_DISABLED_EGU);
nrf_egu_publish_set(NRF_802154_EGU_INSTANCE, NRF_802154_EGU_RAMP_UP_EVENT, PPI_EGU_RAMP_UP);
nrf_dppi_channels_enable(NRF_DPPIC,
nrf_egu_subscribe_set(NRF_802154_EGU_INSTANCE, NRF_802154_EGU_RAMP_UP_TASK, PPI_DISABLED_EGU);
nrf_dppi_channels_enable(NRF_802154_DPPIC_INSTANCE,
(1UL << PPI_EGU_RAMP_UP));
if (trigg_mode == TRX_RAMP_UP_HW_TRIGGER)
{
nrf_radio_subscribe_set(NRF_RADIO,
NRF_RADIO_TASK_DISABLE,
NRF_802154_DPPI_RADIO_HW_TRIGGER);
}
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
}
void nrf_802154_trx_ppi_for_ramp_up_reconfigure(void)
{
// Intentionally empty
}
void nrf_802154_trx_ppi_for_ramp_up_clear(nrf_radio_task_t ramp_up_task, bool start_timer)
{
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
nrf_dppi_channels_disable(NRF_DPPIC,
nrf_dppi_channels_disable(NRF_802154_DPPIC_INSTANCE,
(1UL << PPI_EGU_RAMP_UP));
nrf_egu_publish_clear(NRF_802154_EGU_INSTANCE, EGU_EVENT);
nrf_egu_publish_clear(NRF_802154_EGU_INSTANCE, NRF_802154_EGU_RAMP_UP_EVENT);
nrf_radio_subscribe_clear(NRF_RADIO, ramp_up_task);
nrf_dppi_subscribe_clear(NRF_DPPIC, DPPI_CHGRP_RAMP_UP_DIS_TASK);
nrf_dppi_channels_remove_from_group(NRF_DPPIC, 1UL << PPI_EGU_RAMP_UP, DPPI_CHGRP_RAMP_UP);
nrf_radio_subscribe_clear(NRF_RADIO, NRF_RADIO_TASK_DISABLE);
nrf_dppi_subscribe_clear(NRF_802154_DPPIC_INSTANCE, DPPI_CHGRP_RAMP_UP_DIS_TASK);
nrf_dppi_channels_remove_from_group(NRF_802154_DPPIC_INSTANCE,
1UL << PPI_EGU_RAMP_UP,
DPPI_CHGRP_RAMP_UP);
if (start_timer)
{
nrf_timer_subscribe_clear(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_START);
}
nrf_egu_subscribe_clear(NRF_802154_EGU_INSTANCE, EGU_TASK);
nrf_egu_subscribe_clear(NRF_802154_EGU_INSTANCE, NRF_802154_EGU_RAMP_UP_TASK);
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
}
@ -179,7 +216,7 @@ bool nrf_802154_trx_ppi_for_ramp_up_was_triggered(void)
// Wait for PPIs
nrf_802154_trx_ppi_for_ramp_up_propagation_delay_wait();
if (nrf_egu_event_check(NRF_802154_EGU_INSTANCE, EGU_EVENT))
if (nrf_egu_event_check(NRF_802154_EGU_INSTANCE, NRF_802154_EGU_RAMP_UP_EVENT))
{
// If EGU event is set, procedure is running.
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
@ -198,7 +235,7 @@ void nrf_802154_trx_ppi_for_ack_tx_set(void)
nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_TXEN, PPI_TIMER_TX_ACK);
nrf_timer_publish_set(NRF_802154_TIMER_INSTANCE, NRF_TIMER_EVENT_COMPARE1, PPI_TIMER_TX_ACK);
nrf_dppi_channels_enable(NRF_DPPIC, (1UL << PPI_TIMER_TX_ACK));
nrf_dppi_channels_enable(NRF_802154_DPPIC_INSTANCE, (1UL << PPI_TIMER_TX_ACK));
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
}
@ -207,7 +244,7 @@ void nrf_802154_trx_ppi_for_ack_tx_clear(void)
{
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
nrf_dppi_channels_disable(NRF_DPPIC, (1UL << PPI_TIMER_TX_ACK));
nrf_dppi_channels_disable(NRF_802154_DPPIC_INSTANCE, (1UL << PPI_TIMER_TX_ACK));
nrf_radio_subscribe_clear(NRF_RADIO, NRF_RADIO_TASK_TXEN);
nrf_timer_publish_clear(NRF_802154_TIMER_INSTANCE, NRF_TIMER_EVENT_COMPARE1);
@ -246,7 +283,7 @@ void nrf_802154_trx_ppi_for_radio_sync_set(nrf_egu_task_t task)
nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_SYNC, PPI_RADIO_SYNC_EGU_SYNC);
nrf_egu_subscribe_set(NRF_802154_EGU_INSTANCE, task, PPI_RADIO_SYNC_EGU_SYNC);
nrf_dppi_channels_enable(NRF_DPPIC, (1UL << PPI_RADIO_SYNC_EGU_SYNC));
nrf_dppi_channels_enable(NRF_802154_DPPIC_INSTANCE, (1UL << PPI_RADIO_SYNC_EGU_SYNC));
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
}
@ -255,7 +292,7 @@ void nrf_802154_trx_ppi_for_radio_sync_clear(nrf_egu_task_t task)
{
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
nrf_dppi_channels_disable(NRF_DPPIC, (1UL << PPI_RADIO_SYNC_EGU_SYNC));
nrf_dppi_channels_disable(NRF_802154_DPPIC_INSTANCE, (1UL << PPI_RADIO_SYNC_EGU_SYNC));
nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_SYNC);
nrf_egu_subscribe_clear(NRF_802154_EGU_INSTANCE, task);
@ -264,4 +301,4 @@ void nrf_802154_trx_ppi_for_radio_sync_clear(nrf_egu_task_t task)
#endif
#endif // NRF53_SERIES
#endif // defined(DPPI_PRESENT)

View File

@ -61,6 +61,7 @@
#define PPI_CHGRP_ABORT NRF_802154_PPI_ABORT_GROUP ///< PPI group used to disable PPIs when async event aborting radio operation is propagated through the system
#define PPI_DISABLED_EGU NRF_802154_PPI_RADIO_DISABLED_TO_EGU ///< PPI that connects RADIO DISABLED event with EGU task
#define PPI_RAMP_UP_TRG_EGU NRF_802154_PPI_RADIO_RAMP_UP_TRIGG ///< PPI that connects ramp up trigger event with EGU task
#define PPI_EGU_RAMP_UP NRF_802154_PPI_EGU_TO_RADIO_RAMP_UP ///< PPI that connects EGU event with RADIO TXEN or RXEN task
#define PPI_EGU_TIMER_START NRF_802154_PPI_EGU_TO_TIMER_START ///< PPI that connects EGU event with TIMER START task
#define PPI_TIMER_TX_ACK NRF_802154_PPI_TIMER_COMPARE_TO_RADIO_TXEN ///< PPI that connects TIMER COMPARE event with RADIO TXEN task
@ -76,13 +77,22 @@ void nrf_802154_trx_ppi_for_disable(void)
// Intentionally empty.
}
void nrf_802154_trx_ppi_for_ramp_up_set(nrf_radio_task_t ramp_up_task, bool start_timer)
uint8_t nrf_802154_trx_ppi_for_ramp_up_channel_id_get(void)
{
return PPI_RAMP_UP_TRG_EGU;
}
void nrf_802154_trx_ppi_for_ramp_up_set(nrf_radio_task_t ramp_up_task,
nrf_802154_trx_ramp_up_trigger_mode_t trigg_mode,
bool start_timer)
{
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
// Clr event EGU (needed for nrf_802154_trx_ppi_for_ramp_up_was_triggered)
nrf_egu_event_clear(NRF_802154_EGU_INSTANCE, EGU_EVENT);
uint32_t ppi_mask = (1UL << PPI_EGU_RAMP_UP) | (1UL << PPI_RAMP_UP_TRG_EGU);
nrf_ppi_channel_and_fork_endpoint_setup(NRF_PPI,
PPI_EGU_RAMP_UP,
nrf_egu_event_address_get(
@ -100,35 +110,50 @@ void nrf_802154_trx_ppi_for_ramp_up_set(nrf_radio_task_t ramp_up_task, bool star
EGU_EVENT),
nrf_timer_task_address_get(NRF_802154_TIMER_INSTANCE,
NRF_TIMER_TASK_START));
}
nrf_ppi_channel_endpoint_setup(NRF_PPI,
PPI_DISABLED_EGU,
nrf_radio_event_address_get(NRF_RADIO, NRF_RADIO_EVENT_DISABLED),
nrf_egu_task_address_get(NRF_802154_EGU_INSTANCE, EGU_TASK));
nrf_ppi_channel_include_in_group(NRF_PPI, PPI_EGU_RAMP_UP, PPI_CHGRP_RAMP_UP);
uint32_t ppi_mask = (1UL << PPI_EGU_RAMP_UP) |
(1UL << PPI_DISABLED_EGU);
if (start_timer)
{
ppi_mask |= (1UL << PPI_EGU_TIMER_START);
}
if (trigg_mode == TRX_RAMP_UP_SW_TRIGGER)
{
nrf_ppi_channel_endpoint_setup(NRF_PPI,
PPI_RAMP_UP_TRG_EGU,
nrf_radio_event_address_get(NRF_RADIO,
NRF_RADIO_EVENT_DISABLED),
nrf_egu_task_address_get(NRF_802154_EGU_INSTANCE, EGU_TASK));
}
else
{
nrf_ppi_task_endpoint_setup(NRF_PPI,
PPI_RAMP_UP_TRG_EGU,
nrf_egu_task_address_get(NRF_802154_EGU_INSTANCE, EGU_TASK));
}
nrf_ppi_channel_include_in_group(NRF_PPI, PPI_EGU_RAMP_UP, PPI_CHGRP_RAMP_UP);
nrf_ppi_channels_enable(NRF_PPI, ppi_mask);
nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
}
void nrf_802154_trx_ppi_for_ramp_up_reconfigure(void)
{
nrf_egu_event_clear(NRF_802154_EGU_INSTANCE, EGU_EVENT);
nrf_ppi_channel_endpoint_setup(NRF_PPI,
PPI_DISABLED_EGU,
nrf_radio_event_address_get(NRF_RADIO,
NRF_RADIO_EVENT_DISABLED),
nrf_egu_task_address_get(NRF_802154_EGU_INSTANCE, EGU_TASK));
}
void nrf_802154_trx_ppi_for_ramp_up_clear(nrf_radio_task_t ramp_up_task, bool start_timer)
{
(void)ramp_up_task;
nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
uint32_t ppi_mask = (1UL << PPI_EGU_RAMP_UP) |
(1UL << PPI_DISABLED_EGU);
(1UL << PPI_RAMP_UP_TRG_EGU);
if (start_timer)
{
@ -136,9 +161,8 @@ void nrf_802154_trx_ppi_for_ramp_up_clear(nrf_radio_task_t ramp_up_task, bool st
}
nrf_ppi_channels_disable(NRF_PPI, ppi_mask);
nrf_ppi_channel_and_fork_endpoint_setup(NRF_PPI, PPI_EGU_RAMP_UP, 0, 0, 0);
nrf_ppi_channel_endpoint_setup(NRF_PPI, PPI_DISABLED_EGU, 0, 0);
nrf_ppi_channel_endpoint_setup(NRF_PPI, PPI_RAMP_UP_TRG_EGU, 0, 0);
if (start_timer)
{

View File

@ -45,6 +45,7 @@
#include "hal/nrf_egu.h"
#include "hal/nrf_radio.h"
#include "nrf_802154_trx.h"
/**
* @brief Configures (D)PPI connections required for TRX operation.
@ -62,35 +63,80 @@ void nrf_802154_trx_ppi_for_enable(void);
void nrf_802154_trx_ppi_for_disable(void);
/**
* @brief Set PPIs to connect RADIO DISABLED event with tasks needed to ramp up.
* @brief Set PPIs to connect trigger event with tasks needed to ramp up.
*
* Connections created by this function in DPPI variant:
* When @p trigg_mode is TRX_RAMP_UP_SW_TRIGGER, the trigger event is RADIO_DISABLED and
* PPI connections are made to it.
* When @p trigg_mode is TRX_RAMP_UP_HW_TRIGGER, the trigger event is defined outside the module
* and PPI connections are only partially created. To complete the connection creation, the trigger
* event must be connected to the (D)PPI channel specified with
* @ref nrf_802154_trx_ppi_for_ramp_up_channel_id_get.
*
* Connections created by this function in DPPI variant and TRX_RAMP_UP_SW_TRIGGER mode:
*
* RADIO_DISABLED ----> EGU -----> ramp_up_task
* | \--> self disable
* if (start_timer)
* \-------------> TIMER_START
*
* Connections created by this function in PPI variant:
* Connections created by this function in DPPI variant and TRX_RAMP_UP_HW_TRIGGER mode:
*
* [DPPI] -----------------------> RADIO_TASK_DISABLE
*
* RADIO_DISABLED ----> EGU -----> ramp_up_task
* | \--> self disable
* if (start_timer)
* \--------------> TIMER_START
*
* Connections created by this function in PPI variant and TRX_RAMP_UP_SW_TRIGGER mode:
*
* RADIO_DISABLED ----> EGU -----> ramp_up_task
* \--> self disable
*
* EGU ---> if (start_timer) ----> TIMER_START
*
* Connections created by this function in PPI variant and TRX_RAMP_UP_HW_TRIGGER mode:
*
* [PPI] --------> EGU ----------> ramp_up_task
* \--> self disable
*
* EGU ---> if (start_timer) ----> TIMER_START
*
* @param[in] ramp_up_task Task triggered to start ramp up procedure.
* @param[in] trigg_mode Trigger mode the connections must conform to.
* @param[in] start_timer If timer is to be started on RADIO DISABLED event.
*/
void nrf_802154_trx_ppi_for_ramp_up_set(nrf_radio_task_t ramp_up_task, bool start_timer);
void nrf_802154_trx_ppi_for_ramp_up_set(nrf_radio_task_t ramp_up_task,
nrf_802154_trx_ramp_up_trigger_mode_t trigg_mode,
bool start_timer);
/**
* @brief Clear PPIs to connect RADIO DISABLED event with tasks needed to ramp up.
* @brief Reconfigure (D)PPIs for the next steps in receiving or transmitting.
*
* Due to limited resources on some platforms, some PPIs have many uses: when starting an operation,
* one is used to trigger the radio ramp up, then when the radio is "up", this PPI must be
* reconfigured so it can be used to disable the radio when needed.
* This is the PPI reconfiguration routine. It is intended to be called in the radio READY event
* handler.
*/
void nrf_802154_trx_ppi_for_ramp_up_reconfigure(void);
/**
* @brief Clear (D)PPIs that are configured for ramp up procedure.
*
* @param[in] ramp_up_task Task triggered to start ramp up procedure.
* @param[in] start_timer If timer start on RADIO DISABLED event is to be deconfigured as well. See @ref nrf_802154_trx_ppi_for_ramp_up_set.
*/
void nrf_802154_trx_ppi_for_ramp_up_clear(nrf_radio_task_t ramp_up_task, bool start_timer);
/**
* @brief Get (D)PPI channel used to trigger ramp up procedure start.
*
* @retval NRF_802154_DPPI_EGU_TO_RADIO_RAMP_UP in DPPI variant.
* @retval NRF_802154_PPI_RADIO_RAMP_UP_TRIGG in PPI variant.
*/
uint8_t nrf_802154_trx_ppi_for_ramp_up_channel_id_get(void);
/**
* @brief Wait until PPIs configured to ramp up radio are propagated through PPI system.
*
@ -104,8 +150,13 @@ void nrf_802154_trx_ppi_for_ramp_up_propagation_delay_wait(void);
/**
* @brief Detect if PPIs configured to start radio operation were triggered.
*
* Radio ramp up starts by design from RADIO DISABLED event. This functions verifies this event
* and PPIs status.
* In TRX_RAMP_UP_SW_TRIGGER mode, radio ramp up starts by design from RADIO DISABLED event.
* This functions verifies occurrence of this event and PPIs status.
*
* The function is intended to be used only when all of the following conditions apply:
* - the connections are already made with @ref nrf_802154_trx_ppi_for_ramp_up_set
* - TRX_RAMP_UP_SW_TRIGGER mode was used to create connections
* - connections have not yet been cleared
*
* @retval true PPIs were triggered.
* @retval false PPIs were not triggered. To trigger them, the caller must trigger RADIO DISABLE task.

View File

@ -830,6 +830,13 @@ uint64_t nrf_802154_time_get(void);
*/
void nrf_802154_security_global_frame_counter_set(uint32_t frame_counter);
/**
* @brief Sets nRF 802.15.4 Radio Driver MAC Global Frame Counter if the value passed is larger than current.
*
* @param[in] frame_counter Frame counter to set.
*/
void nrf_802154_security_global_frame_counter_set_if_larger(uint32_t frame_counter);
/**
* @brief Store the 802.15.4 MAC Security Key inside the nRF 802.15.4 Radio Driver.
*

View File

@ -44,14 +44,12 @@
that the maximum value in EDSAMPLE which can be reported in compliance with the 802.15.4 specification is
255/ED_RSSISCALE. */
#if defined (NRF52840_XXAA)
#define ED_RSSIOFFS (-92) ///< dBm value corresponding to value 0 in the EDSAMPLE register.
#define ED_RSSISCALE 4 ///< Factor needed to calculate the ED result based on the data from the RADIO peripheral.
#elif defined (NRF52833_XXAA) || defined(NRF5340_XXAA)
#define ED_RSSIOFFS (-93) ///< dBm value corresponding to value 0 in the EDSAMPLE register.
#define ED_RSSISCALE 5 ///< Factor needed to calculate the ED result based on the data from the RADIO peripheral.
#if defined (NRF52833_XXAA) || defined(NRF5340_XXAA)
#define ED_RSSIOFFS (-93) ///< dBm value corresponding to value 0 in the EDSAMPLE register.
#define ED_RSSISCALE 5 ///< Factor needed to calculate the ED result based on the data from the RADIO peripheral.
#else
#error "Selected chip is not supported."
#define ED_RSSIOFFS (-92) ///< dBm value corresponding to value 0 in the EDSAMPLE register.
#define ED_RSSISCALE 4 ///< Factor needed to calculate the ED result based on the data from the RADIO peripheral.
#endif
#define EDSAMPLE_MIN_REPORTED_VALUE (PHY_MIN_RECEIVER_SENSITIVITY - ED_RSSIOFFS + 10) ///< Minimal reported EDSAMPLE value (reported as 0)

View File

@ -447,6 +447,12 @@ typedef enum
SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSL_WRITER_ANCHOR_TIME_SET =
SPINEL_PROP_VENDOR_NORDIC_NRF_802154__BEGIN + 63,
/**
* Vendor property for nrf_802154_security_global_frame_counter_set_if_larger serialization.
*/
SPINEL_PROP_VENDOR_NORDIC_NRF_802154_SECURITY_GLOBAL_FRAME_COUNTER_SET_IF_LARGER =
SPINEL_PROP_VENDOR_NORDIC_NRF_802154__BEGIN + 64,
} spinel_prop_vendor_key_t;
/**

View File

@ -1820,6 +1820,32 @@ bail:
return;
}
void nrf_802154_security_global_frame_counter_set_if_larger(uint32_t frame_counter)
{
nrf_802154_ser_err_t res;
SERIALIZATION_ERROR_INIT(error);
NRF_802154_SPINEL_LOG_BANNER_CALLING();
nrf_802154_spinel_response_notifier_lock_before_request(SPINEL_PROP_LAST_STATUS);
res = nrf_802154_spinel_send_cmd_prop_value_set(
SPINEL_PROP_VENDOR_NORDIC_NRF_802154_SECURITY_GLOBAL_FRAME_COUNTER_SET_IF_LARGER,
SPINEL_DATATYPE_NRF_802154_SECURITY_GLOBAL_FRAME_COUNTER_SET,
frame_counter);
SERIALIZATION_ERROR_CHECK(res, error, bail);
res = status_ok_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT);
SERIALIZATION_ERROR_CHECK(res, error, bail);
bail:
SERIALIZATION_ERROR_RAISE_IF_FAILED(error);
return;
}
nrf_802154_security_error_t nrf_802154_security_key_store(nrf_802154_key_t * p_key)
{
nrf_802154_ser_err_t res;

View File

@ -1653,6 +1653,35 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_security_global_frame_
return nrf_802154_spinel_send_prop_last_status_is(SPINEL_STATUS_OK);
}
/**
* @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_SECURITY_GLOBAL_FRAME_COUNTER_SET_IF_LARGER.
*
* @param[in] p_property_data Pointer to a buffer that contains data to be decoded.
* @param[in] property_data_len Size of the @ref p_property_data buffer.
*
*/
static nrf_802154_ser_err_t
spinel_decode_prop_nrf_802154_security_global_frame_counter_set_if_larger(
const void * p_property_data,
size_t property_data_len)
{
spinel_ssize_t siz;
uint32_t frame_counter;
siz = spinel_datatype_unpack(p_property_data,
property_data_len,
SPINEL_DATATYPE_NRF_802154_SECURITY_GLOBAL_FRAME_COUNTER_SET,
&frame_counter);
if (siz < 0)
{
return NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE;
}
nrf_802154_security_global_frame_counter_set_if_larger(frame_counter);
return nrf_802154_spinel_send_prop_last_status_is(SPINEL_STATUS_OK);
}
/**
* @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_SECURITY_KEY_STORE.
*
@ -2022,6 +2051,11 @@ nrf_802154_ser_err_t nrf_802154_spinel_decode_cmd_prop_value_set(const void * p_
return spinel_decode_prop_nrf_802154_stat_timestamps_get(p_property_data,
property_data_len);
case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_SECURITY_GLOBAL_FRAME_COUNTER_SET_IF_LARGER:
return spinel_decode_prop_nrf_802154_security_global_frame_counter_set_if_larger(
p_property_data,
property_data_len);
default:
NRF_802154_SPINEL_LOG_RAW("Unsupported property: %s(%u)\n",
spinel_prop_key_to_cstr(property),

View File

@ -40,6 +40,10 @@
#ifndef NRF_802154_SL_CONFIG_H__
#define NRF_802154_SL_CONFIG_H__
#if NRF_802154_USE_INTERNAL_INCLUDES
#include "nrf_802154_sl_config_internal.h"
#endif
/**
* @def NRF_802154_SL_COEX_INITIALLY_ENABLED
*

View File

@ -41,10 +41,9 @@
#define NRF_802154_SL_PERIPHS_H__
#include <nrfx.h>
#if defined(DPPI_PRESENT)
#include "hal/nrf_dppi.h"
#else
#include "hal/nrf_ppi.h"
#if NRF_802154_USE_INTERNAL_INCLUDES
#include "nrf_802154_sl_periphs_internal.h"
#endif
/**

View File

@ -65,6 +65,7 @@ extern "C" {
* Possible values:
* @ref NRF_802154_SL_TIMER_RET_SUCCESS
* @ref NRF_802154_SL_TIMER_RET_TOO_LATE
* @ref NRF_802154_SL_TIMER_RET_TOO_DISTANT
* @ref NRF_802154_SL_TIMER_RET_NO_RESOURCES
* @ref NRF_802154_SL_TIMER_RET_INACTIVE
* @ref NRF_802154_SL_TIMER_RET_BAD_REQUEST
@ -83,6 +84,14 @@ typedef uint32_t nrf_802154_sl_timer_ret_t;
/**@brief Operation was requested too late to be performed in requested time. */
#define NRF_802154_SL_TIMER_RET_TOO_LATE 2U
/**@brief The trigger time for the requested operation is too distant.
*
* Some platforms have a limitation to how far in the future operation can be
* scheduled. This result may happen for @ref nrf_802154_sl_timer_add with
* @ref nrf_802154_sl_timer_t::trigger_time containing a value too far from `now`.
*/
#define NRF_802154_SL_TIMER_RET_TOO_DISTANT 3U
/**@brief There were no available resources required to schedule requested activity.
*
* This result may happen for @ref nrf_802154_sl_timer_add with
@ -91,10 +100,10 @@ typedef uint32_t nrf_802154_sl_timer_ret_t;
* some hardware resources like PPI/DPPI channels, EGU channels, timer compare channels
* (implementation dependent) were needed, but they were unavailable.
*/
#define NRF_802154_SL_TIMER_RET_NO_RESOURCES 3U
#define NRF_802154_SL_TIMER_RET_NO_RESOURCES 4U
/**@brief The timer was inactive at the moment of requested operation. */
#define NRF_802154_SL_TIMER_RET_INACTIVE 4U
#define NRF_802154_SL_TIMER_RET_INACTIVE 5U
/**@brief Type representing a timer. */
typedef struct nrf_802154_sl_timer_s nrf_802154_sl_timer_t;
@ -115,6 +124,11 @@ typedef uint8_t nrf_802154_sl_timer_action_type_t;
/**@brief Timer action type mask allowing triggering a hardware task. */
#define NRF_802154_SL_TIMER_ACTION_TYPE_HARDWARE (1U << 1)
/**
* @brief Special value that indicates that (D)PPI configuration is incomplete.
*/
#define NRF_802154_SL_TIMER_INVALID_PPI_CHANNEL UINT32_MAX
/**@brief Structure that represents private fields of a timer required by the implementation. */
typedef struct
{
@ -178,6 +192,11 @@ struct nrf_802154_sl_timer_s
* of these resources. Moreover, the API user must keep the hardware bindings enabled
* and functional until the requested hardware task is triggered or until the timer
* is successfully removed.
*
* A special value of @ref NRF_802154_SL_TIMER_INVALID_PPI_CHANNEL can be set. In this
* case, the binding creation is postponed and the user is required to use the
* @ref nrf_802154_sl_timer_update_ppi to complete the configuration. Must do so
* before @c trigger_time expires.
*/
uint32_t ppi_channel;
} hardware;
@ -268,6 +287,25 @@ nrf_802154_sl_timer_ret_t nrf_802154_sl_timer_add(nrf_802154_sl_timer_t * p_time
*/
nrf_802154_sl_timer_ret_t nrf_802154_sl_timer_remove(nrf_802154_sl_timer_t * p_timer);
/**@brief Updates the (D)PPI channel to be triggered.
*
* @param p_timer Pointer to a timer instance to be updated.
* @param ppi_chn Identifier of (D)PPI channel to be triggered at @c trigger_time.
*
* @retval NRF_802154_SL_TIMER_RET_SUCCESS
* The (D)PPI channel was updated and it was done on time, i.e. before specified
* trigger time.
* @retval NRF_802154_SL_TIMER_RET_TOO_LATE
* It has been detected that the timer has already fired and because of this the update
* could not complete at all or did not complete on time. Nevertheless, the (D)PPI may
* have been triggered, but it cannot be stated reliably.
* @retval NRF_802154_SL_TIMER_RET_BAD_REQUEST
* A user passed invalid parameters in @p p_timer, e.g. @c action_type does not contain
* @ref NRF_802154_SL_TIMER_ACTION_TYPE_HARDWARE.
*/
nrf_802154_sl_timer_ret_t nrf_802154_sl_timer_update_ppi(nrf_802154_sl_timer_t * p_timer,
uint32_t ppi_chn);
/**
*@}
**/

View File

@ -164,6 +164,8 @@ typedef void (* rsch_dly_ts_started_callback_t)(rsch_dly_ts_id_t dly_ts_id);
typedef struct
{
uint64_t trigger_time; ///< Trigger time of the timeslot start, in microseconds.
bool ppi_trigger_en; ///< Enable the (D)PPI triggering after the start of the timeslot.
uint32_t ppi_trigger_dly; ///< Time delta between @p trigger_time and the moment of (D)PPI triggering.
rsch_prio_t prio; ///< Priority level required for the delayed timeslot.
rsch_dly_ts_op_t op; ///< Operation to be performed in the requested timeslot.
rsch_dly_ts_type_t type; ///< Type of the requested timeslot.
@ -282,6 +284,19 @@ bool nrf_802154_rsch_delayed_timeslot_request(const rsch_dly_ts_param_t * p_dly_
*/
bool nrf_802154_rsch_delayed_timeslot_cancel(rsch_dly_ts_id_t dly_ts_id, bool handler);
/**
* @brief Updates the id of (D)PPI channel to be triggered in the current timeslot.
*
* The update must be done after the start of the timeslot but earlier than @c ppi_trigger_dly.
* If updating does not complete on time, (D)PPI triggering may not be performed.
*
* @retval true (D)PPI channel has been updated and it was done on time, i.e. before
* target trigger time.
* @retval false Update could not complete or did not complete on time. Nevertheless,
* the (D)PPI may have been triggered, but it cannot be stated reliably.
*/
bool nrf_802154_rsch_delayed_timeslot_ppi_update(uint32_t ppi_channel);
/**
* @brief Updates priority of a requested delayed timeslot.
*

View File

@ -180,3 +180,10 @@ bool nrf_802154_rsch_delayed_timeslot_priority_update(rsch_dly_ts_id_t dly_ts_id
return false;
}
bool nrf_802154_rsch_delayed_timeslot_ppi_update(uint32_t ppi_channel)
{
(void)ppi_channel;
return false;
}