[nRF52840] Update radio driver (#1941)

This commit is contained in:
Hubert Miś
2017-06-27 17:51:58 +02:00
committed by Jonathan Hui
parent 8924a545c0
commit 50ee0d864e
18 changed files with 598 additions and 295 deletions
+3 -2
View File
@@ -324,7 +324,7 @@ otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame)
aFrame->mPsdu[-1] = aFrame->mLength;
if (nrf_drv_radio802154_transmit(&aFrame->mPsdu[-1], aFrame->mChannel, aFrame->mPower))
if (nrf_drv_radio802154_transmit(&aFrame->mPsdu[-1], aFrame->mChannel, aFrame->mPower, true))
{
clearPendingEvents();
}
@@ -637,7 +637,8 @@ void nrf_drv_radio802154_busy_channel(void)
void nrf_drv_radio802154_energy_detected(int8_t result)
{
sEnergyDetected = result;
// TODO: Correct RSSI calculation after lab tests.
sEnergyDetected = 94 - result;
setPendingEvent(kPendingEventEnergyDetected);
}
@@ -165,12 +165,12 @@ void nrf_drv_radio802154_receive(uint8_t channel)
nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_RECEIVE);
}
bool nrf_drv_radio802154_transmit(const uint8_t * p_data, uint8_t channel, int8_t power)
bool nrf_drv_radio802154_transmit(const uint8_t * p_data, uint8_t channel, int8_t power, bool cca)
{
bool result;
nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_TRANSMIT);
result = nrf_drv_radio802154_request_transmit(p_data, channel, power);
result = nrf_drv_radio802154_request_transmit(p_data, channel, power, cca);
nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_TRANSMIT);
return result;
@@ -246,23 +246,38 @@ void nrf_drv_radio802154_pending_bit_for_addr_reset(bool extended)
nrf_drv_radio802154_ack_pending_bit_for_addr_reset(extended);
}
__WEAK void nrf_drv_radio802154_rx_started(void)
{
// Intentionally empty
}
__WEAK void nrf_drv_radio802154_received(uint8_t * p_data, int8_t power, int8_t lqi)
{
(void) p_data;
(void) power;
(void) lqi;
nrf_drv_radio802154_buffer_free(p_data);
}
__WEAK void nrf_drv_radio802154_tx_started(void)
{
// Intentionally empty
}
__WEAK void nrf_drv_radio802154_transmitted(uint8_t * p_ack, int8_t power, int8_t lqi)
{
(void) p_ack;
(void) power;
(void) lqi;
if (p_ack != NULL)
{
nrf_drv_radio802154_buffer_free(p_ack);
}
}
__WEAK void nrf_drv_radio802154_busy_channel(void)
{
// Intentionally empty
}
__WEAK void nrf_drv_radio802154_energy_detected(int8_t result)
@@ -176,11 +176,12 @@ void nrf_drv_radio802154_receive(uint8_t channel);
* @param[in] channel Channel number on which radio will transmit given frame.
* @param[in] power Transmission power [dBm]. Given value is rounded up to nearest permitted
* value.
* @param[in] cca If the driver should perform CCA procedure before transmission.
*
* @return true If the transmission procedure was scheduled.
* @return false If the driver could not schedule the transmission procedure.
*/
bool nrf_drv_radio802154_transmit(const uint8_t *p_data, uint8_t channel, int8_t power);
bool nrf_drv_radio802154_transmit(const uint8_t *p_data, uint8_t channel, int8_t power, bool cca);
/**
* @brief Change radio state to Energy Detection.
@@ -206,6 +207,15 @@ bool nrf_drv_radio802154_energy_detection(uint8_t channel, uint32_t time_us);
* @section Calls to higher layer.
*/
/**
* @brief Notify that receiving frame has started.
*
* @note It is possible the frame is dropped during receive procedure and
* @sa nrf_drv_radio802154_received won't be called.
* @note This function should be very short to prevent dropping frames by the driver.
*/
extern void nrf_drv_radio802154_rx_started(void);
/**
* @brief Notify that frame was received.
*
@@ -221,6 +231,15 @@ bool nrf_drv_radio802154_energy_detection(uint8_t channel, uint32_t time_us);
*/
extern void nrf_drv_radio802154_received(uint8_t * p_data, int8_t power, int8_t lqi);
/**
* @brief Notify that transmitting frame has started.
*
* @note It is possible that transmit procedure is interrupted and
* @sa nrf_drv_radio802154_transmitted won't be called.
* @note This function should be very short to prevent dropping frames by the driver.
*/
extern void nrf_drv_radio802154_tx_started(void);
/**
* @brief Notify that frame was transmitted.
*
@@ -45,20 +45,20 @@
#include "hal/nrf_radio.h"
// Maximum number of Short Addresses of nodes for which there is pending data in buffer.
/// Maximum number of Short Addresses of nodes for which there is pending data in buffer.
#define NUM_PENDING_SHORT_ADDRESSES RADIO_PENDING_SHORT_ADDRESSES
// Maximum number of Extended Addresses of nodes for which there is pending data in buffer.
/// Maximum number of Extended Addresses of nodes for which there is pending data in buffer.
#define NUM_PENDING_EXTENDED_ADDRESSES RADIO_PENDING_EXTENDED_ADDRESSES
// Value used to mark Short Address as unused.
/// Value used to mark Short Address as unused.
#define UNUSED_PENDING_SHORT_ADDRESS ((uint8_t [SHORT_ADDRESS_SIZE]) {0xff, 0xff})
// Value used to mark Extended Address as unused.
/// Value used to mark Extended Address as unused.
#define UNUSED_PENDING_EXTENDED_ADDRESS ((uint8_t [EXTENDED_ADDRESS_SIZE]) {0})
// If pending bit in ACK frame should be set to valid or default value.
/// If pending bit in ACK frame should be set to valid or default value.
static bool m_setting_pending_bit_enabled;
// Array of Short Addresses of nodes for which there is pending data in the buffer.
/// Array of Short Addresses of nodes for which there is pending data in the buffer.
static uint8_t m_pending_short[NUM_PENDING_SHORT_ADDRESSES][SHORT_ADDRESS_SIZE];
// Array of Extended Addresses of nodes for which there is pending data in the buffer.
/// Array of Extended Addresses of nodes for which there is pending data in the buffer.
static uint8_t m_pending_extended[NUM_PENDING_EXTENDED_ADDRESSES][EXTENDED_ADDRESS_SIZE];
void nrf_drv_radio802154_ack_pending_bit_init(void)
@@ -36,47 +36,40 @@
#ifndef NRF_DRV_RADIO802154_CONST_H_
#define NRF_DRV_RADIO802154_CONST_H_
#define ACK_HEADER_WITH_PENDING 0x12 // First byte of ACK frame containing pending bit
#define ACK_HEADER_WITHOUT_PENDING 0x02 // First byte of ACK frame without pending bit
#define ACK_HEADER_WITH_PENDING 0x12 ///< First byte of ACK frame containing pending bit
#define ACK_HEADER_WITHOUT_PENDING 0x02 ///< First byte of ACK frame without pending bit
#define ACK_LENGTH 5 // Length of ACK frame
#define ACK_REQUEST_BIT (1 << 5) // Ack request bit
#define ACK_REQUEST_OFFSET 1 // Byte containing Ack request bit (+1 for frame length byte)
#define DEST_ADDR_TYPE_EXTENDED 0x0c // Bits containing extended destination address type
#define DEST_ADDR_TYPE_MASK 0x0c // Mask of bits containing destination address type
#define DEST_ADDR_TYPE_OFFSET 2 // Byte containing destination address type (+1 for frame length byte)
#define DEST_ADDR_TYPE_SHORT 0x08 // Bits containing short destination address type
#define DEST_ADDR_OFFSET 5 // Offset of destination address in Data frame
#define DSN_OFFSET 3 // Byte containing DSN value (+1 for frame length byte)
#define FRAME_PENDING_BIT (1 << 4) // Pending bit
#define FRAME_PENDING_OFFSET 1 // Byte containing pending bit (+1 for frame length byte)
#define FRAME_TYPE_ACK 0x02 // Bits containing ACK frame type
#define FRAME_TYPE_BEACON 0x00 // Bits containing Beacon frame type
#define FRAME_TYPE_COMMAND 0x03 // Bits containing Command frame type
#define FRAME_TYPE_DATA 0x01 // Bits containing Data frame type
#define FRAME_TYPE_MASK 0x07 // Mask of bits containing frame type
#define FRAME_TYPE_OFFSET 1 // Byte containing frame type bits (+1 for frame length byte)
#define PAN_ID_COMPR_OFFSET 1 // Byte containing Pan Id compression bit (+1 for frame length byte)
#define PAN_ID_COMPR_MASK 0x40 // Pan Id compression bit
#define PAN_ID_OFFSET 3 // Offset of Pan Id in Data frame
#define SRC_ADDR_TYPE_EXTENDED 0xc0 // Bits containing extended source address type
#define SRC_ADDR_TYPE_MASK 0xc0 // Mask of bits containing source address type
#define SRC_ADDR_TYPE_OFFSET 2 // Byte containing source address type (+1 for frame length byte)
#define SRC_ADDR_TYPE_SHORT 0x80 // Bits containing short source address type
#define SRC_ADDR_OFFSET_SHORT_DST 8 // Offset of source address in Data frame if destination address is short
#define SRC_ADDR_OFFSET_EXTENDED_DST 14 // Offset of source address in Data frame if destination address is extended
#define ACK_LENGTH 5 ///< Length of ACK frame
#define ACK_REQUEST_BIT (1 << 5) ///< Ack request bit
#define ACK_REQUEST_OFFSET 1 ///< Byte containing Ack request bit (+1 for frame length byte)
#define DEST_ADDR_TYPE_EXTENDED 0x0c ///< Bits containing extended destination address type
#define DEST_ADDR_TYPE_MASK 0x0c ///< Mask of bits containing destination address type
#define DEST_ADDR_TYPE_OFFSET 2 ///< Byte containing destination address type (+1 for frame length byte)
#define DEST_ADDR_TYPE_SHORT 0x08 ///< Bits containing short destination address type
#define DEST_ADDR_OFFSET 5 ///< Offset of destination address in Data frame
#define DSN_OFFSET 3 ///< Byte containing DSN value (+1 for frame length byte)
#define FRAME_PENDING_BIT (1 << 4) ///< Pending bit
#define FRAME_PENDING_OFFSET 1 ///< Byte containing pending bit (+1 for frame length byte)
#define FRAME_TYPE_ACK 0x02 ///< Bits containing ACK frame type
#define FRAME_TYPE_BEACON 0x00 ///< Bits containing Beacon frame type
#define FRAME_TYPE_COMMAND 0x03 ///< Bits containing Command frame type
#define FRAME_TYPE_DATA 0x01 ///< Bits containing Data frame type
#define FRAME_TYPE_MASK 0x07 ///< Mask of bits containing frame type
#define FRAME_TYPE_OFFSET 1 ///< Byte containing frame type bits (+1 for frame length byte)
#define PAN_ID_COMPR_OFFSET 1 ///< Byte containing Pan Id compression bit (+1 for frame length byte)
#define PAN_ID_COMPR_MASK 0x40 ///< Pan Id compression bit
#define PAN_ID_OFFSET 3 ///< Offset of Pan Id in Data frame
#define SRC_ADDR_TYPE_EXTENDED 0xc0 ///< Bits containing extended source address type
#define SRC_ADDR_TYPE_MASK 0xc0 ///< Mask of bits containing source address type
#define SRC_ADDR_TYPE_OFFSET 2 ///< Byte containing source address type (+1 for frame length byte)
#define SRC_ADDR_TYPE_SHORT 0x80 ///< Bits containing short source address type
#define SRC_ADDR_OFFSET_SHORT_DST 8 ///< Offset of source address in Data frame if destination address is short
#define SRC_ADDR_OFFSET_EXTENDED_DST 14 ///< Offset of source address in Data frame if destination address is extended
#define CRC_LENGTH 2 // Length of CRC in 802.15.4 frames [bytes]
#define CRC_POLYNOMIAL 0x011021 // Polynomial used for CRC calculation in 802.15.4 frames
#define MHMU_MASK 0xff000700 // Mask of known bytes in ACK packet
#define MHMU_PATTERN 0x00000200 // Values of known bytes in ACK packet
#define MHMU_PATTERN_DSN_OFFSET 24 // Offset of DSN in MHMU_PATTER [bits]
#define PAN_ID_SIZE 2 // Size of Pan Id
#define SHORT_ADDRESS_SIZE 2 // Size of Short Mac Address
#define EXTENDED_ADDRESS_SIZE 8 // Size of Extended Mac Address
#define MAX_PACKET_SIZE 127 // Maximal size of radio packet
#define PAN_ID_SIZE 2 ///< Size of Pan Id
#define SHORT_ADDRESS_SIZE 2 ///< Size of Short Mac Address
#define EXTENDED_ADDRESS_SIZE 8 ///< Size of Extended Mac Address
#define MAX_PACKET_SIZE 127 ///< Maximal size of radio packet
#endif // NRD_DRV_RADIO802154_CONST_H_
@@ -48,22 +48,27 @@
#if RAAL_SOFTDEVICE
// When Softdevice is selected as arbiter critical sections should not be nested.
static volatile bool m_in_critical_section;
#define PREVENT_NESTED_CRIT_SECTIONS 1
#endif // RAAL_SOFTDEVICE
#if PREVENT_NESTED_CRIT_SECTIONS
/// Flag indicating if the driver entered critical section.
static volatile bool m_in_critical_section;
#endif // PREVENT_NESTED_CRIT_SECTIONS
void nrf_drv_radio802154_critical_section_enter(void)
{
nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_CRIT_SECT_ENTER);
radio_state_t state;
#if RAAL_SOFTDEVICE
#if PREVENT_NESTED_CRIT_SECTIONS
__disable_irq();
__DSB();
__ISB();
assert(!m_in_critical_section);
m_in_critical_section = true;
#endif // RAAL_SOFTDEVICE
#endif // PREVENT_NESTED_CRIT_SECTIONS
nrf_raal_critical_section_enter();
@@ -79,9 +84,9 @@ void nrf_drv_radio802154_critical_section_enter(void)
#endif // !RAAL_SOFTDEVICE
}
#if RAAL_SOFTDEVICE
#if PREVENT_NESTED_CRIT_SECTIONS
__enable_irq();
#endif // RAAL_SOFTDEVICE
#endif // PREVENT_NESTED_CRIT_SECTIONS
nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_CRIT_SECT_ENTER);
}
@@ -90,10 +95,10 @@ void nrf_drv_radio802154_critical_section_exit(void)
{
nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_CRIT_SECT_EXIT);
#if RAAL_SOFTDEVICE
#if PREVENT_NESTED_CRIT_SECTIONS
assert(m_in_critical_section);
m_in_critical_section = false;
#endif // RAAL_SOFTDEVICE
#endif // PREVENT_NESTED_CRIT_SECTIONS
radio_state_t state;
@@ -44,11 +44,16 @@
#include "nrf.h"
#if ENABLE_DEBUG_LOG
/// Buffer used to store debug log messages.
volatile uint32_t nrf_drv_radio802154_debug_log_buffer[NRF_DRV_RADIO802154_DEBUG_LOG_BUFFER_LEN];
/// Index of the log buffer pointing to the element that should be filled with next log message.
volatile uint32_t nrf_drv_radio802154_debug_log_ptr = 0;
#endif
#if ENABLE_DEBUG_GPIO
/**
* @brief Initialize PPI to toggle GPIO pins on radio events.
*/
static void radio_event_gpio_toggle_init(void)
{
nrf_gpio_cfg_output(PIN_DBG_RADIO_EVT_END);
@@ -82,6 +87,9 @@ static void radio_event_gpio_toggle_init(void)
nrf_ppi_channel_enable(NRF_PPI_CHANNEL4);
}
/**
* @brief Initialize GPIO to set it simulated arbiter events.
*/
static void raal_simulator_gpio_init(void)
{
#if RAAL_SIMULATOR
@@ -90,6 +98,10 @@ static void raal_simulator_gpio_init(void)
#endif
}
/**
* @brief Initialize PPI to toggle GPIO pins on Softdevice events. Initialize GPIO to set it
* according to Softdevice arbiter client events.
*/
static void raal_softdevice_event_gpio_toggle_init(void)
{
#if RAAL_SOFTDEVICE
@@ -44,61 +44,64 @@ extern "C" {
#define NRF_DRV_RADIO802154_DEBUG_LOG_BUFFER_LEN 1024
#define EVENT_TRACE_ENTER 0x0001UL
#define EVENT_TRACE_EXIT 0x0002UL
#define EVENT_MUTEX_LOCK 0x0003UL
#define EVENT_MUTEX_UNLOCK 0x0004UL
#define EVENT_SET_STATE 0x0005UL
#define EVENT_RADIO_RESET 0x0006UL
#define EVENT_TRACE_ENTER 0x0001UL
#define EVENT_TRACE_EXIT 0x0002UL
#define EVENT_MUTEX_LOCK 0x0003UL
#define EVENT_MUTEX_UNLOCK 0x0004UL
#define EVENT_SET_STATE 0x0005UL
#define EVENT_RADIO_RESET 0x0006UL
#define FUNCTION_SLEEP 0x0001UL
#define FUNCTION_RECEIVE 0x0002UL
#define FUNCTION_TRANSMIT 0x0003UL
#define FUNCTION_ENERGY_DETECTION 0x0004UL
#define FUNCTION_BUFFER_FREE 0x0005UL
#define FUNCTION_SLEEP 0x0001UL
#define FUNCTION_RECEIVE 0x0002UL
#define FUNCTION_TRANSMIT 0x0003UL
#define FUNCTION_ENERGY_DETECTION 0x0004UL
#define FUNCTION_BUFFER_FREE 0x0005UL
#define FUNCTION_IRQ_HANDLER 0x0100UL
#define FUNCTION_EVENT_FRAMESTART 0x0101UL
#define FUNCTION_EVENT_BCMATCH 0x0102UL
#define FUNCTION_EVENT_END 0x0103UL
#define FUNCTION_EVENT_DISABLED 0x0104UL
#define FUNCTION_EVENT_READY 0x0105UL
#define FUNCTION_EVENT_CCAIDLE 0x0106UL
#define FUNCTION_EVENT_CCABUSY 0x0107UL
#define FUNCTION_EVENT_EDEND 0x0108UL
#define FUNCTION_IRQ_HANDLER 0x0100UL
#define FUNCTION_EVENT_FRAMESTART 0x0101UL
#define FUNCTION_EVENT_BCMATCH 0x0102UL
#define FUNCTION_EVENT_END 0x0103UL
#define FUNCTION_EVENT_DISABLED 0x0104UL
#define FUNCTION_EVENT_READY 0x0105UL
#define FUNCTION_EVENT_CCAIDLE 0x0106UL
#define FUNCTION_EVENT_CCABUSY 0x0107UL
#define FUNCTION_EVENT_EDEND 0x0108UL
#define FUNCTION_AUTO_ACK_ABORT 0x0201UL
#define FUNCTION_TIMESLOT_STARTED 0x0202UL
#define FUNCTION_TIMESLOT_ENDED 0x0203UL
#define FUNCTION_CRIT_SECT_ENTER 0x0204UL
#define FUNCTION_CRIT_SECT_EXIT 0x0205UL
#define FUNCTION_AUTO_ACK_ABORT 0x0201UL
#define FUNCTION_TIMESLOT_STARTED 0x0202UL
#define FUNCTION_TIMESLOT_ENDED 0x0203UL
#define FUNCTION_CRIT_SECT_ENTER 0x0204UL
#define FUNCTION_CRIT_SECT_EXIT 0x0205UL
#define FUNCTION_RAAL_CRIT_SECT_ENTER 0x0301UL
#define FUNCTION_RAAL_CRIT_SECT_EXIT 0x0302UL
#define FUNCTION_RAAL_CONTINUOUS_ENTER 0x0303UL
#define FUNCTION_RAAL_CONTINUOUS_EXIT 0x0304UL
#define FUNCTION_RAAL_CRIT_SECT_ENTER 0x0301UL
#define FUNCTION_RAAL_CRIT_SECT_EXIT 0x0302UL
#define FUNCTION_RAAL_CONTINUOUS_ENTER 0x0303UL
#define FUNCTION_RAAL_CONTINUOUS_EXIT 0x0304UL
#define FUNCTION_RAAL_SIG_HANDLER 0x0400UL
#define FUNCTION_RAAL_SIG_EVENT_START 0x0401UL
#define FUNCTION_RAAL_SIG_EVENT_MARGIN 0x0402UL
#define FUNCTION_RAAL_SIG_EVENT_EXTEND 0x0403UL
#define FUNCTION_RAAL_SIG_EVENT_ENDED 0x0404UL
#define FUNCTION_RAAL_SIG_HANDLER 0x0400UL
#define FUNCTION_RAAL_SIG_EVENT_START 0x0401UL
#define FUNCTION_RAAL_SIG_EVENT_MARGIN 0x0402UL
#define FUNCTION_RAAL_SIG_EVENT_EXTEND 0x0403UL
#define FUNCTION_RAAL_SIG_EVENT_ENDED 0x0404UL
#define FUNCTION_RAAL_SIG_EVENT_RADIO 0x0405UL
#define FUNCTION_RAAL_SIG_EVENT_EXCEED_SUCCESS 0x0406UL
#define FUNCTION_RAAL_SIG_EVENT_EXCEED_FAIL 0x0407UL
#define PIN_DBG_RADIO_EVT_END 11
#define PIN_DBG_RADIO_EVT_DISABLED 12
#define PIN_DBG_RADIO_EVT_READY 13
#define PIN_DBG_RADIO_EVT_FRAMESTART 14
#define PIN_DBG_RADIO_EVT_EDEND 25
#define PIN_DBG_RADIO_EVT_END 11
#define PIN_DBG_RADIO_EVT_DISABLED 12
#define PIN_DBG_RADIO_EVT_READY 13
#define PIN_DBG_RADIO_EVT_FRAMESTART 14
#define PIN_DBG_RADIO_EVT_EDEND 25
#define PIN_DBG_TIMESLOT_ACTIVE 3
#define PIN_DBG_TIMESLOT_EXTEND_REQ 4
#define PIN_DBG_TIMESLOT_SESSION_IDLE 16
#define PIN_DBG_TIMESLOT_RADIO_IRQ 28
#define PIN_DBG_TIMESLOT_FAILED 29
#define PIN_DBG_TIMESLOT_BLOCKED 30
#define PIN_DBG_RAAL_CRITICAL_SECTION 15
#define PIN_DBG_TIMESLOT_ACTIVE 3
#define PIN_DBG_TIMESLOT_EXTEND_REQ 4
#define PIN_DBG_TIMESLOT_SESSION_IDLE 16
#define PIN_DBG_TIMESLOT_RADIO_IRQ 28
#define PIN_DBG_TIMESLOT_FAILED 29
#define PIN_DBG_TIMESLOT_BLOCKED 30
#define PIN_DBG_RAAL_CRITICAL_SECTION 15
#define PIN_DBG_RTC0_EVT_REM 31
#define PIN_DBG_RTC0_EVT_REM 31
#if ENABLE_DEBUG_LOG
extern volatile uint32_t nrf_drv_radio802154_debug_log_buffer[
@@ -41,6 +41,7 @@
#include <stdint.h>
#include <string.h>
#include "nrf_drv_radio802154.h"
#include "nrf_drv_radio802154_ack_pending_bit.h"
#include "nrf_drv_radio802154_config.h"
#include "nrf_drv_radio802154_const.h"
@@ -53,46 +54,62 @@
#include "hal/nrf_radio.h"
#include "raal/nrf_raal_api.h"
/// Value set to SHORTS register when no shorts should be enabled.
#define SHORTS_IDLE 0
/// Value set to SHORTS register when receiver is waiting for incoming frame.
#define SHORTS_RX_INITIAL (NRF_RADIO_SHORT_END_DISABLE_MASK | NRF_RADIO_SHORT_DISABLED_TXEN_MASK | \
NRF_RADIO_SHORT_FRAMESTART_BCSTART_MASK)
/// Value set to SHORTS register when receiver started receiving a frame.
#define SHORTS_RX_FOLLOWING (NRF_RADIO_SHORT_END_DISABLE_MASK | NRF_RADIO_SHORT_READY_START_MASK | \
NRF_RADIO_SHORT_FRAMESTART_BCSTART_MASK)
/// Value set to SHORTS register when received frame should be acknowledged.
#define SHORTS_TX_ACK (NRF_RADIO_SHORT_END_DISABLE_MASK)
#if RADIO_SHORT_CCAIDLE_TXEN
/// Value set to SHORTS register during transmission of a frame
#define SHORTS_TX_FRAME (NRF_RADIO_SHORT_END_DISABLE_MASK | NRF_RADIO_SHORT_READY_START_MASK | \
NRF_RADIO_SHORT_CCAIDLE_TXEN_MASK)
#else
/// Value set to SHORTS register during transmission of a frame
#define SHORTS_TX_FRAME (NRF_RADIO_SHORT_END_DISABLE_MASK | NRF_RADIO_SHORT_READY_START_MASK)
#endif
// Delay before sending ACK (10sym = 192uS)
/// Delay before sending ACK (12sym = 192uS)
#define TIFS_ACK_US 192
// Delay before first check of received frame: 16 bits is MAC Frame Control field.
/// Delay before first check of received frame: 16 bits is MAC Frame Control field.
#define BCC_INIT (2 * 8)
// Delay before second check of received frame if destination address is short.
/// Delay before second check of received frame if destination address is short.
#define BCC_SHORT_ADDR ((DEST_ADDR_OFFSET + SHORT_ADDRESS_SIZE) * 8)
// Delay before second check of received frame if destination address is extended.
/// Delay before second check of received frame if destination address is extended.
#define BCC_EXTENDED_ADDR ((DEST_ADDR_OFFSET + EXTENDED_ADDRESS_SIZE) * 8)
// Duration of single iteration of Energy Detection procedure
/// Duration of single iteration of Energy Detection procedure
#define ED_ITER_DURATION 128U
// Overhead of hardware preparation for ED procedure (aTurnaroundTime) [number of iterations]
/// Overhead of hardware preparation for ED procedure (aTurnaroundTime) [number of iterations]
#define ED_ITERS_OVERHEAD 2U
// Get LQI of given received packet. If CRC is calculated by hardware LQI is included instead of CRC
// in the frame. Length is stored in byte with index 0; CRC is 2 last bytes.
#define CRC_LENGTH 2 ///< Length of CRC in 802.15.4 frames [bytes]
#define CRC_POLYNOMIAL 0x011021 ///< Polynomial used for CRC calculation in 802.15.4 frames
#define MHMU_MASK 0xff000700 ///< Mask of known bytes in ACK packet
#define MHMU_PATTERN 0x00000200 ///< Values of known bytes in ACK packet
#define MHMU_PATTERN_DSN_OFFSET 24 ///< Offset of DSN in MHMU_PATTER [bits]
/** Get LQI of given received packet. If CRC is calculated by hardware LQI is included instead of CRC
* in the frame. Length is stored in byte with index 0; CRC is 2 last bytes.
*/
#define RX_FRAME_LQI(psdu) ((psdu)[(psdu)[0] - 1])
#if RADIO_RX_BUFFERS > 1
static rx_buffer_t * mp_current_rx_buffer; // Pointer to currently used receive buffer.
/// Pointer to currently used receive buffer.
static rx_buffer_t * mp_current_rx_buffer;
#else
static rx_buffer_t * const mp_current_rx_buffer = &nrf_drv_radio802154_rx_buffers[0]; // If there is only one buffer use const pointer.
/// If there is only one buffer use const pointer to the receive buffer.
static rx_buffer_t * const mp_current_rx_buffer = &nrf_drv_radio802154_rx_buffers[0];
#endif
#if defined ( __GNUC__ )
// Ack frame buffer (EasyDMA cannot address whole RAM. Place buffer in the special section.)
/// Ack frame buffer (EasyDMA cannot address whole RAM. Place buffer in the special section.)
static uint8_t m_ack_psdu[ACK_LENGTH + 1]
__attribute__ ((section ("nrf_radio_buffer.m_ack_psdu")));
@@ -103,27 +120,26 @@ static uint8_t m_ack_psdu[ACK_LENGTH + 1];
#endif
static const uint8_t * mp_tx_data; // Pointer to data to transmit.
static uint32_t m_ed_time_left; // Remaining time of current energy detection procedure [us].
static uint8_t m_ed_result; // Result of current energy detection procedure.
static const uint8_t * mp_tx_data; ///< Pointer to data to transmit.
static uint32_t m_ed_time_left; ///< Remaining time of current energy detection procedure [us].
static uint8_t m_ed_result; ///< Result of current energy detection procedure.
static volatile radio_state_t m_state = RADIO_STATE_SLEEP; // State of the radio driver
static volatile radio_state_t m_state = RADIO_STATE_SLEEP; ///< State of the radio driver
typedef struct
{
bool prevent_ack :1; // If frame being received is not destined to this node (promiscuous mode).
bool prevent_ack :1; ///< If frame being received is not destined to this node (promiscuous mode).
} nrf_radio802154_flags_t;
static nrf_radio802154_flags_t m_flags;
static nrf_radio802154_flags_t m_flags; ///< Flags used to store current driver state.
// Mutex preventing race condition.
static volatile uint8_t m_mutex;
static volatile uint8_t m_mutex; ///< Mutex preventing race condition.
/***************************************************************************************************
* @section Mutex
**************************************************************************************************/
// Lock mutex to prevent run conditions.
/// Lock mutex to prevent race conditions.
static bool mutex_lock(void)
{
do
@@ -149,7 +165,7 @@ static bool mutex_lock(void)
return true;
}
// Unlock mutex.
/// Unlock mutex.
static void mutex_unlock(void)
{
assert(m_state == RADIO_STATE_SLEEP ||
@@ -166,7 +182,10 @@ static void mutex_unlock(void)
* @section FSM common operations
**************************************************************************************************/
// Set radio state
/** Set driver state.
*
* @param[in] state Driver state to set.
*/
static inline void state_set(radio_state_t state)
{
m_state = state;
@@ -174,7 +193,7 @@ static inline void state_set(radio_state_t state)
nrf_drv_radio802154_log(EVENT_SET_STATE, (uint32_t)state);
}
// Set state to SLEEP, exit timeslot, stop clock, unlock mutex.
/// Common procedure when the driver enters SLEEP state.
static inline void sleep_start(void)
{
state_set(RADIO_STATE_SLEEP);
@@ -182,24 +201,33 @@ static inline void sleep_start(void)
mutex_unlock();
}
// Start receiver to wait for frames.
/// Start receiver to wait for frames.
static inline void rx_start(void)
{
nrf_radio_packet_ptr_set(mp_current_rx_buffer->psdu);
nrf_radio_task_trigger(NRF_RADIO_TASK_START);
}
/// Start receiver to wait for frame that can be acknowledged.
static inline void rx_frame_start(void)
{
rx_start();
// Just after starting receiving to receive buffer set packet pointer to ACK frame that can be
// sent automatically.
nrf_radio_packet_ptr_set(m_ack_psdu);
}
// Get result of last RSSI measurement
/** Get result of last RSSI measurement.
*
* @returns Result of last RSSI measurement [dBm].
*/
static inline int8_t rssi_last_measurement_get(void)
{
return -((int8_t)nrf_radio_rssi_sample_get());
}
// Notify MAC layer that a frame was received.
/// Notify MAC layer that a frame was received.
static inline void received_frame_notify(void)
{
mp_current_rx_buffer->free = false;
@@ -208,6 +236,10 @@ static inline void received_frame_notify(void)
RX_FRAME_LQI(mp_current_rx_buffer->psdu)); // lqi
}
/** Set currently used rx buffer to given address.
*
* @param[in] p_rx_buffer Pointer to receive buffer that should be used now.
*/
static inline void rx_buffer_in_use_set(rx_buffer_t * p_rx_buffer)
{
#if RADIO_RX_BUFFERS > 1
@@ -222,19 +254,30 @@ static inline void rx_buffer_in_use_set(rx_buffer_t * p_rx_buffer)
* @section Radio parameters calculators
**************************************************************************************************/
// Set radio channel
/** Set radio channel
*
* @param[in] channel Channel number to set (11-26).
*/
static void channel_set(uint8_t channel)
{
assert(channel >= 11 && channel <= 26);
nrf_radio_frequency_set(5 + (5 * (channel - 11)));
}
// Get radio channel
/** Get radio channel.
*
* @returns Currently set channel number.
*/
static uint8_t channel_get(void)
{
return ((nrf_radio_frequency_get() - 5) / 5) + 11;
}
// Set transmit power
/** Set transmit power.
*
* @param[in] dbm Transmit power to set [dbm].
*/
static void tx_power_set(int8_t dbm)
{
const int8_t allowed_values[] = {-40, -20, -16, -12, -8, -4, 0, 2, 3, 4, 5, 6, 7, 8, 9};
@@ -263,21 +306,20 @@ static void tx_power_set(int8_t dbm)
* @section Shorts management
**************************************************************************************************/
// Disable peripheral shorts.
/// Disable peripheral shorts.
static inline void shorts_disable(void)
{
nrf_radio_shorts_set(SHORTS_IDLE);
nrf_radio_ifs_set(0);
}
// Enable peripheral shorts used during data frame transmission.
/// Enable peripheral shorts used during data frame transmission.
static inline void shorts_tx_frame_set(void)
{
nrf_radio_shorts_set(SHORTS_TX_FRAME);
}
// Enable peripheral shorts used during automatic ACK transmission.
// TIFS shorts are splitted
/// Enable peripheral shorts used in receive state to enable automatic ACK procedure.
static inline void shorts_rx_initial_set(void)
{
nrf_radio_ifs_set(TIFS_ACK_US);
@@ -286,14 +328,13 @@ static inline void shorts_rx_initial_set(void)
nrf_radio_shorts_set(SHORTS_RX_INITIAL);
}
// Enable peripheral shorts used during automatic ACK transmission.
/// Enable peripheral shorts used during automatic ACK transmission.
static inline void shorts_rx_following_set(void)
{
nrf_radio_shorts_set(SHORTS_RX_FOLLOWING);
}
// Disable peripheral shorts used during automatic ACK transmission if ACK is transmitted
// (short disabling transmitter persists).
/// Disable peripheral shorts used during automatic ACK transmission when ACK is being transmitted
static inline void shorts_tx_ack_set(void)
{
// If ACK is sent END_DISABLE short should persist to disable transmitter automatically.
@@ -306,14 +347,14 @@ static inline void shorts_tx_ack_set(void)
* @section ACK transmission management
**************************************************************************************************/
// Set valid sequence number in ACK frame.
/// Set valid sequence number in ACK frame.
static inline void ack_prepare(void)
{
// Copy sequence number from received frame to ACK frame.
m_ack_psdu[DSN_OFFSET] = mp_current_rx_buffer->psdu[DSN_OFFSET];
}
// Set pending bit in ACK frame.
/// Set pending bit in ACK frame.
static inline void ack_pending_bit_set(void)
{
m_ack_psdu[FRAME_PENDING_OFFSET] = ACK_HEADER_WITH_PENDING;
@@ -324,13 +365,22 @@ static inline void ack_pending_bit_set(void)
}
}
// Check if ACK is requested in given frame.
/** Check if ACK is requested in given frame.
*
* @param[in] p_frame Pointer to a frame to check.
*
* @retval true ACK is requested in given frame.
* @retval false ACK is not requested in given frame.
*/
static inline bool ack_is_requested(const uint8_t * p_frame)
{
return (p_frame[ACK_REQUEST_OFFSET] & ACK_REQUEST_BIT) ? true : false;
}
// Abort automatic sending ACK.
/** Abort automatic ACK procedure.
*
* @param[in] state_to_set Driver state that shall be set after the procedure is aborted.
*/
static void auto_ack_abort(radio_state_t state_to_set)
{
nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_AUTO_ACK_ABORT);
@@ -367,6 +417,7 @@ static void auto_ack_abort(radio_state_t state_to_set)
* @section ACK receiving management
**************************************************************************************************/
/// Enable hardware ACK matching accelerator.
static inline void ack_matching_enable(void)
{
nrf_radio_event_clear(NRF_RADIO_EVENT_MHRMATCH);
@@ -375,18 +426,25 @@ static inline void ack_matching_enable(void)
MHMU_PATTERN_DSN_OFFSET));
}
/// Disable hardware ACK matching accelerator.
static inline void ack_matching_disable(void)
{
nrf_radio_mhmu_search_pattern_set(0);
nrf_radio_event_clear(NRF_RADIO_EVENT_MHRMATCH);
}
/** Check if hardware ACK matching accelerator matched ACK pattern in received frame.
*
* @retval true ACK matching accelerator matched ACK pattern.
* @retval false ACK matching accelerator did not match ACK pattern.
*/
static inline bool ack_is_matched(void)
{
return (nrf_radio_event_get(NRF_RADIO_EVENT_MHRMATCH)) &&
(nrf_radio_crc_status_get() == NRF_RADIO_CRC_STATUS_OK);
}
/// Start receiver to receive data after receiving of ACK frame.
static inline void frame_rx_start_after_ack_rx(void)
{
ack_matching_disable();
@@ -398,7 +456,7 @@ static inline void frame_rx_start_after_ack_rx(void)
* @section RADIO peripheral management
**************************************************************************************************/
// Initialize radio peripheral
/// Initialize radio peripheral
static void nrf_radio_init(void)
{
nrf_radio_mode_set(NRF_RADIO_MODE_IEEE802154_250KBIT);
@@ -434,7 +492,7 @@ static void nrf_radio_init(void)
nrf_radio_int_enable(NRF_RADIO_INT_EDEND_MASK);
}
// Reset radio peripheral
/// Reset radio peripheral
static void nrf_radio_reset(void)
{
nrf_radio_power_set(false);
@@ -443,7 +501,7 @@ static void nrf_radio_reset(void)
nrf_drv_radio802154_log(EVENT_RADIO_RESET, 0);
}
// Initialize interrupts for radio peripheral
/// Initialize interrupts for radio peripheral
static void irq_init(void)
{
NVIC_SetPriority(RADIO_IRQn, RADIO_IRQ_PRIORITY);
@@ -451,7 +509,7 @@ static void irq_init(void)
NVIC_EnableIRQ(RADIO_IRQn);
}
// Deinitialize interrupts for radio peripheral
/// Deinitialize interrupts for radio peripheral
static void irq_deinit(void)
{
NVIC_DisableIRQ(RADIO_IRQn);
@@ -467,6 +525,17 @@ static void irq_deinit(void)
* @section Energy detection management
**************************************************************************************************/
/** Setup next iteration of energy detection procedure.
*
* Energy detection procedure is performed in iterations to make sure it is performed for requested
* time regardless radio arbitration.
*
* @param[in] Remaining time of energy detection procedure [us].
*
* @retval true Next iteration of energy detection procedure will be performed now.
* @retval false Next iteration of energy detection procedure will not be performed now due to
* ending timeslot.
*/
static inline bool ed_iter_setup(uint32_t time_us)
{
uint32_t us_left_in_timeslot = nrf_raal_timeslot_us_left_get();
@@ -592,7 +661,7 @@ void nrf_raal_timeslot_ended(void)
* @section RADIO interrupt handler
**************************************************************************************************/
// When the radio starts receiving a frame it generates this event.
/// This event is handled when the radio starts receiving a frame.
static inline void irq_framestart_state_waiting_rx_frame(void)
{
if (mutex_lock())
@@ -611,6 +680,8 @@ static inline void irq_framestart_state_waiting_rx_frame(void)
else
{
nrf_radio_task_trigger(NRF_RADIO_TASK_RSSISTART);
nrf_drv_radio802154_rx_started();
}
}
@@ -641,7 +712,7 @@ static inline void irq_framestart_state_waiting_rx_frame(void)
}
}
// When the radio starts receiving an ACK frame this event is generated.
/// This event is handled when the radio starts receiving an ACK frame.
static inline void irq_framestart_state_rx_ack(void)
{
assert(nrf_radio_shorts_get() == SHORTS_IDLE);
@@ -660,7 +731,13 @@ static inline void irq_framestart_state_rx_ack(void)
}
}
// This event is handled when MHR was received
/// This event is handled when the radio starts transmitting a requested frame.
static inline void irq_framestart_state_tx_frame(void)
{
nrf_drv_radio802154_tx_started();
}
/// This event is handled when MHR is received
static inline void irq_bcmatch_mhr(void)
{
// Verify if time slot for receiving is available.
@@ -726,7 +803,7 @@ static inline void irq_bcmatch_mhr(void)
}
}
// This event is generated when destination address fields are received
/// This event is generated when destination address fields are received.
static inline void irq_bcmatch_address(void)
{
if (nrf_drv_radio802154_pib_dest_addr_matches(mp_current_rx_buffer->psdu))
@@ -750,9 +827,9 @@ static inline void irq_bcmatch_address(void)
}
}
// This event is generated two times during frame reception:
// When MHR is received
// When destination address fields are received
/** This event is generated twice during frame reception:
* when MHR is received and when destination address fields are received.
*/
static inline void irq_bcmatch_state_rx_header(void)
{
assert(nrf_radio_shorts_get() == SHORTS_RX_INITIAL);
@@ -795,8 +872,9 @@ static inline void irq_bcmatch_state_rx_header(void)
}
}
// This event is generated when radio receives invalid frame with length set to 0 or started
// receiving a frame after other procedure locked mutex.
/** This event is generated when radio receives invalid frame with length set to 0 or started
* receiving a frame after other procedure locked mutex.
*/
static inline void irq_end_state_waiting_rx_frame(void)
{
// Radio state is not asserted here. It can be a lot of states due to shorts.
@@ -816,7 +894,7 @@ static inline void irq_end_state_waiting_rx_frame(void)
}
}
// This event is generated if frame being received is shorter than expected MAC header length.
/// This event is generated if frame being received is shorter than expected MAC header length.
static inline void irq_end_state_rx_header(void)
{
// Frame ended before header was received.
@@ -824,7 +902,7 @@ static inline void irq_end_state_rx_header(void)
nrf_radio_event_clear(NRF_RADIO_EVENT_READY);
}
// This event is generated when radio peripheral ends receiving of a complete frame.
/// This event is generated when radio peripheral ends receiving of a complete frame.
static inline void irq_end_state_rx_frame(void)
{
assert(nrf_radio_shorts_get() == SHORTS_RX_INITIAL);
@@ -871,7 +949,7 @@ static inline void irq_end_state_rx_frame(void)
}
}
// This event is generated when the radio ends transmission of ACK frame.
/// This event is generated when the radio ends transmission of ACK frame.
static inline void irq_end_state_tx_ack(void)
{
assert(nrf_radio_shorts_get() == SHORTS_TX_ACK);
@@ -883,13 +961,15 @@ static inline void irq_end_state_tx_ack(void)
// Receiver is enabled by shorts.
}
// This could happen at the beginning of transmission procedure (the procedure already has disabled shorts).
/** This event may occur at the beginning of transmission procedure (the procedure already has
* disabled shorts).
*/
static inline void irq_end_state_cca(void)
{
assert(nrf_radio_shorts_get() == SHORTS_IDLE);
}
// This event is generated when the radio ends transmission of a frame.
/// This event is generated when the radio ends transmission of a frame.
static inline void irq_end_state_tx_frame(void)
{
shorts_disable();
@@ -911,7 +991,7 @@ static inline void irq_end_state_tx_frame(void)
// Task DISABLE is triggered by shorts.
}
// This event is generated when the radio ends receiving of ACK frame.
/// This event is generated when the radio ends receiving of ACK frame.
static inline void irq_end_state_rx_ack(void)
{
assert(nrf_radio_shorts_get() == SHORTS_IDLE);
@@ -932,7 +1012,7 @@ static inline void irq_end_state_rx_ack(void)
frame_rx_start_after_ack_rx();
}
// This event is generated when radio peripheral disables in order to enter sleep state.
/// This event is generated when radio peripheral disables in order to enter sleep state.
static inline void irq_disabled_state_disabling(void)
{
assert(nrf_radio_shorts_get() == SHORTS_IDLE);
@@ -940,8 +1020,10 @@ static inline void irq_disabled_state_disabling(void)
sleep_start();
}
// This event is generated when the driver enters receive state. The radio is now disabled and the
// driver starts enabling receiver.
/** This event is generated when the driver enters receive state.
*
* The radio is now disabled and the driver starts enabling receiver.
*/
static inline void irq_disabled_state_waiting_rx_frame(void)
{
assert(nrf_radio_shorts_get() == SHORTS_IDLE);
@@ -964,8 +1046,25 @@ static inline void irq_disabled_state_waiting_rx_frame(void)
nrf_radio_event_clear(NRF_RADIO_EVENT_DISABLED);
}
// This event is generated during automatic ACK transmission: receiver is disabled and transmitter
// is being enabled by shorts.
/** This event is generated in case both END and DISABLED events are notified between
* checking if END event was notified and checking if DISABLED event was notified.
*
* In this invalid and rare case just drop received frame.
*/
static inline void irq_disabled_state_rx_frame(void)
{
assert(nrf_radio_event_get(NRF_RADIO_EVENT_END));
assert(nrf_radio_shorts_get() == SHORTS_RX_INITIAL);
auto_ack_abort(RADIO_STATE_WAITING_RX_FRAME);
nrf_radio_event_clear(NRF_RADIO_EVENT_END);
nrf_radio_event_clear(NRF_RADIO_EVENT_READY);
}
/** This event is generated during automatic ACK transmission.
*
* Receiver is disabled and transmitter is being enabled by shorts.
*/
static inline void irq_disabled_state_tx_ack(void)
{
assert(nrf_radio_shorts_get() == SHORTS_RX_INITIAL);
@@ -984,8 +1083,10 @@ static inline void irq_disabled_state_tx_ack(void)
}
}
// This event is generated before CCA procedure starts. The radio is disabled and the drivers
// enables receiver in order to start CCA procedure.
/** This event is generated before CCA procedure starts.
*
* The radio is disabled and the drivers enables receiver in order to start CCA procedure.
*/
static inline void irq_disabled_state_cca(void)
{
assert(nrf_radio_shorts_get() == SHORTS_IDLE);
@@ -993,18 +1094,25 @@ static inline void irq_disabled_state_cca(void)
nrf_radio_task_trigger(NRF_RADIO_TASK_RXEN);
}
// This event is generated before transmission of a frame starts. The radio is disabled and
// enabling transmitter is requested by shorts or by the driver.
/** This event is generated before transmission of a frame starts.
*
* The radio is disabled and enabling transmitter is requested by shorts or by the driver.
*/
static inline void irq_disabled_state_tx_frame(void)
{
if (nrf_radio_state_get() == NRF_RADIO_STATE_DISABLED)
{
shorts_tx_frame_set();
nrf_radio_task_trigger(NRF_RADIO_TASK_TXEN);
}
assert(nrf_radio_shorts_get() == SHORTS_TX_FRAME);
#if !RADIO_SHORT_CCAIDLE_TXEN
nrf_radio_task_trigger(NRF_RADIO_TASK_TXEN);
#endif
}
// This event is generated when radio is disabled after transmission of a frame with ACK request.
// The driver enables receiver to receive ACK frame.
/** This event is generated when radio is disabled after transmission of a frame with ACK request.
*
* The driver enables receiver to receive ACK frame.
*/
static inline void irq_disabled_state_rx_ack(void)
{
assert(nrf_radio_shorts_get() == SHORTS_IDLE);
@@ -1017,8 +1125,11 @@ static inline void irq_disabled_state_rx_ack(void)
}
}
// This event is generated before energy detection procedure. The radio is disabled and the driver
// enables receiver in order to start energy detection procedure.
/** This event is generated before energy detection procedure.
*
* The radio is disabled and the driver enables receiver in order to start energy detection
* procedure.
*/
static inline void irq_disabled_state_ed(void)
{
assert(nrf_radio_shorts_get() == SHORTS_IDLE);
@@ -1026,8 +1137,10 @@ static inline void irq_disabled_state_ed(void)
nrf_radio_task_trigger(NRF_RADIO_TASK_RXEN);
}
// This event is generated when receiver is ready to start receiving a frame. Driver checks if
// buffer for a frame is available and starts receiver.
/** This event is generated when receiver is ready to start receiving a frame.
*
* Driver checks if buffer for a frame is available and starts receiver.
*/
static inline void irq_ready_state_waiting_rx_frame(void)
{
assert(nrf_radio_shorts_get() == SHORTS_IDLE);
@@ -1038,23 +1151,27 @@ static inline void irq_ready_state_waiting_rx_frame(void)
if (mutex_lock())
{
shorts_rx_initial_set();
rx_start();
rx_frame_start();
mutex_unlock();
}
}
}
// This event is generated when transmitter is ready to transmit ACK frame. Transmission is started
// by shorts. The driver sets shorts to gracefully end transmission of ACK.
/** This event is generated when transmitter is ready to transmit ACK frame.
*
* Transmission is started by shorts. The driver sets shorts to gracefully end transmission of ACK.
*/
static inline void irq_ready_state_tx_ack(void)
{
assert(nrf_radio_shorts_get() == SHORTS_RX_FOLLOWING);
shorts_tx_ack_set();
}
// This event is generated when receiver is ready to start CCA procedure. The driver prepares for
// transmission and starts CCA procedure.
/** This event is generated when receiver is ready to start CCA procedure.
*
* The driver prepares for transmission and starts CCA procedure.
*/
static inline void irq_ready_state_cca(void)
{
assert(nrf_radio_shorts_get() == SHORTS_IDLE);
@@ -1066,14 +1183,16 @@ static inline void irq_ready_state_cca(void)
nrf_radio_task_trigger(NRF_RADIO_TASK_CCASTART);
}
// This event is generated when transmitter is ready to transmit a frame. Transmission is started by
// shorts.
/** This event is generated when transmitter is ready to transmit a frame.
*
* Transmission is started by shorts.
*/
static inline void irq_ready_state_tx_frame(void)
{
assert(nrf_radio_shorts_get() == SHORTS_TX_FRAME);
}
// This event is generated when receiver is ready to receive an ACK frame.
/// This event is generated when receiver is ready to receive an ACK frame.
static inline void irq_ready_state_rx_ack(void)
{
assert(nrf_radio_shorts_get() == SHORTS_IDLE);
@@ -1090,7 +1209,7 @@ static inline void irq_ready_state_rx_ack(void)
}
}
// This event is generated when receiver is ready to start energy detection procedure.
/// This event is generated when receiver is ready to start energy detection procedure.
static inline void irq_ready_state_ed(void)
{
assert(nrf_radio_shorts_get() == SHORTS_IDLE);
@@ -1099,16 +1218,17 @@ static inline void irq_ready_state_ed(void)
}
#if !RADIO_SHORT_CCAIDLE_TXEN
// This event is generated when CCA reports that channel is idle.
/// This event is generated when CCA reports that channel is idle.
static inline void irq_ccaidle(void)
{
assert (m_state == RADIO_STATE_TX_FRAME);
assert(m_state == RADIO_STATE_TX_FRAME);
assert(nrf_radio_shorts_get() == SHORTS_TX_FRAME);
nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE);
}
#endif // RADIO_SHORT_CCAIDLE_TXEN
// This event is generated when CCA reports busy channel prior to transmission.
/// This event is generated when CCA reports busy channel prior to transmission.
static inline void irq_ccabusy_state_tx_frame(void)
{
assert(nrf_radio_shorts_get() == SHORTS_TX_FRAME);
@@ -1122,7 +1242,7 @@ static inline void irq_ccabusy_state_tx_frame(void)
nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE);
}
// This event is generated when energy detection procedure ends.
/// This event is generated when energy detection procedure ends.
static inline void irq_edend(void)
{
assert(m_state == RADIO_STATE_ED);
@@ -1148,7 +1268,7 @@ static inline void irq_edend(void)
}
}
// Handler of radio interrupts.
/// Handler of radio interrupts.
void RADIO_IRQHandler(void)
{
nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_IRQ_HANDLER);
@@ -1168,8 +1288,11 @@ void RADIO_IRQHandler(void)
irq_framestart_state_rx_ack();
break;
case RADIO_STATE_TX_ACK:
case RADIO_STATE_TX_FRAME:
irq_framestart_state_tx_frame();
break;
case RADIO_STATE_TX_ACK:
case RADIO_STATE_CCA: // This could happen at the beginning of transmission procedure.
case RADIO_STATE_WAITING_TIMESLOT:
break;
@@ -1267,6 +1390,11 @@ void RADIO_IRQHandler(void)
irq_disabled_state_waiting_rx_frame();
break;
case RADIO_STATE_RX_HEADER:
case RADIO_STATE_RX_FRAME:
irq_disabled_state_rx_frame();
break;
case RADIO_STATE_TX_ACK:
irq_disabled_state_tx_ack();
break;
@@ -1392,8 +1520,10 @@ void RADIO_IRQHandler(void)
* @section FSM transition request sub-procedures
**************************************************************************************************/
// Abort transmission procedure.
// This function is called when MAC layer requests transition from transmit to receive state.
/** Abort transmission procedure.
*
* This function is called when MAC layer requests transition from transmit to receive state.
*/
static inline void tx_procedure_abort(void)
{
shorts_disable();
@@ -1563,7 +1693,7 @@ bool nrf_drv_radio802154_fsm_receive(uint8_t channel)
return result;
}
bool nrf_drv_radio802154_fsm_transmit(const uint8_t * p_data, uint8_t channel, int8_t power)
bool nrf_drv_radio802154_fsm_transmit(const uint8_t * p_data, uint8_t channel, int8_t power, bool cca)
{
bool result = false;
mp_tx_data = p_data;
@@ -1576,9 +1706,8 @@ bool nrf_drv_radio802154_fsm_transmit(const uint8_t * p_data, uint8_t channel, i
assert(m_state == RADIO_STATE_WAITING_RX_FRAME);
channel_set(channel);
auto_ack_abort(RADIO_STATE_CCA);
assert(nrf_radio_shorts_get() == SHORTS_IDLE);
auto_ack_abort(cca ? RADIO_STATE_CCA : RADIO_STATE_TX_FRAME);
tx_power_set(power);
nrf_radio_packet_ptr_set(p_data);
@@ -1707,7 +1836,7 @@ void nrf_drv_radio802154_fsm_notify_buffer_free(rx_buffer_t * p_buffer)
shorts_rx_initial_set();
rx_buffer_in_use_set(p_buffer);
rx_start();
rx_frame_start();
// Clear events that could have happened in critical section due to RX
// ramp up.
@@ -130,11 +130,12 @@ bool nrf_drv_radio802154_fsm_receive(uint8_t channel);
* @param[in] p_data Pointer to a frame to transmit.
* @param[in] channel Channel number that the radio should use to transmit the frame.
* @param[in] power Transmission power.
* @param[in] cca If the driver should perform CCA procedure before transmission.
*
* @retval true Entering TRANSMIT state succeeded.
* @retval false Entering TRANSMIT state failed (driver is performing other procedure).
*/
bool nrf_drv_radio802154_fsm_transmit(const uint8_t * p_data, uint8_t channel, int8_t power);
bool nrf_drv_radio802154_fsm_transmit(const uint8_t * p_data, uint8_t channel, int8_t power, bool cca);
/**
* @brief Request transition to ENERGY_DETECTION state.
@@ -42,20 +42,20 @@
#include "nrf_drv_radio802154_const.h"
#define BROADCAST_ADDRESS ((uint8_t [SHORT_ADDRESS_SIZE]) {0xff, 0xff}) // Broadcast Short Address
#define BROADCAST_ADDRESS ((uint8_t [SHORT_ADDRESS_SIZE]) {0xff, 0xff}) ///< Broadcast Short Address
typedef struct
{
int8_t tx_power; // Transmit power.
uint8_t pan_id[PAN_ID_SIZE]; // Pan Id of this node.
uint8_t short_addr[SHORT_ADDRESS_SIZE]; // Short Address of this node.
uint8_t extended_addr[EXTENDED_ADDRESS_SIZE]; // Extended Address of this node.
bool promiscuous :1; // Indicating if radio is in promiscuous mode.
bool auto_ack :1; // Indicating if auto ACK procedure is enabled.
uint8_t channel :5; // Channel on which the node receives messages.
int8_t tx_power; ///< Transmit power.
uint8_t pan_id[PAN_ID_SIZE]; ///< Pan Id of this node.
uint8_t short_addr[SHORT_ADDRESS_SIZE]; ///< Short Address of this node.
uint8_t extended_addr[EXTENDED_ADDRESS_SIZE]; ///< Extended Address of this node.
bool promiscuous :1; ///< Indicating if radio is in promiscuous mode.
bool auto_ack :1; ///< Indicating if auto ACK procedure is enabled.
uint8_t channel :5; ///< Channel on which the node receives messages.
} nrf_drv_radio802154_pib_data_t;
static nrf_drv_radio802154_pib_data_t m_data;
static nrf_drv_radio802154_pib_data_t m_data; ///< Buffer containing PIB data.
void nrf_drv_radio802154_pib_init(void)
{
@@ -74,11 +74,12 @@ bool nrf_drv_radio802154_request_receive(uint8_t channel);
* @param[in] p_data Pointer to the frame to transmit.
* @param[in] channel Channel number used to transmit the frame.
* @param[in] power Transmitter power used to transmit the frame.
* @param[in] cca If the driver should perform CCA procedure before transmission.
*
* @retval true The driver will enter transmit state.
* @retval false The driver cannot enter transmit state due to ongoing operation.
*/
bool nrf_drv_radio802154_request_transmit(const uint8_t * p_data, uint8_t channel, int8_t power);
bool nrf_drv_radio802154_request_transmit(const uint8_t * p_data, uint8_t channel, int8_t power, bool cca);
/**
* @brief Request entering energy detection state.
@@ -72,12 +72,12 @@ bool nrf_drv_radio802154_request_receive(uint8_t channel)
return result;
}
bool nrf_drv_radio802154_request_transmit(const uint8_t * p_data, uint8_t channel, int8_t power)
bool nrf_drv_radio802154_request_transmit(const uint8_t * p_data, uint8_t channel, int8_t power, bool cca)
{
bool result;
nrf_drv_radio802154_critical_section_enter();
result = nrf_drv_radio802154_fsm_transmit(p_data, channel, power);
result = nrf_drv_radio802154_fsm_transmit(p_data, channel, power, cca);
nrf_drv_radio802154_critical_section_exit();
return result;
@@ -37,6 +37,7 @@
#include "nrf_drv_radio802154_request.h"
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
@@ -51,12 +52,31 @@
#include <cmsis/core_cmFunc.h>
#include <cmsis/core_cm4.h>
static bool active_verctor_priority_is_high(void)
{
uint32_t active_vector_id = (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) >> SCB_ICSR_VECTACTIVE_Pos;
uint32_t active_priority = NVIC_GetPriority((IRQn_Type)active_vector_id);
#define CMSIS_IRQ_NUM_VECTACTIVE_DIFF 16
return active_priority >= RADIO_NOTIFICATION_SWI_PRIORITY;
/** Check if active vector priority is high enough to call requests directly.
*
* @retval true Active vector priority is greater or equal to SWI priority.
* @retval false Active vector priority is lower than SWI priority.
*/
static bool active_vector_priority_is_high(void)
{
uint32_t active_vector_id = (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) >> SCB_ICSR_VECTACTIVE_Pos;
IRQn_Type irq_number;
uint32_t active_priority;
// Check if this function is called from main thread.
if (active_vector_id == 0)
{
return false;
}
assert(active_vector_id >= CMSIS_IRQ_NUM_VECTACTIVE_DIFF);
irq_number = (IRQn_Type)(active_vector_id - CMSIS_IRQ_NUM_VECTACTIVE_DIFF);
active_priority = NVIC_GetPriority(irq_number);
return active_priority <= RADIO_NOTIFICATION_SWI_PRIORITY;
}
void nrf_drv_radio802154_request_init(void)
@@ -68,7 +88,7 @@ bool nrf_drv_radio802154_request_sleep(void)
{
bool result = false;
if (active_verctor_priority_is_high())
if (active_vector_priority_is_high())
{
nrf_drv_radio802154_critical_section_enter();
result = nrf_drv_radio802154_fsm_sleep();
@@ -86,7 +106,7 @@ bool nrf_drv_radio802154_request_receive(uint8_t channel)
{
bool result = false;
if (active_verctor_priority_is_high())
if (active_vector_priority_is_high())
{
nrf_drv_radio802154_critical_section_enter();
result = nrf_drv_radio802154_fsm_receive(channel);
@@ -100,19 +120,19 @@ bool nrf_drv_radio802154_request_receive(uint8_t channel)
return result;
}
bool nrf_drv_radio802154_request_transmit(const uint8_t * p_data, uint8_t channel, int8_t power)
bool nrf_drv_radio802154_request_transmit(const uint8_t * p_data, uint8_t channel, int8_t power, bool cca)
{
bool result = false;
if (active_verctor_priority_is_high())
if (active_vector_priority_is_high())
{
nrf_drv_radio802154_critical_section_enter();
result = nrf_drv_radio802154_fsm_transmit(p_data, channel, power);
result = nrf_drv_radio802154_fsm_transmit(p_data, channel, power, cca);
nrf_drv_radio802154_critical_section_exit();
}
else
{
nrf_drv_radio802154_swi_transmit(p_data, channel, power, &result);
nrf_drv_radio802154_swi_transmit(p_data, channel, power, cca, &result);
}
return result;
@@ -122,7 +142,7 @@ bool nrf_drv_radio802154_request_energy_detection(uint8_t channel, uint32_t time
{
bool result = false;
if (active_verctor_priority_is_high())
if (active_vector_priority_is_high())
{
nrf_drv_radio802154_critical_section_enter();
result = nrf_drv_radio802154_fsm_energy_detection(channel, time_us);
@@ -138,5 +158,14 @@ bool nrf_drv_radio802154_request_energy_detection(uint8_t channel, uint32_t time
void nrf_drv_radio802154_request_buffer_free(uint8_t * p_data)
{
nrf_drv_radio802154_swi_buffer_free(p_data);
if (active_vector_priority_is_high())
{
nrf_drv_radio802154_critical_section_enter();
nrf_drv_radio802154_fsm_notify_buffer_free((rx_buffer_t *)p_data);
nrf_drv_radio802154_critical_section_exit();
}
else
{
nrf_drv_radio802154_swi_buffer_free(p_data);
}
}
@@ -46,7 +46,7 @@
#if defined ( __GNUC__ )
// Receive buffer (EasyDMA cannot address whole RAM. Place buffer in the special section.)
/// Receive buffer (EasyDMA cannot address whole RAM. Place buffer in the special section.)
rx_buffer_t nrf_drv_radio802154_rx_buffers[RADIO_RX_BUFFERS]
__attribute__ ((section ("nrf_radio_buffer.nrf_drv_radio802154_rx_buffers")));
@@ -48,59 +48,71 @@
#include "hal/nrf_egu.h"
#include "raal/nrf_raal_api.h"
#define NTF_QUEUE_SIZE (RADIO_RX_BUFFERS + 3) // for each rx buffer, 1 for tx, 1 for channel busy, 1 for energy detection
#define REQ_QUEUE_SIZE 2 // minimal queue size
/** Size of notification queue.
*
* One slot for each receive buffer, one for transmission, one for busy channel and one for energy
* detection.
*/
#define NTF_QUEUE_SIZE (RADIO_RX_BUFFERS + 3)
/** Size of requests queue.
*
* Two is minimal queue size. It is not expected in current implementation to queue a few requests.
*/
#define REQ_QUEUE_SIZE 2
#define SWI_EGU NRF_EGU3
#define SWI_IRQn SWI3_EGU3_IRQn
#define SWI_IRQHandler SWI3_EGU3_IRQHandler
#define SWI_EGU NRF_EGU3 ///< Label of SWI peripheral.
#define SWI_IRQn SWI3_EGU3_IRQn ///< Symbol of SWI IRQ number.
#define SWI_IRQHandler SWI3_EGU3_IRQHandler ///< Symbol of SWI IRQ handler.
#define NTF_INT NRF_EGU_INT_TRIGGERED0
#define NTF_TASK NRF_EGU_TASK_TRIGGER0
#define NTF_EVENT NRF_EGU_EVENT_TRIGGERED0
#define NTF_INT NRF_EGU_INT_TRIGGERED0 ///< Label of notification interrupt.
#define NTF_TASK NRF_EGU_TASK_TRIGGER0 ///< Label of notification task.
#define NTF_EVENT NRF_EGU_EVENT_TRIGGERED0 ///< Label of notification event.
#define TIMESLOT_EXIT_INT NRF_EGU_INT_TRIGGERED1
#define TIMESLOT_EXIT_TASK NRF_EGU_TASK_TRIGGER1
#define TIMESLOT_EXIT_EVENT NRF_EGU_EVENT_TRIGGERED1
#define TIMESLOT_EXIT_INT NRF_EGU_INT_TRIGGERED1 ///< Label of timeslot exit interrupt.
#define TIMESLOT_EXIT_TASK NRF_EGU_TASK_TRIGGER1 ///< Label of timeslot exit task.
#define TIMESLOT_EXIT_EVENT NRF_EGU_EVENT_TRIGGERED1 ///< Label of timeslot exit event.
#define REQ_INT NRF_EGU_INT_TRIGGERED2
#define REQ_TASK NRF_EGU_TASK_TRIGGER2
#define REQ_EVENT NRF_EGU_EVENT_TRIGGERED2
#define REQ_INT NRF_EGU_INT_TRIGGERED2 ///< Label of request interrupt.
#define REQ_TASK NRF_EGU_TASK_TRIGGER2 ///< Label of request task.
#define REQ_EVENT NRF_EGU_EVENT_TRIGGERED2 ///< Label of request event.
/// Types of notifications in notification queue.
typedef enum
{
NTF_TYPE_RECEIVED,
NTF_TYPE_TRANSMITTED,
NTF_TYPE_CHANNEL_BUSY,
NTF_TYPE_ENERGY_DETECTED,
NTF_TYPE_RECEIVED, ///< Frame received
NTF_TYPE_TRANSMITTED, ///< Frame transmitted
NTF_TYPE_CHANNEL_BUSY, ///< Frame transmission failure
NTF_TYPE_ENERGY_DETECTED, ///< Energy detection procedure ended
} nrf_drv_radio802154_ntf_type_t;
/// Notification data in the notification queue.
typedef struct
{
nrf_drv_radio802154_ntf_type_t type;
nrf_drv_radio802154_ntf_type_t type; ///< Notification type.
union
{
struct
{
uint8_t * p_psdu;
int8_t power;
int8_t lqi;
} received;
uint8_t * p_psdu; ///< Pointer to received frame PSDU.
int8_t power; ///< RSSI of received frame.
int8_t lqi; ///< LQI of received frame.
} received; ///< Received frame details.
struct
{
uint8_t * p_psdu;
int8_t power;
int8_t lqi;
} transmitted;
uint8_t * p_psdu; ///< Pointer to received ACK PSDU or NULL.
int8_t power; ///< RSSI of received ACK or 0.
int8_t lqi; ///< LQI of received ACK or 0.
} transmitted; ///< Transmitted frame details.
struct
{
int8_t result;
} energy_detected;
} data;
int8_t result; ///< Energy detection result.
} energy_detected; ///< Energy detection details.
} data; ///< Notification data depending on it's type.
} nrf_drv_radio802154_ntf_data_t;
/// Type of requests in request queue.
typedef enum
{
REQ_TYPE_SLEEP,
@@ -110,52 +122,60 @@ typedef enum
REQ_TYPE_BUFFER_FREE,
} nrf_drv_radio802154_req_type_t;
/// Request data in request queue.
typedef struct
{
nrf_drv_radio802154_req_type_t type;
nrf_drv_radio802154_req_type_t type; ///< Type of the request.
union
{
struct
{
bool * p_result;
} sleep;
bool * p_result; ///< Sleep request result.
} sleep; ///< Sleep request details.
struct
{
bool * p_result;
uint8_t channel;
} receive;
bool * p_result; ///< Receive request result.
uint8_t channel; ///< Channel to receive on.
} receive; ///< Receive request details.
struct
{
bool * p_result;
const uint8_t * p_data;
uint8_t channel;
int8_t power;
} transmit;
bool * p_result; ///< Transmit request result.
const uint8_t * p_data; ///< Pointer to PSDU to transmit.
uint8_t channel; ///< Channel to transmit on.
int8_t power; ///< Requested transmission power.
bool cca; ///< If CCA was requested prior to transmission.
} transmit; ///< Transmit request details.
struct
{
bool * p_result;
uint8_t channel;
uint32_t time_us;
} energy_detection;
bool * p_result; ///< Energy detection request result.
uint8_t channel; ///< Channel to perform energy detection on.
uint32_t time_us; ///< Requested time of energy detection procedure.
} energy_detection; ///< Energy detection request details.
struct
{
rx_buffer_t * p_data;
} buffer_free;
} data;
rx_buffer_t * p_data; ///< Pointer to receive buffer to free.
} buffer_free; ///< Buffer free request details.
} data; ///< Request data depending on it's type.
} nrf_drv_radio802154_req_data_t;
static nrf_drv_radio802154_ntf_data_t m_ntf_queue[NTF_QUEUE_SIZE];
static uint8_t m_ntf_r_ptr;
static uint8_t m_ntf_w_ptr;
static nrf_drv_radio802154_ntf_data_t m_ntf_queue[NTF_QUEUE_SIZE]; ///< Notification queue.
static uint8_t m_ntf_r_ptr; ///< Notification queue read index.
static uint8_t m_ntf_w_ptr; ///< Notification queue write index.
static nrf_drv_radio802154_req_data_t m_req_queue[REQ_QUEUE_SIZE];
static uint8_t m_req_r_ptr;
static uint8_t m_req_w_ptr;
static nrf_drv_radio802154_req_data_t m_req_queue[REQ_QUEUE_SIZE]; ///< Request queue.
static uint8_t m_req_r_ptr; // Request queue read index.
static uint8_t m_req_w_ptr; // Request queue write index.
/**
* Increment given index for any queue.
*
* @param[inout] p_ptr Index to increment.
* @param[in] queue_size Number of elements in the queue.
*/
static void queue_ptr_increment(uint8_t * p_ptr, uint8_t queue_size)
{
if (++(*p_ptr) >= queue_size)
@@ -164,6 +184,16 @@ static void queue_ptr_increment(uint8_t * p_ptr, uint8_t queue_size)
}
}
/**
* Check if given queue is full.
*
* @param[in] r_ptr Read index associated with given queue.
* @param[in] w_ptr Write index associated with given queue.
* @param[in] queue_size Number of elements in the queue.
*
* @retval true Given queue is full.
* @retval false Given queue is not full.
*/
static bool queue_is_full(uint8_t r_ptr, uint8_t w_ptr, uint8_t queue_size)
{
if (w_ptr == (r_ptr - 1))
@@ -179,36 +209,79 @@ static bool queue_is_full(uint8_t r_ptr, uint8_t w_ptr, uint8_t queue_size)
return false;
}
/**
* Check if given queue is empty.
*
* @param[in] r_ptr Read index associated with given queue.
* @param[in] w_ptr Write index associated with given queue.
*
* @retval true Given queue is empty.
* @retval false Given queue is not empty.
*/
static bool queue_is_empty(uint8_t r_ptr, uint8_t w_ptr)
{
return (r_ptr == w_ptr);
}
/**
* Increment given index associated with notification queue.
*
* @param[inout] p_ptr Pointer to the index to increment.
*/
static void ntf_queue_ptr_increment(uint8_t * p_ptr)
{
queue_ptr_increment(p_ptr, NTF_QUEUE_SIZE);
}
/**
* Check if notification queue is full.
*
* @retval true Notification queue is full.
* @retval false Notification queue is not full.
*/
static bool ntf_queue_is_full(void)
{
return queue_is_full(m_ntf_r_ptr, m_ntf_w_ptr, NTF_QUEUE_SIZE);
}
/**
* Check if notification queue is empty.
*
* @retval true Notification queue is empty.
* @retval false Notification queue is not empty.
*/
static bool ntf_queue_is_empty(void)
{
return queue_is_empty(m_ntf_r_ptr, m_ntf_w_ptr);
}
/**
* Increment given index associated with request queue.
*
* @param[inout] p_ptr Pointer to the index to increment.
*/
static void req_queue_ptr_increment(uint8_t * p_ptr)
{
queue_ptr_increment(p_ptr, REQ_QUEUE_SIZE);
}
/**
* Check if request queue is full.
*
* @retval true Request queue is full.
* @retval false Request queue is not full.
*/
static bool req_queue_is_full(void)
{
return queue_is_full(m_req_r_ptr, m_req_w_ptr, REQ_QUEUE_SIZE);
}
/**
* Check if request queue is empty.
*
* @retval true Request queue is empty.
* @retval false Request queue is not empty.
*/
static bool req_queue_is_empty(void)
{
return queue_is_empty(m_req_r_ptr, m_req_w_ptr);
@@ -331,6 +404,7 @@ void nrf_drv_radio802154_swi_receive(uint8_t channel, bool * p_result)
void nrf_drv_radio802154_swi_transmit(const uint8_t * p_data,
uint8_t channel,
int8_t power,
bool cca,
bool * p_result)
{
nrf_drv_radio802154_critical_section_enter();
@@ -342,6 +416,7 @@ void nrf_drv_radio802154_swi_transmit(const uint8_t * p_data,
p_slot->data.transmit.p_data = p_data;
p_slot->data.transmit.channel = channel;
p_slot->data.transmit.power = power;
p_slot->data.transmit.cca = cca;
p_slot->data.transmit.p_result = p_result;
req_queue_ptr_increment(&m_req_w_ptr);
@@ -454,7 +529,8 @@ void SWI_IRQHandler(void)
*(p_slot->data.transmit.p_result) = nrf_drv_radio802154_fsm_transmit(
p_slot->data.transmit.p_data,
p_slot->data.transmit.channel,
p_slot->data.transmit.power);
p_slot->data.transmit.power,
p_slot->data.transmit.cca);
break;
case REQ_TYPE_ENERGY_DETECTION:
@@ -108,11 +108,13 @@ void nrf_drv_radio802154_swi_receive(uint8_t channel, bool * p_result);
* @param[in] p_data Pointer to PSDU of the frame to transmit.
* @param[in] channel Channel number used for requested transmission.
* @param[in] power Transmitter power for requested transmission.
* @param[in] cca If the driver should perform CCA procedure before transmission.
* @param[out] p_result Result of entering transmit state.
*/
void nrf_drv_radio802154_swi_transmit(const uint8_t * p_data,
uint8_t channel,
int8_t power,
bool cca,
bool * p_result);
/**
@@ -128,6 +128,12 @@ static inline uint32_t timer_time_get(void)
return NRF_TIMER0->CC[TIMER_CC_CAPTURE];
}
/**@brief Check if margin is already reached. */
static inline bool timer_is_margin_reached(void)
{
return NRF_TIMER0->EVENTS_COMPARE[TIMER_CC_MARGIN];
}
/**@brief Enter timeslot critical section. */
static inline void timeslot_critical_section_enter(void)
{
@@ -438,28 +444,38 @@ static nrf_radio_signal_callback_return_param_t *signal_handler(uint8_t signal_t
case NRF_RADIO_CALLBACK_SIGNAL_TYPE_RADIO: /**< This signal indicates the NRF_RADIO interrupt. */
nrf_drv_radio802154_pin_set(PIN_DBG_TIMESLOT_RADIO_IRQ);
nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_RADIO);
if (m_in_timeslot && !NRF_TIMER0->EVENTS_COMPARE[TIMER_CC_MARGIN])
if (m_in_timeslot)
{
RADIO_IRQHandler();
}
else
{
NVIC_ClearPendingIRQ(RADIO_IRQn);
if (!timer_is_margin_reached())
{
RADIO_IRQHandler();
}
else
{
// Handle margin exceeded event.
timer_irq_handle();
}
}
nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_EVENT_RADIO);
nrf_drv_radio802154_pin_clr(PIN_DBG_TIMESLOT_RADIO_IRQ);
break;
case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_FAILED: /**< This signal indicates extend action failed. */
nrf_drv_radio802154_pin_clr(PIN_DBG_TIMESLOT_EXTEND_REQ);
nrf_drv_radio802154_pin_tgl(PIN_DBG_TIMESLOT_FAILED);
nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_EXCEED_FAIL);
timeslot_extend();
nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_EVENT_EXCEED_FAIL);
break;
case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_SUCCEEDED: /**< This signal indicates extend action succeeded. */
nrf_drv_radio802154_pin_clr(PIN_DBG_TIMESLOT_EXTEND_REQ);
nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_EXCEED_SUCCESS);
timer_extend();
@@ -467,7 +483,8 @@ static nrf_radio_signal_callback_return_param_t *signal_handler(uint8_t signal_t
{
timeslot_extend();
}
nrf_drv_radio802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_EVENT_EXCEED_SUCCESS);
break;
default: