[nrf52840] update nRF802154-radio-driver (#2268)

This commit is contained in:
Łukasz Duda
2017-10-17 09:55:31 -07:00
committed by Jonathan Hui
parent 7950203691
commit db91ff13c5
8 changed files with 91 additions and 126 deletions
-7
View File
@@ -90,13 +90,6 @@ SECTIONS
__etext = .;
nrf_radio_buffer (NOLOAD):
{
__nrf_radio_buffer_start__ = .;
*(nrf_radio_buffer*)
__nrf_radio_buffer_end__ = .;
} > RAM
.data : AT (__etext)
{
__data_start__ = .;
-11
View File
@@ -73,19 +73,8 @@ static bool sDisabled;
static otError sReceiveError = OT_ERROR_NONE;
static otRadioFrame sReceivedFrames[RADIO_RX_BUFFERS];
static otRadioFrame sTransmitFrame;
#if defined ( __GNUC__ )
static uint8_t sTransmitPsdu[OT_RADIO_FRAME_MAX_SIZE + 1]
__attribute__((section("nrf_radio_buffer.sTransmiPsdu")));
#elif defined ( __ICCARM__ )
#pragma location="NRF_RADIO_BUFFER"
static uint8_t sTransmitPsdu[OT_RADIO_FRAME_MAX_SIZE + 1];
#endif
static otRadioFrame sAckFrame;
static int8_t sDefaultTxPower;
@@ -238,18 +238,8 @@ bool nrf_drv_radio802154_transmit_raw(const uint8_t * p_data, bool cca)
bool nrf_drv_radio802154_transmit(const uint8_t * p_data, uint8_t length, bool cca)
{
#if defined ( __GNUC__ )
static uint8_t tx_buffer[RAW_PAYLOAD_OFFSET + MAX_PACKET_SIZE]
__attribute__ ((section ("nrf_radio_buffer.tx_buffer")));
#elif defined ( __ICCARM__ )
#pragma location="NRF_RADIO_BUFFER"
static uint8_t tx_buffer[RAW_PAYLOAD_OFFSET + MAX_PACKET_SIZE];
#endif
assert(length <= MAX_PACKET_SIZE - FCS_SIZE);
tx_buffer[RAW_LENGTH_OFFSET] = length + FCS_SIZE;
@@ -53,39 +53,36 @@ extern "C" {
/**
* @brief States of the driver.
*/
typedef enum
{
NRF_DRV_RADIO802154_STATE_INVALID,
NRF_DRV_RADIO802154_STATE_SLEEP,
NRF_DRV_RADIO802154_STATE_RECEIVE,
NRF_DRV_RADIO802154_STATE_TRANSMIT,
NRF_DRV_RADIO802154_STATE_ENERGY_DETECTION,
NRF_DRV_RADIO802154_STATE_CCA,
NRF_DRV_RADIO802154_STATE_CONTINUOUS_CARRIER,
} nrf_drv_radio802154_state_t;
typedef uint8_t nrf_drv_radio802154_state_t;
#define NRF_DRV_RADIO802154_STATE_INVALID 0x01 /**< Radio in an invalid state. */
#define NRF_DRV_RADIO802154_STATE_SLEEP 0x02 /**< Radio in Sleep state. */
#define NRF_DRV_RADIO802154_STATE_RECEIVE 0x03 /**< Radio in Receive state. */
#define NRF_DRV_RADIO802154_STATE_TRANSMIT 0x04 /**< Radio in Transmit state. */
#define NRF_DRV_RADIO802154_STATE_ENERGY_DETECTION 0x05 /**< Radio in Energy Detection state. */
#define NRF_DRV_RADIO802154_STATE_CCA 0x06 /**< Radio in CCA state. */
#define NRF_DRV_RADIO802154_STATE_CONTINUOUS_CARRIER 0x07 /**< Radio in Continuous Carrier state. */
/**
* Errors reported during frame transmission.
* @brief Errors reported during frame transmission.
*/
typedef enum
{
NRF_DRV_RADIO802154_TX_ERROR_BUSY_CHANNEL, /**< CCA reported busy channel prior to transmission. */
NRF_DRV_RADIO802154_TX_ERROR_INVALID_ACK, /**< Received ACK frame is other than expected. */
NRF_DRV_RADIO802154_TX_ERROR_NO_MEM, /**< No receive buffer are available to receive an ACK. */
NRF_DRV_RADIO802154_TX_ERROR_TIMESLOT_ENDED, /**< Radio timeslot ended during transmission procedure. */
} nrf_drv_radio802154_tx_error_t;
typedef uint8_t nrf_drv_radio802154_tx_error_t;
#define NRF_DRV_RADIO802154_TX_ERROR_BUSY_CHANNEL 0x01 /**< CCA reported busy channel prior to transmission. */
#define NRF_DRV_RADIO802154_TX_ERROR_INVALID_ACK 0x02 /**< Received ACK frame is other than expected. */
#define NRF_DRV_RADIO802154_TX_ERROR_NO_MEM 0x03 /**< No receive buffer are available to receive an ACK. */
#define NRF_DRV_RADIO802154_TX_ERROR_TIMESLOT_ENDED 0x04 /**< Radio timeslot ended during transmission procedure. */
/**
* @brief Possible errors during frame reception.
*/
typedef enum
{
NRF_DRV_RADIO802154_RX_ERROR_INVALID_FRAME, /**< Received a malformed frame */
NRF_DRV_RADIO802154_RX_ERROR_INVALID_FCS, /**< Received a frame with invalid checksum. */
NRF_DRV_RADIO802154_RX_ERROR_INVALID_DEST_ADDR, /**< Received a frame with mismatched destination address. */
NRF_DRV_RADIO802154_RX_ERROR_RUNTIME, /**< A runtime error occured (e.g. CPU was hold for too long.) */
NRF_DRV_RADIO802154_RX_ERROR_TIMESLOT_ENDED, /**< Radio timeslot ended during frame reception. */
} nrf_drv_radio802154_rx_error_t;
typedef uint8_t nrf_drv_radio802154_rx_error_t;
#define NRF_DRV_RADIO802154_RX_ERROR_INVALID_FRAME 0x01 /**< Received a malformed frame */
#define NRF_DRV_RADIO802154_RX_ERROR_INVALID_FCS 0x02 /**< Received a frame with invalid checksum. */
#define NRF_DRV_RADIO802154_RX_ERROR_INVALID_DEST_ADDR 0x03 /**< Received a frame with mismatched destination address. */
#define NRF_DRV_RADIO802154_RX_ERROR_RUNTIME 0x04 /**< A runtime error occured (e.g. CPU was hold for too long.) */
#define NRF_DRV_RADIO802154_RX_ERROR_TIMESLOT_ENDED 0x05 /**< Radio timeslot ended during frame reception. */
/**
* @brief Structure for configuring CCA.
@@ -192,7 +192,7 @@ bool nrf_drv_radio802154_ack_pending_bit_should_be_set(const uint8_t * p_psdu)
if (0 == (p_psdu[PAN_ID_COMPR_OFFSET] & PAN_ID_COMPR_MASK))
{
p_src_addr += 2;
p_src_addr += PAN_ID_SIZE;
}
switch (p_psdu[SRC_ADDR_TYPE_OFFSET] & SRC_ADDR_TYPE_MASK)
@@ -108,22 +108,10 @@ static rx_buffer_t * mp_current_rx_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.)
static uint8_t m_ack_psdu[ACK_LENGTH + 1]
__attribute__ ((section ("nrf_radio_buffer.m_ack_psdu")));
#elif defined ( __ICCARM__ )
#pragma location="NRF_RADIO_BUFFER"
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 uint8_t m_ack_psdu[ACK_LENGTH + 1]; ///< Ack frame buffer.
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
@@ -44,18 +44,7 @@
#error Not enough rx buffers in the 802.15.4 radio driver.
#endif
#if defined ( __GNUC__ )
/// 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")));
#elif defined ( __ICCARM__ )
#pragma location="NRF_RADIO_BUFFER"
static rx_buffer_t nrf_drv_radio802154_rx_buffers[RADIO_RX_BUFFERS];
#endif
rx_buffer_t nrf_drv_radio802154_rx_buffers[RADIO_RX_BUFFERS]; ///< Receive buffers.
void nrf_drv_radio802154_rx_buffer_init(void)
{
@@ -45,25 +45,32 @@
#include <nrf_raal_api.h>
#include <nrf_drv_radio802154.h>
#include <nrf_drv_radio802154_debug.h>
#include <hal/nrf_timer.h>
#include <nrf_drv_clock.h>
#include <softdevice.h>
/**@brief Enable Request and End on timeslot safety interrupt. */
#define ENABLE_REQUEST_AND_END_ON_TIMESLOT_END 0
/**@brief RAAL Timer instance. */
#define RAAL_TIMER NRF_TIMER0
/**@brief RAAL Timer interrupt number. */
#define RAAL_TIMER_IRQn TIMER0_IRQn
/**@brief Maximum jitter relative to the start time of START and TIMER0 (safety margin) events . */
#define TIMER_TO_SIGNAL_JITTER_US NRF_RADIO_START_JITTER_US + 6
/**@brief Timer compare channel definitions. */
#define TIMER_CC_EXTEND 0
#define TIMER_CC_EXTEND_INTENSET TIMER_INTENSET_COMPARE0_Msk
#define TIMER_CC_EXTEND_INTENCLR TIMER_INTENCLR_COMPARE0_Pos
#define TIMER_CC_EXTEND NRF_TIMER_CC_CHANNEL0
#define TIMER_CC_EXTEND_EVENT NRF_TIMER_EVENT_COMPARE0
#define TIMER_CC_EXTEND_INT NRF_TIMER_INT_COMPARE0_MASK
#define TIMER_CC_MARGIN 1
#define TIMER_CC_MARGIN_INTENSET TIMER_INTENSET_COMPARE1_Msk
#define TIMER_CC_MARGIN_INTENCLR TIMER_INTENCLR_COMPARE1_Pos
#define TIMER_CC_MARGIN NRF_TIMER_CC_CHANNEL1
#define TIMER_CC_MARGIN_EVENT NRF_TIMER_EVENT_COMPARE1
#define TIMER_CC_MARGIN_INT NRF_TIMER_INT_COMPARE1_MASK
#define TIMER_CC_CAPTURE 2
#define TIMER_CC_CAPTURE NRF_TIMER_CC_CHANNEL2
/**@brief Defines number of microseconds in one second. */
#define US_PER_S 1000000
@@ -122,20 +129,20 @@ static inline void timeslot_data_init(void)
/**@brief Get actual time. */
static inline uint32_t timer_time_get(void)
{
NRF_TIMER0->TASKS_CAPTURE[TIMER_CC_CAPTURE] = 1;
return NRF_TIMER0->CC[TIMER_CC_CAPTURE];
RAAL_TIMER->TASKS_CAPTURE[TIMER_CC_CAPTURE] = 1;
return RAAL_TIMER->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];
return RAAL_TIMER->EVENTS_COMPARE[TIMER_CC_MARGIN];
}
/**@brief Enter timeslot critical section. */
static inline void timeslot_critical_section_enter(void)
{
NVIC_DisableIRQ(TIMER0_IRQn);
NVIC_DisableIRQ(RAAL_TIMER_IRQn);
__DSB();
__ISB();
}
@@ -143,7 +150,7 @@ static inline void timeslot_critical_section_enter(void)
/**@brief Exit timeslot critical section. */
static inline void timeslot_critical_section_exit(void)
{
NVIC_EnableIRQ(TIMER0_IRQn);
NVIC_EnableIRQ(RAAL_TIMER_IRQn);
}
static inline void timeslot_started_notify(void)
@@ -191,38 +198,42 @@ static void timeslot_request(void)
/**@brief Set timer on timeslot started. */
static void timer_start(void)
{
NRF_TIMER0->TASKS_STOP = 1;
NRF_TIMER0->TASKS_CLEAR = 1;
NRF_TIMER0->BITMODE = TIMER_BITMODE_BITMODE_32Bit;
NRF_TIMER0->INTENSET = TIMER_CC_MARGIN_INTENSET;
NRF_TIMER0->CC[TIMER_CC_EXTEND] = 0;
NRF_TIMER0->CC[TIMER_CC_MARGIN] = m_timeslot_length - m_config.timeslot_safe_margin;
NRF_TIMER0->TASKS_START = 1;
nrf_timer_task_trigger(RAAL_TIMER, NRF_TIMER_TASK_STOP);
nrf_timer_task_trigger(RAAL_TIMER, NRF_TIMER_TASK_CLEAR);
nrf_timer_bit_width_set(RAAL_TIMER, NRF_TIMER_BIT_WIDTH_32);
nrf_timer_int_enable(RAAL_TIMER, TIMER_CC_MARGIN_INT);
nrf_timer_cc_write(RAAL_TIMER, TIMER_CC_EXTEND, 0);
nrf_timer_cc_write(RAAL_TIMER, TIMER_CC_MARGIN, m_timeslot_length - m_config.timeslot_safe_margin);
nrf_timer_task_trigger(RAAL_TIMER, NRF_TIMER_TASK_START);
NVIC_EnableIRQ(TIMER0_IRQn);
NVIC_EnableIRQ(RAAL_TIMER_IRQn);
}
/**@brief Reset timer. */
static void timer_reset(void)
{
NRF_TIMER0->TASKS_STOP = 1;
NRF_TIMER0->EVENTS_COMPARE[TIMER_CC_EXTEND] = 0;
NRF_TIMER0->EVENTS_COMPARE[TIMER_CC_MARGIN] = 0;
NVIC_ClearPendingIRQ(TIMER0_IRQn);
nrf_timer_task_trigger(RAAL_TIMER, NRF_TIMER_TASK_STOP);
nrf_timer_event_clear(RAAL_TIMER, TIMER_CC_EXTEND_EVENT);
nrf_timer_event_clear(RAAL_TIMER, TIMER_CC_MARGIN_EVENT);
NVIC_ClearPendingIRQ(RAAL_TIMER_IRQn);
}
/**@brief Set timer on extend event. */
static void timer_extend(void)
{
NVIC_ClearPendingIRQ(TIMER0_IRQn);
NVIC_ClearPendingIRQ(RAAL_TIMER_IRQn);
NRF_TIMER0->INTENSET = TIMER_CC_MARGIN_INTENSET;
NRF_TIMER0->CC[TIMER_CC_MARGIN] += m_timeslot_length;
nrf_timer_int_enable(RAAL_TIMER, TIMER_CC_MARGIN_INT);
nrf_timer_cc_write(RAAL_TIMER,
TIMER_CC_MARGIN,
nrf_timer_cc_read(RAAL_TIMER, TIMER_CC_MARGIN) + m_timeslot_length);
if (!m_alloc_iters)
{
NRF_TIMER0->INTENSET = TIMER_CC_EXTEND_INTENSET;
NRF_TIMER0->CC[TIMER_CC_EXTEND] += m_timeslot_length;
nrf_timer_int_enable(RAAL_TIMER, TIMER_CC_EXTEND_INT);
nrf_timer_cc_write(RAAL_TIMER,
TIMER_CC_EXTEND,
nrf_timer_cc_read(RAAL_TIMER, TIMER_CC_EXTEND) + m_timeslot_length);
}
}
@@ -248,21 +259,28 @@ static void timer_jitter_adjust(void)
rtc_ticks = DIVIDE_AND_CEIL((rtc_ticks * US_PER_S), 32768);
// Check if we are still in time.
uint32_t cc_margin = NRF_TIMER0->CC[TIMER_CC_MARGIN];
uint32_t cc_margin = nrf_timer_cc_read(RAAL_TIMER, TIMER_CC_MARGIN);
assert(cc_margin > rtc_ticks + rtc_drift_calculate(cc_margin));
if (rtc_ticks > timer_ticks)
{
NRF_TIMER0->CC[TIMER_CC_MARGIN] -= (rtc_ticks - timer_ticks);
nrf_timer_cc_write(RAAL_TIMER,
TIMER_CC_MARGIN,
cc_margin - (rtc_ticks - timer_ticks));
}
else
{
NRF_TIMER0->CC[TIMER_CC_MARGIN] += (timer_ticks - rtc_ticks);
nrf_timer_cc_write(RAAL_TIMER,
TIMER_CC_MARGIN,
cc_margin + (rtc_ticks - timer_ticks));
}
// Add safety drift time.
NRF_TIMER0->CC[TIMER_CC_MARGIN] -= rtc_drift_calculate(2 * m_config.timeslot_length) +
TIMER_TO_SIGNAL_JITTER_US;
uint32_t safety_drift_time = rtc_drift_calculate(2 * m_config.timeslot_length) +
TIMER_TO_SIGNAL_JITTER_US;
nrf_timer_cc_write(RAAL_TIMER,
TIMER_CC_MARGIN,
nrf_timer_cc_read(RAAL_TIMER, TIMER_CC_MARGIN) - safety_drift_time);
}
/**@brief Decrease timeslot length. */
@@ -294,7 +312,7 @@ static void timeslot_extend(void)
static void timer_irq_handle(void)
{
// Safe margin exceeded.
if (NRF_TIMER0->EVENTS_COMPARE[TIMER_CC_MARGIN])
if (RAAL_TIMER->EVENTS_COMPARE[TIMER_CC_MARGIN])
{
nrf_drv_radio802154_pin_clr(PIN_DBG_TIMESLOT_ACTIVE);
nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_MARGIN);
@@ -336,15 +354,16 @@ static void timer_irq_handle(void)
}
// Extension margin exceeded.
else if (NRF_TIMER0->EVENTS_COMPARE[TIMER_CC_EXTEND])
else if (RAAL_TIMER->EVENTS_COMPARE[TIMER_CC_EXTEND])
{
nrf_drv_radio802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_EXTEND);
NRF_TIMER0->INTENCLR = (1 << TIMER_CC_EXTEND_INTENCLR);
NRF_TIMER0->EVENTS_COMPARE[TIMER_CC_EXTEND] = 0;
nrf_timer_int_disable(RAAL_TIMER, TIMER_CC_EXTEND_INT);
nrf_timer_event_clear(RAAL_TIMER, TIMER_CC_EXTEND_EVENT);
if (m_continuous &&
NRF_TIMER0->CC[TIMER_CC_EXTEND] + m_config.timeslot_length < m_config.timeslot_max_length)
(nrf_timer_cc_read(RAAL_TIMER, TIMER_CC_EXTEND) +
m_config.timeslot_length < m_config.timeslot_max_length))
{
nrf_drv_radio802154_pin_set(PIN_DBG_TIMESLOT_EXTEND_REQ);
@@ -436,7 +455,7 @@ static nrf_radio_signal_callback_return_param_t *signal_handler(uint8_t signal_t
break;
}
case NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0: /**< This signal indicates the NRF_TIMER0 interrupt. */
case NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0: /**< This signal indicates the TIMER0 interrupt. */
timer_irq_handle();
break;
@@ -621,7 +640,7 @@ void nrf_raal_continuous_mode_exit(void)
// Emulate signal interrupt to inform SD about end of m_continuous mode.
if (m_in_timeslot)
{
NVIC_SetPendingIRQ(TIMER0_IRQn);
NVIC_SetPendingIRQ(RAAL_TIMER_IRQn);
}
nrf_drv_clock_hfclk_release();
@@ -636,7 +655,7 @@ bool nrf_raal_timeslot_request(uint32_t length_us)
return false;
}
return timer_time_get() + length_us < NRF_TIMER0->CC[TIMER_CC_MARGIN];
return timer_time_get() + length_us < nrf_timer_cc_read(RAAL_TIMER, TIMER_CC_MARGIN);
}
uint32_t nrf_raal_timeslot_us_left_get(void)
@@ -646,7 +665,7 @@ uint32_t nrf_raal_timeslot_us_left_get(void)
return 0;
}
return NRF_TIMER0->CC[TIMER_CC_MARGIN] - timer_time_get();
return nrf_timer_cc_read(RAAL_TIMER, TIMER_CC_MARGIN) - timer_time_get();
}
void nrf_raal_critical_section_enter(void)