[nrf52840] update nRF52840 radio driver to version 1.2.3 (#3432)

This commit is contained in:
Kamil Sroka
2019-01-04 17:45:41 +01:00
committed by Jonathan Hui
parent 7554e344ce
commit 979b50522d
67 changed files with 2541 additions and 1919 deletions
+13 -9
View File
@@ -54,7 +54,8 @@ COMMONCPPFLAGS
-I$(top_srcdir)/third_party/NordicSemiconductor/drivers/common \
-I$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio \
-I$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/hal \
-I$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/raal \
-I$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/rsch \
-I$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/rsch/raal \
-I$(top_srcdir)/third_party/NordicSemiconductor/drivers/power \
-I$(top_srcdir)/third_party/NordicSemiconductor/drivers/systick \
-I$(top_srcdir)/third_party/NordicSemiconductor/drivers/usbd \
@@ -100,7 +101,7 @@ SINGLEPHY_SOURCES
@top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154_notification_direct.c \
@top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154_priority_drop_direct.c \
@top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154_request_direct.c \
@top_builddir@/third_party/NordicSemiconductor/drivers/radio/raal/single_phy/single_phy.c \
@top_builddir@/third_party/NordicSemiconductor/drivers/radio/rsch/raal/single_phy/single_phy.c \
$(NULL)
SINGLEPHY_CPPFLAGS = \
@@ -115,11 +116,11 @@ SOFTDEVICE_SOURCES
@top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154_priority_drop_swi.c \
@top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154_request_swi.c \
@top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154_swi.c \
@top_builddir@/third_party/NordicSemiconductor/drivers/radio/raal/softdevice/nrf_raal_softdevice.c \
@top_builddir@/third_party/NordicSemiconductor/drivers/radio/rsch/raal/softdevice/nrf_raal_softdevice.c \
$(NULL)
SOFTDEVICE_CPPFLAGS = \
-I$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/raal/softdevice \
-I$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/rsch/raal/softdevice \
-I$(top_srcdir)/third_party/NordicSemiconductor/softdevice/s140/headers \
-DSOFTDEVICE_PRESENT \
-DS140 \
@@ -149,7 +150,6 @@ RADIO_DRIVER_SOURCES
@top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154_debug.c \
@top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154_pib.c \
@top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154_revision.c \
@top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154_rsch.c \
@top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154_rssi.c \
@top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154_rx_buffer.c \
@top_builddir@/third_party/NordicSemiconductor/drivers/radio/nrf_802154_timer_coord.c \
@@ -160,6 +160,8 @@ RADIO_DRIVER_SOURCES
@top_builddir@/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_filter.c \
@top_builddir@/third_party/NordicSemiconductor/drivers/radio/platform/clock/nrf_802154_clock_sdk.c \
@top_builddir@/third_party/NordicSemiconductor/drivers/radio/platform/hp_timer/nrf_802154_hp_timer.c \
@top_builddir@/third_party/NordicSemiconductor/drivers/radio/rsch/nrf_802154_rsch.c \
@top_builddir@/third_party/NordicSemiconductor/drivers/radio/rsch/nrf_802154_rsch_crit_sect.c \
@top_builddir@/third_party/NordicSemiconductor/drivers/radio/timer_scheduler/nrf_802154_timer_sched.c \
$(NULL)
@@ -286,7 +288,6 @@ noinst_HEADERS
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_procedures_duration.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_request.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_revision.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_rsch.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_rssi.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_rx_buffer.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_timer_coord.h \
@@ -302,9 +303,12 @@ noinst_HEADERS
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/platform/temperature/nrf_802154_temperature.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/platform/hp_timer/nrf_802154_hp_timer.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/platform/lp_timer/nrf_802154_lp_timer.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/raal/nrf_raal_api.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/raal/nrf_raal_config.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/raal/softdevice/nrf_raal_softdevice.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/rsch/nrf_802154_rsch.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/rsch/nrf_802154_wifi_coex.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/rsch/nrf_802154_rsch_crit_sect.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/rsch/raal/nrf_raal_api.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/rsch/raal/nrf_raal_config.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/rsch/raal/softdevice/nrf_raal_softdevice.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/timer_scheduler/nrf_802154_timer_sched.h \
$(top_srcdir)/third_party/NordicSemiconductor/libraries/app_error/app_error_weak.h \
$(top_srcdir)/third_party/NordicSemiconductor/libraries/app_error/app_error.h \
@@ -40,10 +40,10 @@
/** @brief RAAL Softdevice default parameters. */
#define PLATFORM_SOFTDEVICE_RAAL_TIMESLOT_DEFAULT_LENGTH 6400
#define PLATFORM_SOFTDEVICE_RAAL_TIMESLOT_DEFAULT_ALLOC_ITERS 5
#define PLATFORM_SOFTDEVICE_RAAL_TIMESLOT_DEFAULT_SAFE_MARGIN 91
#define PLATFORM_SOFTDEVICE_RAAL_TIMESLOT_DEFAULT_SAFE_MARGIN 126
#define PLATFORM_SOFTDEVICE_RAAL_TIMESLOT_DEFAULT_TIMEOUT 6400
#define PLATFORM_SOFTDEVICE_RAAL_TIMESLOT_DEFAULT_MAX_LENGTH 120000000
#define PLATFORM_SOFTDEVICE_RAAL_DEFAULT_LF_CLK_ACCURACY_PPM 25
#define PLATFORM_SOFTDEVICE_RAAL_DEFAULT_LF_CLK_ACCURACY_PPM 500
/** @brief RAAL Softdevice configuration parameters. */
typedef struct
+1
View File
@@ -737,6 +737,7 @@ void nrf_802154_receive_failed(nrf_802154_rx_error_t error)
case NRF_802154_RX_ERROR_RUNTIME:
case NRF_802154_RX_ERROR_TIMESLOT_ENDED:
case NRF_802154_RX_ERROR_ABORTED:
case NRF_802154_RX_ERROR_INVALID_LENGTH:
sReceiveError = OT_ERROR_FAILED;
break;
@@ -52,7 +52,7 @@
#if ENABLE_FEM
static nrf_fem_control_cfg_t m_nrf_fem_control_cfg; /**< FEM controller configuration. */
static nrf_fem_control_cfg_t m_nrf_fem_control_cfg; /**< FEM controller configuration. */
/** Check whether pin is valid and enabled. */
static bool pin_is_enabled(nrf_fem_control_pin_t pin)
@@ -102,14 +102,14 @@ static void gpiote_configure(void)
nrf_gpiote_task_configure(m_nrf_fem_control_cfg.lna_gpiote_ch_id,
m_nrf_fem_control_cfg.lna_cfg.gpio_pin,
(nrf_gpiote_polarity_t)GPIOTE_CONFIG_POLARITY_None,
(nrf_gpiote_outinit_t)!m_nrf_fem_control_cfg.lna_cfg.active_high);
(nrf_gpiote_outinit_t) !m_nrf_fem_control_cfg.lna_cfg.active_high);
nrf_gpiote_task_enable(m_nrf_fem_control_cfg.lna_gpiote_ch_id);
nrf_gpiote_task_configure(m_nrf_fem_control_cfg.pa_gpiote_ch_id,
m_nrf_fem_control_cfg.pa_cfg.gpio_pin,
(nrf_gpiote_polarity_t)GPIOTE_CONFIG_POLARITY_None,
(nrf_gpiote_outinit_t)!m_nrf_fem_control_cfg.pa_cfg.active_high);
(nrf_gpiote_outinit_t) !m_nrf_fem_control_cfg.pa_cfg.active_high);
nrf_gpiote_task_enable(m_nrf_fem_control_cfg.pa_gpiote_ch_id);
}
@@ -125,12 +125,12 @@ static void ppi_init(void)
nrf_ppi_channel_and_fork_endpoint_setup(
(nrf_ppi_channel_t)m_nrf_fem_control_cfg.ppi_ch_id_clr,
(uint32_t)(&NRF_RADIO->EVENTS_DISABLED),
(m_nrf_fem_control_cfg.lna_cfg.active_high ?
(uint32_t)(&NRF_GPIOTE->TASKS_CLR[m_nrf_fem_control_cfg.lna_gpiote_ch_id]) :
(uint32_t)(&NRF_GPIOTE->TASKS_SET[m_nrf_fem_control_cfg.lna_gpiote_ch_id])),
(m_nrf_fem_control_cfg.pa_cfg.active_high ?
(uint32_t)(&NRF_GPIOTE->TASKS_CLR[m_nrf_fem_control_cfg.pa_gpiote_ch_id]) :
(uint32_t)(&NRF_GPIOTE->TASKS_SET[m_nrf_fem_control_cfg.pa_gpiote_ch_id])));
(m_nrf_fem_control_cfg.lna_cfg.active_high ?
(uint32_t)(&NRF_GPIOTE->TASKS_CLR[m_nrf_fem_control_cfg.lna_gpiote_ch_id]) :
(uint32_t)(&NRF_GPIOTE->TASKS_SET[m_nrf_fem_control_cfg.lna_gpiote_ch_id])),
(m_nrf_fem_control_cfg.pa_cfg.active_high ?
(uint32_t)(&NRF_GPIOTE->TASKS_CLR[m_nrf_fem_control_cfg.pa_gpiote_ch_id]) :
(uint32_t)(&NRF_GPIOTE->TASKS_SET[m_nrf_fem_control_cfg.pa_gpiote_ch_id])));
}
/** Setup PPI to set LNA pin on a timer event. */
@@ -141,8 +141,8 @@ static void ppi_lna_enable_setup(nrf_timer_cc_channel_t timer_cc_channel)
(nrf_ppi_channel_t)m_nrf_fem_control_cfg.ppi_ch_id_set,
(uint32_t)(&NRF_FEM_TIMER_INSTANCE->EVENTS_COMPARE[timer_cc_channel]),
(m_nrf_fem_control_cfg.lna_cfg.active_high ?
(uint32_t)(&NRF_GPIOTE->TASKS_SET[m_nrf_fem_control_cfg.lna_gpiote_ch_id]) :
(uint32_t)(&NRF_GPIOTE->TASKS_CLR[m_nrf_fem_control_cfg.lna_gpiote_ch_id])));
(uint32_t)(&NRF_GPIOTE->TASKS_SET[m_nrf_fem_control_cfg.lna_gpiote_ch_id]) :
(uint32_t)(&NRF_GPIOTE->TASKS_CLR[m_nrf_fem_control_cfg.lna_gpiote_ch_id])));
}
/** Setup PPI to set PA pin on a timer event. */
@@ -153,8 +153,8 @@ static void ppi_pa_enable_setup(nrf_timer_cc_channel_t timer_cc_channel)
(nrf_ppi_channel_t)m_nrf_fem_control_cfg.ppi_ch_id_set,
(uint32_t)(&NRF_FEM_TIMER_INSTANCE->EVENTS_COMPARE[timer_cc_channel]),
(m_nrf_fem_control_cfg.pa_cfg.active_high ?
(uint32_t)(&NRF_GPIOTE->TASKS_SET[m_nrf_fem_control_cfg.pa_gpiote_ch_id]) :
(uint32_t)(&NRF_GPIOTE->TASKS_CLR[m_nrf_fem_control_cfg.pa_gpiote_ch_id])));
(uint32_t)(&NRF_GPIOTE->TASKS_SET[m_nrf_fem_control_cfg.pa_gpiote_ch_id]) :
(uint32_t)(&NRF_GPIOTE->TASKS_CLR[m_nrf_fem_control_cfg.pa_gpiote_ch_id])));
}
/**
@@ -258,23 +258,24 @@ void nrf_fem_control_pin_clear(void)
if (pin_is_enabled(NRF_FEM_CONTROL_PA_PIN))
{
nrf_gpiote_task_force(m_nrf_fem_control_cfg.pa_gpiote_ch_id,
(nrf_gpiote_outinit_t)!m_nrf_fem_control_cfg.pa_cfg.active_high);
(nrf_gpiote_outinit_t) !m_nrf_fem_control_cfg.pa_cfg.active_high);
}
if (pin_is_enabled(NRF_FEM_CONTROL_LNA_PIN))
{
nrf_gpiote_task_force(m_nrf_fem_control_cfg.lna_gpiote_ch_id,
(nrf_gpiote_outinit_t)!m_nrf_fem_control_cfg.lna_cfg.active_high);
(nrf_gpiote_outinit_t) !m_nrf_fem_control_cfg.lna_cfg.active_high);
}
}
void nrf_fem_control_timer_set(nrf_fem_control_pin_t pin,
void nrf_fem_control_timer_set(nrf_fem_control_pin_t pin,
nrf_timer_cc_channel_t timer_cc_channel,
nrf_timer_short_mask_t short_mask)
{
if (pin_is_enabled(pin))
{
uint32_t target_time = nrf_fem_control_delay_get(pin);
nrf_timer_shorts_enable(NRF_FEM_TIMER_INSTANCE, short_mask);
nrf_timer_cc_write(NRF_FEM_TIMER_INSTANCE, timer_cc_channel, target_time);
}
@@ -333,11 +334,13 @@ void nrf_fem_control_ppi_pin_task_setup(nrf_ppi_channel_t ppi_channel,
if ((lna_pin_set && m_nrf_fem_control_cfg.lna_cfg.active_high) ||
(!lna_pin_set && !m_nrf_fem_control_cfg.lna_cfg.active_high))
{
lna_task_addr = (uint32_t)(&NRF_GPIOTE->TASKS_SET[m_nrf_fem_control_cfg.lna_gpiote_ch_id]);
lna_task_addr =
(uint32_t)(&NRF_GPIOTE->TASKS_SET[m_nrf_fem_control_cfg.lna_gpiote_ch_id]);
}
else
{
lna_task_addr = (uint32_t)(&NRF_GPIOTE->TASKS_CLR[m_nrf_fem_control_cfg.lna_gpiote_ch_id]);
lna_task_addr =
(uint32_t)(&NRF_GPIOTE->TASKS_CLR[m_nrf_fem_control_cfg.lna_gpiote_ch_id]);
}
}
@@ -346,17 +349,20 @@ void nrf_fem_control_ppi_pin_task_setup(nrf_ppi_channel_t ppi_channel,
if ((pa_pin_set && m_nrf_fem_control_cfg.pa_cfg.active_high) ||
(!pa_pin_set && !m_nrf_fem_control_cfg.pa_cfg.active_high))
{
pa_task_addr = (uint32_t)(&NRF_GPIOTE->TASKS_SET[m_nrf_fem_control_cfg.pa_gpiote_ch_id]);
pa_task_addr =
(uint32_t)(&NRF_GPIOTE->TASKS_SET[m_nrf_fem_control_cfg.pa_gpiote_ch_id]);
}
else
{
pa_task_addr = (uint32_t)(&NRF_GPIOTE->TASKS_CLR[m_nrf_fem_control_cfg.pa_gpiote_ch_id]);
pa_task_addr =
(uint32_t)(&NRF_GPIOTE->TASKS_CLR[m_nrf_fem_control_cfg.pa_gpiote_ch_id]);
}
}
if (lna_task_addr != 0 || pa_task_addr != 0)
{
nrf_ppi_channel_and_fork_endpoint_setup(ppi_channel, event_addr, lna_task_addr, pa_task_addr);
nrf_ppi_channel_and_fork_endpoint_setup(ppi_channel, event_addr, lna_task_addr,
pa_task_addr);
nrf_ppi_channel_enable(ppi_channel);
}
}
@@ -51,22 +51,22 @@ extern "C" {
*/
/** Default Power Amplifier pin. */
#define NRF_FEM_CONTROL_DEFAULT_PA_PIN 26
#define NRF_FEM_CONTROL_DEFAULT_PA_PIN 15
/** Default Low Noise Amplifier pin. */
#define NRF_FEM_CONTROL_DEFAULT_LNA_PIN 27
#define NRF_FEM_CONTROL_DEFAULT_LNA_PIN 16
/** Default PPI channel for pin setting. */
#define NRF_FEM_CONTROL_DEFAULT_SET_PPI_CHANNEL 15
#define NRF_FEM_CONTROL_DEFAULT_SET_PPI_CHANNEL 15
/** Default PPI channel for pin clearing. */
#define NRF_FEM_CONTROL_DEFAULT_CLR_PPI_CHANNEL 16
#define NRF_FEM_CONTROL_DEFAULT_CLR_PPI_CHANNEL 16
/** Default GPIOTE channel for FEM control. */
#define NRF_FEM_CONTROL_DEFAULT_LNA_GPIOTE_CHANNEL 6
#define NRF_FEM_CONTROL_DEFAULT_LNA_GPIOTE_CHANNEL 6
/** Default GPIOTE channel for FEM control. */
#define NRF_FEM_CONTROL_DEFAULT_PA_GPIOTE_CHANNEL 7
#define NRF_FEM_CONTROL_DEFAULT_PA_GPIOTE_CHANNEL 7
#if ENABLE_FEM
@@ -75,9 +75,9 @@ extern "C" {
*/
typedef struct
{
uint8_t enable :1; /**< Enable toggling for this amplifier */
uint8_t active_high :1; /**< Set the pin to be active high */
uint8_t gpio_pin :6; /**< The GPIO pin to toggle for this amplifier */
uint8_t enable : 1; /**< Enable toggling for this amplifier */
uint8_t active_high : 1; /**< Set the pin to be active high */
uint8_t gpio_pin : 6; /**< The GPIO pin to toggle for this amplifier */
} nrf_fem_control_pa_lna_cfg_t;
/**
@@ -94,12 +94,12 @@ typedef struct
*/
typedef struct
{
nrf_fem_control_pa_lna_cfg_t pa_cfg; /**< Power Amplifier configuration */
nrf_fem_control_pa_lna_cfg_t lna_cfg; /**< Low Noise Amplifier configuration */
uint8_t pa_gpiote_ch_id; /**< GPIOTE channel used for Power Amplifier pin toggling */
uint8_t lna_gpiote_ch_id; /**< GPIOTE channel used for Low Noise Amplifier pin toggling */
uint8_t ppi_ch_id_set; /**< PPI channel used for radio Power Amplifier and Low Noise Amplifier pins setting */
uint8_t ppi_ch_id_clr; /**< PPI channel used for radio pin clearing */
nrf_fem_control_pa_lna_cfg_t pa_cfg; /**< Power Amplifier configuration */
nrf_fem_control_pa_lna_cfg_t lna_cfg; /**< Low Noise Amplifier configuration */
uint8_t pa_gpiote_ch_id; /**< GPIOTE channel used for Power Amplifier pin toggling */
uint8_t lna_gpiote_ch_id; /**< GPIOTE channel used for Low Noise Amplifier pin toggling */
uint8_t ppi_ch_id_set; /**< PPI channel used for radio Power Amplifier and Low Noise Amplifier pins setting */
uint8_t ppi_ch_id_clr; /**< PPI channel used for radio pin clearing */
} nrf_fem_control_cfg_t;
/**
@@ -141,7 +141,7 @@ void nrf_fem_control_activate(void);
void nrf_fem_control_deactivate(void);
/**@brief Configure PPI to activate one of the Front End Module pins on an appropriate timer event.
*
*
* @param[in] pin The Front End Module controlled pin to be connected to the PPI.
* @param[in] timer_cc_channel Timer CC channel that triggers the @p pin activation through the PPI.
*
@@ -156,9 +156,9 @@ void nrf_fem_control_ppi_enable(nrf_fem_control_pin_t pin, nrf_timer_cc_channel_
void nrf_fem_control_ppi_disable(nrf_fem_control_pin_t pin);
/**@brief Calculate target time for a timer, which activates one of the Front End Module pins.
*
*
* @param[in] pin The Front End Module controlled pin to be activated.
*
*
* @return @p pin activation delay in microseconds.
*
*/
@@ -170,7 +170,7 @@ uint32_t nrf_fem_control_delay_get(nrf_fem_control_pin_t pin);
void nrf_fem_control_pin_clear(void);
/**@brief Configure and set a timer for one of the Front End Module pins activation.
*
*
* @param[in] pin The Front End Module controlled pin to be activated.
* @param[in] timer_cc_channel Timer CC channel to set.
* @param[in] short_mask Mask of timer shortcuts to be enabled.
@@ -181,7 +181,7 @@ void nrf_fem_control_timer_set(nrf_fem_control_pin_t pin,
nrf_timer_short_mask_t short_mask);
/**@brief Clear timer configuration after one of the Front End Module pins deactivation.
*
*
* @param[in] pin The Front End Module controlled pin that was deactivated.
* @param[in] short_mask Mask of timer shortcuts to be disabled.
*
@@ -189,7 +189,7 @@ void nrf_fem_control_timer_set(nrf_fem_control_pin_t pin,
void nrf_fem_control_timer_reset(nrf_fem_control_pin_t pin, nrf_timer_short_mask_t short_mask);
/**@brief Setup a PPI fork task necessary for one of the Front End Module pins.
*
*
* @param[in] pin The Front End Module controlled pin that was deactivated.
* @param[in] ppi_channel PPI channel to connect the fork task to.
*
@@ -199,7 +199,7 @@ void nrf_fem_control_ppi_fork_setup(nrf_fem_control_pin_t pin,
uint32_t task_addr);
/**@brief Setup a PPI task necessary for one of the Front End Module pins.
*
*
* @param[in] pin The Front End Module controlled pin that was deactivated.
* @param[in] ppi_channel PPI channel to connect the task to.
* @param[in] event_addr Address of the event to be connected to the PPI.
@@ -212,7 +212,7 @@ void nrf_fem_control_ppi_task_setup(nrf_fem_control_pin_t pin,
uint32_t task_addr);
/**@brief Clear a PPI fork task configuration for one of the Front End Module pins.
*
*
* @param[in] pin The Front End Module controlled pin that was deactivated.
* @param[in] ppi_channel PPI channel to disconnect the fork task from.
*
@@ -220,7 +220,7 @@ void nrf_fem_control_ppi_task_setup(nrf_fem_control_pin_t pin,
void nrf_fem_control_ppi_fork_clear(nrf_fem_control_pin_t pin, nrf_ppi_channel_t ppi_channel);
/**@brief Setup PPI task and fork that set or clear Front End Module pins on a given event.
*
*
* @param[in] ppi_channel PPI channel to connect the task and fork to.
* @param[in] event_addr Address of the event to be connected to the PPI.
* @param[in] lna_pin_set If true, the Low Noise Amplifier pin will be set on the event @p event_addr.
@@ -234,7 +234,7 @@ void nrf_fem_control_ppi_pin_task_setup(nrf_ppi_channel_t ppi_channel,
bool lna_pin_set,
bool pa_pin_set);
#else // ENABLE_FEM
#else // ENABLE_FEM
#define nrf_fem_control_cfg_set(...)
#define nrf_fem_control_cfg_get(...)
@@ -242,7 +242,7 @@ void nrf_fem_control_ppi_pin_task_setup(nrf_ppi_channel_t ppi_channel,
#define nrf_fem_control_deactivate(...)
#define nrf_fem_control_ppi_enable(...)
#define nrf_fem_control_ppi_disable(...)
#define nrf_fem_control_delay_get(...) 1
#define nrf_fem_control_delay_get(...) 1
#define nrf_fem_control_pin_clear(...)
#define nrf_fem_control_timer_set(...)
#define nrf_fem_control_timer_reset(...)
@@ -40,10 +40,10 @@ extern "C" {
*/
/** Time in us when PA GPIO is activated before radio is ready for transmission. */
#define NRF_FEM_PA_TIME_IN_ADVANCE 23
#define NRF_FEM_PA_TIME_IN_ADVANCE 23
/** Time in us when LNA GPIO is activated before radio is ready for reception. */
#define NRF_FEM_LNA_TIME_IN_ADVANCE 5
#define NRF_FEM_LNA_TIME_IN_ADVANCE 5
#ifdef NRF52840_XXAA
+35 -33
View File
@@ -57,7 +57,8 @@ extern "C" {
* @enum nrf_radio_task_t
* @brief RADIO tasks.
*/
typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */
/*lint -save -e30 -esym(628,__INTADDR__) */
typedef enum
{
NRF_RADIO_TASK_TXEN = offsetof(NRF_RADIO_Type, TASKS_TXEN), /**< Enable radio transmitter. */
NRF_RADIO_TASK_RXEN = offsetof(NRF_RADIO_Type, TASKS_RXEN), /**< Enable radio receiver. */
@@ -69,13 +70,13 @@ typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */
NRF_RADIO_TASK_EDSTART = offsetof(NRF_RADIO_Type, TASKS_EDSTART), /**< Start Energy Detection procedure. */
NRF_RADIO_TASK_EDSTOP = offsetof(NRF_RADIO_Type, TASKS_EDSTOP), /**< Stop Energy Detection procedure. */
NRF_RADIO_TASK_RSSISTART = offsetof(NRF_RADIO_Type, TASKS_RSSISTART), /**< Start the RSSI and take one single sample of received signal strength. */
} nrf_radio_task_t; /*lint -restore */
} nrf_radio_task_t;
/**
* @enum nrf_radio_event_t
* @brief RADIO events.
*/
typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */
typedef enum
{
NRF_RADIO_EVENT_READY = offsetof(NRF_RADIO_Type, EVENTS_READY), /**< Radio has ramped up and is ready to be started. */
NRF_RADIO_EVENT_ADDRESS = offsetof(NRF_RADIO_Type, EVENTS_ADDRESS), /**< Address sent or received. */
@@ -93,7 +94,8 @@ typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */
NRF_RADIO_EVENT_RXREADY = offsetof(NRF_RADIO_Type, EVENTS_RXREADY), /**< Radio has ramped up and is ready to be started RX path. */
NRF_RADIO_EVENT_MHRMATCH = offsetof(NRF_RADIO_Type, EVENTS_MHRMATCH), /**< MAC Header match found. */
NRF_RADIO_EVENT_PHYEND = offsetof(NRF_RADIO_Type, EVENTS_PHYEND), /**< Generated in Ble_LR125Kbit, Ble_LR500Kbit and Ieee802154_250Kbit modes when last bit is sent on air. */
} nrf_radio_event_t; /*lint -restore */
} nrf_radio_event_t;
/*lint -restore */
/**
* @enum nrf_radio_int_mask_t
@@ -222,8 +224,8 @@ typedef enum
*/
typedef enum
{
NRF_RADIO_RAMP_UP_MODE_DEFAULT = RADIO_MODECNF0_RU_Default, /**< Default ramp-up mode. */
NRF_RADIO_RAMP_UP_MODE_FAST = RADIO_MODECNF0_RU_Fast /**< Fast ramp-up mode. */
NRF_RADIO_RAMP_UP_MODE_DEFAULT = RADIO_MODECNF0_RU_Default, /**< Default ramp-up mode. */
NRF_RADIO_RAMP_UP_MODE_FAST = RADIO_MODECNF0_RU_Fast /**< Fast ramp-up mode. */
} nrf_radio_ramp_up_mode_t;
/**
@@ -257,7 +259,7 @@ __STATIC_INLINE bool nrf_radio_int_get(nrf_radio_int_mask_t radio_int_mask);
*
* @param[in] radio_task Task.
*/
__STATIC_INLINE uint32_t *nrf_radio_task_address_get(nrf_radio_task_t radio_task);
__STATIC_INLINE uint32_t * nrf_radio_task_address_get(nrf_radio_task_t radio_task);
/**
* @brief Function for setting a specific task.
@@ -273,7 +275,7 @@ __STATIC_INLINE void nrf_radio_task_trigger(nrf_radio_task_t radio_task);
*
* @param[in] radio_event Event.
*/
__STATIC_INLINE uint32_t *nrf_radio_event_address_get(nrf_radio_event_t radio_event);
__STATIC_INLINE uint32_t * nrf_radio_event_address_get(nrf_radio_event_t radio_event);
/**
* @brief Function for clearing a specific event.
@@ -334,7 +336,7 @@ __STATIC_INLINE nrf_radio_state_t nrf_radio_state_get(void);
*
* @param[in] p_radio_packet_ptr Pointer to tx or rx packet buffer.
*/
__STATIC_INLINE void nrf_radio_packet_ptr_set(const void *p_radio_packet_ptr);
__STATIC_INLINE void nrf_radio_packet_ptr_set(const void * p_radio_packet_ptr);
/**
* @brief Function for getting CRC status of last received packet.
@@ -532,7 +534,6 @@ __STATIC_INLINE void nrf_radio_ed_loop_count_set(uint32_t radio_ed_loop_count);
*/
__STATIC_INLINE void nrf_radio_power_set(bool radio_power);
/**
*@}
**/
@@ -554,7 +555,7 @@ __STATIC_INLINE bool nrf_radio_int_get(nrf_radio_int_mask_t radio_int_mask)
return (bool)(NRF_RADIO->INTENCLR & radio_int_mask);
}
__STATIC_INLINE uint32_t *nrf_radio_task_address_get(nrf_radio_task_t radio_task)
__STATIC_INLINE uint32_t * nrf_radio_task_address_get(nrf_radio_task_t radio_task)
{
return (uint32_t *)((uint8_t *)NRF_RADIO + radio_task);
}
@@ -564,7 +565,7 @@ __STATIC_INLINE void nrf_radio_task_trigger(nrf_radio_task_t radio_task)
*((volatile uint32_t *)((uint8_t *)NRF_RADIO + radio_task)) = NRF_RADIO_TASK_SET;
}
__STATIC_INLINE uint32_t *nrf_radio_event_address_get(nrf_radio_event_t radio_event)
__STATIC_INLINE uint32_t * nrf_radio_event_address_get(nrf_radio_event_t radio_event)
{
return (uint32_t *)((uint8_t *)NRF_RADIO + radio_event);
}
@@ -574,13 +575,14 @@ __STATIC_INLINE void nrf_radio_event_clear(nrf_radio_event_t radio_event)
*((volatile uint32_t *)((uint8_t *)NRF_RADIO + radio_event)) = NRF_RADIO_EVENT_CLEAR;
#if __CORTEX_M == 0x04
volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)NRF_RADIO + radio_event));
(void)dummy;
#endif
}
__STATIC_INLINE bool nrf_radio_event_get(nrf_radio_event_t radio_event)
{
return (bool) * ((volatile uint32_t *)((uint8_t *)NRF_RADIO + radio_event));
return (bool)*((volatile uint32_t *)((uint8_t *)NRF_RADIO + radio_event));
}
__STATIC_INLINE void nrf_radio_shorts_enable(uint32_t radio_short_mask)
@@ -605,84 +607,85 @@ __STATIC_INLINE uint32_t nrf_radio_shorts_get(void)
__STATIC_INLINE nrf_radio_state_t nrf_radio_state_get(void)
{
return (nrf_radio_state_t) NRF_RADIO->STATE;
return (nrf_radio_state_t)NRF_RADIO->STATE;
}
__STATIC_INLINE void nrf_radio_packet_ptr_set(const void *p_radio_packet_ptr)
__STATIC_INLINE void nrf_radio_packet_ptr_set(const void * p_radio_packet_ptr)
{
NRF_RADIO->PACKETPTR = (uint32_t) p_radio_packet_ptr;
NRF_RADIO->PACKETPTR = (uint32_t)p_radio_packet_ptr;
}
__STATIC_INLINE nrf_radio_crc_status_t nrf_radio_crc_status_get(void)
{
return (nrf_radio_crc_status_t) NRF_RADIO->CRCSTATUS;
return (nrf_radio_crc_status_t)NRF_RADIO->CRCSTATUS;
}
__STATIC_INLINE void nrf_radio_cca_mode_set(nrf_radio_cca_mode_t radio_cca_mode)
{
NRF_RADIO->CCACTRL &= (~RADIO_CCACTRL_CCAMODE_Msk);
NRF_RADIO->CCACTRL |= ((uint32_t) radio_cca_mode << RADIO_CCACTRL_CCAMODE_Pos);
NRF_RADIO->CCACTRL |= ((uint32_t)radio_cca_mode << RADIO_CCACTRL_CCAMODE_Pos);
}
__STATIC_INLINE void nrf_radio_cca_ed_threshold_set(uint8_t radio_cca_ed_threshold)
{
NRF_RADIO->CCACTRL &= (~RADIO_CCACTRL_CCAEDTHRES_Msk);
NRF_RADIO->CCACTRL |= ((uint32_t) radio_cca_ed_threshold << RADIO_CCACTRL_CCAEDTHRES_Pos);
NRF_RADIO->CCACTRL |= ((uint32_t)radio_cca_ed_threshold << RADIO_CCACTRL_CCAEDTHRES_Pos);
}
__STATIC_INLINE void nrf_radio_cca_corr_threshold_set(uint8_t radio_cca_corr_threshold_set)
{
NRF_RADIO->CCACTRL &= (~RADIO_CCACTRL_CCACORRTHRES_Msk);
NRF_RADIO->CCACTRL |= ((uint32_t) radio_cca_corr_threshold_set << RADIO_CCACTRL_CCACORRTHRES_Pos);
NRF_RADIO->CCACTRL |=
((uint32_t)radio_cca_corr_threshold_set << RADIO_CCACTRL_CCACORRTHRES_Pos);
}
__STATIC_INLINE void nrf_radio_cca_corr_counter_set(uint8_t radio_cca_corr_counter_set)
{
NRF_RADIO->CCACTRL &= (~RADIO_CCACTRL_CCACORRCNT_Msk);
NRF_RADIO->CCACTRL |= ((uint32_t) radio_cca_corr_counter_set << RADIO_CCACTRL_CCACORRCNT_Pos);
NRF_RADIO->CCACTRL |= ((uint32_t)radio_cca_corr_counter_set << RADIO_CCACTRL_CCACORRCNT_Pos);
}
__STATIC_INLINE void nrf_radio_mode_set(nrf_radio_mode_t radio_mode)
{
NRF_RADIO->MODE = ((uint32_t) radio_mode << RADIO_MODE_MODE_Pos);
NRF_RADIO->MODE = ((uint32_t)radio_mode << RADIO_MODE_MODE_Pos);
}
__STATIC_INLINE void nrf_radio_config_length_field_length_set(uint8_t radio_length_length)
{
NRF_RADIO->PCNF0 &= (~RADIO_PCNF0_LFLEN_Msk);
NRF_RADIO->PCNF0 |= ((uint32_t) radio_length_length << RADIO_PCNF0_LFLEN_Pos);
NRF_RADIO->PCNF0 |= ((uint32_t)radio_length_length << RADIO_PCNF0_LFLEN_Pos);
}
__STATIC_INLINE void nrf_radio_config_preamble_length_set(
nrf_radio_preamble_length_t radio_preamble_length)
{
NRF_RADIO->PCNF0 &= (~RADIO_PCNF0_PLEN_Msk);
NRF_RADIO->PCNF0 |= ((uint32_t) radio_preamble_length << RADIO_PCNF0_PLEN_Pos);
NRF_RADIO->PCNF0 |= ((uint32_t)radio_preamble_length << RADIO_PCNF0_PLEN_Pos);
}
__STATIC_INLINE void nrf_radio_config_crc_included_set(bool radio_length_contains_crc)
{
NRF_RADIO->PCNF0 &= (~RADIO_PCNF0_CRCINC_Msk);
NRF_RADIO->PCNF0 |= ((uint32_t) radio_length_contains_crc << RADIO_PCNF0_CRCINC_Pos);
NRF_RADIO->PCNF0 |= ((uint32_t)radio_length_contains_crc << RADIO_PCNF0_CRCINC_Pos);
}
__STATIC_INLINE void nrf_radio_config_max_length_set(uint8_t radio_max_packet_length)
{
NRF_RADIO->PCNF1 &= (~RADIO_PCNF1_MAXLEN_Msk);
NRF_RADIO->PCNF1 |= ((uint32_t) radio_max_packet_length << RADIO_PCNF1_MAXLEN_Pos);
NRF_RADIO->PCNF1 |= ((uint32_t)radio_max_packet_length << RADIO_PCNF1_MAXLEN_Pos);
}
__STATIC_INLINE void nrf_radio_crc_length_set(uint8_t radio_crc_length)
{
NRF_RADIO->CRCCNF &= (~RADIO_CRCCNF_LEN_Msk);
NRF_RADIO->CRCCNF |= ((uint32_t) radio_crc_length << RADIO_CRCCNF_LEN_Pos);
NRF_RADIO->CRCCNF |= ((uint32_t)radio_crc_length << RADIO_CRCCNF_LEN_Pos);
}
__STATIC_INLINE void nrf_radio_crc_includes_address_set(
nrf_radio_crc_includes_addr_t radio_crc_skip_address)
{
NRF_RADIO->CRCCNF &= (~RADIO_CRCCNF_SKIPADDR_Msk);
NRF_RADIO->CRCCNF |= ((uint32_t) radio_crc_skip_address << RADIO_CRCCNF_SKIPADDR_Pos);
NRF_RADIO->CRCCNF |= ((uint32_t)radio_crc_skip_address << RADIO_CRCCNF_SKIPADDR_Pos);
}
__STATIC_INLINE void nrf_radio_crc_polynominal_set(uint32_t radio_crc_polynominal)
@@ -714,7 +717,7 @@ __STATIC_INLINE void nrf_radio_mhmu_pattern_mask_set(uint32_t radio_mhmu_pattern
__STATIC_INLINE void nrf_radio_ramp_up_mode_set(nrf_radio_ramp_up_mode_t ramp_up_mode)
{
NRF_RADIO->MODECNF0 &= (~RADIO_MODECNF0_RU_Msk);
NRF_RADIO->MODECNF0 |= ((uint32_t) ramp_up_mode << RADIO_MODECNF0_RU_Pos);
NRF_RADIO->MODECNF0 |= ((uint32_t)ramp_up_mode << RADIO_MODECNF0_RU_Pos);
}
__STATIC_INLINE void nrf_radio_frequency_set(uint32_t radio_frequency)
@@ -729,7 +732,7 @@ __STATIC_INLINE uint32_t nrf_radio_frequency_get(void)
__STATIC_INLINE void nrf_radio_tx_power_set(int8_t radio_tx_power)
{
NRF_RADIO->TXPOWER = (uint8_t) radio_tx_power;
NRF_RADIO->TXPOWER = (uint8_t)radio_tx_power;
}
__STATIC_INLINE void nrf_radio_ifs_set(uint32_t radio_ifs)
@@ -754,7 +757,7 @@ __STATIC_INLINE uint32_t nrf_radio_bcc_get(void)
__STATIC_INLINE uint8_t nrf_radio_ed_sample_get(void)
{
return (uint8_t) NRF_RADIO->EDSAMPLE;
return (uint8_t)NRF_RADIO->EDSAMPLE;
}
__STATIC_INLINE void nrf_radio_ed_loop_count_set(uint32_t radio_ed_loop_count)
@@ -764,7 +767,7 @@ __STATIC_INLINE void nrf_radio_ed_loop_count_set(uint32_t radio_ed_loop_count)
__STATIC_INLINE void nrf_radio_power_set(bool radio_power)
{
NRF_RADIO->POWER = (uint32_t) radio_power;
NRF_RADIO->POWER = (uint32_t)radio_power;
}
#endif /* SUPPRESS_INLINE_IMPLEMENTATION */
@@ -774,4 +777,3 @@ __STATIC_INLINE void nrf_radio_power_set(bool radio_power)
#endif
#endif /* NRF_RADIO_H__ */
@@ -1,168 +0,0 @@
/* Copyright (c) 2018, Nordic Semiconductor ASA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**
* @file
* This file implements ACK timeout procedure for the 802.15.4 driver.
*
*/
#include "nrf_802154_ack_timeout.h"
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include "nrf_802154_notification.h"
#include "nrf_802154_request.h"
#include "timer_scheduler/nrf_802154_timer_sched.h"
#define RETRY_DELAY 500 ///< Procedure is delayed by this time if cannot be performed at the moment.
#define MAX_RETRY_DELAY 1000000 ///< Maximal allowed delay of procedure retry.
static void timeout_timer_retry(void);
static uint32_t m_timeout = NRF_802154_ACK_TIMEOUT_DEFAULT_TIMEOUT; ///< ACK timeout in us.
static nrf_802154_timer_t m_timer; ///< Timer used to notify when we are waiting too long for ACK.
static volatile bool m_procedure_is_active;
static const uint8_t * mp_frame;
static void notify_tx_error(bool result)
{
if (result)
{
nrf_802154_notify_transmit_failed(mp_frame, NRF_802154_TX_ERROR_NO_ACK);
}
}
static void timeout_timer_fired(void * p_context)
{
(void)p_context;
if (m_procedure_is_active)
{
if (nrf_802154_request_receive(NRF_802154_TERM_802154,
REQ_ORIG_ACK_TIMEOUT,
notify_tx_error,
false))
{
m_procedure_is_active = false;
}
else
{
timeout_timer_retry();
}
}
}
static void timeout_timer_retry(void)
{
m_timer.dt += RETRY_DELAY;
assert(m_timer.dt <= MAX_RETRY_DELAY);
nrf_802154_timer_sched_add(&m_timer, true);
}
static void timeout_timer_start(void)
{
m_timer.callback = timeout_timer_fired;
m_timer.p_context = NULL;
m_timer.t0 = nrf_802154_timer_sched_time_get();
m_timer.dt = m_timeout;
m_procedure_is_active = true;
nrf_802154_timer_sched_add(&m_timer, true);
}
static void timeout_timer_stop(void)
{
m_procedure_is_active = false;
// To make sure `timeout_timer_fired()` detects that procedure is being stopped if it preempts
// this function.
__DMB();
nrf_802154_timer_sched_remove(&m_timer);
}
void nrf_802154_ack_timeout_time_set(uint32_t time)
{
m_timeout = time;
}
bool nrf_802154_ack_timeout_tx_started_hook(const uint8_t * p_frame)
{
mp_frame = p_frame;
timeout_timer_start();
return true;
}
bool nrf_802154_ack_timeout_abort(nrf_802154_term_t term_lvl, req_originator_t req_orig)
{
bool result;
if (!m_procedure_is_active || req_orig == REQ_ORIG_ACK_TIMEOUT)
{
// Ignore if procedure is not running or self-request.
result = true;
}
else if (term_lvl >= NRF_802154_TERM_802154)
{
// Stop procedure only if termination level is high enough.
timeout_timer_stop();
result = true;
}
else
{
result = false;
}
return result;
}
void nrf_802154_ack_timeout_transmitted_hook(const uint8_t * p_frame)
{
assert((p_frame == mp_frame) || (!m_procedure_is_active));
timeout_timer_stop();
}
bool nrf_802154_ack_timeout_tx_failed_hook(const uint8_t * p_frame, nrf_802154_tx_error_t error)
{
(void)error;
assert((p_frame == mp_frame) || (!m_procedure_is_active));
timeout_timer_stop();
return true;
}
@@ -46,7 +46,7 @@
/**
* @brief Set timeout time for ACK timeout feature.
*
*
* @param[in] time Timeout time in us.
* Default value is defined in nrf_802154_config.h.
*/
@@ -83,7 +83,6 @@ void nrf_802154_ack_timeout_transmitted_hook(const uint8_t * p_frame);
*/
bool nrf_802154_ack_timeout_tx_failed_hook(const uint8_t * p_frame, nrf_802154_tx_error_t error);
/**
* @brief Handler of TX started event.
*
@@ -50,12 +50,12 @@
#if NRF_802154_CSMA_CA_ENABLED
static uint8_t m_nb; ///< The number of times the CSMA-CA algorithm was required to back off while attempting the current transmission.
static uint8_t m_be; ///< Backoff exponent, which is related to how many backoff periods a device shall wait before attempting to assess a channel.
static uint8_t m_nb; ///< The number of times the CSMA-CA algorithm was required to back off while attempting the current transmission.
static uint8_t m_be; ///< Backoff exponent, which is related to how many backoff periods a device shall wait before attempting to assess a channel.
static const uint8_t * mp_psdu; ///< Pointer to PSDU of the frame being transmitted.
static nrf_802154_timer_t m_timer; ///< Timer used to back off during CSMA-CA procedure.
static bool m_is_running; ///< Indicates if CSMA-CA procedure is running.
static const uint8_t * mp_psdu; ///< Pointer to PSDU of the frame being transmitted.
static nrf_802154_timer_t m_timer; ///< Timer used to back off during CSMA-CA procedure.
static bool m_is_running; ///< Indicates if CSMA-CA procedure is running.
/**
* @brief Perform appropriate actions for busy channel conditions.
@@ -47,30 +47,55 @@
#include "nrf_802154_procedures_duration.h"
#include "nrf_802154_request.h"
#include "nrf_802154_rsch.h"
#include "timer_scheduler/nrf_802154_timer_sched.h"
#define TX_SETUP_TIME 190 ///< Time [us] needed to change channel, stop rx and setup tx procedure.
#define TX_SETUP_TIME 190u ///< Time [us] needed to change channel, stop rx and setup tx procedure.
#define RX_SETUP_TIME 190u ///< Time [us] needed to change channel, stop tx and setup rx procedure.
static const uint8_t * mp_tx_psdu; ///< Pointer to PHR + PSDU of the frame requested to transmit.
static bool m_tx_cca; ///< If CCA should be performed prior to transmission.
static uint8_t m_tx_channel; ///< Channel number on which transmission should be performed.
static const uint8_t * mp_tx_psdu; ///< Pointer to PHR + PSDU of the frame requested to transmit.
static bool m_tx_cca; ///< If CCA should be performed prior to transmission.
static uint8_t m_tx_channel; ///< Channel number on which transmission should be performed.
static nrf_802154_timer_t m_timeout_timer; ///< Timer for delayed RX timeout handling.
static uint8_t m_rx_channel; ///< Channel number on which reception should be performed.
static bool m_dly_op_in_progress[RSCH_DLY_TS_NUM]; ///< Status of delayed operation.
/**
* Check if delayed transmission procedure is in progress.
* Start delayed timeslot operation.
*
* @retval true Delayed transmission is in progress (waiting or transmitting).
* @retval false Delayed transmission is not in progress.
* @param[in] dly_ts_id Delayed timeslot ID.
*/
static bool tx_is_in_progress(void)
static void dly_op_start(rsch_dly_ts_id_t dly_ts_id)
{
return mp_tx_psdu != NULL;
assert(dly_ts_id < RSCH_DLY_TS_NUM);
m_dly_op_in_progress[dly_ts_id] = true;
}
/**
* Mark that delayed transmission procedure has stopped.
* Stop delayed timeslot operation.
*
* @param[in] dly_ts_id Delayed timeslot ID.
*/
static void tx_stop(void)
static void dly_op_stop(rsch_dly_ts_id_t dly_ts_id)
{
mp_tx_psdu = NULL;
assert(dly_ts_id < RSCH_DLY_TS_NUM);
m_dly_op_in_progress[dly_ts_id] = false;
}
/**
* Check if delayed operation is in progress.
*
* @retval true Delayed operation is in progress (waiting or ongoing).
* @retval false Delayed operation is not in progress.
*/
bool dly_op_is_in_progress(rsch_dly_ts_id_t dly_ts_id)
{
assert(dly_ts_id < RSCH_DLY_TS_NUM);
return m_dly_op_in_progress[dly_ts_id];
}
/**
@@ -86,6 +111,98 @@ static void notify_tx_timeslot_denied(bool result)
}
}
/**
* Notify MAC layer that requested timeslot is not granted if rx request failed.
*
* @param[in] result Result of RX request.
*/
static void notify_rx_timeslot_denied(bool result)
{
if (!result)
{
nrf_802154_notify_receive_failed(NRF_802154_RX_ERROR_DELAYED_TIMESLOT_DENIED);
}
}
/**
* Notify MAC layer that no frame was received before timeout.
*
* @param[in] p_context Not used.
*/
static void notify_rx_timeout(void * p_context)
{
(void)p_context;
dly_op_stop(RSCH_DLY_RX);
nrf_802154_notify_receive_failed(NRF_802154_RX_ERROR_DELAYED_TIMEOUT);
}
/**
* Handle TX timeslot start.
*/
static void nrf_802154_rsch_delayed_tx_timeslot_started(void)
{
bool result;
assert(dly_op_is_in_progress(RSCH_DLY_TX));
nrf_802154_pib_channel_set(m_tx_channel);
result = nrf_802154_request_channel_update();
if (result)
{
result = nrf_802154_request_transmit(NRF_802154_TERM_802154,
REQ_ORIG_DELAYED_TRX,
mp_tx_psdu,
m_tx_cca,
true,
notify_tx_timeslot_denied);
(void)result;
}
else
{
notify_tx_timeslot_denied(result);
}
dly_op_stop(RSCH_DLY_TX);
}
/**
* Handle RX timeslot start.
*/
static void nrf_802154_rsch_delayed_rx_timeslot_started(void)
{
bool result;
assert(dly_op_is_in_progress(RSCH_DLY_RX));
nrf_802154_pib_channel_set(m_rx_channel);
result = nrf_802154_request_channel_update();
if (result)
{
result = nrf_802154_request_receive(NRF_802154_TERM_802154,
REQ_ORIG_DELAYED_TRX,
notify_rx_timeslot_denied,
true);
if (result)
{
m_timeout_timer.t0 = nrf_802154_timer_sched_time_get();
nrf_802154_timer_sched_add(&m_timeout_timer, true);
}
else
{
dly_op_stop(RSCH_DLY_RX);
}
}
else
{
notify_rx_timeslot_denied(result);
dly_op_stop(RSCH_DLY_RX);
}
}
bool nrf_802154_delayed_trx_transmit(const uint8_t * p_data,
bool cca,
uint32_t t0,
@@ -95,7 +212,7 @@ bool nrf_802154_delayed_trx_transmit(const uint8_t * p_data,
bool result = true;
uint16_t timeslot_length;
if (tx_is_in_progress())
if (dly_op_is_in_progress(RSCH_DLY_TX))
{
result = false;
}
@@ -118,50 +235,131 @@ bool nrf_802154_delayed_trx_transmit(const uint8_t * p_data,
cca,
p_data[ACK_REQUEST_OFFSET] & ACK_REQUEST_BIT);
result = nrf_802154_rsch_delayed_timeslot_request(t0, dt, timeslot_length);
dly_op_start(RSCH_DLY_TX);
result = nrf_802154_rsch_delayed_timeslot_request(t0,
dt,
timeslot_length,
RSCH_PRIO_MAX,
RSCH_DLY_TX);
if (!result)
{
notify_tx_timeslot_denied(result);
tx_stop();
dly_op_stop(RSCH_DLY_TX);
}
}
return result;
}
void nrf_802154_rsch_delayed_timeslot_started(void)
bool nrf_802154_delayed_trx_receive(uint32_t t0,
uint32_t dt,
uint32_t timeout,
uint8_t channel)
{
bool result;
assert(tx_is_in_progress());
nrf_802154_pib_channel_set(m_tx_channel);
result = nrf_802154_request_channel_update();
result = !dly_op_is_in_progress(RSCH_DLY_RX);
if (result)
{
result = nrf_802154_request_transmit(NRF_802154_TERM_802154,
REQ_ORIG_DELAYED_TRX,
mp_tx_psdu,
m_tx_cca,
true,
notify_tx_timeslot_denied);
(void)result;
dt -= RX_SETUP_TIME;
dt -= RX_RAMP_UP_TIME;
dly_op_start(RSCH_DLY_RX);
result = nrf_802154_rsch_delayed_timeslot_request(t0,
dt,
timeout +
nrf_802154_rx_duration_get(MAX_PACKET_SIZE,
true),
RSCH_PRIO_MAX,
RSCH_DLY_RX);
if (result)
{
m_timeout_timer.dt = timeout;
m_timeout_timer.callback = notify_rx_timeout;
m_timeout_timer.p_context = NULL;
m_rx_channel = channel;
}
else
{
notify_rx_timeslot_denied(result);
dly_op_stop(RSCH_DLY_RX);
}
}
return result;
}
void nrf_802154_rsch_delayed_timeslot_started(rsch_dly_ts_id_t dly_ts_id)
{
switch (dly_ts_id)
{
case RSCH_DLY_TX:
nrf_802154_rsch_delayed_tx_timeslot_started();
break;
case RSCH_DLY_RX:
nrf_802154_rsch_delayed_rx_timeslot_started();
break;
default:
assert(false);
}
}
void nrf_802154_rsch_delayed_timeslot_failed(rsch_dly_ts_id_t dly_ts_id)
{
assert(dly_ts_id < RSCH_DLY_TS_NUM);
assert(dly_op_is_in_progress(dly_ts_id));
if (RSCH_DLY_TX == dly_ts_id)
{
notify_tx_timeslot_denied(false);
}
else
{
notify_tx_timeslot_denied(result);
notify_rx_timeslot_denied(false);
}
tx_stop();
dly_op_stop(dly_ts_id);
}
void nrf_802154_rsch_delayed_timeslot_failed(void)
bool nrf_802154_delayed_trx_abort(nrf_802154_term_t term_lvl, req_originator_t req_orig)
{
assert(tx_is_in_progress());
bool result = true;
notify_tx_timeslot_denied(false);
if (!dly_op_is_in_progress(RSCH_DLY_RX))
{
// No active procedures, just return true.
}
else if ((REQ_ORIG_HIGHER_LAYER == req_orig) || (term_lvl >= NRF_802154_TERM_802154))
{
nrf_802154_timer_sched_remove(&m_timeout_timer);
dly_op_stop(RSCH_DLY_RX);
}
else
{
result = false;
}
tx_stop();
return result;
}
void nrf_802154_delayed_trx_rx_started_hook(void)
{
if (dly_op_is_in_progress(RSCH_DLY_RX))
{
if (nrf_802154_timer_sched_remaining_time_get(&m_timeout_timer)
< nrf_802154_rx_duration_get(MAX_PACKET_SIZE, true))
{
m_timeout_timer.t0 = nrf_802154_timer_sched_time_get();
m_timeout_timer.dt = nrf_802154_rx_duration_get(MAX_PACKET_SIZE, true);
nrf_802154_timer_sched_add(&m_timeout_timer, true);
}
}
}
@@ -60,8 +60,8 @@
*
* @param[in] p_data Pointer to array containing data to transmit (PHR + PSDU).
* @param[in] cca If the driver should perform CCA procedure before transmission.
* @param[in] t0 Base of delay time.
* @param[in] dt Delta of delay time from @p t0.
* @param[in] t0 Base of delay time [us].
* @param[in] dt Delta of delay time from @p t0 [us].
* @param[in] channel Number of channel on which the frame should be transmitted.
*/
bool nrf_802154_delayed_trx_transmit(const uint8_t * p_data,
@@ -70,6 +70,47 @@ bool nrf_802154_delayed_trx_transmit(const uint8_t * p_data,
uint32_t dt,
uint8_t channel);
/**
*@}
**/
/**
* @brief Request reception of a frame at given time.
*
* If the requested is accepted and a frame is received during defined time slot
* @ref nrf_802154_received is called. If the request is rejected due to denied timeslot request
* or reception timeout expired the @ref nrf_802154_receive_failed function is called.
*
* @param[in] t0 Base of delay time [us].
* @param[in] dt Delta of delay time from @p t0 [us].
* @param[in] timeout Reception timeout (counted from @p t0 + @p dt) [us].
* @param[in] channel Number of channel on which the frame should be received.
*/
bool nrf_802154_delayed_trx_receive(uint32_t t0,
uint32_t dt,
uint32_t timeout,
uint8_t channel);
/**
* @brief Abort started delayed transmit/receive procedure.
*
* @param[in] term_lvl Termination level set by request aborting ongoing operation.
* @param[in] req_orig Module that originates this request.
*
* If delayed transmit/receive procedure are not running during call, this function does nothing.
*
* @retval true transmit/receive procedures have been stopped.
*/
bool nrf_802154_delayed_trx_abort(nrf_802154_term_t term_lvl, req_originator_t req_orig);
/**
* @brief Extends timeout timer when reception start is detected and there is not enough time
* left for delayed RX operation.
*
* If delayed transmit/receive procedure are not running during call, this function does nothing.
*/
void nrf_802154_delayed_trx_rx_started_hook(void);
/**
*@}
**/
@@ -153,12 +153,12 @@ static nrf_802154_rx_error_t dst_addressing_end_offset_get_2006(const uint8_t *
{
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:
@@ -168,12 +168,12 @@ static nrf_802154_rx_error_t dst_addressing_end_offset_get_2006(const uint8_t *
{
case SRC_ADDR_TYPE_SHORT:
*p_num_bytes = SHORT_ADDR_CHECK_OFFSET;
result = NRF_802154_RX_ERROR_NONE;
result = NRF_802154_RX_ERROR_NONE;
break;
case SRC_ADDR_TYPE_EXTENDED:
*p_num_bytes = EXTENDED_ADDR_CHECK_OFFSET;
result = NRF_802154_RX_ERROR_NONE;
result = NRF_802154_RX_ERROR_NONE;
break;
default:
@@ -363,7 +363,7 @@ static bool dst_short_addr_check(const uint8_t * p_psdu)
* @retval true Destination address of incoming frame allows further processing of the frame.
* @retval false Destination address of incoming frame does not allow further processing.
*/
static bool dst_extended_addr_check(const uint8_t *p_psdu)
static bool dst_extended_addr_check(const uint8_t * p_psdu)
{
bool result;
@@ -400,8 +400,7 @@ nrf_802154_rx_error_t nrf_802154_filter_frame_part(const uint8_t * p_psdu, uint8
{
if (p_psdu[0] < IMM_ACK_LENGTH || p_psdu[0] > MAX_PACKET_SIZE)
{
// Frame length is invalid
result = NRF_802154_RX_ERROR_INVALID_FRAME;
result = NRF_802154_RX_ERROR_INVALID_LENGTH;
break;
}
@@ -432,7 +431,7 @@ nrf_802154_rx_error_t nrf_802154_filter_frame_part(const uint8_t * p_psdu, uint8
}
result = dst_short_addr_check(p_psdu) ? NRF_802154_RX_ERROR_NONE :
NRF_802154_RX_ERROR_INVALID_DEST_ADDR;
NRF_802154_RX_ERROR_INVALID_DEST_ADDR;
break;
case EXTENDED_ADDR_CHECK_OFFSET:
@@ -443,7 +442,7 @@ nrf_802154_rx_error_t nrf_802154_filter_frame_part(const uint8_t * p_psdu, uint8
}
result = dst_extended_addr_check(p_psdu) ? NRF_802154_RX_ERROR_NONE :
NRF_802154_RX_ERROR_INVALID_DEST_ADDR;
NRF_802154_RX_ERROR_INVALID_DEST_ADDR;
break;
default:
@@ -48,7 +48,6 @@
* @brief Procedures used to discard incoming frames that contain unexpected data in PHR or MHR.
*/
/**
* @brief Verify if given part of the frame is valid.
*
@@ -75,4 +74,3 @@
nrf_802154_rx_error_t nrf_802154_filter_frame_part(const uint8_t * p_psdu, uint8_t * p_num_bytes);
#endif /* NRF_802154_FILTER_H_ */
@@ -45,13 +45,13 @@
#include "nrf_802154_request.h"
#include "timer_scheduler/nrf_802154_timer_sched.h"
#define RETRY_DELAY 500 ///< Procedure is delayed by this time if it cannot be performed at the moment [us].
#define MAX_RETRY_DELAY 1000000 ///< Maximum allowed delay of procedure retry [us].
#define RETRY_DELAY 500 ///< Procedure is delayed by this time if it cannot be performed at the moment [us].
#define MAX_RETRY_DELAY 1000000 ///< Maximum allowed delay of procedure retry [us].
static void timeout_timer_retry(void);
static uint32_t m_timeout = NRF_802154_PRECISE_ACK_TIMEOUT_DEFAULT_TIMEOUT; ///< ACK timeout in us.
static nrf_802154_timer_t m_timer; ///< Timer used to notify when the ACK frama is not received for too long.
static uint32_t m_timeout = NRF_802154_PRECISE_ACK_TIMEOUT_DEFAULT_TIMEOUT; ///< ACK timeout in us.
static nrf_802154_timer_t m_timer; ///< Timer used to notify when the ACK frama is not received for too long.
static volatile bool m_procedure_is_active;
static const uint8_t * mp_frame;
+57 -24
View File
@@ -54,6 +54,7 @@
#include "nrf_802154_request.h"
#include "nrf_802154_revision.h"
#include "nrf_802154_rsch.h"
#include "nrf_802154_rsch_crit_sect.h"
#include "nrf_802154_rssi.h"
#include "nrf_802154_rx_buffer.h"
#include "nrf_802154_timer_coord.h"
@@ -97,6 +98,7 @@ static void tx_buffer_fill(const uint8_t * p_data, uint8_t length)
m_tx_buffer[RAW_LENGTH_OFFSET] = length + FCS_SIZE;
memcpy(&m_tx_buffer[RAW_PAYLOAD_OFFSET], p_data, length);
}
#endif // !NRF_802154_USE_RAW_API
/**
@@ -129,7 +131,7 @@ static uint32_t last_rx_frame_timestamp_get(void)
return timestamp;
#else // NRF_802154_FRAME_TIMESTAMP_ENABLED
return NRF_802154_NO_TIMESTAMP;
#endif // NRF_802154_FRAME_TIMESTAMP_ENABLED
#endif // NRF_802154_FRAME_TIMESTAMP_ENABLED
}
void nrf_802154_channel_set(uint8_t channel)
@@ -192,6 +194,7 @@ uint8_t nrf_802154_ccaedthres_from_dbm_calculate(int8_t dbm)
uint32_t nrf_802154_first_symbol_timestamp_get(uint32_t end_timestamp, uint8_t psdu_length)
{
uint32_t frame_symbols = PHY_SHR_SYMBOLS;
frame_symbols += (PHR_SIZE + psdu_length) * PHY_SYMBOLS_PER_OCTET;
return end_timestamp - (frame_symbols * PHY_US_PER_SYMBOL);
@@ -210,6 +213,7 @@ void nrf_802154_init(void)
nrf_802154_priority_drop_init();
nrf_802154_request_init();
nrf_802154_revision_init();
nrf_802154_rsch_crit_sect_init();
nrf_802154_rsch_init();
nrf_802154_rx_buffer_init();
nrf_802154_temperature_init();
@@ -233,6 +237,7 @@ void nrf_802154_radio_irq_handler(void)
{
nrf_802154_core_irq_handler();
}
#endif // !NRF_802154_INTERNAL_RADIO_IRQ_HANDLING
#if ENABLE_FEM
@@ -245,33 +250,34 @@ void nrf_802154_fem_control_cfg_get(nrf_802154_fem_control_cfg_t * p_cfg)
{
nrf_fem_control_cfg_get(p_cfg);
}
#endif // ENABLE_FEM
nrf_802154_state_t nrf_802154_state_get(void)
{
switch (nrf_802154_core_state_get())
{
case RADIO_STATE_SLEEP:
case RADIO_STATE_FALLING_ASLEEP:
return NRF_802154_STATE_SLEEP;
case RADIO_STATE_SLEEP:
case RADIO_STATE_FALLING_ASLEEP:
return NRF_802154_STATE_SLEEP;
case RADIO_STATE_RX:
case RADIO_STATE_TX_ACK:
return NRF_802154_STATE_RECEIVE;
case RADIO_STATE_RX:
case RADIO_STATE_TX_ACK:
return NRF_802154_STATE_RECEIVE;
case RADIO_STATE_CCA_TX:
case RADIO_STATE_TX:
case RADIO_STATE_RX_ACK:
return NRF_802154_STATE_TRANSMIT;
case RADIO_STATE_CCA_TX:
case RADIO_STATE_TX:
case RADIO_STATE_RX_ACK:
return NRF_802154_STATE_TRANSMIT;
case RADIO_STATE_ED:
return NRF_802154_STATE_ENERGY_DETECTION;
case RADIO_STATE_ED:
return NRF_802154_STATE_ENERGY_DETECTION;
case RADIO_STATE_CCA:
return NRF_802154_STATE_CCA;
case RADIO_STATE_CCA:
return NRF_802154_STATE_CCA;
case RADIO_STATE_CONTINUOUS_CARRIER:
return NRF_802154_STATE_CONTINUOUS_CARRIER;
case RADIO_STATE_CONTINUOUS_CARRIER:
return NRF_802154_STATE_CONTINUOUS_CARRIER;
}
return NRF_802154_STATE_INVALID;
@@ -280,6 +286,7 @@ nrf_802154_state_t nrf_802154_state_get(void)
bool nrf_802154_sleep(void)
{
bool result;
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_SLEEP);
result = nrf_802154_request_sleep(NRF_802154_TERM_802154);
@@ -291,10 +298,13 @@ bool nrf_802154_sleep(void)
nrf_802154_sleep_error_t nrf_802154_sleep_if_idle(void)
{
nrf_802154_sleep_error_t result;
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_SLEEP);
result = nrf_802154_request_sleep(NRF_802154_TERM_NONE) ? NRF_802154_SLEEP_ERROR_NONE : NRF_802154_SLEEP_ERROR_BUSY;
result =
nrf_802154_request_sleep(NRF_802154_TERM_NONE) ? NRF_802154_SLEEP_ERROR_NONE :
NRF_802154_SLEEP_ERROR_BUSY;
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_SLEEP);
return result;
}
@@ -302,6 +312,7 @@ nrf_802154_sleep_error_t nrf_802154_sleep_if_idle(void)
bool nrf_802154_receive(void)
{
bool result;
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RECEIVE);
result = nrf_802154_request_receive(NRF_802154_TERM_802154, REQ_ORIG_HIGHER_LAYER, NULL, true);
@@ -314,6 +325,7 @@ bool nrf_802154_receive(void)
bool nrf_802154_transmit_raw(const uint8_t * p_data, bool cca)
{
bool result;
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_TRANSMIT);
result = nrf_802154_request_transmit(NRF_802154_TERM_NONE,
@@ -332,6 +344,7 @@ bool nrf_802154_transmit_raw(const uint8_t * p_data, bool cca)
bool nrf_802154_transmit(const uint8_t * p_data, uint8_t length, bool cca)
{
bool result;
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_TRANSMIT);
tx_buffer_fill(p_data, length);
@@ -355,6 +368,7 @@ bool nrf_802154_transmit_raw_at(const uint8_t * p_data,
uint8_t channel)
{
bool result;
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_TRANSMIT_AT);
result = nrf_802154_delayed_trx_transmit(p_data, cca, t0, dt, channel);
@@ -363,9 +377,25 @@ bool nrf_802154_transmit_raw_at(const uint8_t * p_data,
return result;
}
bool nrf_802154_receive_at(uint32_t t0,
uint32_t dt,
uint32_t timeout,
uint8_t channel)
{
bool result;
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RECEIVE_AT);
result = nrf_802154_delayed_trx_receive(t0, dt, timeout, channel);
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RECEIVE_AT);
return result;
}
bool nrf_802154_energy_detection(uint32_t time_us)
{
bool result;
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_ENERGY_DETECTION);
result = nrf_802154_request_energy_detection(NRF_802154_TERM_NONE, time_us);
@@ -377,6 +407,7 @@ bool nrf_802154_energy_detection(uint32_t time_us)
bool nrf_802154_cca(void)
{
bool result;
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_CCA);
result = nrf_802154_request_cca(NRF_802154_TERM_NONE);
@@ -388,6 +419,7 @@ bool nrf_802154_cca(void)
bool nrf_802154_continuous_carrier(void)
{
bool result;
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_CONTINUOUS_CARRIER);
result = nrf_802154_request_continuous_carrier(NRF_802154_TERM_NONE);
@@ -470,11 +502,11 @@ bool nrf_802154_buffer_free_immediately(uint8_t * p_data)
int8_t nrf_802154_rssi_last_get(void)
{
uint8_t minus_dbm = nrf_radio_rssi_sample_get();
uint8_t negative_dbm = nrf_radio_rssi_sample_get();
minus_dbm = nrf_802154_rssi_sample_corrected_get(minus_dbm);
negative_dbm = nrf_802154_rssi_sample_corrected_get(negative_dbm);
return - (int8_t)minus_dbm;
return -(int8_t)negative_dbm;
}
bool nrf_802154_promiscuous_get(void)
@@ -619,6 +651,7 @@ __WEAK void nrf_802154_received_timestamp(uint8_t * p_data,
nrf_802154_buffer_free(p_data);
}
#endif // !NRF_802154_USE_RAW_API
__WEAK void nrf_802154_receive_failed(nrf_802154_rx_error_t error)
@@ -690,8 +723,8 @@ __WEAK void nrf_802154_transmitted_timestamp(const uint8_t * p_frame,
nrf_802154_buffer_free(p_ack);
}
}
#endif // NRF_802154_USE_RAW_API
#endif // NRF_802154_USE_RAW_API
__WEAK void nrf_802154_transmit_failed(const uint8_t * p_frame, nrf_802154_tx_error_t error)
{
+53 -36
View File
@@ -128,22 +128,22 @@ int8_t nrf_802154_tx_power_get(void);
typedef nrf_fem_control_cfg_t nrf_802154_fem_control_cfg_t;
/** Macro with default configuration of the FEM module. */
#define NRF_802154_FEM_DEFAULT_SETTINGS \
((nrf_802154_fem_control_cfg_t) { \
.pa_cfg = { \
.enable = 1, \
.active_high = 1, \
.gpio_pin = NRF_FEM_CONTROL_DEFAULT_PA_PIN, \
}, \
.lna_cfg = { \
.enable = 1, \
.active_high = 1, \
.gpio_pin = NRF_FEM_CONTROL_DEFAULT_LNA_PIN, \
}, \
.pa_gpiote_ch_id = NRF_FEM_CONTROL_DEFAULT_PA_GPIOTE_CHANNEL, \
.lna_gpiote_ch_id = NRF_FEM_CONTROL_DEFAULT_LNA_GPIOTE_CHANNEL, \
.ppi_ch_id_set = NRF_FEM_CONTROL_DEFAULT_SET_PPI_CHANNEL, \
.ppi_ch_id_clr = NRF_FEM_CONTROL_DEFAULT_CLR_PPI_CHANNEL, \
#define NRF_802154_FEM_DEFAULT_SETTINGS \
((nrf_802154_fem_control_cfg_t) { \
.pa_cfg = { \
.enable = 1, \
.active_high = 1, \
.gpio_pin = NRF_FEM_CONTROL_DEFAULT_PA_PIN, \
}, \
.lna_cfg = { \
.enable = 1, \
.active_high = 1, \
.gpio_pin = NRF_FEM_CONTROL_DEFAULT_LNA_PIN, \
}, \
.pa_gpiote_ch_id = NRF_FEM_CONTROL_DEFAULT_PA_GPIOTE_CHANNEL, \
.lna_gpiote_ch_id = NRF_FEM_CONTROL_DEFAULT_LNA_GPIOTE_CHANNEL, \
.ppi_ch_id_set = NRF_FEM_CONTROL_DEFAULT_SET_PPI_CHANNEL, \
.ppi_ch_id_clr = NRF_FEM_CONTROL_DEFAULT_CLR_PPI_CHANNEL, \
})
/**
@@ -166,9 +166,8 @@ void nrf_802154_fem_control_cfg_get(nrf_802154_fem_control_cfg_t * p_cfg);
#endif // ENABLE_FEM
/**
* @}
* @}
* @defgroup nrf_802154_addresses Setting addresses and PAN ID of the device
* @{
*/
@@ -180,7 +179,7 @@ void nrf_802154_fem_control_cfg_get(nrf_802154_fem_control_cfg_t * p_cfg);
*
* This function makes a copy of the PAN ID.
*/
void nrf_802154_pan_id_set(const uint8_t *p_pan_id);
void nrf_802154_pan_id_set(const uint8_t * p_pan_id);
/**
* @brief Set the extended address of the device.
@@ -189,7 +188,7 @@ void nrf_802154_pan_id_set(const uint8_t *p_pan_id);
*
* This function makes a copy of the address.
*/
void nrf_802154_extended_address_set(const uint8_t *p_extended_address);
void nrf_802154_extended_address_set(const uint8_t * p_extended_address);
/**
* @brief Set the short address of the device.
@@ -198,8 +197,7 @@ void nrf_802154_extended_address_set(const uint8_t *p_extended_address);
*
* This function makes a copy of the address.
*/
void nrf_802154_short_address_set(const uint8_t *p_short_address);
void nrf_802154_short_address_set(const uint8_t * p_short_address);
/**
* @}
@@ -236,7 +234,6 @@ uint8_t nrf_802154_ccaedthres_from_dbm_calculate(int8_t dbm);
*/
uint32_t nrf_802154_first_symbol_timestamp_get(uint32_t end_timestamp, uint8_t psdu_length);
/**
* @}
* @defgroup nrf_802154_transitions Functions to request FSM transitions and check current state
@@ -290,11 +287,36 @@ nrf_802154_sleep_error_t nrf_802154_sleep_if_idle(void);
*/
bool nrf_802154_receive(void);
/**
* @brief Request reception at specified time.
*
* This function works as delayed version of the @sref nrf_802154_receive. It is not
* blocking, but queues delayed reception using Radio Scheduler module. If delayed reception
* cannot be performed (the @ref nrf_802154_receive_at would return false) or requested
* reception timeslot is denied, the @ref nrf_drv_radio802154_receive_failed with the
* @ref NRF_802154_RX_ERROR_DELAYED_TIMESLOT_DENIED argument is called.
*
* If the requested reception time is in the past, the function returns false and does not
* schedule reception.
*
* @param[in] t0 Base of delay time - absolute time used by the Timer Scheduler [us].
* @param[in] dt Delta of delay time from @p t0 [us].
* @param[in] timeout Reception timeout (counted from @p t0 + @p dt) [us].
* @param[in] channel Radio channel on which the frame should be received.
*
* @retval true If the transmission procedure was scheduled.
* @retval false If the driver could not schedule the transmission procedure.
*/
bool nrf_802154_receive_at(uint32_t t0,
uint32_t dt,
uint32_t timeout,
uint8_t channel);
#if NRF_802154_USE_RAW_API
/**
* @brief Change radio state to transmit.
*
* @note If the CPU is halted or interrupted while this function is executed,
* @note If the CPU is halted or interrupted while this function is executed,
* @ref nrf_802154_transmitted or @ref nrf_802154_transmit_failed may be called before this
* function returns a result.
* @note This function is implemented in zero-copy fashion. It passes the given buffer pointer to
@@ -334,7 +356,7 @@ bool nrf_802154_transmit_raw(const uint8_t * p_data, bool cca);
/**
* @brief Change radio state to transmit.
*
* @note If the CPU is halted or interrupted while this function is executed,
* @note If the CPU is halted or interrupted while this function is executed,
* @ref nrf_802154_transmitted or @ref nrf_802154_transmit_failed must be called before this
* function returns a result.
* @note This function copies the given buffer. It maintains an internal buffer, which is used to
@@ -455,7 +477,6 @@ bool nrf_802154_cca(void);
*/
bool nrf_802154_continuous_carrier(void);
/**
* @}
* @defgroup nrf_802154_calls Calls to higher layer
@@ -586,7 +607,7 @@ extern void nrf_802154_receive_failed(nrf_802154_rx_error_t error);
* @brief Notify that transmitting a frame has started.
*
* @note Usually, @ref nrf_802154_transmitted is called shortly after this function.
* However, if the transmit procedure is interrupted, it might happen that
* However, if the transmit procedure is interrupted, it might happen that
* @ref nrf_802154_transmitted is not called.
* @note This function should be very short to prevent dropping frames by the driver.
*
@@ -694,7 +715,7 @@ extern void nrf_802154_transmitted(const uint8_t * p_frame,
*
* @param[in] p_frame Pointer to the buffer containing PSDU of the transmitted frame.
* @param[in] p_ack Pointer to the buffer containing the received ACK payload (PHR excluding FCS).
* If ACK was not requested, @p p_ack is set to NULL.
* If ACK was not requested, @p p_ack is set to NULL.
* @param[in] length Length of the received ACK payload.
* @param[in] power RSSI of received frame or 0 if ACK was not requested.
* @param[in] lqi LQI of received frame or 0 if ACK was not requested.
@@ -753,7 +774,6 @@ extern void nrf_802154_cca_done(bool channel_free);
*/
extern void nrf_802154_cca_failed(nrf_802154_cca_error_t error);
/**
* @}
* @defgroup nrf_802154_memman Driver memory management
@@ -822,7 +842,6 @@ bool nrf_802154_buffer_free_immediately(uint8_t * p_data);
#endif // NRF_802154_USE_RAW_API
/**
* @}
* @defgroup nrf_802154_rssi RSSI measurement function
@@ -846,7 +865,6 @@ void nrf_802154_rssi_measure(void);
*/
int8_t nrf_802154_rssi_last_get(void);
/**
* @}
* @defgroup nrf_802154_prom Promiscuous mode
@@ -876,7 +894,6 @@ void nrf_802154_promiscuous_set(bool enabled);
*/
bool nrf_802154_promiscuous_get(void);
/**
* @}
* @defgroup nrf_802154_autoack Auto ACK management
@@ -958,7 +975,7 @@ void nrf_802154_auto_pending_bit_set(bool enabled);
* @retval True If the address is successfully added to the list.
* @retval False If there is not enough memory to store the address in the list.
*/
bool nrf_802154_pending_bit_for_addr_set(const uint8_t *p_addr, bool extended);
bool nrf_802154_pending_bit_for_addr_set(const uint8_t * p_addr, bool extended);
/**
* @brief Remove address of a peer node for which there is no more pending data in the buffer.
@@ -969,7 +986,7 @@ bool nrf_802154_pending_bit_for_addr_set(const uint8_t *p_addr, bool extended);
* @retval True If the address is successfully removed from the list.
* @retval False If there is no such address in the list.
*/
bool nrf_802154_pending_bit_for_addr_clear(const uint8_t *p_addr, bool extended);
bool nrf_802154_pending_bit_for_addr_clear(const uint8_t * p_addr, bool extended);
/**
* @brief Remove all addresses of a given type from the pending bit list.
@@ -1063,9 +1080,9 @@ void nrf_802154_transmit_csma_ca(const uint8_t * p_data, uint8_t length);
/**
* @brief Set timeout for the ACK timeout feature.
*
*
* A timeout is notified by @ref nrf_802154_transmit_failed.
*
*
* @param[in] time Timeout in us.
* A default value is defined in nrf_802154_config.h.
*/
@@ -50,9 +50,9 @@
/// Maximum number of Extended Addresses of nodes for which there is pending data in buffer.
#define NUM_PENDING_EXTENDED_ADDRESSES NRF_802154_PENDING_EXTENDED_ADDRESSES
/// Value used to mark Short Address as unused.
#define UNUSED_PENDING_SHORT_ADDRESS ((uint8_t [SHORT_ADDRESS_SIZE]) {0xff, 0xff})
#define UNUSED_PENDING_SHORT_ADDRESS ((uint8_t[SHORT_ADDRESS_SIZE]) {0xff, 0xff})
/// Value used to mark Extended Address as unused.
#define UNUSED_PENDING_EXTENDED_ADDRESS ((uint8_t [EXTENDED_ADDRESS_SIZE]) {0})
#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.
static bool m_setting_pending_bit_enabled;
@@ -139,7 +139,9 @@ static int8_t short_addr_compare(const uint8_t * p_first_addr, const uint8_t * p
* @retval 0 First address is equal to the second address.
* @retval 1 First address is greater than the second address.
*/
static int8_t addr_compare(const uint8_t * p_first_addr, const uint8_t * p_second_addr, bool extended)
static int8_t addr_compare(const uint8_t * p_first_addr,
const uint8_t * p_second_addr,
bool extended)
{
if (extended)
{
@@ -258,12 +260,15 @@ static bool addr_index_find(const uint8_t * p_addr,
*/
static bool addr_add(const uint8_t * p_addr, uint8_t location, bool extended)
{
uint8_t * p_addr_array = extended ? (uint8_t *)m_pending_extended :
(uint8_t *)m_pending_short;
uint8_t max_addr_array_len = extended ? NUM_PENDING_EXTENDED_ADDRESSES :
NUM_PENDING_SHORT_ADDRESSES;
uint8_t * p_addr_array_len = extended ? &m_num_of_pending_extended : &m_num_of_pending_short;
uint8_t entry_size = extended ? EXTENDED_ADDRESS_SIZE : SHORT_ADDRESS_SIZE;
uint8_t * p_addr_array;
uint8_t max_addr_array_len;
uint8_t * p_addr_array_len;
uint8_t entry_size;
p_addr_array = extended ? (uint8_t *)m_pending_extended : (uint8_t *)m_pending_short;
max_addr_array_len = extended ? NUM_PENDING_EXTENDED_ADDRESSES : NUM_PENDING_SHORT_ADDRESSES;
p_addr_array_len = extended ? &m_num_of_pending_extended : &m_num_of_pending_short;
entry_size = extended ? EXTENDED_ADDRESS_SIZE : SHORT_ADDRESS_SIZE;
if (*p_addr_array_len == max_addr_array_len)
{
@@ -292,10 +297,13 @@ static bool addr_add(const uint8_t * p_addr, uint8_t location, bool extended)
*/
static bool addr_remove(uint8_t location, bool extended)
{
uint8_t * p_addr_array = extended ? (uint8_t *)m_pending_extended :
(uint8_t *)m_pending_short;
uint8_t * p_addr_array_len = extended ? &m_num_of_pending_extended : &m_num_of_pending_short;
uint8_t entry_size = extended ? EXTENDED_ADDRESS_SIZE : SHORT_ADDRESS_SIZE;
uint8_t * p_addr_array;
uint8_t * p_addr_array_len;
uint8_t entry_size;
p_addr_array = extended ? (uint8_t *)m_pending_extended : (uint8_t *)m_pending_short;
p_addr_array_len = extended ? &m_num_of_pending_extended : &m_num_of_pending_short;
entry_size = extended ? EXTENDED_ADDRESS_SIZE : SHORT_ADDRESS_SIZE;
if (*p_addr_array_len == 0)
{
@@ -108,4 +108,3 @@ bool nrf_802154_ack_pending_bit_should_be_set(const uint8_t * p_psdu);
#endif
#endif /* NRF_802154_ACK_PENDING_BIT_H_ */
@@ -60,7 +60,7 @@ extern "C" {
*
*/
#ifndef NRF_802154_CCA_MODE_DEFAULT
#define NRF_802154_CCA_MODE_DEFAULT NRF_RADIO_CCA_MODE_ED
#define NRF_802154_CCA_MODE_DEFAULT NRF_RADIO_CCA_MODE_ED
#endif
/**
@@ -70,7 +70,7 @@ extern "C" {
*
*/
#ifndef NRF_802154_CCA_ED_THRESHOLD_DEFAULT
#define NRF_802154_CCA_ED_THRESHOLD_DEFAULT 0x14
#define NRF_802154_CCA_ED_THRESHOLD_DEFAULT 0x14
#endif
/**
@@ -80,7 +80,7 @@ extern "C" {
*
*/
#ifndef NRF_802154_CCA_CORR_THRESHOLD_DEFAULT
#define NRF_802154_CCA_CORR_THRESHOLD_DEFAULT 0x14
#define NRF_802154_CCA_CORR_THRESHOLD_DEFAULT 0x14
#endif
/**
@@ -90,7 +90,7 @@ extern "C" {
*
*/
#ifndef NRF_802154_CCA_CORR_LIMIT_DEFAULT
#define NRF_802154_CCA_CORR_LIMIT_DEFAULT 0x02
#define NRF_802154_CCA_CORR_LIMIT_DEFAULT 0x02
#endif
/**
@@ -103,11 +103,11 @@ extern "C" {
#ifndef NRF_802154_INTERNAL_RADIO_IRQ_HANDLING
#if RAAL_SOFTDEVICE
#if RAAL_SOFTDEVICE || RAAL_REM
#define NRF_802154_INTERNAL_RADIO_IRQ_HANDLING 0
#else // RAAL_SOFTDEVICE
#else // RAAL_SOFTDEVICE || RAAL_REM
#define NRF_802154_INTERNAL_RADIO_IRQ_HANDLING 1
#endif // RAAL_SOFTDEVICE
#endif // RAAL_SOFTDEVICE || RAAL_REM
#endif // NRF_802154_INTERNAL_RADIO_IRQ_HANDLING
@@ -120,7 +120,7 @@ extern "C" {
*
*/
#ifndef NRF_802154_IRQ_PRIORITY
#define NRF_802154_IRQ_PRIORITY 0
#define NRF_802154_IRQ_PRIORITY 0
#endif
/**
@@ -213,7 +213,7 @@ extern "C" {
*
*/
#ifndef NRF_802154_PENDING_SHORT_ADDRESSES
#define NRF_802154_PENDING_SHORT_ADDRESSES 10
#define NRF_802154_PENDING_SHORT_ADDRESSES 10
#endif
/**
@@ -223,7 +223,7 @@ extern "C" {
*
*/
#ifndef NRF_802154_PENDING_EXTENDED_ADDRESSES
#define NRF_802154_PENDING_EXTENDED_ADDRESSES 10
#define NRF_802154_PENDING_EXTENDED_ADDRESSES 10
#endif
/**
@@ -233,7 +233,7 @@ extern "C" {
*
*/
#ifndef NRF_802154_RX_BUFFERS
#define NRF_802154_RX_BUFFERS 16
#define NRF_802154_RX_BUFFERS 16
#endif
/**
@@ -256,7 +256,7 @@ extern "C" {
*
*/
#ifndef NRF_802154_NOTIFY_CRCERROR
#define NRF_802154_NOTIFY_CRCERROR 1
#define NRF_802154_NOTIFY_CRCERROR 1
#endif
/**
@@ -330,7 +330,7 @@ extern "C" {
*
*/
#ifndef NRF_802154_RTC_IRQ_PRIORITY
#define NRF_802154_RTC_IRQ_PRIORITY 6
#define NRF_802154_RTC_IRQ_PRIORITY 6
#endif
/**
@@ -343,7 +343,7 @@ extern "C" {
*
*/
#ifndef NRF_802154_RTC_INSTANCE
#define NRF_802154_RTC_INSTANCE NRF_RTC2
#define NRF_802154_RTC_INSTANCE NRF_RTC2
#endif
/**
@@ -356,10 +356,9 @@ extern "C" {
*
*/
#ifndef NRF_802154_RTC_IRQ_HANDLER
#define NRF_802154_RTC_IRQ_HANDLER RTC2_IRQHandler
#define NRF_802154_RTC_IRQ_HANDLER RTC2_IRQHandler
#endif
/**
* @def NRF_802154_RTC_IRQN
*
@@ -370,10 +369,9 @@ extern "C" {
*
*/
#ifndef NRF_802154_RTC_IRQN
#define NRF_802154_RTC_IRQN RTC2_IRQn
#define NRF_802154_RTC_IRQN RTC2_IRQn
#endif
/**
* @}
* @defgroup nrf_802154_config_csma CSMA/CA procedure configuration
@@ -39,77 +39,77 @@
#include <stdint.h>
#include "nrf_802154_config.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_REQUEST_OFFSET 1 ///< Byte containing Ack request bit (+1 for frame length byte).
#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 ACK_REQUEST_BIT (1 << 5) ///< Ack request bit.
#define DEST_ADDR_TYPE_OFFSET 2 ///< Byte containing destination address type (+1 for frame length byte).
#define DEST_ADDR_TYPE_MASK 0x0c ///< Mask of bits containing destination address type.
#define DEST_ADDR_TYPE_EXTENDED 0x0c ///< Bits containing extended destination address type.
#define DEST_ADDR_TYPE_NONE 0x00 ///< Bits containing not present destination address type.
#define DEST_ADDR_TYPE_SHORT 0x08 ///< Bits containing short destination address type.
#define DEST_ADDR_OFFSET 6 ///< Offset of destination address in Data frame (+1 for frame length byte).
#define DEST_ADDR_TYPE_OFFSET 2 ///< Byte containing destination address type (+1 for frame length byte).
#define DEST_ADDR_TYPE_MASK 0x0c ///< Mask of bits containing destination address type.
#define DEST_ADDR_TYPE_EXTENDED 0x0c ///< Bits containing extended destination address type.
#define DEST_ADDR_TYPE_NONE 0x00 ///< Bits containing not present destination address type.
#define DEST_ADDR_TYPE_SHORT 0x08 ///< Bits containing short destination address type.
#define DEST_ADDR_OFFSET 6 ///< Offset of destination address in Data frame (+1 for frame length byte).
#define DSN_OFFSET 3 ///< Byte containing DSN value (+1 for frame length byte).
#define DSN_OFFSET 3 ///< Byte containing DSN value (+1 for frame length byte).
#define FRAME_PENDING_OFFSET 1 ///< Byte containing pending bit (+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_PENDING_BIT (1 << 4) ///< Pending bit.
#define FRAME_TYPE_OFFSET 1 ///< Byte containing frame type bits (+1 for frame length byte).
#define FRAME_TYPE_MASK 0x07 ///< Mask of bits containing frame type.
#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_EXTENDED 0x07 ///< Bits containing Extended frame type.
#define FRAME_TYPE_FRAGMENT 0x06 ///< Bits containing Fragment or Frak frame type.
#define FRAME_TYPE_MULTIPURPOSE 0x05 ///< Bits containing Multipurpose frame type.
#define FRAME_TYPE_OFFSET 1 ///< Byte containing frame type bits (+1 for frame length byte).
#define FRAME_TYPE_MASK 0x07 ///< Mask of bits containing frame type.
#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_EXTENDED 0x07 ///< Bits containing Extended frame type.
#define FRAME_TYPE_FRAGMENT 0x06 ///< Bits containing Fragment or Frak frame type.
#define FRAME_TYPE_MULTIPURPOSE 0x05 ///< Bits containing Multipurpose frame type.
#define FRAME_VERSION_OFFSET 2 ///< Byte containing frame version bits (+1 for frame length byte).
#define FRAME_VERSION_MASK 0x30 ///< Mask of bits containing frame version.
#define FRAME_VERSION_0 0x00 ///< Bits containing frame version 0b00.
#define FRAME_VERSION_1 0x10 ///< Bits containing frame version 0b01.
#define FRAME_VERSION_2 0x20 ///< Bits containing frame version 0b10.
#define FRAME_VERSION_3 0x30 ///< Bits containing frame version 0b11.
#define FRAME_VERSION_OFFSET 2 ///< Byte containing frame version bits (+1 for frame length byte).
#define FRAME_VERSION_MASK 0x30 ///< Mask of bits containing frame version.
#define FRAME_VERSION_0 0x00 ///< Bits containing frame version 0b00.
#define FRAME_VERSION_1 0x10 ///< Bits containing frame version 0b01.
#define FRAME_VERSION_2 0x20 ///< Bits containing frame version 0b10.
#define FRAME_VERSION_3 0x30 ///< Bits containing frame version 0b11.
#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_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 4 ///< Offset of Pan Id in Data frame (+1 for frame length byte).
#define PAN_ID_OFFSET 4 ///< Offset of Pan Id in Data frame (+1 for frame length byte).
#define SRC_ADDR_TYPE_EXTENDED 0xc0 ///< Bits containing extended source address type.
#define SRC_ADDR_TYPE_NONE 0x00 ///< Bits containing not present 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_TYPE_EXTENDED 0xc0 ///< Bits containing extended source address type.
#define SRC_ADDR_TYPE_NONE 0x00 ///< Bits containing not present 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 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 PHR_SIZE 1 ///< Size of PHR field.
#define FCF_SIZE 2 ///< Size of FCF field.
#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 FCS_SIZE 2 ///< Size of FCS field.
#define IMM_ACK_LENGTH 5 ///< Length of ACK frame.
#define MAX_PACKET_SIZE 127 ///< Maximum size of radio packet.
#define PHR_SIZE 1 ///< Size of PHR field.
#define FCF_SIZE 2 ///< Size of FCF field.
#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 FCS_SIZE 2 ///< Size of FCS field.
#define IMM_ACK_LENGTH 5 ///< Length of ACK frame.
#define MAX_PACKET_SIZE 127 ///< Maximum size of radio packet.
#define TURNAROUND_TIME 192UL ///< aTurnaroundTime [us].
#define CCA_TIME 128UL ///< aCcaTime [us].
#define UNIT_BACKOFF_PERIOD (TURNAROUND_TIME + CCA_TIME) ///< aUnitBackoffPeriod [us].
#define TURNAROUND_TIME 192UL ///< aTurnaroundTime [us].
#define CCA_TIME 128UL ///< aCcaTime [us].
#define UNIT_BACKOFF_PERIOD (TURNAROUND_TIME + CCA_TIME) ///< aUnitBackoffPeriod [us].
#define PHY_US_PER_SYMBOL 16 ///< Duration of a single symbol in microseconds [us].
#define PHY_SYMBOLS_PER_OCTET 2 ///< Number of symbols in a single byte (octet).
#define PHY_SHR_SYMBOLS 10 ///< Number of symbols in Synchronization Header (SHR).
#define PHY_US_PER_SYMBOL 16 ///< Duration of a single symbol in microseconds [us].
#define PHY_SYMBOLS_PER_OCTET 2 ///< Number of symbols in a single byte (octet).
#define PHY_SHR_SYMBOLS 10 ///< Number of symbols in Synchronization Header (SHR).
#define ED_MIN_DBM (-94) ///< dBm value corresponding to value 0 in EDSAMPLE register.
#define ED_RESULT_FACTOR 4 ///< Factor needed to calculate ED result based on data from RADIO peripheral.
#define ED_RESULT_MAX 0xff ///< Maximal ED result.
#define ED_MIN_DBM (-94) ///< dBm value corresponding to value 0 in EDSAMPLE register.
#define ED_RESULT_FACTOR 4 ///< Factor needed to calculate ED result based on data from RADIO peripheral.
#define ED_RESULT_MAX 0xff ///< Maximal ED result.
#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 enum
{
+260 -223
View File
@@ -49,10 +49,8 @@
#include "nrf_802154_debug.h"
#include "nrf_802154_notification.h"
#include "nrf_802154_pib.h"
#include "nrf_802154_priority_drop.h"
#include "nrf_802154_procedures_duration.h"
#include "nrf_802154_revision.h"
#include "nrf_802154_rsch.h"
#include "nrf_802154_rssi.h"
#include "nrf_802154_rx_buffer.h"
#include "nrf_802154_timer_coord.h"
@@ -62,35 +60,37 @@
#include "hal/nrf_ppi.h"
#include "hal/nrf_radio.h"
#include "hal/nrf_timer.h"
#include "mac_features/nrf_802154_delayed_trx.h"
#include "mac_features/nrf_802154_filter.h"
#include "rsch/nrf_802154_rsch.h"
#include "rsch/nrf_802154_rsch_crit_sect.h"
#include "nrf_802154_core_hooks.h"
#define EGU_EVENT NRF_EGU_EVENT_TRIGGERED15
#define EGU_TASK NRF_EGU_TASK_TRIGGER15
#define PPI_CH0 NRF_PPI_CHANNEL6
#define PPI_CH1 NRF_PPI_CHANNEL7
#define PPI_CH2 NRF_PPI_CHANNEL8
#define PPI_CH3 NRF_PPI_CHANNEL9
#define PPI_CH4 NRF_PPI_CHANNEL10
#define PPI_CH5 NRF_PPI_CHANNEL11
#define PPI_CH6 NRF_PPI_CHANNEL12
#define PPI_CHGRP0 NRF_PPI_CHANNEL_GROUP0 ///< PPI group used to disable self-disabling PPIs
#define PPI_CHGRP0_DIS_TASK NRF_PPI_TASK_CHG0_DIS ///< PPI task used to disable self-disabling PPIs
#define EGU_EVENT NRF_EGU_EVENT_TRIGGERED15
#define EGU_TASK NRF_EGU_TASK_TRIGGER15
#define PPI_CH0 NRF_PPI_CHANNEL6
#define PPI_CH1 NRF_PPI_CHANNEL7
#define PPI_CH2 NRF_PPI_CHANNEL8
#define PPI_CH3 NRF_PPI_CHANNEL9
#define PPI_CH4 NRF_PPI_CHANNEL10
#define PPI_CH5 NRF_PPI_CHANNEL11
#define PPI_CH6 NRF_PPI_CHANNEL12
#define PPI_CHGRP0 NRF_PPI_CHANNEL_GROUP0 ///< PPI group used to disable self-disabling PPIs
#define PPI_CHGRP0_DIS_TASK NRF_PPI_TASK_CHG0_DIS
#define PPI_DISABLED_EGU PPI_CH0 ///< PPI that connects RADIO DISABLED event with EGU task
#define PPI_EGU_RAMP_UP PPI_CH1 ///< PPI that connects EGU event with RADIO TXEN or RXEN task
#define PPI_EGU_TIMER_START PPI_CH2 ///< PPI that connects EGU event with TIMER START task
#define PPI_CRCERROR_CLEAR PPI_CH3 ///< PPI that connects RADIO CRCERROR event with TIMER CLEAR task
#define PPI_CCAIDLE_FEM PPI_CH3 ///< PPI that connects RADIO CCAIDLE event with GPIOTE tasks used by FEM
#define PPI_TIMER_TX_ACK PPI_CH3 ///< PPI that connects TIMER COMPARE event with RADIO TXEN task
#define PPI_CRCOK_DIS_PPI PPI_CH4 ///< PPI that connects RADIO CRCOK event with task that disables PPI group
#define PPI_DISABLED_EGU PPI_CH0 ///< PPI that connects RADIO DISABLED event with EGU task
#define PPI_EGU_RAMP_UP PPI_CH1 ///< PPI that connects EGU event with RADIO TXEN or RXEN task
#define PPI_EGU_TIMER_START PPI_CH2 ///< PPI that connects EGU event with TIMER START task
#define PPI_CRCERROR_CLEAR PPI_CH3 ///< PPI that connects RADIO CRCERROR event with TIMER CLEAR task
#define PPI_CCAIDLE_FEM PPI_CH3 ///< PPI that connects RADIO CCAIDLE event with GPIOTE tasks used by FEM
#define PPI_TIMER_TX_ACK PPI_CH3 ///< PPI that connects TIMER COMPARE event with RADIO TXEN task
#define PPI_CRCOK_DIS_PPI PPI_CH4 ///< PPI that connects RADIO CRCOK event with task that disables PPI group
#if NRF_802154_DISABLE_BCC_MATCHING
#define PPI_ADDRESS_COUNTER_COUNT PPI_CH5 ///< PPI that connects RADIO ADDRESS event with TIMER COUNT task
#define PPI_CRCERROR_COUNTER_CLEAR PPI_CH6 ///< PPI that connects RADIO CRCERROR event with TIMER CLEAR task
#endif // NRF_802154_DISABLE_BCC_MATCHING
#define PPI_ADDRESS_COUNTER_COUNT PPI_CH5 ///< PPI that connects RADIO ADDRESS event with TIMER COUNT task
#define PPI_CRCERROR_COUNTER_CLEAR PPI_CH6 ///< PPI that connects RADIO CRCERROR event with TIMER CLEAR task
#endif // NRF_802154_DISABLE_BCC_MATCHING
/// Workaround for missing PHYEND event in older chip revision.
static inline uint32_t short_phyend_disable_mask_get(void)
@@ -104,77 +104,78 @@ static inline uint32_t short_phyend_disable_mask_get(void)
}
#if NRF_802154_DISABLE_BCC_MATCHING
#define SHORT_ADDRESS_BCSTART 0UL
#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
#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
#define SHORTS_IDLE 0
/// Value set to SHORTS register for RX operation.
#define SHORTS_RX (NRF_RADIO_SHORT_ADDRESS_RSSISTART_MASK | \
NRF_RADIO_SHORT_END_DISABLE_MASK | \
SHORT_ADDRESS_BCSTART)
#define SHORTS_RX (NRF_RADIO_SHORT_ADDRESS_RSSISTART_MASK | \
NRF_RADIO_SHORT_END_DISABLE_MASK | \
SHORT_ADDRESS_BCSTART)
#define SHORTS_RX_FREE_BUFFER (NRF_RADIO_SHORT_RXREADY_START_MASK)
#define SHORTS_RX_FREE_BUFFER (NRF_RADIO_SHORT_RXREADY_START_MASK)
#define SHORTS_TX_ACK (NRF_RADIO_SHORT_TXREADY_START_MASK | \
short_phyend_disable_mask_get())
#define SHORTS_TX_ACK (NRF_RADIO_SHORT_TXREADY_START_MASK | \
short_phyend_disable_mask_get())
#define SHORTS_CCA_TX (NRF_RADIO_SHORT_RXREADY_CCASTART_MASK | \
NRF_RADIO_SHORT_CCABUSY_DISABLE_MASK | \
NRF_RADIO_SHORT_CCAIDLE_TXEN_MASK | \
NRF_RADIO_SHORT_TXREADY_START_MASK | \
short_phyend_disable_mask_get())
#define SHORTS_CCA_TX (NRF_RADIO_SHORT_RXREADY_CCASTART_MASK | \
NRF_RADIO_SHORT_CCABUSY_DISABLE_MASK | \
NRF_RADIO_SHORT_CCAIDLE_TXEN_MASK | \
NRF_RADIO_SHORT_TXREADY_START_MASK | \
short_phyend_disable_mask_get())
#define SHORTS_TX (NRF_RADIO_SHORT_TXREADY_START_MASK | \
short_phyend_disable_mask_get())
#define SHORTS_TX (NRF_RADIO_SHORT_TXREADY_START_MASK | \
short_phyend_disable_mask_get())
#define SHORTS_RX_ACK (NRF_RADIO_SHORT_ADDRESS_RSSISTART_MASK | \
NRF_RADIO_SHORT_END_DISABLE_MASK)
#define SHORTS_RX_ACK (NRF_RADIO_SHORT_ADDRESS_RSSISTART_MASK | \
NRF_RADIO_SHORT_END_DISABLE_MASK)
#define SHORTS_ED (NRF_RADIO_SHORT_READY_EDSTART_MASK)
#define SHORTS_ED (NRF_RADIO_SHORT_READY_EDSTART_MASK)
#define SHORTS_CCA (NRF_RADIO_SHORT_RXREADY_CCASTART_MASK | \
NRF_RADIO_SHORT_CCABUSY_DISABLE_MASK)
#define SHORTS_CCA (NRF_RADIO_SHORT_RXREADY_CCASTART_MASK | \
NRF_RADIO_SHORT_CCABUSY_DISABLE_MASK)
/// Delay before first check of received frame: 24 bits is PHY header and MAC Frame Control field.
#define BCC_INIT (3 * 8)
#define BCC_INIT (3 * 8)
/// Duration of single iteration of Energy Detection procedure
#define ED_ITER_DURATION 128U
#define ED_ITER_DURATION 128U
/// Overhead of hardware preparation for ED procedure (aTurnaroundTime) [number of iterations]
#define ED_ITERS_OVERHEAD 2U
#define ED_ITERS_OVERHEAD 2U
#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 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 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 ACK_IFS TURNAROUND_TIME ///< Ack Inter Frame Spacing [us] - delay between last symbol of received frame and first symbol of transmitted Ack
#define TXRU_TIME 40 ///< Transmitter ramp up time [us]
#define EVENT_LAT 23 ///< END event latency [us]
#define ACK_IFS TURNAROUND_TIME ///< Ack Inter Frame Spacing [us] - delay between last symbol of received frame and first symbol of transmitted Ack
#define TXRU_TIME 40 ///< Transmitter ramp up time [us]
#define EVENT_LAT 23 ///< END event latency [us]
#define MAX_CRIT_SECT_TIME 60 ///< Maximal time that the driver spends in single critical section.
#define LQI_VALUE_FACTOR 4 ///< Factor needed to calculate LQI value based on data from RADIO peripheral
#define LQI_MAX 0xff ///< Maximal LQI value
#define MAX_CRIT_SECT_TIME 60 ///< Maximal time that the driver spends in single critical section.
#define LQI_VALUE_FACTOR 4 ///< Factor needed to calculate LQI value based on data from RADIO peripheral
#define LQI_MAX 0xff ///< Maximal LQI value
/** 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])
#define RX_FRAME_LQI(psdu) ((psdu)[(psdu)[0] - 1])
#if NRF_802154_RX_BUFFERS > 1
/// Pointer to currently used receive buffer.
static rx_buffer_t * mp_current_rx_buffer;
#else
/// If there is only one buffer use const pointer to the receive buffer.
static rx_buffer_t * const mp_current_rx_buffer = &nrf_802154_rx_buffers[0];
#endif
static uint8_t m_ack_psdu[IMM_ACK_LENGTH + 1]; ///< ACK frame buffer.
@@ -182,22 +183,25 @@ static const uint8_t * mp_tx_data; ///< Pointer to the data
static uint32_t m_ed_time_left; ///< Remaining time of the current energy detection procedure [us].
static uint8_t m_ed_result; ///< Result of the current energy detection procedure.
static volatile radio_state_t m_state; ///< State of the radio driver.
static volatile radio_state_t m_state; ///< State of the radio driver.
typedef struct
{
bool frame_filtered :1; ///< If frame being received passed filtering operation.
bool rx_timeslot_requested :1; ///< If timeslot for the frame being received is already requested.
#if !NRF_802154_DISABLE_BCC_MATCHING
bool psdu_being_received :1; ///< If PSDU is currently being received.
#endif // !NRF_802154_DISABLE_BCC_MATCHING
#if NRF_802154_TX_STARTED_NOTIFY_ENABLED
bool tx_started :1; ///< If requested transmission has started.
#endif // NRF_802154_TX_STARTED_NOTIFY_ENABLED
} nrf_802154_flags_t;
static nrf_802154_flags_t m_flags; ///< Flags used to store current driver state.
bool frame_filtered : 1; ///< If frame being received passed filtering operation.
bool rx_timeslot_requested : 1; ///< If timeslot for the frame being received is already requested.
static volatile bool m_rsch_timeslot_is_granted; ///< State of the RSCH timeslot.
#if !NRF_802154_DISABLE_BCC_MATCHING
bool psdu_being_received : 1; ///< If PSDU is currently being received.
#endif // !NRF_802154_DISABLE_BCC_MATCHING
#if NRF_802154_TX_STARTED_NOTIFY_ENABLED
bool tx_started : 1; ///< If requested transmission has started.
#endif // NRF_802154_TX_STARTED_NOTIFY_ENABLED
} nrf_802154_flags_t;
static nrf_802154_flags_t m_flags; ///< Flags used to store current driver state.
static volatile bool m_rsch_timeslot_is_granted; ///< State of the RSCH timeslot.
/***************************************************************************************************
* @section Common core operations
@@ -220,7 +224,7 @@ static void rx_flags_clear(void)
m_flags.frame_filtered = false;
m_flags.rx_timeslot_requested = false;
#if !NRF_802154_DISABLE_BCC_MATCHING
m_flags.psdu_being_received = false;
m_flags.psdu_being_received = false;
#endif // !NRF_802154_DISABLE_BCC_MATCHING
}
@@ -247,7 +251,7 @@ static uint8_t lqi_get(const uint8_t * p_data)
{
uint32_t lqi = RX_FRAME_LQI(p_data);
lqi = nrf_802154_rssi_lqi_corrected_get(lqi);
lqi = nrf_802154_rssi_lqi_corrected_get(lqi);
lqi *= LQI_VALUE_FACTOR;
if (lqi > LQI_MAX)
@@ -260,9 +264,9 @@ static uint8_t lqi_get(const uint8_t * p_data)
static void received_frame_notify(uint8_t * p_psdu)
{
nrf_802154_notify_received(p_psdu, // data
rssi_last_measurement_get(), // rssi
lqi_get(p_psdu)); // lqi
nrf_802154_notify_received(p_psdu, // data
rssi_last_measurement_get(), // rssi
lqi_get(p_psdu)); // lqi
}
/** Allow nesting critical sections and notify MAC layer that a frame was received. */
@@ -297,6 +301,15 @@ static void transmit_started_notify(void)
}
#if !NRF_802154_DISABLE_BCC_MATCHING
/** Notify that reception of a frame has started. */
static void receive_started_notify(void)
{
nrf_802154_core_hooks_rx_started();
}
#endif
/** Notify MAC layer that a frame was transmitted. */
static void transmitted_frame_notify(uint8_t * p_ack, int8_t power, int8_t lqi)
{
@@ -359,7 +372,7 @@ static void cca_configuration_update(void)
nrf_802154_pib_cca_cfg_get(&cca_cfg);
nrf_radio_cca_mode_set(cca_cfg.mode);
nrf_radio_cca_ed_threshold_set(
nrf_802154_rssi_cca_ed_threshold_corrected_get(cca_cfg.ed_threshold));
nrf_802154_rssi_cca_ed_threshold_corrected_get(cca_cfg.ed_threshold));
nrf_radio_cca_corr_threshold_set(cca_cfg.corr_threshold);
nrf_radio_cca_corr_counter_set(cca_cfg.corr_limit);
}
@@ -371,7 +384,8 @@ static void cca_configuration_update(void)
static bool 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));
nrf_timer_task_trigger(NRF_802154_COUNTER_TIMER_INSTANCE,
nrf_timer_capture_task_get(NRF_TIMER_CC_CHANNEL0));
uint32_t counter = nrf_timer_cc_read(NRF_802154_COUNTER_TIMER_INSTANCE, NRF_TIMER_CC_CHANNEL0);
assert(counter <= 1);
@@ -379,7 +393,7 @@ static bool psdu_is_being_received(void)
return counter > 0;
#else // NRF_802154_DISABLE_BCC_MATCHING
return m_flags.psdu_being_received;
#endif // NRF_802154_DISABLE_BCC_MATCHING
#endif // NRF_802154_DISABLE_BCC_MATCHING
}
/** Check if requested transmission has already started.
@@ -393,7 +407,7 @@ static bool transmission_has_started(void)
return m_flags.tx_started;
#else // NRF_802154_TX_STARTED_NOTIFY_ENABLED
return nrf_radio_event_get(NRF_RADIO_EVENT_ADDRESS);
#endif // NRF_802154_TX_STARTED_NOTIFY_ENABLED
#endif // NRF_802154_TX_STARTED_NOTIFY_ENABLED
}
/** Check if timeslot is currently granted.
@@ -419,7 +433,7 @@ static void rx_buffer_in_use_set(rx_buffer_t * p_rx_buffer)
#if NRF_802154_RX_BUFFERS > 1
mp_current_rx_buffer = p_rx_buffer;
#else
(void) p_rx_buffer;
(void)p_rx_buffer;
#endif
}
@@ -500,7 +514,7 @@ static void ack_matching_enable(void)
{
nrf_radio_event_clear(NRF_RADIO_EVENT_MHRMATCH);
nrf_radio_mhmu_search_pattern_set(MHMU_PATTERN |
((uint32_t) mp_tx_data[DSN_OFFSET] <<
((uint32_t)mp_tx_data[DSN_OFFSET] <<
MHMU_PATTERN_DSN_OFFSET));
}
@@ -519,7 +533,7 @@ static void ack_matching_disable(void)
static bool ack_is_matched(void)
{
return (nrf_radio_event_get(NRF_RADIO_EVENT_MHRMATCH)) &&
(nrf_radio_crc_status_get() == NRF_RADIO_CRC_STATUS_OK);
(nrf_radio_crc_status_get() == NRF_RADIO_CRC_STATUS_OK);
}
/***************************************************************************************************
@@ -579,7 +593,6 @@ static void irq_deinit(void)
__ISB();
}
/***************************************************************************************************
* @section TIMER peripheral management
**************************************************************************************************/
@@ -610,7 +623,7 @@ static uint8_t ed_result_get(void)
{
uint32_t result = m_ed_result;
result = nrf_802154_rssi_ed_corrected_get(result);
result = nrf_802154_rssi_ed_corrected_get(result);
result *= ED_RESULT_FACTOR;
if (result > ED_RESULT_MAX)
@@ -666,7 +679,6 @@ static bool ed_iter_setup(uint32_t time_us)
}
}
/***************************************************************************************************
* @section FSM transition request sub-procedures
**************************************************************************************************/
@@ -728,26 +740,26 @@ static void ppis_for_egu_and_ramp_up_set(nrf_radio_task_t ramp_up_task, bool sel
{
nrf_ppi_channel_and_fork_endpoint_setup(PPI_EGU_RAMP_UP,
(uint32_t)nrf_egu_event_address_get(
NRF_802154_SWI_EGU_INSTANCE,
EGU_EVENT),
NRF_802154_SWI_EGU_INSTANCE,
EGU_EVENT),
(uint32_t)nrf_radio_task_address_get(ramp_up_task),
(uint32_t)nrf_ppi_task_address_get(
PPI_CHGRP0_DIS_TASK));
PPI_CHGRP0_DIS_TASK));
}
else
{
nrf_ppi_channel_endpoint_setup(PPI_EGU_RAMP_UP,
(uint32_t)nrf_egu_event_address_get(
NRF_802154_SWI_EGU_INSTANCE,
EGU_EVENT),
NRF_802154_SWI_EGU_INSTANCE,
EGU_EVENT),
(uint32_t)nrf_radio_task_address_get(ramp_up_task));
}
nrf_ppi_channel_endpoint_setup(PPI_DISABLED_EGU,
(uint32_t)nrf_radio_event_address_get(NRF_RADIO_EVENT_DISABLED),
(uint32_t)nrf_egu_task_address_get(
NRF_802154_SWI_EGU_INSTANCE,
EGU_TASK));
NRF_802154_SWI_EGU_INSTANCE,
EGU_TASK));
if (self_disabling)
{
@@ -767,8 +779,8 @@ static void fem_for_lna_set(nrf_timer_cc_channel_t cc_channel,
nrf_fem_control_ppi_task_setup(NRF_FEM_CONTROL_LNA_PIN,
PPI_EGU_TIMER_START,
(uint32_t)nrf_egu_event_address_get(
NRF_802154_SWI_EGU_INSTANCE,
EGU_EVENT),
NRF_802154_SWI_EGU_INSTANCE,
EGU_EVENT),
(uint32_t)nrf_timer_task_address_get(
NRF_802154_TIMER_INSTANCE,
NRF_TIMER_TASK_START));
@@ -845,8 +857,8 @@ static void fem_for_tx_reset(bool disable_ppi_egu_timer_start)
{
nrf_fem_control_ppi_disable(NRF_FEM_CONTROL_ANY_PIN);
nrf_fem_control_timer_reset(NRF_FEM_CONTROL_ANY_PIN,
(nrf_timer_short_mask_t) (NRF_TIMER_SHORT_COMPARE0_STOP_MASK |
NRF_TIMER_SHORT_COMPARE1_STOP_MASK));
(nrf_timer_short_mask_t)(NRF_TIMER_SHORT_COMPARE0_STOP_MASK |
NRF_TIMER_SHORT_COMPARE1_STOP_MASK));
nrf_fem_control_ppi_fork_clear(NRF_FEM_CONTROL_ANY_PIN, PPI_CCAIDLE_FEM);
nrf_ppi_channel_disable(PPI_CCAIDLE_FEM);
@@ -891,7 +903,7 @@ static void rx_restart(bool set_shorts)
// Prepare the timer coordinator to get a precise timestamp of the CRCOK event.
nrf_802154_timer_coord_timestamp_prepare(
(uint32_t)nrf_radio_event_address_get(NRF_RADIO_EVENT_CRCOK));
(uint32_t)nrf_radio_event_address_get(NRF_RADIO_EVENT_CRCOK));
if (!ppi_egu_worked())
{
@@ -947,8 +959,7 @@ static void falling_asleep_terminate(void)
/** Terminate Sleep procedure. */
static void sleep_terminate(void)
{
nrf_802154_priority_drop_timeslot_exit_terminate();
nrf_802154_rsch_continuous_mode_enter();
nrf_802154_rsch_crit_sect_prio_request(RSCH_PRIO_MAX);
}
/** Terminate RX procedure. */
@@ -974,11 +985,13 @@ static void rx_terminate(void)
nrf_ppi_fork_endpoint_setup(PPI_EGU_TIMER_START, 0);
#else // NRF_802154_DISABLE_BCC_MATCHING
nrf_ppi_fork_endpoint_setup(PPI_EGU_RAMP_UP, 0);
#endif // NRF_802154_DISABLE_BCC_MATCHING
#endif // NRF_802154_DISABLE_BCC_MATCHING
// Anomaly 78: use SHUTDOWN instead of STOP and CLEAR.
nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_SHUTDOWN);
nrf_timer_shorts_disable(NRF_802154_TIMER_INSTANCE, NRF_TIMER_SHORT_COMPARE0_STOP_MASK | NRF_TIMER_SHORT_COMPARE2_STOP_MASK);
nrf_timer_shorts_disable(NRF_802154_TIMER_INSTANCE,
NRF_TIMER_SHORT_COMPARE0_STOP_MASK |
NRF_TIMER_SHORT_COMPARE2_STOP_MASK);
#if NRF_802154_DISABLE_BCC_MATCHING
// Anomaly 78: use SHUTDOWN instead of STOP and CLEAR.
@@ -1023,7 +1036,9 @@ static void tx_ack_terminate(void)
// Anomaly 78: use SHUTDOWN instead of STOP and CLEAR.
nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_SHUTDOWN);
nrf_timer_shorts_disable(NRF_802154_TIMER_INSTANCE, NRF_TIMER_SHORT_COMPARE0_STOP_MASK | NRF_TIMER_SHORT_COMPARE2_STOP_MASK);
nrf_timer_shorts_disable(NRF_802154_TIMER_INSTANCE,
NRF_TIMER_SHORT_COMPARE0_STOP_MASK |
NRF_TIMER_SHORT_COMPARE2_STOP_MASK);
#if NRF_802154_DISABLE_BCC_MATCHING
// Anomaly 78: use SHUTDOWN instead of STOP and CLEAR.
@@ -1034,7 +1049,7 @@ static void tx_ack_terminate(void)
if (timeslot_is_granted())
{
ints_to_disable = nrf_802154_revision_has_phyend_event() ?
NRF_RADIO_INT_PHYEND_MASK : NRF_RADIO_INT_END_MASK;
NRF_RADIO_INT_PHYEND_MASK : NRF_RADIO_INT_END_MASK;
#if NRF_802154_TX_STARTED_NOTIFY_ENABLED
ints_to_disable |= NRF_RADIO_INT_ADDRESS_MASK;
#endif // NRF_802154_TX_STARTED_NOTIFY_ENABLED
@@ -1061,7 +1076,7 @@ static void tx_terminate(void)
if (timeslot_is_granted())
{
ints_to_disable = nrf_802154_revision_has_phyend_event() ?
NRF_RADIO_INT_PHYEND_MASK : NRF_RADIO_INT_END_MASK;
NRF_RADIO_INT_PHYEND_MASK : NRF_RADIO_INT_END_MASK;
ints_to_disable |= NRF_RADIO_INT_CCABUSY_MASK;
#if NRF_802154_TX_STARTED_NOTIFY_ENABLED
ints_to_disable |= NRF_RADIO_INT_ADDRESS_MASK;
@@ -1090,7 +1105,7 @@ static void rx_ack_terminate(void)
nrf_radio_int_disable(NRF_RADIO_INT_END_MASK);
nrf_radio_shorts_set(SHORTS_IDLE);
nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE);
ack_matching_disable();
}
}
@@ -1153,7 +1168,7 @@ static void continuous_carrier_terminate(void)
*
* This function is called when MAC layer requests transition to another operation.
*
* After calling this function RADIO should enter DISABLED state and Radio Scheduler
* After calling this function RADIO should enter DISABLED state and Radio Scheduler
* should be in continuous mode.
*
* @param[in] term_lvl Termination level of this request. Selects procedures to abort.
@@ -1312,7 +1327,7 @@ static bool current_operation_terminate(nrf_802154_term_t term_lvl,
/** Enter Sleep state. */
static void sleep_init(void)
{
nrf_802154_priority_drop_timeslot_exit();
nrf_802154_rsch_crit_sect_prio_request(RSCH_PRIO_IDLE);
m_rsch_timeslot_is_granted = false;
nrf_802154_timer_coord_stop();
}
@@ -1415,64 +1430,64 @@ static void rx_init(bool disabled_was_triggered)
#if NRF_802154_DISABLE_BCC_MATCHING
nrf_ppi_channel_endpoint_setup(PPI_EGU_RAMP_UP,
(uint32_t)nrf_egu_event_address_get(
NRF_802154_SWI_EGU_INSTANCE,
EGU_EVENT),
NRF_802154_SWI_EGU_INSTANCE,
EGU_EVENT),
(uint32_t)nrf_radio_task_address_get(NRF_RADIO_TASK_RXEN));
nrf_ppi_channel_and_fork_endpoint_setup(PPI_EGU_TIMER_START,
(uint32_t)nrf_egu_event_address_get(
NRF_802154_SWI_EGU_INSTANCE,
EGU_EVENT),
NRF_802154_SWI_EGU_INSTANCE,
EGU_EVENT),
(uint32_t)nrf_timer_task_address_get(
NRF_802154_TIMER_INSTANCE,
NRF_TIMER_TASK_START),
NRF_802154_TIMER_INSTANCE,
NRF_TIMER_TASK_START),
(uint32_t)nrf_timer_task_address_get(
NRF_802154_COUNTER_TIMER_INSTANCE,
NRF_TIMER_TASK_START));
NRF_802154_COUNTER_TIMER_INSTANCE,
NRF_TIMER_TASK_START));
// Anomaly 78: use SHUTDOWN instead of CLEAR.
nrf_ppi_channel_endpoint_setup(PPI_CRCERROR_CLEAR,
(uint32_t)nrf_radio_event_address_get(NRF_RADIO_EVENT_CRCERROR),
(uint32_t)nrf_timer_task_address_get(
NRF_802154_TIMER_INSTANCE,
NRF_TIMER_TASK_SHUTDOWN));
NRF_802154_TIMER_INSTANCE,
NRF_TIMER_TASK_SHUTDOWN));
nrf_ppi_channel_endpoint_setup(PPI_CRCOK_DIS_PPI,
(uint32_t)nrf_radio_event_address_get(NRF_RADIO_EVENT_CRCOK),
(uint32_t)nrf_ppi_task_address_get(PPI_CHGRP0_DIS_TASK));
#else // NRF_802154_DISABLE_BCC_MATCHING
nrf_ppi_channel_and_fork_endpoint_setup(PPI_EGU_RAMP_UP,
(uint32_t)nrf_egu_event_address_get(
NRF_802154_SWI_EGU_INSTANCE,
EGU_EVENT),
NRF_802154_SWI_EGU_INSTANCE,
EGU_EVENT),
(uint32_t)nrf_radio_task_address_get(
NRF_RADIO_TASK_RXEN),
NRF_RADIO_TASK_RXEN),
(uint32_t)nrf_ppi_task_address_get(
PPI_CHGRP0_DIS_TASK));
PPI_CHGRP0_DIS_TASK));
nrf_ppi_channel_endpoint_setup(PPI_EGU_TIMER_START,
(uint32_t)nrf_egu_event_address_get(
NRF_802154_SWI_EGU_INSTANCE,
EGU_EVENT),
NRF_802154_SWI_EGU_INSTANCE,
EGU_EVENT),
(uint32_t)nrf_timer_task_address_get(
NRF_802154_TIMER_INSTANCE,
NRF_TIMER_TASK_START));
NRF_802154_TIMER_INSTANCE,
NRF_TIMER_TASK_START));
#endif // NRF_802154_DISABLE_BCC_MATCHING
nrf_ppi_channel_include_in_group(PPI_EGU_RAMP_UP, PPI_CHGRP0);
nrf_ppi_channel_endpoint_setup(PPI_DISABLED_EGU,
(uint32_t)nrf_radio_event_address_get(NRF_RADIO_EVENT_DISABLED),
(uint32_t)nrf_egu_task_address_get(
NRF_802154_SWI_EGU_INSTANCE,
EGU_TASK));
NRF_802154_SWI_EGU_INSTANCE,
EGU_TASK));
#if NRF_802154_DISABLE_BCC_MATCHING
nrf_ppi_channel_endpoint_setup(PPI_ADDRESS_COUNTER_COUNT,
(uint32_t)nrf_radio_event_address_get(NRF_RADIO_EVENT_ADDRESS),
(uint32_t)nrf_timer_task_address_get(
NRF_802154_COUNTER_TIMER_INSTANCE,
NRF_TIMER_TASK_COUNT));
NRF_802154_COUNTER_TIMER_INSTANCE,
NRF_TIMER_TASK_COUNT));
// Anomaly 78: use SHUTDOWN instead of CLEAR.
nrf_ppi_channel_endpoint_setup(PPI_CRCERROR_COUNTER_CLEAR,
(uint32_t)nrf_radio_event_address_get(NRF_RADIO_EVENT_CRCERROR),
(uint32_t)nrf_timer_task_address_get(
NRF_802154_COUNTER_TIMER_INSTANCE,
NRF_TIMER_TASK_SHUTDOWN));
NRF_802154_COUNTER_TIMER_INSTANCE,
NRF_TIMER_TASK_SHUTDOWN));
#endif // NRF_802154_DISABLE_BCC_MATCHING
nrf_ppi_channel_enable(PPI_EGU_RAMP_UP);
@@ -1487,7 +1502,7 @@ static void rx_init(bool disabled_was_triggered)
// Configure the timer coordinator to get a timestamp of the CRCOK event.
nrf_802154_timer_coord_timestamp_prepare(
(uint32_t)nrf_radio_event_address_get(NRF_RADIO_EVENT_CRCOK));
(uint32_t)nrf_radio_event_address_get(NRF_RADIO_EVENT_CRCOK));
// Start procedure if necessary
if (!disabled_was_triggered || !ppi_egu_worked())
@@ -1550,7 +1565,7 @@ static bool tx_init(const uint8_t * p_data, bool cca, bool disabled_was_triggere
nrf_radio_event_clear(NRF_RADIO_EVENT_ADDRESS);
#if NRF_802154_TX_STARTED_NOTIFY_ENABLED
ints_to_enable |= NRF_RADIO_INT_ADDRESS_MASK;
ints_to_enable |= NRF_RADIO_INT_ADDRESS_MASK;
m_flags.tx_started = false;
#endif // NRF_802154_TX_STARTED_NOTIFY_ENABLED
@@ -1658,17 +1673,15 @@ static void continuous_carrier_init(bool disabled_was_triggered)
}
}
/***************************************************************************************************
* @section Radio Scheduler notification handlers
**************************************************************************************************/
void nrf_802154_critical_section_rsch_prec_approved(void)
static void cont_prec_approved(void)
{
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_TIMESLOT_STARTED);
if (remaining_timeslot_time_is_enough_for_crit_sect())
if (remaining_timeslot_time_is_enough_for_crit_sect() && !timeslot_is_granted())
{
nrf_radio_reset();
nrf_radio_init();
@@ -1721,69 +1734,84 @@ void nrf_802154_critical_section_rsch_prec_approved(void)
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_TIMESLOT_STARTED);
}
void nrf_802154_critical_section_rsch_prec_denied(void)
static void cont_prec_denied(void)
{
bool result;
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_TIMESLOT_ENDED);
irq_deinit();
nrf_radio_reset();
nrf_fem_control_pin_clear();
m_rsch_timeslot_is_granted = false;
nrf_802154_timer_coord_stop();
result = current_operation_terminate(NRF_802154_TERM_802154, REQ_ORIG_RSCH, false);
assert(result);
(void)result;
switch (m_state)
if (timeslot_is_granted())
{
case RADIO_STATE_SLEEP:
// Intentionally empty.
// Ignore this notification if continuous mode was not requested.
break;
irq_deinit();
nrf_radio_reset();
nrf_fem_control_pin_clear();
case RADIO_STATE_FALLING_ASLEEP:
state_set(RADIO_STATE_SLEEP);
sleep_init();
break;
m_rsch_timeslot_is_granted = false;
nrf_802154_timer_coord_stop();
case RADIO_STATE_RX:
if (psdu_is_being_received())
{
receive_failed_notify(NRF_802154_RX_ERROR_TIMESLOT_ENDED);
}
result = current_operation_terminate(NRF_802154_TERM_802154, REQ_ORIG_RSCH, false);
assert(result);
(void)result;
break;
switch (m_state)
{
case RADIO_STATE_SLEEP:
// Intentionally empty.
// Ignore this notification if continuous mode was not requested.
break;
case RADIO_STATE_TX_ACK:
state_set(RADIO_STATE_RX);
mp_current_rx_buffer->free = false;
received_frame_notify_and_nesting_allow(mp_current_rx_buffer->psdu);
break;
case RADIO_STATE_FALLING_ASLEEP:
state_set(RADIO_STATE_SLEEP);
sleep_init();
break;
case RADIO_STATE_CCA_TX:
case RADIO_STATE_TX:
case RADIO_STATE_RX_ACK:
state_set(RADIO_STATE_RX);
transmit_failed_notify_and_nesting_allow(NRF_802154_TX_ERROR_TIMESLOT_ENDED);
break;
case RADIO_STATE_RX:
if (psdu_is_being_received())
{
receive_failed_notify(NRF_802154_RX_ERROR_TIMESLOT_ENDED);
}
case RADIO_STATE_ED:
case RADIO_STATE_CCA:
case RADIO_STATE_CONTINUOUS_CARRIER:
// Intentionally empty.
break;
break;
default:
assert(false);
case RADIO_STATE_TX_ACK:
state_set(RADIO_STATE_RX);
mp_current_rx_buffer->free = false;
received_frame_notify_and_nesting_allow(mp_current_rx_buffer->psdu);
break;
case RADIO_STATE_CCA_TX:
case RADIO_STATE_TX:
case RADIO_STATE_RX_ACK:
state_set(RADIO_STATE_RX);
transmit_failed_notify_and_nesting_allow(NRF_802154_TX_ERROR_TIMESLOT_ENDED);
break;
case RADIO_STATE_ED:
case RADIO_STATE_CCA:
case RADIO_STATE_CONTINUOUS_CARRIER:
// Intentionally empty.
break;
default:
assert(false);
}
}
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_TIMESLOT_ENDED);
}
void nrf_802154_rsch_crit_sect_prio_changed(rsch_prio_t prio)
{
if (prio > RSCH_PRIO_IDLE)
{
cont_prec_approved();
}
else
{
cont_prec_denied();
nrf_802154_rsch_continuous_ended();
}
}
/***************************************************************************************************
* @section RADIO interrupt handler
@@ -1828,7 +1856,8 @@ static void irq_bcmatch_state_rx(void)
if (!m_flags.frame_filtered)
{
m_flags.psdu_being_received = true;
filter_result = nrf_802154_filter_frame_part(mp_current_rx_buffer->psdu, &num_psdu_bytes);
filter_result = nrf_802154_filter_frame_part(mp_current_rx_buffer->psdu,
&num_psdu_bytes);
if (filter_result == NRF_802154_RX_ERROR_NONE)
{
@@ -1841,7 +1870,7 @@ static void irq_bcmatch_state_rx(void)
m_flags.frame_filtered = true;
}
}
else if ((filter_result == NRF_802154_RX_ERROR_INVALID_FRAME) ||
else if ((filter_result == NRF_802154_RX_ERROR_INVALID_LENGTH) ||
(!nrf_802154_pib_promiscuous_get()))
{
rx_terminate();
@@ -1864,10 +1893,12 @@ static void irq_bcmatch_state_rx(void)
if ((!m_flags.rx_timeslot_requested) && (frame_accepted))
{
if (nrf_802154_rsch_timeslot_request(nrf_802154_rx_duration_get(
mp_current_rx_buffer->psdu[0],
ack_is_requested(mp_current_rx_buffer->psdu))))
mp_current_rx_buffer->psdu[0],
ack_is_requested(mp_current_rx_buffer->psdu))))
{
m_flags.rx_timeslot_requested = true;
receive_started_notify();
}
else
{
@@ -1878,25 +1909,28 @@ static void irq_bcmatch_state_rx(void)
}
}
}
#endif //!NRF_802154_DISABLE_BCC_MATCHING
#endif // !NRF_802154_DISABLE_BCC_MATCHING
#if !NRF_802154_DISABLE_BCC_MATCHING || NRF_802154_NOTIFY_CRCERROR
static void irq_crcerror_state_rx(void)
{
#if !NRF_802154_DISABLE_BCC_MATCHING
rx_restart(false);
#endif //!NRF_802154_DISABLE_BCC_MATCHING
#endif // !NRF_802154_DISABLE_BCC_MATCHING
#if NRF_802154_NOTIFY_CRCERROR
receive_failed_notify(NRF_802154_RX_ERROR_INVALID_FCS);
#endif //NRF_802154_NOTIFY_CRCERROR
#endif // NRF_802154_NOTIFY_CRCERROR
}
#endif //!NRF_802154_DISABLE_BCC_MATCHING || NRF_802154_NOTIFY_CRCERROR
#endif // !NRF_802154_DISABLE_BCC_MATCHING || NRF_802154_NOTIFY_CRCERROR
static void irq_crcok_state_rx(void)
{
uint8_t * p_received_psdu = mp_current_rx_buffer->psdu;
uint32_t ints_to_disable = 0;
uint32_t ints_to_enable = 0;
#if NRF_802154_DISABLE_BCC_MATCHING
uint8_t num_psdu_bytes = PHR_SIZE + FCF_SIZE;
uint8_t prev_num_psdu_bytes = 0;
@@ -1974,10 +2008,10 @@ static void irq_crcok_state_rx(void)
// Set PPIs
nrf_ppi_channel_endpoint_setup(PPI_TIMER_TX_ACK,
(uint32_t)nrf_timer_event_address_get(
NRF_802154_TIMER_INSTANCE,
NRF_TIMER_EVENT_COMPARE1),
NRF_802154_TIMER_INSTANCE,
NRF_TIMER_EVENT_COMPARE1),
(uint32_t)nrf_radio_task_address_get(
NRF_RADIO_TASK_TXEN));
NRF_RADIO_TASK_TXEN));
#if !NRF_802154_DISABLE_BCC_MATCHING
nrf_ppi_channel_enable(PPI_TIMER_TX_ACK);
@@ -2111,7 +2145,7 @@ static void irq_crcok_state_rx(void)
}
#else // NRF_802154_DISABLE_BCC_MATCHING
receive_failed_notify(NRF_802154_RX_ERROR_RUNTIME);
#endif // NRF_802154_DISABLE_BCC_MATCHING
#endif // NRF_802154_DISABLE_BCC_MATCHING
}
}
@@ -2136,7 +2170,7 @@ static void irq_phyend_state_tx_ack(void)
#endif // !NRF_802154_DISABLE_BCC_MATCHING
ints_to_disable = nrf_802154_revision_has_phyend_event() ?
NRF_RADIO_INT_PHYEND_MASK : NRF_RADIO_INT_END_MASK;
NRF_RADIO_INT_PHYEND_MASK : NRF_RADIO_INT_END_MASK;
#if NRF_802154_TX_STARTED_NOTIFY_ENABLED
ints_to_disable |= NRF_RADIO_INT_ADDRESS_MASK;
@@ -2172,16 +2206,16 @@ static void irq_phyend_state_tx_ack(void)
nrf_ppi_channel_endpoint_setup(PPI_CRCERROR_CLEAR,
(uint32_t)nrf_radio_event_address_get(NRF_RADIO_EVENT_CRCERROR),
(uint32_t)nrf_timer_task_address_get(
NRF_802154_TIMER_INSTANCE,
NRF_TIMER_TASK_SHUTDOWN));
NRF_802154_TIMER_INSTANCE,
NRF_TIMER_TASK_SHUTDOWN));
nrf_ppi_fork_endpoint_setup(PPI_EGU_TIMER_START,
(uint32_t)nrf_timer_task_address_get(
NRF_802154_COUNTER_TIMER_INSTANCE,
NRF_TIMER_TASK_START));
NRF_802154_COUNTER_TIMER_INSTANCE,
NRF_TIMER_TASK_START));
#else // NRF_802154_DISABLE_BCC_MATCHING
nrf_ppi_channel_disable(PPI_TIMER_TX_ACK);
#endif // NRF_802154_DISABLE_BCC_MATCHING
#endif // NRF_802154_DISABLE_BCC_MATCHING
// Enable PPI disabled by CRCOK
nrf_ppi_channel_enable(PPI_EGU_RAMP_UP);
@@ -2196,7 +2230,7 @@ static void irq_phyend_state_tx_ack(void)
// Prepare the timer coordinator to get a precise timestamp of the CRCOK event.
nrf_802154_timer_coord_timestamp_prepare(
(uint32_t)nrf_radio_event_address_get(NRF_RADIO_EVENT_CRCOK));
(uint32_t)nrf_radio_event_address_get(NRF_RADIO_EVENT_CRCOK));
if (!ppi_egu_worked())
{
@@ -2240,7 +2274,7 @@ static void irq_phyend_state_tx_frame(void)
{
bool rx_buffer_free = rx_buffer_is_available();
uint32_t shorts = rx_buffer_free ?
(SHORTS_RX_ACK | SHORTS_RX_FREE_BUFFER) : SHORTS_RX_ACK;
(SHORTS_RX_ACK | SHORTS_RX_FREE_BUFFER) : SHORTS_RX_ACK;
// Disable EGU PPI to prevent unsynchronized PPIs
nrf_ppi_channel_disable(PPI_DISABLED_EGU);
@@ -2272,12 +2306,12 @@ static void irq_phyend_state_tx_frame(void)
nrf_ppi_channel_and_fork_endpoint_setup(PPI_EGU_RAMP_UP,
(uint32_t)nrf_egu_event_address_get(
NRF_802154_SWI_EGU_INSTANCE,
EGU_EVENT),
NRF_802154_SWI_EGU_INSTANCE,
EGU_EVENT),
(uint32_t)nrf_radio_task_address_get(
NRF_RADIO_TASK_RXEN),
NRF_RADIO_TASK_RXEN),
(uint32_t)nrf_ppi_task_address_get(
PPI_CHGRP0_DIS_TASK));
PPI_CHGRP0_DIS_TASK));
nrf_egu_event_clear(NRF_802154_SWI_EGU_INSTANCE, EGU_EVENT);
@@ -2329,7 +2363,7 @@ static void irq_end_state_rx_ack(void)
if (ack_match)
{
p_ack_buffer = mp_current_rx_buffer;
p_ack_buffer = mp_current_rx_buffer;
mp_current_rx_buffer->free = false;
}
@@ -2339,9 +2373,9 @@ static void irq_end_state_rx_ack(void)
if (ack_match)
{
transmitted_frame_notify(p_ack_buffer->psdu, // psdu
rssi_last_measurement_get(), // rssi
lqi_get(p_ack_buffer->psdu)); // lqi;
transmitted_frame_notify(p_ack_buffer->psdu, // psdu
rssi_last_measurement_get(), // rssi
lqi_get(p_ack_buffer->psdu)); // lqi;
}
else
{
@@ -2388,7 +2422,8 @@ static void irq_ccabusy_state_cca(void)
static void irq_edend_state_ed(void)
{
uint32_t result = nrf_radio_ed_sample_get();
m_ed_result = result > m_ed_result ? result : m_ed_result;
m_ed_result = result > m_ed_result ? result : m_ed_result;
if (m_ed_time_left)
{
@@ -2519,8 +2554,8 @@ static void irq_handler(void)
switch (m_state)
{
case RADIO_STATE_TX_ACK:
irq_phyend_state_tx_ack();
break;
irq_phyend_state_tx_ack();
break;
case RADIO_STATE_CCA_TX:
case RADIO_STATE_TX:
@@ -2656,7 +2691,6 @@ static void irq_handler(void)
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_IRQ_HANDLER);
}
/***************************************************************************************************
* @section API functions
**************************************************************************************************/
@@ -2664,9 +2698,11 @@ static void irq_handler(void)
void nrf_802154_core_init(void)
{
const uint8_t ack_psdu[] = {0x05, ACK_HEADER_WITH_PENDING, 0x00, 0x00, 0x00, 0x00};
memcpy(m_ack_psdu, ack_psdu, sizeof(ack_psdu));
m_state = RADIO_STATE_SLEEP;
m_state = RADIO_STATE_SLEEP;
m_rsch_timeslot_is_granted = false;
nrf_timer_init();
}
@@ -2677,10 +2713,10 @@ void nrf_802154_core_deinit(void)
{
nrf_radio_reset();
}
nrf_fem_control_pin_clear();
nrf_fem_control_deactivate();
irq_deinit();
}
@@ -2950,7 +2986,8 @@ bool nrf_802154_core_channel_update(void)
channel_set(nrf_802154_pib_channel_get());
}
term_result = current_operation_terminate(NRF_802154_TERM_NONE, REQ_ORIG_CORE, true);
term_result =
current_operation_terminate(NRF_802154_TERM_NONE, REQ_ORIG_CORE, true);
if (term_result)
{
@@ -3015,7 +3052,7 @@ bool nrf_802154_core_cca_cfg_update(void)
void RADIO_IRQHandler(void)
#else // NRF_802154_INTERNAL_RADIO_IRQ_HANDLING
void nrf_802154_core_irq_handler(void)
#endif // NRF_802154_INTERNAL_RADIO_IRQ_HANDLING
#endif // NRF_802154_INTERNAL_RADIO_IRQ_HANDLING
{
irq_handler();
}
@@ -239,4 +239,3 @@ void nrf_802154_core_irq_handler(void);
#endif
#endif /* NRF_802154_CORE_H_ */
@@ -43,14 +43,15 @@
#include "mac_features/nrf_802154_ack_timeout.h"
#include "mac_features/nrf_802154_csma_ca.h"
#include "mac_features/nrf_802154_delayed_trx.h"
#include "nrf_802154_config.h"
#include "nrf_802154_types.h"
typedef bool (* abort_hook)(nrf_802154_term_t term_lvl, req_originator_t req_orig);
typedef void (* transmitted_hook)(const uint8_t * p_frame);
typedef bool (* tx_failed_hook)(const uint8_t * p_frame, nrf_802154_tx_error_t error);
typedef bool (* tx_started_hook)(const uint8_t * p_frame);
typedef void (* rx_started_hook)(void);
/* Since some compilers do not allow empty initializers for arrays with unspecified bounds,
* NULL pointer is appended to below arrays if the compiler used is not GCC. It is intentionally
@@ -67,6 +68,10 @@ static const abort_hook m_abort_hooks[] =
nrf_802154_ack_timeout_abort,
#endif
#if NRF_802154_DELAYED_TRX_ENABLED
nrf_802154_delayed_trx_abort,
#endif
NULL,
};
@@ -105,6 +110,15 @@ static const tx_started_hook m_tx_started_hooks[] =
NULL,
};
static const rx_started_hook m_rx_started_hooks[] =
{
#if NRF_802154_DELAYED_TRX_ENABLED
nrf_802154_delayed_trx_rx_started_hook,
#endif
NULL,
};
bool nrf_802154_core_hooks_terminate(nrf_802154_term_t term_lvl, req_originator_t req_orig)
{
bool result = true;
@@ -183,3 +197,16 @@ bool nrf_802154_core_hooks_tx_started(const uint8_t * p_frame)
return result;
}
void nrf_802154_core_hooks_rx_started(void)
{
for (uint32_t i = 0; i < sizeof(m_rx_started_hooks) / sizeof(m_rx_started_hooks[0]); i++)
{
if (m_rx_started_hooks[i] == NULL)
{
break;
}
m_rx_started_hooks[i]();
}
}
@@ -88,6 +88,11 @@ bool nrf_802154_core_hooks_tx_failed(const uint8_t * p_frame, nrf_802154_tx_erro
*/
bool nrf_802154_core_hooks_tx_started(const uint8_t * p_frame);
/**
* @brief Process hooks for the RX started event.
*/
void nrf_802154_core_hooks_rx_started(void);
/**
*@}
**/
@@ -47,103 +47,13 @@
#include <nrf.h>
#define CMSIS_IRQ_NUM_VECTACTIVE_DIFF 16
#define CMSIS_IRQ_NUM_VECTACTIVE_DIFF 16
#define NESTED_CRITICAL_SECTION_ALLOWED_PRIORITY_NONE (-1)
static volatile uint8_t m_critical_section_monitor; ///< Monitors each critical section enter operation
static volatile uint8_t m_nested_critical_section_counter; ///< Counter of nested critical sections
static volatile int8_t m_nested_critical_section_allowed_priority; ///< Indicator if nested critical sections are currently allowed
typedef enum
{
RSCH_EVT_NONE,
RSCH_EVT_STARTED,
RSCH_EVT_ENDED,
} rsch_evt_t;
static volatile uint8_t m_rsch_pending_evt; ///< Indicator of pending RSCH event.
/***************************************************************************************************
* @section RSCH pending events management
**************************************************************************************************/
static void rsch_pending_evt_set(rsch_evt_t evt)
{
rsch_evt_t curr_evt;
rsch_evt_t new_evt;
uint8_t evt_value;
do
{
evt_value = __LDREXB(&m_rsch_pending_evt);
curr_evt = (rsch_evt_t)evt_value;
switch (curr_evt)
{
case RSCH_EVT_NONE:
new_evt = evt;
break;
case RSCH_EVT_ENDED:
assert(evt == RSCH_EVT_STARTED);
new_evt = RSCH_EVT_NONE;
break;
case RSCH_EVT_STARTED:
assert(evt == RSCH_EVT_ENDED);
new_evt = RSCH_EVT_NONE;
break;
default:
assert(false);
}
evt_value = (uint8_t)new_evt;
} while (__STREXB(evt_value, &m_rsch_pending_evt));
}
static rsch_evt_t rsch_pending_evt_clear(void)
{
rsch_evt_t evt;
uint8_t evt_value;
do
{
evt_value = __LDREXB(&m_rsch_pending_evt);
evt = (rsch_evt_t)evt_value;
evt_value = RSCH_EVT_NONE;
} while (__STREXB(evt_value, &m_rsch_pending_evt));
return evt;
}
static bool rsch_pending_evt_is_none(void)
{
return (rsch_evt_t)m_rsch_pending_evt == RSCH_EVT_NONE;
}
static void rsch_evt_process(rsch_evt_t evt)
{
switch (evt)
{
case RSCH_EVT_NONE:
break;
case RSCH_EVT_STARTED:
nrf_802154_critical_section_rsch_prec_approved();
break;
case RSCH_EVT_ENDED:
nrf_802154_critical_section_rsch_prec_denied();
break;
default:
assert(false);
}
}
static volatile uint8_t m_critical_section_monitor; ///< Monitors each critical section enter operation
static volatile uint8_t m_nested_critical_section_counter; ///< Counter of nested critical sections
static volatile int8_t m_nested_critical_section_allowed_priority; ///< Indicator if nested critical sections are currently allowed
/***************************************************************************************************
* @section Critical sections management
@@ -156,7 +66,7 @@ static void rsch_evt_process(rsch_evt_t evt)
*/
static void radio_critical_section_enter(void)
{
if (nrf_802154_rsch_prec_is_approved(RSCH_PREC_RAAL))
if (nrf_802154_rsch_prec_is_approved(RSCH_PREC_RAAL, RSCH_PRIO_MIN_APPROVED))
{
NVIC_DisableIRQ(RADIO_IRQn);
}
@@ -169,7 +79,7 @@ static void radio_critical_section_enter(void)
*/
static void radio_critical_section_exit(void)
{
if (nrf_802154_rsch_prec_is_approved(RSCH_PREC_RAAL))
if (nrf_802154_rsch_prec_is_approved(RSCH_PREC_RAAL, RSCH_PRIO_MIN_APPROVED))
{
NVIC_EnableIRQ(RADIO_IRQn);
}
@@ -194,8 +104,7 @@ static int8_t active_priority_convert(uint32_t active_priority)
static bool nested_critical_section_is_allowed_in_this_context(void)
{
return m_nested_critical_section_allowed_priority ==
active_priority_convert(
nrf_802154_critical_section_active_vector_priority_get());
active_priority_convert(nrf_802154_critical_section_active_vector_priority_get());
}
static bool critical_section_enter(bool forced)
@@ -215,6 +124,7 @@ static bool critical_section_enter(bool forced)
}
while (__STREXB(cnt + 1, &m_nested_critical_section_counter));
nrf_802154_critical_section_rsch_enter();
nrf_802154_lp_timer_critical_section_enter();
radio_critical_section_enter();
__DSB();
@@ -230,8 +140,7 @@ static bool critical_section_enter(bool forced)
static void critical_section_exit(void)
{
uint8_t cnt = m_nested_critical_section_counter;
rsch_evt_t rsch_evt = RSCH_EVT_NONE;
uint8_t cnt = m_nested_critical_section_counter;
uint8_t monitor;
uint8_t atomic_cnt;
static bool exiting_crit_sect;
@@ -239,11 +148,6 @@ static void critical_section_exit(void)
assert(cnt > 0);
if (cnt == 1)
{
rsch_evt = rsch_pending_evt_clear();
}
do
{
monitor = m_critical_section_monitor;
@@ -255,7 +159,7 @@ static void critical_section_exit(void)
(void)exiting_crit_sect;
exiting_crit_sect = true;
rsch_evt_process(rsch_evt);
nrf_802154_critical_section_rsch_exit();
radio_critical_section_exit();
nrf_802154_lp_timer_critical_section_exit();
@@ -273,10 +177,9 @@ static void critical_section_exit(void)
// change of state or critical section was visited by higher priority IRQ meantime.
if (cnt == 1)
{
rsch_evt = rsch_pending_evt_clear();
// Check if critical section must be exited again.
if ((rsch_evt != RSCH_EVT_NONE) || (monitor != m_critical_section_monitor))
if (nrf_802154_critical_section_rsch_event_is_pending() ||
(monitor != m_critical_section_monitor))
{
result = critical_section_enter(false);
assert(result);
@@ -341,11 +244,11 @@ void nrf_802154_critical_section_exit(void)
void nrf_802154_critical_section_nesting_allow(void)
{
assert(m_nested_critical_section_allowed_priority ==
NESTED_CRITICAL_SECTION_ALLOWED_PRIORITY_NONE);
NESTED_CRITICAL_SECTION_ALLOWED_PRIORITY_NONE);
assert(m_nested_critical_section_counter >= 1);
m_nested_critical_section_allowed_priority = active_priority_convert(
nrf_802154_critical_section_active_vector_priority_get());
nrf_802154_critical_section_active_vector_priority_get());
}
void nrf_802154_critical_section_nesting_deny(void)
@@ -380,46 +283,3 @@ uint32_t nrf_802154_critical_section_active_vector_priority_get(void)
return active_priority;
}
/***************************************************************************************************
* @section RSCH callbacks
**************************************************************************************************/
void nrf_802154_rsch_prec_approved(void)
{
bool crit_sect_success = critical_section_enter(false);
if (crit_sect_success && rsch_pending_evt_is_none())
{
nrf_802154_critical_section_rsch_prec_approved();
}
else
{
rsch_pending_evt_set(RSCH_EVT_STARTED);
}
if (crit_sect_success)
{
critical_section_exit();
}
}
void nrf_802154_rsch_prec_denied(void)
{
bool crit_sect_success = critical_section_enter(false);
if (crit_sect_success && rsch_pending_evt_is_none())
{
nrf_802154_critical_section_rsch_prec_denied();
}
else
{
rsch_pending_evt_set(RSCH_EVT_ENDED);
}
if (crit_sect_success)
{
critical_section_exit();
}
}
@@ -104,24 +104,20 @@ bool nrf_802154_critical_section_is_nested(void);
*/
uint32_t nrf_802154_critical_section_active_vector_priority_get(void);
/**
* @brief Function called to enter critical section in the RSCH module.
*/
extern void nrf_802154_critical_section_rsch_enter(void);
/**
* @brief The critical section module calls this function to notify the core that all RSCH
* preconditions are met.
*
* @note This function is called from critical section context and does not preempt other critical
* sections.
* @brief Function called to exit critical section in the RSCH module.
*/
extern void nrf_802154_critical_section_rsch_prec_approved(void);
extern void nrf_802154_critical_section_rsch_exit(void);
/**
* @brief The critical section module calls this function to notify the core that any of RSCH
* preconditions is not met anymore.
*
* @note This function is called from critical section context and does not preempt other critical
* sections.
* @brief Check if there is pending event in the RSCH critical section.
*/
extern void nrf_802154_critical_section_rsch_prec_denied(void);
extern bool nrf_802154_critical_section_rsch_event_is_pending(void);
/**
*@}
@@ -48,6 +48,7 @@
volatile uint32_t nrf_802154_debug_log_buffer[NRF_802154_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_802154_debug_log_ptr = 0;
#endif
#if ENABLE_DEBUG_GPIO
@@ -63,12 +64,30 @@ static void radio_event_gpio_toggle_init(void)
nrf_gpio_cfg_output(PIN_DBG_RADIO_EVT_EDEND);
nrf_gpio_cfg_output(PIN_DBG_RADIO_EVT_PHYEND);
nrf_gpiote_task_configure(0, PIN_DBG_RADIO_EVT_END, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_HIGH);
nrf_gpiote_task_configure(1, PIN_DBG_RADIO_EVT_DISABLED, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_HIGH);
nrf_gpiote_task_configure(2, PIN_DBG_RADIO_EVT_READY, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_HIGH);
nrf_gpiote_task_configure(3, PIN_DBG_RADIO_EVT_FRAMESTART, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_HIGH);
nrf_gpiote_task_configure(4, PIN_DBG_RADIO_EVT_EDEND, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_HIGH);
nrf_gpiote_task_configure(5, PIN_DBG_RADIO_EVT_PHYEND, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_HIGH);
nrf_gpiote_task_configure(0,
PIN_DBG_RADIO_EVT_END,
NRF_GPIOTE_POLARITY_TOGGLE,
NRF_GPIOTE_INITIAL_VALUE_HIGH);
nrf_gpiote_task_configure(1,
PIN_DBG_RADIO_EVT_DISABLED,
NRF_GPIOTE_POLARITY_TOGGLE,
NRF_GPIOTE_INITIAL_VALUE_HIGH);
nrf_gpiote_task_configure(2,
PIN_DBG_RADIO_EVT_READY,
NRF_GPIOTE_POLARITY_TOGGLE,
NRF_GPIOTE_INITIAL_VALUE_HIGH);
nrf_gpiote_task_configure(3,
PIN_DBG_RADIO_EVT_FRAMESTART,
NRF_GPIOTE_POLARITY_TOGGLE,
NRF_GPIOTE_INITIAL_VALUE_HIGH);
nrf_gpiote_task_configure(4,
PIN_DBG_RADIO_EVT_EDEND,
NRF_GPIOTE_POLARITY_TOGGLE,
NRF_GPIOTE_INITIAL_VALUE_HIGH);
nrf_gpiote_task_configure(5,
PIN_DBG_RADIO_EVT_PHYEND,
NRF_GPIOTE_POLARITY_TOGGLE,
NRF_GPIOTE_INITIAL_VALUE_HIGH);
nrf_gpiote_task_enable(0);
nrf_gpiote_task_enable(1);
@@ -77,12 +96,24 @@ static void radio_event_gpio_toggle_init(void)
nrf_gpiote_task_enable(4);
nrf_gpiote_task_enable(5);
nrf_ppi_channel_endpoint_setup(NRF_PPI_CHANNEL0, (uint32_t) &NRF_RADIO->EVENTS_END, nrf_gpiote_task_addr_get(NRF_GPIOTE_TASKS_OUT_0));
nrf_ppi_channel_endpoint_setup(NRF_PPI_CHANNEL1, (uint32_t) &NRF_RADIO->EVENTS_DISABLED, nrf_gpiote_task_addr_get(NRF_GPIOTE_TASKS_OUT_1));
nrf_ppi_channel_endpoint_setup(NRF_PPI_CHANNEL2, (uint32_t) &NRF_RADIO->EVENTS_READY, nrf_gpiote_task_addr_get(NRF_GPIOTE_TASKS_OUT_2));
nrf_ppi_channel_endpoint_setup(NRF_PPI_CHANNEL3, (uint32_t) &NRF_RADIO->EVENTS_FRAMESTART, nrf_gpiote_task_addr_get(NRF_GPIOTE_TASKS_OUT_3));
nrf_ppi_channel_endpoint_setup(NRF_PPI_CHANNEL4, (uint32_t) &NRF_RADIO->EVENTS_EDEND, nrf_gpiote_task_addr_get(NRF_GPIOTE_TASKS_OUT_4));
nrf_ppi_channel_endpoint_setup(NRF_PPI_CHANNEL5, (uint32_t) &NRF_RADIO->EVENTS_PHYEND, nrf_gpiote_task_addr_get(NRF_GPIOTE_TASKS_OUT_5));
nrf_ppi_channel_endpoint_setup(NRF_PPI_CHANNEL0,
(uint32_t)&NRF_RADIO->EVENTS_END,
nrf_gpiote_task_addr_get(NRF_GPIOTE_TASKS_OUT_0));
nrf_ppi_channel_endpoint_setup(NRF_PPI_CHANNEL1,
(uint32_t)&NRF_RADIO->EVENTS_DISABLED,
nrf_gpiote_task_addr_get(NRF_GPIOTE_TASKS_OUT_1));
nrf_ppi_channel_endpoint_setup(NRF_PPI_CHANNEL2,
(uint32_t)&NRF_RADIO->EVENTS_READY,
nrf_gpiote_task_addr_get(NRF_GPIOTE_TASKS_OUT_2));
nrf_ppi_channel_endpoint_setup(NRF_PPI_CHANNEL3,
(uint32_t)&NRF_RADIO->EVENTS_FRAMESTART,
nrf_gpiote_task_addr_get(NRF_GPIOTE_TASKS_OUT_3));
nrf_ppi_channel_endpoint_setup(NRF_PPI_CHANNEL4,
(uint32_t)&NRF_RADIO->EVENTS_EDEND,
nrf_gpiote_task_addr_get(NRF_GPIOTE_TASKS_OUT_4));
nrf_ppi_channel_endpoint_setup(NRF_PPI_CHANNEL5,
(uint32_t)&NRF_RADIO->EVENTS_PHYEND,
nrf_gpiote_task_addr_get(NRF_GPIOTE_TASKS_OUT_5));
nrf_ppi_channel_enable(NRF_PPI_CHANNEL0);
nrf_ppi_channel_enable(NRF_PPI_CHANNEL1);
@@ -118,15 +149,21 @@ static void raal_softdevice_event_gpio_toggle_init(void)
nrf_gpio_cfg_output(PIN_DBG_TIMESLOT_BLOCKED);
nrf_gpio_cfg_output(PIN_DBG_RTC0_EVT_REM);
nrf_gpiote_task_configure(5, PIN_DBG_RTC0_EVT_REM, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_HIGH);
nrf_gpiote_task_configure(5,
PIN_DBG_RTC0_EVT_REM,
NRF_GPIOTE_POLARITY_TOGGLE,
NRF_GPIOTE_INITIAL_VALUE_HIGH);
nrf_gpiote_task_enable(5);
nrf_ppi_channel_endpoint_setup(NRF_PPI_CHANNEL5, (uint32_t) &NRF_RTC0->EVENTS_COMPARE[1], nrf_gpiote_task_addr_get(NRF_GPIOTE_TASKS_OUT_5));
nrf_ppi_channel_endpoint_setup(NRF_PPI_CHANNEL5,
(uint32_t)&NRF_RTC0->EVENTS_COMPARE[1],
nrf_gpiote_task_addr_get(NRF_GPIOTE_TASKS_OUT_5));
nrf_ppi_channel_enable(NRF_PPI_CHANNEL5);
#endif // RAAL_SOFTDEVICE
}
#endif // ENABLE_DEBUG_GPIO
void nrf_802154_debug_init(void)
@@ -139,15 +176,17 @@ void nrf_802154_debug_init(void)
}
#if ENABLE_DEBUG_ASSERT
void __assert_func(const char *file, int line, const char *func, const char *cond)
void __assert_func(const char * file, int line, const char * func, const char * cond)
{
(void) file;
(void) line;
(void) func;
(void) cond;
(void)file;
(void)line;
(void)func;
(void)cond;
__disable_irq();
while (1);
while (1)
;
}
#endif // ENABLE_DEBUG_ASSERT
@@ -42,7 +42,7 @@
extern "C" {
#endif
#define NRF_802154_DEBUG_LOG_BUFFER_LEN 1024
#define NRF_802154_DEBUG_LOG_BUFFER_LEN 1024
#define EVENT_TRACE_ENTER 0x0001UL
#define EVENT_TRACE_EXIT 0x0002UL
@@ -60,6 +60,7 @@ extern "C" {
#define FUNCTION_CONTINUOUS_CARRIER 0x0007UL
#define FUNCTION_CSMACA 0x0008UL
#define FUNCTION_TRANSMIT_AT 0x0009UL
#define FUNCTION_RECEIVE_AT 0x000AUL
#define FUNCTION_IRQ_HANDLER 0x0100UL
#define FUNCTION_EVENT_FRAMESTART 0x0101UL
@@ -96,21 +97,22 @@ extern "C" {
#define FUNCTION_RAAL_EVT_BLOCKED 0x0408UL
#define FUNCTION_RAAL_EVT_SESSION_IDLE 0x0409UL
#define FUNCTION_RAAL_EVT_HFCLK_READY 0x040AUL
#define FUNCTION_RAAL_SIG_EVENT_MARGIN_MOVE 0x040BUL
#define FUNCTION_RSCH_CONTINUOUS_ENTER 0x040BUL
#define FUNCTION_RSCH_CONTINUOUS_EXIT 0x040CUL
#define FUNCTION_RSCH_CRITICAL_SECTION_ENTER 0x040DUL
#define FUNCTION_RSCH_CRITICAL_SECTION_EXIT 0x040EUL
#define FUNCTION_RSCH_TIMESLOT_STARTED 0x040FUL
#define FUNCTION_RSCH_TIMESLOT_ENDED 0x0410UL
#define FUNCTION_RSCH_PEND_GRANTED 0x0411UL
#define FUNCTION_RSCH_PEND_REVOKED 0x0412UL
#define FUNCTION_RSCH_NOTIFY_GRANTED 0x0413UL
#define FUNCTION_RSCH_NOTIFY_REVOKED 0x0414UL
#define FUNCTION_RSCH_NOTIFY_IF_PENDING 0x0415UL
#define FUNCTION_RSCH_DELAYED_TIMESLOT_REQ 0x0416UL
#define FUNCTION_RSCH_TIMER_DELAYED_PREC 0x0417UL
#define FUNCTION_RSCH_TIMER_DELAYED_START 0x0418UL
#define FUNCTION_RSCH_CONTINUOUS_ENTER 0x0480UL
#define FUNCTION_RSCH_CONTINUOUS_EXIT 0x0481UL
#define FUNCTION_RSCH_CRITICAL_SECTION_ENTER 0x0482UL
#define FUNCTION_RSCH_CRITICAL_SECTION_EXIT 0x0483UL
#define FUNCTION_RSCH_TIMESLOT_STARTED 0x0484UL
#define FUNCTION_RSCH_TIMESLOT_ENDED 0x0485UL
#define FUNCTION_RSCH_PEND_GRANTED 0x0486UL
#define FUNCTION_RSCH_PEND_REVOKED 0x0487UL
#define FUNCTION_RSCH_NOTIFY_GRANTED 0x0488UL
#define FUNCTION_RSCH_NOTIFY_REVOKED 0x0489UL
#define FUNCTION_RSCH_NOTIFY_IF_PENDING 0x048AUL
#define FUNCTION_RSCH_DELAYED_TIMESLOT_REQ 0x048BUL
#define FUNCTION_RSCH_TIMER_DELAYED_PREC 0x048CUL
#define FUNCTION_RSCH_TIMER_DELAYED_START 0x048DUL
#define FUNCTION_CSMA_ABORT 0x0500UL
#define FUNCTION_CSMA_TX_FAILED 0x0501UL
@@ -140,16 +142,19 @@ extern "C" {
#if ENABLE_DEBUG_LOG
extern volatile uint32_t nrf_802154_debug_log_buffer[
NRF_802154_DEBUG_LOG_BUFFER_LEN];
NRF_802154_DEBUG_LOG_BUFFER_LEN];
extern volatile uint32_t nrf_802154_debug_log_ptr;
#define nrf_802154_log(EVENT_CODE, EVENT_ARG) \
do { \
uint32_t ptr = nrf_802154_debug_log_ptr; \
nrf_802154_debug_log_buffer[ptr] = ((EVENT_CODE) | ((EVENT_ARG) << 16)); \
nrf_802154_debug_log_ptr = \
ptr < (NRF_802154_DEBUG_LOG_BUFFER_LEN - 1) ? ptr + 1 : 0; \
} while (0)
#define nrf_802154_log(EVENT_CODE, EVENT_ARG) \
do \
{ \
uint32_t ptr = nrf_802154_debug_log_ptr; \
\
nrf_802154_debug_log_buffer[ptr] = ((EVENT_CODE) | ((EVENT_ARG) << 16)); \
nrf_802154_debug_log_ptr = \
ptr < (NRF_802154_DEBUG_LOG_BUFFER_LEN - 1) ? ptr + 1 : 0; \
} \
while (0)
#else // ENABLE_DEBUG_LOG
@@ -161,10 +166,15 @@ extern volatile uint32_t nrf_802154_debug_log_ptr;
#define nrf_802154_pin_set(pin) NRF_P0->OUTSET = (1UL << (pin))
#define nrf_802154_pin_clr(pin) NRF_P0->OUTCLR = (1UL << (pin))
#define nrf_802154_pin_tgl(pin) do { volatile uint32_t ps = NRF_P0->OUT; \
NRF_P0->OUTSET = (~ps & (1UL << (pin))); \
NRF_P0->OUTCLR = (ps & (1UL << (pin))); \
} while(0);
#define nrf_802154_pin_tgl(pin) \
do \
{ \
volatile uint32_t ps = NRF_P0->OUT; \
\
NRF_P0->OUTSET = (~ps & (1UL << (pin))); \
NRF_P0->OUTCLR = (ps & (1UL << (pin))); \
} \
while (0);
#else // ENABLE_DEBUG_GPIO
@@ -55,7 +55,7 @@ extern "C" {
*
* @param[in] result If called request succeeded.
*/
typedef void (*nrf_802154_notification_func_t)(bool result);
typedef void (* nrf_802154_notification_func_t)(bool result);
/**
* @brief Initialize notification module.
@@ -56,7 +56,7 @@ void nrf_802154_notify_received(uint8_t * p_data, int8_t power, int8_t lqi)
nrf_802154_received_raw(p_data, power, lqi);
#else // NRF_802154_USE_RAW_API
nrf_802154_received(p_data + RAW_PAYLOAD_OFFSET, p_data[RAW_LENGTH_OFFSET], power, lqi);
#endif // NRF_802154_USE_RAW_API
#endif // NRF_802154_USE_RAW_API
}
void nrf_802154_notify_receive_failed(nrf_802154_rx_error_t error)
@@ -86,7 +86,7 @@ void nrf_802154_notify_transmit_failed(const uint8_t * p_frame, nrf_802154_tx_er
nrf_802154_transmit_failed(p_frame, error);
#else // NRF_802154_USE_RAW_API
nrf_802154_transmit_failed(p_frame + RAW_PAYLOAD_OFFSET, error);
#endif // NRF_802154_USE_RAW_API
#endif // NRF_802154_USE_RAW_API
}
void nrf_802154_notify_energy_detected(uint8_t result)
@@ -89,4 +89,3 @@ void nrf_802154_notify_cca_failed(nrf_802154_cca_error_t error)
{
nrf_802154_swi_notify_cca_failed(error);
}
@@ -46,18 +46,19 @@
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.
nrf_802154_cca_cfg_t cca; ///< CCA mode and thresholds.
bool promiscuous :1; ///< Indicating if radio is in promiscuous mode.
bool auto_ack :1; ///< Indicating if auto ACK procedure is enabled.
bool pan_coord :1; ///< Indicating if radio is configured as the PAN coordinator.
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.
nrf_802154_cca_cfg_t cca; ///< CCA mode and thresholds.
bool promiscuous : 1; ///< Indicating if radio is in promiscuous mode.
bool auto_ack : 1; ///< Indicating if auto ACK procedure is enabled.
bool pan_coord : 1; ///< Indicating if radio is configured as the PAN coordinator.
uint8_t channel : 5; ///< Channel on which the node receives messages.
} nrf_802154_pib_data_t;
static nrf_802154_pib_data_t m_data; ///< Buffer containing PIB data.
// Static variables.
static nrf_802154_pib_data_t m_data; ///< Buffer containing PIB data.
void nrf_802154_pib_init(void)
{
@@ -125,7 +126,9 @@ int8_t nrf_802154_pib_tx_power_get(void)
void nrf_802154_pib_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};
const int8_t highest_value = allowed_values[(sizeof(allowed_values) / sizeof(allowed_values[0])) - 1];
const int8_t highest_value =
allowed_values[(sizeof(allowed_values) / sizeof(allowed_values[0])) - 1];
if (dbm > highest_value)
{
dbm = highest_value;
@@ -95,7 +95,6 @@ bool nrf_802154_pib_pan_coord_get(void);
*/
void nrf_802154_pib_pan_coord_set(bool enabled);
/**
* @brief Get currently used channel.
*
@@ -191,4 +190,3 @@ void nrf_802154_pib_cca_cfg_get(nrf_802154_cca_cfg_t * p_cca_cfg);
#endif
#endif /* NRF_802154_PIB_H_ */
@@ -49,20 +49,21 @@ extern "C" {
void nrf_802154_priority_drop_init(void);
/**
* @brief Request discarding of the timeslot.
* @brief Request stop of the high frequency clock.
*
* @note This function should be called through this module to prevent calling it from arbiter context.
* @note This function should be called through this module to prevent calling it from the arbiter
* context.
*/
void nrf_802154_priority_drop_timeslot_exit(void);
void nrf_802154_priority_drop_hfclk_stop(void);
/**
* @brief Terminate requesting of timeslot discarding.
* @brief Terminate requesting of high frequency clock stop.
*
* Function used to to terminate timeslot exit procedure requested by previous call to
* @rev nrf_802154_priority_drop_timeslot_exit. Timeslot discarding is terminated only if it has
* Function used to to terminate HFClk stop procedure requested by previous call to
* @rev nrf_802154_priority_drop_hfclk_stop. The HFClk stop procedure is terminated only if it has
* not been started.
*/
void nrf_802154_priority_drop_timeslot_exit_terminate(void);
void nrf_802154_priority_drop_hfclk_stop_terminate(void);
/**
*@}
@@ -73,4 +74,3 @@ void nrf_802154_priority_drop_timeslot_exit_terminate(void);
#endif
#endif // NRF_802154_PRIORITY_DROP_H__
@@ -37,21 +37,20 @@
#include "nrf_802154_priority_drop.h"
#include "nrf_802154_rsch.h"
#include "platform/clock/nrf_802154_clock.h"
void nrf_802154_priority_drop_init(void)
{
// Intentionally empty
}
void nrf_802154_priority_drop_timeslot_exit(void)
void nrf_802154_priority_drop_hfclk_stop(void)
{
nrf_802154_rsch_continuous_mode_exit();
nrf_802154_clock_hfclk_stop();
}
void nrf_802154_priority_drop_timeslot_exit_terminate(void)
void nrf_802154_priority_drop_hfclk_stop_terminate(void)
{
// Intentionally empty:
// nrf_802154_priority_drop_timeslot_exit is synchronous and cannot be terminated.
// nrf_802154_priority_drop_hfclk_stop is synchronous and cannot be terminated.
}
@@ -44,13 +44,12 @@ void nrf_802154_priority_drop_init(void)
nrf_802154_swi_init();
}
void nrf_802154_priority_drop_timeslot_exit(void)
void nrf_802154_priority_drop_hfclk_stop(void)
{
nrf_802154_swi_timeslot_exit();
nrf_802154_swi_hfclk_stop();
}
void nrf_802154_priority_drop_timeslot_exit_terminate(void)
void nrf_802154_priority_drop_hfclk_stop_terminate(void)
{
nrf_802154_swi_timeslot_exit_terminate();
nrf_802154_swi_hfclk_stop_terminate();
}
@@ -42,25 +42,26 @@
#include "nrf_802154_const.h"
#define TX_RAMP_UP_TIME 40 // us
#define RX_RAMP_UP_TIME 40 // us
#define RX_RAMP_DOWN_TIME 0 // us
#define MAX_RAMP_DOWN_TIME 6 // us
#define RX_TX_TURNAROUND_TIME 20 // us
#define TX_RAMP_UP_TIME 40 // us
#define RX_RAMP_UP_TIME 40 // us
#define RX_RAMP_DOWN_TIME 0 // us
#define MAX_RAMP_DOWN_TIME 6 // us
#define RX_TX_TURNAROUND_TIME 20 // us
#define A_CCA_DURATION_SYMBOLS 8 // sym
#define A_TURNAROUND_TIME_SYMBOLS 12 // sym
#define A_UNIT_BACKOFF_SYMBOLS 20 // sym
#define A_CCA_DURATION_SYMBOLS 8 // sym
#define A_TURNAROUND_TIME_SYMBOLS 12 // sym
#define A_UNIT_BACKOFF_SYMBOLS 20 // sym
#define PHY_SYMBOLS_FROM_OCTETS(octets) ((octets) * PHY_SYMBOLS_PER_OCTET)
#define PHY_US_TIME_FROM_SYMBOLS(symbols) ((symbols) * PHY_US_PER_SYMBOL)
#define IMM_ACK_SYMBOLS (PHY_SHR_SYMBOLS + PHY_SYMBOLS_FROM_OCTETS(IMM_ACK_LENGTH + PHR_SIZE))
#define IMM_ACK_DURATION (PHY_US_TIME_FROM_SYMBOLS(IMM_ACK_SYMBOLS))
#define IMM_ACK_SYMBOLS (PHY_SHR_SYMBOLS + \
PHY_SYMBOLS_FROM_OCTETS(IMM_ACK_LENGTH + PHR_SIZE))
#define IMM_ACK_DURATION (PHY_US_TIME_FROM_SYMBOLS(IMM_ACK_SYMBOLS))
#define MAC_IMM_ACK_WAIT_SYMBOLS (A_UNIT_BACKOFF_SYMBOLS + \
A_TURNAROUND_TIME_SYMBOLS + \
IMM_ACK_SYMBOLS)
#define MAC_IMM_ACK_WAIT_SYMBOLS (A_UNIT_BACKOFF_SYMBOLS + \
A_TURNAROUND_TIME_SYMBOLS + \
IMM_ACK_SYMBOLS)
__STATIC_INLINE uint16_t nrf_802154_tx_duration_get(uint8_t psdu_length,
bool cca,
@@ -101,7 +102,10 @@ __STATIC_INLINE uint16_t nrf_802154_tx_duration_get(uint8_t psdu_length,
// if CCA: + RX ramp up + CCA + RX ramp down
// + TX ramp up + SHR + PHR + PSDU
// if ACK: + macAckWaitDuration
uint16_t us_time = MAX_RAMP_DOWN_TIME + TX_RAMP_UP_TIME + nrf_802154_frame_duration_get(psdu_length, true, true);
uint16_t us_time = MAX_RAMP_DOWN_TIME + TX_RAMP_UP_TIME + nrf_802154_frame_duration_get(
psdu_length,
true,
true);
if (ack_requested)
{
@@ -110,7 +114,8 @@ __STATIC_INLINE uint16_t nrf_802154_tx_duration_get(uint8_t psdu_length,
if (cca)
{
us_time += RX_RAMP_UP_TIME + RX_RAMP_DOWN_TIME + PHY_US_TIME_FROM_SYMBOLS(A_CCA_DURATION_SYMBOLS);
us_time += RX_RAMP_UP_TIME + RX_RAMP_DOWN_TIME + PHY_US_TIME_FROM_SYMBOLS(
A_CCA_DURATION_SYMBOLS);
}
return us_time;
@@ -42,14 +42,13 @@
#include "nrf_802154_core.h"
#include "hal/nrf_radio.h"
#define REQUEST_FUNCTION(func_core, ...) \
bool result; \
\
result = func_core(__VA_ARGS__); \
\
#define REQUEST_FUNCTION(func_core, ...) \
bool result; \
\
result = func_core(__VA_ARGS__); \
\
return result;
void nrf_802154_request_init(void)
{
// Intentionally empty
@@ -75,7 +74,13 @@ bool nrf_802154_request_transmit(nrf_802154_term_t term_lvl,
bool immediate,
nrf_802154_notification_func_t notify_function)
{
REQUEST_FUNCTION(nrf_802154_core_transmit, term_lvl, req_orig, p_data, cca, immediate, notify_function)
REQUEST_FUNCTION(nrf_802154_core_transmit,
term_lvl,
req_orig,
p_data,
cca,
immediate,
notify_function)
}
bool nrf_802154_request_energy_detection(nrf_802154_term_t term_lvl, uint32_t time_us)
@@ -57,34 +57,34 @@ static inline void assert_interrupt_status(void)
assert(nrf_is_nvic_irq_enabled(NRF_802154_SWI_IRQN));
}
#define REQUEST_FUNCTION(func_core, func_swi, ...) \
bool result = false; \
\
if (active_vector_priority_is_high()) \
{ \
result = func_core(__VA_ARGS__); \
} \
else \
{ \
assert_interrupt_status(); \
func_swi(__VA_ARGS__, &result); \
} \
\
#define REQUEST_FUNCTION(func_core, func_swi, ...) \
bool result = false; \
\
if (active_vector_priority_is_high()) \
{ \
result = func_core(__VA_ARGS__); \
} \
else \
{ \
assert_interrupt_status(); \
func_swi(__VA_ARGS__, &result); \
} \
\
return result;
#define REQUEST_FUNCTION_NO_ARGS(func_core, func_swi) \
bool result = false; \
\
if (active_vector_priority_is_high()) \
{ \
result = func_core(); \
} \
else \
{ \
assert_interrupt_status(); \
func_swi(&result); \
} \
\
#define REQUEST_FUNCTION_NO_ARGS(func_core, func_swi) \
bool result = false; \
\
if (active_vector_priority_is_high()) \
{ \
result = func_core(); \
} \
else \
{ \
assert_interrupt_status(); \
func_swi(&result); \
} \
\
return result;
/** Check if active vector priority is high enough to call requests directly.
@@ -154,7 +154,8 @@ bool nrf_802154_request_cca(nrf_802154_term_t term_lvl)
bool nrf_802154_request_continuous_carrier(nrf_802154_term_t term_lvl)
{
REQUEST_FUNCTION(nrf_802154_core_continuous_carrier, nrf_802154_swi_continuous_carrier, term_lvl)
REQUEST_FUNCTION(nrf_802154_core_continuous_carrier, nrf_802154_swi_continuous_carrier,
term_lvl)
}
bool nrf_802154_request_buffer_free(uint8_t * p_data)
@@ -171,4 +172,3 @@ bool nrf_802154_request_cca_cfg_update(void)
{
REQUEST_FUNCTION_NO_ARGS(nrf_802154_core_cca_cfg_update, nrf_802154_swi_cca_cfg_update)
}
@@ -115,17 +115,17 @@ bool nrf_802154_revision_has_phyend_event(void)
switch (m_nrf52840_revision)
{
case NRF52840_REVISION_AAAA:
result = false;
break;
case NRF52840_REVISION_AAAA:
result = false;
break;
case NRF52840_REVISION_AABA:
case NRF52840_REVISION_UNKNOWN:
result = true;
break;
case NRF52840_REVISION_AABA:
case NRF52840_REVISION_UNKNOWN:
result = true;
break;
default:
assert(false);
default:
assert(false);
}
return result;
@@ -1,466 +0,0 @@
#include "nrf_802154_rsch.h"
#include <assert.h>
#include <stddef.h>
#include <nrf.h>
#include "nrf_802154_debug.h"
#include "platform/clock/nrf_802154_clock.h"
#include "raal/nrf_raal_api.h"
#include "timer_scheduler/nrf_802154_timer_sched.h"
#define PREC_RAMP_UP_TIME 300 ///< Ramp-up time of preconditions [us]. 300 is worst case for HFclock
typedef enum
{
RSCH_PREC_STATE_IDLE,
RSCH_PREC_STATE_REQUESTED,
RSCH_PREC_STATE_APPROVED,
} rsch_prec_state_t;
static volatile uint8_t m_mutex; ///< Mutex for notyfying core.
static volatile uint8_t m_mutex_monitor; ///< Mutex monitor, incremented every failed mutex lock.
static volatile bool m_last_notified_approved; ///< Last reported state was approved.
static volatile rsch_prec_state_t m_prec_states[RSCH_PREC_CNT]; ///< State of all preconditions.
static bool m_in_cont_mode; ///< If RSCH operates in continuous mode.
static bool m_delayed_timeslot_is_scheduled; ///< If delayed timeslot is scheduled at the moment.
static uint32_t m_delayed_timeslot_t0; ///< Time base of the delayed timeslot trigger time.
static uint32_t m_delayed_timeslot_dt; ///< Time delta of the delayed timeslot trigger time.
static nrf_802154_timer_t m_timer; ///< Timer used to trigger delayed timeslot.
/** @brief Non-blocking mutex for notifying core.
*
* @retval true Mutex was acquired.
* @retval false Mutex could not be acquired.
*/
static inline bool mutex_trylock(void)
{
do
{
uint8_t mutex_value = __LDREXB(&m_mutex);
if (mutex_value)
{
__CLREX();
m_mutex_monitor++;
return false;
}
} while (__STREXB(1, &m_mutex));
__DMB();
return true;
}
/** @brief Release mutex. */
static inline void mutex_unlock(void)
{
__DMB();
m_mutex = 0;
}
/** @brief Check if any precondition should be requested at the moment for delayed timeslot.
*
* To meet delayed timeslot timing requirements there is a time window in which radio
* preconditions should be requested. This function is used to prevent releasing preconditions
* in this time window.
*
* @retval true A precondition should be requested at the moment for delayed timeslot feature.
* @retval false None of preconditions should be requested at the moment for delayed timeslot.
*/
static bool any_prec_should_be_requested_for_delayed_timeslot(void)
{
uint32_t now = nrf_802154_timer_sched_time_get();
uint32_t t0 = m_delayed_timeslot_t0;
uint32_t dt = m_delayed_timeslot_dt - PREC_RAMP_UP_TIME -
nrf_802154_timer_sched_granularity_get();
return (m_delayed_timeslot_is_scheduled &&
!nrf_802154_timer_sched_time_is_in_future(now, t0, dt));
}
/** @brief Set RSCH_PREC_STATE_APPROVED state on given precondition @p prec only if
* its current state is other than RSCH_PREC_STATE_IDLE.
*
* @param[in] prec Precondition which state will be changed.
*/
static inline void prec_approve(rsch_prec_t prec)
{
do
{
rsch_prec_state_t old_state = (rsch_prec_state_t) __LDREXB((uint8_t*)&m_prec_states[prec]);
assert(old_state != RSCH_PREC_STATE_APPROVED);
if (old_state == RSCH_PREC_STATE_IDLE)
{
__CLREX();
return;
}
} while (__STREXB((uint8_t)RSCH_PREC_STATE_APPROVED, (uint8_t*)&m_prec_states[prec]));
}
/** @brief Set RSCH_PREC_STATE_REQUESTED state on given precondition @p prec only if
* its current state is RSCH_PREC_STATE_APPROVED.
*
* @param[in] prec Precondition which state will be changed.
*/
static inline void prec_deny(rsch_prec_t prec)
{
do
{
rsch_prec_state_t old_state = (rsch_prec_state_t) __LDREXB((uint8_t*)&m_prec_states[prec]);
assert(old_state != RSCH_PREC_STATE_REQUESTED);
if (old_state != RSCH_PREC_STATE_APPROVED)
{
__CLREX();
return;
}
} while (__STREXB((uint8_t)RSCH_PREC_STATE_REQUESTED, (uint8_t*)&m_prec_states[prec]));
}
/** @brief Set RSCH_PREC_STATE_REQUESTED state on given precondition @p prec only if
* its current state is RSCH_PREC_STATE_IDLE.
*
* @param[in] prec Precondition which state will be changed.
*
* @retval true Precondition changed state to requested.
* @retval false Precondition cannot change state to requested due to invalid state.
*/
static inline bool prec_request(rsch_prec_t prec)
{
do
{
rsch_prec_state_t old_state = (rsch_prec_state_t) __LDREXB((uint8_t*)&m_prec_states[prec]);
if (old_state != RSCH_PREC_STATE_IDLE)
{
__CLREX();
return false;
}
} while (__STREXB((uint8_t)RSCH_PREC_STATE_REQUESTED, (uint8_t*)&m_prec_states[prec]));
return true;
}
/** @brief Set RSCH_PREC_STATE_IDLE state on given precondition @p prec.
*
* @param[in] prec Precondition which state will be changed.
*/
static inline void prec_release(rsch_prec_t prec)
{
assert(m_prec_states[prec] != RSCH_PREC_STATE_IDLE);
m_prec_states[prec] = RSCH_PREC_STATE_IDLE;
__CLREX();
}
/** @brief Request all preconditions.
*/
static inline void all_prec_request(void)
{
if (prec_request(RSCH_PREC_HFCLK))
{
nrf_802154_clock_hfclk_start();
}
if (prec_request(RSCH_PREC_RAAL))
{
nrf_raal_continuous_mode_enter();
}
}
/** @brief Release all preconditions if not needed.
*
* If RSCH is not in continuous mode and delayed timeslot is not expected all preconditions are
* released.
*/
static inline void all_prec_release(void)
{
if (!m_in_cont_mode && !any_prec_should_be_requested_for_delayed_timeslot())
{
prec_release(RSCH_PREC_HFCLK);
nrf_802154_clock_hfclk_stop();
prec_release(RSCH_PREC_RAAL);
nrf_raal_continuous_mode_exit();
}
}
/** @brief Check if all preconditions are met.
*
* @retval true All preconditions are met.
* @retval false At least one precondition is not met.
*/
static inline bool all_prec_are_approved(void)
{
for (uint32_t i = 0; i < RSCH_PREC_CNT; i++)
{
if (m_prec_states[i] != RSCH_PREC_STATE_APPROVED)
{
return false;
}
}
return true;
}
/** @brief Check if all preconditions are requested or met.
*
* @retval true All preconditions are requested or met.
* @retval false At least one precondition is idle.
*/
static inline bool all_prec_are_requested(void)
{
for (uint32_t i = 0; i < RSCH_PREC_CNT; i++)
{
if (m_prec_states[i] == RSCH_PREC_STATE_IDLE)
{
return false;
}
}
return true;
}
/** @brief Notify core if preconditions are approved or denied if current state differs from last reported.
*/
static inline void notify_core(void)
{
bool notify_approved;
uint8_t temp_mon;
do
{
if (!mutex_trylock())
{
return;
}
/* It is possible that preemption is not detected (m_mutex_monitor is read after acquiring mutex).
* It is not a problem because we will call proper handler function requested by preempting context.
* Avoiding this race would generate one additional iteration without any effect.
*/
temp_mon = m_mutex_monitor;
notify_approved = all_prec_are_approved();
if (m_in_cont_mode && (m_last_notified_approved != notify_approved))
{
m_last_notified_approved = notify_approved;
if (notify_approved)
{
nrf_802154_rsch_prec_approved();
}
else
{
nrf_802154_rsch_prec_denied();
}
}
mutex_unlock();
} while(temp_mon != m_mutex_monitor);
}
/** Timer callback used to trigger delayed timeslot.
*
* @param[in] p_context Unused parameter.
*/
static void delayed_timeslot_start(void * p_context)
{
(void)p_context;
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RSCH_TIMER_DELAYED_START);
m_delayed_timeslot_is_scheduled = false;
if (all_prec_are_approved())
{
nrf_802154_rsch_delayed_timeslot_started();
}
else
{
nrf_802154_rsch_delayed_timeslot_failed();
}
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RSCH_TIMER_DELAYED_START);
}
/** Timer callback used to request preconditions for delayed timeslot.
*
* @param[in] p_context Unused parameter.
*/
static void delayed_timeslot_prec_request(void * p_context)
{
(void)p_context;
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RSCH_TIMER_DELAYED_PREC);
all_prec_request();
m_timer.t0 = m_delayed_timeslot_t0;
m_timer.dt = m_delayed_timeslot_dt;
m_timer.callback = delayed_timeslot_start;
m_timer.p_context = NULL;
nrf_802154_timer_sched_add(&m_timer, true);
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RSCH_TIMER_DELAYED_PREC);
}
/***************************************************************************************************
* Public API
**************************************************************************************************/
void nrf_802154_rsch_init(void)
{
nrf_raal_init();
m_mutex = 0;
m_last_notified_approved = false;
m_in_cont_mode = false;
m_delayed_timeslot_is_scheduled = false;
for (uint32_t i = 0; i < RSCH_PREC_CNT; i++)
{
m_prec_states[i] = RSCH_PREC_STATE_IDLE;
}
}
void nrf_802154_rsch_uninit(void)
{
nrf_802154_timer_sched_remove(&m_timer);
nrf_raal_uninit();
}
void nrf_802154_rsch_continuous_mode_enter(void)
{
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RSCH_CONTINUOUS_ENTER);
m_in_cont_mode = true;
__DMB();
all_prec_request();
notify_core();
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RSCH_CONTINUOUS_ENTER);
}
void nrf_802154_rsch_continuous_mode_exit(void)
{
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RSCH_CONTINUOUS_EXIT);
__DMB();
m_in_cont_mode = false;
all_prec_release();
notify_core();
m_last_notified_approved = false;
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RSCH_CONTINUOUS_EXIT);
}
bool nrf_802154_rsch_prec_is_approved(rsch_prec_t prec)
{
assert(prec < RSCH_PREC_CNT);
return m_prec_states[prec] == RSCH_PREC_STATE_APPROVED;
}
bool nrf_802154_rsch_timeslot_request(uint32_t length_us)
{
return nrf_raal_timeslot_request(length_us);
}
bool nrf_802154_rsch_delayed_timeslot_request(uint32_t t0, uint32_t dt, uint32_t length)
{
(void)length;
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RSCH_DELAYED_TIMESLOT_REQ);
uint32_t now = nrf_802154_timer_sched_time_get();
uint32_t req_dt = dt - PREC_RAMP_UP_TIME;
bool result;
assert(!nrf_802154_timer_sched_is_running(&m_timer));
assert(!m_delayed_timeslot_is_scheduled);
if (nrf_802154_timer_sched_time_is_in_future(now, t0, req_dt))
{
m_delayed_timeslot_is_scheduled = true;
m_delayed_timeslot_t0 = t0;
m_delayed_timeslot_dt = dt;
m_timer.t0 = t0;
m_timer.dt = req_dt;
m_timer.callback = delayed_timeslot_prec_request;
m_timer.p_context = NULL;
nrf_802154_timer_sched_add(&m_timer, false);
result = true;
}
else if (all_prec_are_requested() && nrf_802154_timer_sched_time_is_in_future(now, t0, dt))
{
m_delayed_timeslot_is_scheduled = true;
m_delayed_timeslot_t0 = t0;
m_delayed_timeslot_dt = dt;
m_timer.t0 = t0;
m_timer.dt = dt;
m_timer.callback = delayed_timeslot_start;
m_timer.p_context = NULL;
nrf_802154_timer_sched_add(&m_timer, true);
result = true;
}
else
{
result = false;
}
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RSCH_DELAYED_TIMESLOT_REQ);
return result;
}
uint32_t nrf_802154_rsch_timeslot_us_left_get(void)
{
return nrf_raal_timeslot_us_left_get();
}
// External handlers
void nrf_raal_timeslot_started(void)
{
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RSCH_TIMESLOT_STARTED);
prec_approve(RSCH_PREC_RAAL);
notify_core();
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RSCH_TIMESLOT_STARTED);
}
void nrf_raal_timeslot_ended(void)
{
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RSCH_TIMESLOT_ENDED);
prec_deny(RSCH_PREC_RAAL);
notify_core();
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RSCH_TIMESLOT_ENDED);
}
void nrf_802154_clock_hfclk_ready(void)
{
prec_approve(RSCH_PREC_HFCLK);
notify_core();
}
@@ -51,7 +51,7 @@ extern "C" {
typedef struct
{
uint8_t psdu[MAX_PACKET_SIZE + 1];
bool free; // If this buffer is free or contains a frame.
bool free; // If this buffer is free or contains a frame.
} rx_buffer_t;
/**
@@ -80,4 +80,3 @@ rx_buffer_t * nrf_802154_rx_buffer_free_find(void);
#endif
#endif /* NRF_802154_RX_BUFFER_H_ */
+120 -118
View File
@@ -43,38 +43,37 @@
#include "nrf_802154.h"
#include "nrf_802154_config.h"
#include "nrf_802154_core.h"
#include "nrf_802154_rsch.h"
#include "nrf_802154_rx_buffer.h"
#include "hal/nrf_egu.h"
#include "platform/clock/nrf_802154_clock.h"
/** 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 (NRF_802154_RX_BUFFERS + 3)
#define NTF_QUEUE_SIZE (NRF_802154_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 REQ_QUEUE_SIZE 2
#define SWI_EGU NRF_802154_SWI_EGU_INSTANCE ///< Label of SWI peripheral.
#define SWI_IRQn NRF_802154_SWI_IRQN ///< Symbol of SWI IRQ number.
#define SWI_IRQHandler NRF_802154_SWI_IRQ_HANDLER ///< Symbol of SWI IRQ handler.
#define SWI_EGU NRF_802154_SWI_EGU_INSTANCE ///< Label of SWI peripheral.
#define SWI_IRQn NRF_802154_SWI_IRQN ///< Symbol of SWI IRQ number.
#define SWI_IRQHandler NRF_802154_SWI_IRQ_HANDLER ///< Symbol of SWI IRQ handler.
#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 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 ///< 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 HFCLK_STOP_INT NRF_EGU_INT_TRIGGERED1 ///< Label of HFClk stop interrupt.
#define HFCLK_STOP_TASK NRF_EGU_TASK_TRIGGER1 ///< Label of HFClk stop task.
#define HFCLK_STOP_EVENT NRF_EGU_EVENT_TRIGGERED1 ///< Label of HFClk stop event.
#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.
#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.
#define RAW_LENGTH_OFFSET 0
#define RAW_PAYLOAD_OFFSET 1
@@ -82,68 +81,69 @@
/// Types of notifications in notification queue.
typedef enum
{
NTF_TYPE_RECEIVED, ///< Frame received
NTF_TYPE_RECEIVE_FAILED, ///< Frame reception failed
NTF_TYPE_TRANSMITTED, ///< Frame transmitted
NTF_TYPE_TRANSMIT_FAILED, ///< Frame transmission failure
NTF_TYPE_ENERGY_DETECTED, ///< Energy detection procedure ended
NTF_TYPE_ENERGY_DETECTION_FAILED, ///< Energy detection procedure failed
NTF_TYPE_CCA, ///< CCA procedure ended
NTF_TYPE_CCA_FAILED, ///< CCA procedure failed
NTF_TYPE_RECEIVED, ///< Frame received
NTF_TYPE_RECEIVE_FAILED, ///< Frame reception failed
NTF_TYPE_TRANSMITTED, ///< Frame transmitted
NTF_TYPE_TRANSMIT_FAILED, ///< Frame transmission failure
NTF_TYPE_ENERGY_DETECTED, ///< Energy detection procedure ended
NTF_TYPE_ENERGY_DETECTION_FAILED, ///< Energy detection procedure failed
NTF_TYPE_CCA, ///< CCA procedure ended
NTF_TYPE_CCA_FAILED, ///< CCA procedure failed
} nrf_802154_ntf_type_t;
/// Notification data in the notification queue.
typedef struct
{
nrf_802154_ntf_type_t type; ///< Notification type.
nrf_802154_ntf_type_t type; ///< Notification type.
union
{
struct
{
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.
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
{
nrf_802154_rx_error_t error; ///< An error code that indicates reason of the failure.
nrf_802154_rx_error_t error; ///< An error code that indicates reason of the failure.
} receive_failed;
struct
{
const uint8_t * p_frame; ///< Pointer to frame that was 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.
const uint8_t * p_frame; ///< Pointer to frame that was 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
{
const uint8_t * p_frame; ///< Pointer to frame that was requested to be transmitted, but failed.
nrf_802154_tx_error_t error; ///< An error code that indicates reason of the failure.
const uint8_t * p_frame; ///< Pointer to frame that was requested to be transmitted, but failed.
nrf_802154_tx_error_t error; ///< An error code that indicates reason of the failure.
} transmit_failed;
struct
{
int8_t result; ///< Energy detection result.
} energy_detected; ///< Energy detection details.
int8_t result; ///< Energy detection result.
} energy_detected; ///< Energy detection details.
struct
{
nrf_802154_ed_error_t error; ///< An error code that indicates reason of the failure.
} energy_detection_failed; ///< Energy detection failure details.
nrf_802154_ed_error_t error; ///< An error code that indicates reason of the failure.
} energy_detection_failed; ///< Energy detection failure details.
struct
{
bool result; ///< CCA result.
} cca; ///< CCA details.
bool result; ///< CCA result.
} cca; ///< CCA details.
struct
{
nrf_802154_cca_error_t error; ///< An error code that indicates reason of the failure.
} cca_failed; ///< CCA failure details.
} data; ///< Notification data depending on it's type.
nrf_802154_cca_error_t error; ///< An error code that indicates reason of the failure.
} cca_failed; ///< CCA failure details.
} data; ///< Notification data depending on it's type.
} nrf_802154_ntf_data_t;
/// Type of requests in request queue.
@@ -163,79 +163,80 @@ typedef enum
/// Request data in request queue.
typedef struct
{
nrf_802154_req_type_t type; ///< Type of the request.
nrf_802154_req_type_t type; ///< Type of the request.
union
{
struct
{
nrf_802154_term_t term_lvl; ///< Request priority.
bool * p_result; ///< Sleep request result.
} sleep; ///< Sleep request details.
nrf_802154_term_t term_lvl; ///< Request priority.
bool * p_result; ///< Sleep request result.
} sleep; ///< Sleep request details.
struct
{
nrf_802154_notification_func_t notif_func; ///< Error notified in case of success.
nrf_802154_term_t term_lvl; ///< Request priority.
req_originator_t req_orig; ///< Request originator.
bool notif_abort; ///< If function termination should be notified.
bool * p_result; ///< Receive request result.
} receive; ///< Receive request details.
nrf_802154_notification_func_t notif_func; ///< Error notified in case of success.
nrf_802154_term_t term_lvl; ///< Request priority.
req_originator_t req_orig; ///< Request originator.
bool notif_abort; ///< If function termination should be notified.
bool * p_result; ///< Receive request result.
} receive; ///< Receive request details.
struct
{
nrf_802154_notification_func_t notif_func; ///< Error notified in case of success.
nrf_802154_term_t term_lvl; ///< Request priority.
req_originator_t req_orig; ///< Request originator.
const uint8_t * p_data; ///< Pointer to PSDU to transmit.
bool cca; ///< If CCA was requested prior to transmission.
bool immediate; ///< If TX procedure must be performed immediately.
bool * p_result; ///< Transmit request result.
} transmit; ///< Transmit request details.
nrf_802154_notification_func_t notif_func; ///< Error notified in case of success.
nrf_802154_term_t term_lvl; ///< Request priority.
req_originator_t req_orig; ///< Request originator.
const uint8_t * p_data; ///< Pointer to PSDU to transmit.
bool cca; ///< If CCA was requested prior to transmission.
bool immediate; ///< If TX procedure must be performed immediately.
bool * p_result; ///< Transmit request result.
} transmit; ///< Transmit request details.
struct
{
nrf_802154_term_t term_lvl; ///< Request priority.
bool * p_result; ///< Energy detection request result.
uint32_t time_us; ///< Requested time of energy detection procedure.
} energy_detection; ///< Energy detection request details.
nrf_802154_term_t term_lvl; ///< Request priority.
bool * p_result; ///< Energy detection request result.
uint32_t time_us; ///< Requested time of energy detection procedure.
} energy_detection; ///< Energy detection request details.
struct
{
nrf_802154_term_t term_lvl; ///< Request priority.
bool * p_result; ///< CCA request result.
} cca; ///< CCA request details.
nrf_802154_term_t term_lvl; ///< Request priority.
bool * p_result; ///< CCA request result.
} cca; ///< CCA request details.
struct
{
nrf_802154_term_t term_lvl; ///< Request priority.
bool * p_result; ///< Continuous carrier request result.
} continuous_carrier; ///< Continuous carrier request details.
nrf_802154_term_t term_lvl; ///< Request priority.
bool * p_result; ///< Continuous carrier request result.
} continuous_carrier; ///< Continuous carrier request details.
struct
{
uint8_t * p_data; ///< Pointer to receive buffer to free.
bool * p_result; ///< Buffer free request result.
} buffer_free; ///< Buffer free request details.
uint8_t * p_data; ///< Pointer to receive buffer to free.
bool * p_result; ///< Buffer free request result.
} buffer_free; ///< Buffer free request details.
struct
{
bool * p_result; ///< Channel update request result.
} channel_update; ///< Channel update request details.
bool * p_result; ///< Channel update request result.
} channel_update; ///< Channel update request details.
struct
{
bool * p_result; ///< CCA config update request result.
} cca_cfg_update; ///< CCA config update request details.
} data; ///< Request data depending on it's type.
bool * p_result; ///< CCA config update request result.
} cca_cfg_update; ///< CCA config update request details.
} data; ///< Request data depending on it's type.
} nrf_802154_req_data_t;
static nrf_802154_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_802154_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_802154_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.
static nrf_802154_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.
@@ -431,7 +432,7 @@ void nrf_802154_swi_init(void)
m_ntf_r_ptr = 0;
m_ntf_w_ptr = 0;
nrf_egu_int_enable(SWI_EGU, NTF_INT | TIMESLOT_EXIT_INT | REQ_INT);
nrf_egu_int_enable(SWI_EGU, NTF_INT | HFCLK_STOP_INT | REQ_INT);
NVIC_SetPriority(SWI_IRQn, NRF_802154_SWI_PRIORITY);
NVIC_ClearPendingIRQ(SWI_IRQn);
@@ -527,16 +528,16 @@ void nrf_802154_swi_notify_cca_failed(nrf_802154_cca_error_t error)
ntf_exit();
}
void nrf_802154_swi_timeslot_exit(void)
void nrf_802154_swi_hfclk_stop(void)
{
assert(!nrf_egu_event_check(SWI_EGU, TIMESLOT_EXIT_EVENT));
assert(!nrf_egu_event_check(SWI_EGU, HFCLK_STOP_EVENT));
nrf_egu_task_trigger(SWI_EGU, TIMESLOT_EXIT_TASK);
nrf_egu_task_trigger(SWI_EGU, HFCLK_STOP_TASK);
}
void nrf_802154_swi_timeslot_exit_terminate(void)
void nrf_802154_swi_hfclk_stop_terminate(void)
{
nrf_egu_event_clear(SWI_EGU, TIMESLOT_EXIT_EVENT);
nrf_egu_event_clear(SWI_EGU, HFCLK_STOP_EVENT);
}
void nrf_802154_swi_sleep(nrf_802154_term_t term_lvl, bool * p_result)
@@ -695,7 +696,7 @@ void SWI_IRQHandler(void)
#else // NRF_802154_USE_RAW_API
nrf_802154_transmitted(p_slot->data.transmitted.p_frame + RAW_PAYLOAD_OFFSET,
p_slot->data.transmitted.p_psdu == NULL ? NULL :
p_slot->data.transmitted.p_psdu + RAW_PAYLOAD_OFFSET,
p_slot->data.transmitted.p_psdu + RAW_PAYLOAD_OFFSET,
p_slot->data.transmitted.p_psdu[RAW_LENGTH_OFFSET],
p_slot->data.transmitted.power,
p_slot->data.transmitted.lqi);
@@ -707,8 +708,9 @@ void SWI_IRQHandler(void)
nrf_802154_transmit_failed(p_slot->data.transmit_failed.p_frame,
p_slot->data.transmit_failed.error);
#else // NRF_802154_USE_RAW_API
nrf_802154_transmit_failed(p_slot->data.transmit_failed.p_frame + RAW_PAYLOAD_OFFSET,
p_slot->data.transmit_failed.error);
nrf_802154_transmit_failed(
p_slot->data.transmit_failed.p_frame + RAW_PAYLOAD_OFFSET,
p_slot->data.transmit_failed.error);
#endif
break;
@@ -718,7 +720,7 @@ void SWI_IRQHandler(void)
case NTF_TYPE_ENERGY_DETECTION_FAILED:
nrf_802154_energy_detection_failed(
p_slot->data.energy_detection_failed.error);
p_slot->data.energy_detection_failed.error);
break;
case NTF_TYPE_CCA:
@@ -737,11 +739,11 @@ void SWI_IRQHandler(void)
}
}
if (nrf_egu_event_check(SWI_EGU, TIMESLOT_EXIT_EVENT))
if (nrf_egu_event_check(SWI_EGU, HFCLK_STOP_EVENT))
{
nrf_802154_rsch_continuous_mode_exit();
nrf_802154_clock_hfclk_stop();
nrf_egu_event_clear(SWI_EGU, TIMESLOT_EXIT_EVENT);
nrf_egu_event_clear(SWI_EGU, HFCLK_STOP_EVENT);
}
if (nrf_egu_event_check(SWI_EGU, REQ_EVENT))
@@ -756,32 +758,32 @@ void SWI_IRQHandler(void)
{
case REQ_TYPE_SLEEP:
*(p_slot->data.sleep.p_result) =
nrf_802154_core_sleep(p_slot->data.sleep.term_lvl);
nrf_802154_core_sleep(p_slot->data.sleep.term_lvl);
break;
case REQ_TYPE_RECEIVE:
*(p_slot->data.receive.p_result) =
nrf_802154_core_receive(p_slot->data.receive.term_lvl,
p_slot->data.receive.req_orig,
p_slot->data.receive.notif_func,
p_slot->data.receive.notif_abort);
nrf_802154_core_receive(p_slot->data.receive.term_lvl,
p_slot->data.receive.req_orig,
p_slot->data.receive.notif_func,
p_slot->data.receive.notif_abort);
break;
case REQ_TYPE_TRANSMIT:
*(p_slot->data.transmit.p_result) =
nrf_802154_core_transmit(p_slot->data.transmit.term_lvl,
p_slot->data.transmit.req_orig,
p_slot->data.transmit.p_data,
p_slot->data.transmit.cca,
p_slot->data.transmit.immediate,
p_slot->data.transmit.notif_func);
nrf_802154_core_transmit(p_slot->data.transmit.term_lvl,
p_slot->data.transmit.req_orig,
p_slot->data.transmit.p_data,
p_slot->data.transmit.cca,
p_slot->data.transmit.immediate,
p_slot->data.transmit.notif_func);
break;
case REQ_TYPE_ENERGY_DETECTION:
*(p_slot->data.energy_detection.p_result) =
nrf_802154_core_energy_detection(
p_slot->data.energy_detection.term_lvl,
p_slot->data.energy_detection.time_us);
nrf_802154_core_energy_detection(
p_slot->data.energy_detection.term_lvl,
p_slot->data.energy_detection.time_us);
break;
case REQ_TYPE_CCA:
@@ -790,13 +792,13 @@ void SWI_IRQHandler(void)
case REQ_TYPE_CONTINUOUS_CARRIER:
*(p_slot->data.continuous_carrier.p_result) =
nrf_802154_core_continuous_carrier(
p_slot->data.continuous_carrier.term_lvl);
nrf_802154_core_continuous_carrier(
p_slot->data.continuous_carrier.term_lvl);
break;
case REQ_TYPE_BUFFER_FREE:
*(p_slot->data.buffer_free.p_result) =
nrf_802154_core_notify_buffer_free(p_slot->data.buffer_free.p_data);
nrf_802154_core_notify_buffer_free(p_slot->data.buffer_free.p_data);
break;
case REQ_TYPE_CHANNEL_UPDATE:
@@ -121,18 +121,19 @@ void nrf_802154_swi_notify_cca(bool channel_free);
void nrf_802154_swi_notify_cca_failed(nrf_802154_cca_error_t error);
/**
* @brief Request discarding of the timeslot from SWI priority level.
* @brief Request stop of the HF clock from the SWI priority level.
*
* @note This function should be called through notification module to prevent calling it from arbiter context.
* @note This function should be called through notification module to prevent calling it from
* the arbiter context.
*/
void nrf_802154_swi_timeslot_exit(void);
void nrf_802154_swi_hfclk_stop(void);
/**
* @brief Terminate discarding of the timeslot.
* @brief Terminate stopping of the HF clock.
*
* @note This function terminates discrading of timeslot only if it has not been performed.
* @note This function terminates stopping of the HF clock only if it has not been performed.
*/
void nrf_802154_swi_timeslot_exit_terminate(void);
void nrf_802154_swi_hfclk_stop_terminate(void);
/**
* @brief Request entering sleep state from SWI priority.
@@ -45,23 +45,24 @@
#include "platform/hp_timer/nrf_802154_hp_timer.h"
#include "platform/lp_timer/nrf_802154_lp_timer.h"
#define DIV_ROUND_POSITIVE(n, d) (((n) + (d)/2)/(d))
#define DIV_ROUND_NEGATIVE(n, d) (((n) - (d)/2)/(d))
#define DIV_ROUND(n, d) ((((n) < 0) ^ ((d) < 0)) ? DIV_ROUND_NEGATIVE(n, d) : DIV_ROUND_POSITIVE(n, d))
#define DIV_ROUND_POSITIVE(n, d) (((n) + (d) / 2) / (d))
#define DIV_ROUND_NEGATIVE(n, d) (((n) - (d) / 2) / (d))
#define DIV_ROUND(n, d) ((((n) < 0) ^ ((d) < 0)) ? \
DIV_ROUND_NEGATIVE(n, d) : \
DIV_ROUND_POSITIVE(n, d))
#define TIME_BASE (1UL << 22) ///< Unit used to calculate PPTB (Point per Time Base). It is not equal million to speed up computations and increase precision.
#define FIRST_RESYNC_TIME TIME_BASE ///< Delay of the first resynchronization. The first resynchronization is needed to measure timers drift.
#define RESYNC_TIME (64 * TIME_BASE) ///< Delay of following resynchronizations.
#define EWMA_COEF (8) ///< Weight used in the EWMA algorithm.
#define TIME_BASE (1UL << 22) ///< Unit used to calculate PPTB (Point per Time Base). It is not equal million to speed up computations and increase precision.
#define FIRST_RESYNC_TIME TIME_BASE ///< Delay of the first resynchronization. The first resynchronization is needed to measure timers drift.
#define RESYNC_TIME (64 * TIME_BASE) ///< Delay of following resynchronizations.
#define EWMA_COEF (8) ///< Weight used in the EWMA algorithm.
#define PPI_CH0 NRF_PPI_CHANNEL13
#define PPI_CH1 NRF_PPI_CHANNEL14
#define PPI_CHGRP0 NRF_PPI_CHANNEL_GROUP1
#define PPI_CH0 NRF_PPI_CHANNEL13
#define PPI_CH1 NRF_PPI_CHANNEL14
#define PPI_CHGRP0 NRF_PPI_CHANNEL_GROUP1
#define PPI_SYNC PPI_CH0
#define PPI_TIMESTAMP PPI_CH1
#define PPI_TIMESTAMP_GROUP PPI_CHGRP0
#define PPI_SYNC PPI_CH0
#define PPI_TIMESTAMP PPI_CH1
#define PPI_TIMESTAMP_GROUP PPI_CHGRP0
#if NRF_802154_FRAME_TIMESTAMP_ENABLED
// Structure holding common timepoint from both timers.
@@ -71,6 +72,7 @@ typedef struct
uint32_t hp_timer_time; ///< HP Timer time of common timepoint.
} common_timepoint_t;
// Static variables.
static common_timepoint_t m_last_sync; ///< Common timepoint of last synchronization event.
static volatile bool m_synchronized; ///< If timers were synchronized since last start.
static bool m_drift_known; ///< If timer drift value is known.
@@ -125,7 +127,8 @@ void nrf_802154_timer_coord_timestamp_prepare(uint32_t event_addr)
nrf_ppi_channel_and_fork_endpoint_setup(PPI_TIMESTAMP,
event_addr,
nrf_802154_hp_timer_timestamp_task_get(),
(uint32_t)nrf_ppi_task_group_disable_address_get(PPI_TIMESTAMP_GROUP));
(uint32_t)nrf_ppi_task_group_disable_address_get(
PPI_TIMESTAMP_GROUP));
nrf_ppi_group_enable(PPI_TIMESTAMP_GROUP);
}
@@ -67,7 +67,7 @@ void nrf_802154_timer_coord_uninit(void);
/**
* @brief Start the Timer Coordinator.
*
*
* This function starts the HP timer and synchronizes it with the LP timer.
*
* Started Timer Coordinator resynchronizes automatically in constant interval.
@@ -47,63 +47,66 @@
*/
typedef uint8_t nrf_802154_state_t;
#define NRF_802154_STATE_INVALID 0x01 //!< Radio in an invalid state.
#define NRF_802154_STATE_SLEEP 0x02 //!< Radio in sleep state.
#define NRF_802154_STATE_RECEIVE 0x03 //!< Radio in receive state.
#define NRF_802154_STATE_TRANSMIT 0x04 //!< Radio in transmit state.
#define NRF_802154_STATE_ENERGY_DETECTION 0x05 //!< Radio in energy detection state.
#define NRF_802154_STATE_CCA 0x06 //!< Radio in CCA state.
#define NRF_802154_STATE_CONTINUOUS_CARRIER 0x07 //!< Radio in continuous carrier state.
#define NRF_802154_STATE_INVALID 0x01 // !< Radio in an invalid state.
#define NRF_802154_STATE_SLEEP 0x02 // !< Radio in sleep state.
#define NRF_802154_STATE_RECEIVE 0x03 // !< Radio in receive state.
#define NRF_802154_STATE_TRANSMIT 0x04 // !< Radio in transmit state.
#define NRF_802154_STATE_ENERGY_DETECTION 0x05 // !< Radio in energy detection state.
#define NRF_802154_STATE_CCA 0x06 // !< Radio in CCA state.
#define NRF_802154_STATE_CONTINUOUS_CARRIER 0x07 // !< Radio in continuous carrier state.
/**
* @brief Errors reported during frame transmission.
*/
typedef uint8_t nrf_802154_tx_error_t;
#define NRF_802154_TX_ERROR_NONE 0x00 //!< There is no transmit error.
#define NRF_802154_TX_ERROR_BUSY_CHANNEL 0x01 //!< CCA reported busy channel prior to transmission.
#define NRF_802154_TX_ERROR_INVALID_ACK 0x02 //!< Received ACK frame is other than expected.
#define NRF_802154_TX_ERROR_NO_MEM 0x03 //!< No receive buffer is available to receive an ACK.
#define NRF_802154_TX_ERROR_TIMESLOT_ENDED 0x04 //!< Radio timeslot ended during transmission procedure.
#define NRF_802154_TX_ERROR_NO_ACK 0x05 //!< ACK frame was not received during timeout period.
#define NRF_802154_TX_ERROR_ABORTED 0x06 //!< Procedure was aborted by another driver operation with FORCE priority.
#define NRF_802154_TX_ERROR_TIMESLOT_DENIED 0x07 //!< Transmission did not start due to denied timeslot request.
#define NRF_802154_TX_ERROR_NONE 0x00 // !< There is no transmit error.
#define NRF_802154_TX_ERROR_BUSY_CHANNEL 0x01 // !< CCA reported busy channel prior to transmission.
#define NRF_802154_TX_ERROR_INVALID_ACK 0x02 // !< Received ACK frame is other than expected.
#define NRF_802154_TX_ERROR_NO_MEM 0x03 // !< No receive buffer is available to receive an ACK.
#define NRF_802154_TX_ERROR_TIMESLOT_ENDED 0x04 // !< Radio timeslot ended during transmission procedure.
#define NRF_802154_TX_ERROR_NO_ACK 0x05 // !< ACK frame was not received during timeout period.
#define NRF_802154_TX_ERROR_ABORTED 0x06 // !< Procedure was aborted by another driver operation with FORCE priority.
#define NRF_802154_TX_ERROR_TIMESLOT_DENIED 0x07 // !< Transmission did not start due to denied timeslot request.
/**
* @brief Possible errors during frame reception.
*/
typedef uint8_t nrf_802154_rx_error_t;
#define NRF_802154_RX_ERROR_NONE 0x00 //!< There is no receive error.
#define NRF_802154_RX_ERROR_INVALID_FRAME 0x01 //!< Received a malformed frame.
#define NRF_802154_RX_ERROR_INVALID_FCS 0x02 //!< Received a frame with invalid checksum.
#define NRF_802154_RX_ERROR_INVALID_DEST_ADDR 0x03 //!< Received a frame with mismatched destination address.
#define NRF_802154_RX_ERROR_RUNTIME 0x04 //!< A runtime error occurred (for example, CPU was held for too long).
#define NRF_802154_RX_ERROR_TIMESLOT_ENDED 0x05 //!< Radio timeslot ended during frame reception.
#define NRF_802154_RX_ERROR_ABORTED 0x06 //!< Procedure was aborted by another driver operation with FORCE priority.
#define NRF_802154_RX_ERROR_NONE 0x00 // !< There is no receive error.
#define NRF_802154_RX_ERROR_INVALID_FRAME 0x01 // !< Received a malformed frame.
#define NRF_802154_RX_ERROR_INVALID_FCS 0x02 // !< Received a frame with invalid checksum.
#define NRF_802154_RX_ERROR_INVALID_DEST_ADDR 0x03 // !< Received a frame with mismatched destination address.
#define NRF_802154_RX_ERROR_RUNTIME 0x04 // !< A runtime error occurred (for example, CPU was held for too long).
#define NRF_802154_RX_ERROR_TIMESLOT_ENDED 0x05 // !< Radio timeslot ended during frame reception.
#define NRF_802154_RX_ERROR_ABORTED 0x06 // !< Procedure was aborted by another driver operation with FORCE priority.
#define NRF_802154_RX_ERROR_DELAYED_TIMESLOT_DENIED 0x07 // !< Delayed reception request was rejected due to denied timeslot request.
#define NRF_802154_RX_ERROR_DELAYED_TIMEOUT 0x08 // !< Frame not received during delayed reception time slot.
#define NRF_802154_RX_ERROR_INVALID_LENGTH 0x09 // !< Received a frame with invalid length.
/**
* @brief Possible errors during energy detection.
*/
typedef uint8_t nrf_802154_ed_error_t;
#define NRF_802154_ED_ERROR_ABORTED 0x01 //!< Procedure was aborted by another driver operation with FORCE priority.
#define NRF_802154_ED_ERROR_ABORTED 0x01 // !< Procedure was aborted by another driver operation with FORCE priority.
/**
* @brief Possible errors during CCA procedure.
*/
typedef uint8_t nrf_802154_cca_error_t;
#define NRF_802154_CCA_ERROR_ABORTED 0x01 //!< Procedure was aborted by another driver operation with FORCE priority.
#define NRF_802154_CCA_ERROR_ABORTED 0x01 // !< Procedure was aborted by another driver operation with FORCE priority.
/**
* @brief Possible errors during sleep procedure call.
*/
typedef uint8_t nrf_802154_sleep_error_t;
#define NRF_802154_SLEEP_ERROR_NONE 0x00 //!< There is no error.
#define NRF_802154_SLEEP_ERROR_BUSY 0x01 //!< The driver cannot enter sleep state due to ongoing operation.
#define NRF_802154_SLEEP_ERROR_NONE 0x00 // !< There is no error.
#define NRF_802154_SLEEP_ERROR_BUSY 0x01 // !< The driver cannot enter sleep state due to ongoing operation.
/**
* @brief Termination level selected for a particular request.
*
@@ -112,18 +115,18 @@ typedef uint8_t nrf_802154_sleep_error_t;
*/
typedef uint8_t nrf_802154_term_t;
#define NRF_802154_TERM_NONE 0x00 //!< Request is skipped if another operation is ongoing.
#define NRF_802154_TERM_802154 0x01 //!< Request terminates ongoing 802.15.4 operation.
#define NRF_802154_TERM_NONE 0x00 // !< Request is skipped if another operation is ongoing.
#define NRF_802154_TERM_802154 0x01 // !< Request terminates ongoing 802.15.4 operation.
/**
* @brief Structure for configuring CCA.
*/
typedef struct
{
nrf_radio_cca_mode_t mode; //!< CCA mode.
uint8_t ed_threshold; //!< CCA energy busy threshold. Not used in NRF_RADIO_CCA_MODE_CARRIER.
uint8_t corr_threshold; //!< CCA correlator busy threshold. Not used in NRF_RADIO_CCA_MODE_ED.
uint8_t corr_limit; //!< Limit of occurrences above CCA correlator busy threshold. Not used in NRF_RADIO_CCA_MODE_ED.
nrf_radio_cca_mode_t mode; // !< CCA mode.
uint8_t ed_threshold; // !< CCA energy busy threshold. Not used in NRF_RADIO_CCA_MODE_CARRIER.
uint8_t corr_threshold; // !< CCA correlator busy threshold. Not used in NRF_RADIO_CCA_MODE_ED.
uint8_t corr_limit; // !< Limit of occurrences above CCA correlator busy threshold. Not used in NRF_RADIO_CCA_MODE_ED.
} nrf_802154_cca_cfg_t;
/**
@@ -43,26 +43,25 @@
*/
/**@brief RTC clock frequency. */
#define NRF_802154_RTC_FREQUENCY 32768UL
#define NRF_802154_RTC_FREQUENCY 32768UL
/**@brief Defines number of microseconds in one second. */
#define NRF_802154_US_PER_S 1000000ULL
#define NRF_802154_US_PER_S 1000000ULL
/**@brief Number of microseconds in one RTC tick. (rounded up) */
#define NRF_802154_US_PER_TICK NRF_802154_RTC_TICKS_TO_US(1)
#define NRF_802154_US_PER_TICK NRF_802154_RTC_TICKS_TO_US(1)
/**@brief Number of bits to shift RTC_FREQUENCY and US_PER_S to achieve division by greatest common divisor. */
#define NRF_802154_FREQUENCY_US_PER_S_GCD_BITS 6
#define NRF_802154_FREQUENCY_US_PER_S_GCD_BITS 6
/**@brief Ceil division helper */
#define NRF_802154_DIVIDE_AND_CEIL(A, B) (((A) + (B) - 1) / (B))
#define NRF_802154_DIVIDE_AND_CEIL(A, B) (((A) + (B)-1) / (B))
/**@brief RTC ticks to us conversion. */
#define NRF_802154_RTC_TICKS_TO_US(ticks) \
NRF_802154_DIVIDE_AND_CEIL( \
(ticks) * (NRF_802154_US_PER_S >> NRF_802154_FREQUENCY_US_PER_S_GCD_BITS), \
(NRF_802154_RTC_FREQUENCY >> NRF_802154_FREQUENCY_US_PER_S_GCD_BITS))
#define NRF_802154_RTC_TICKS_TO_US(ticks) \
NRF_802154_DIVIDE_AND_CEIL( \
(ticks) * (NRF_802154_US_PER_S >> NRF_802154_FREQUENCY_US_PER_S_GCD_BITS), \
(NRF_802154_RTC_FREQUENCY >> NRF_802154_FREQUENCY_US_PER_S_GCD_BITS))
static inline uint64_t NRF_802154_US_TO_RTC_TICKS(uint64_t time)
{
@@ -101,11 +100,11 @@ static inline uint64_t NRF_802154_US_TO_RTC_TICKS(uint64_t time)
There is a possible loss of precision so that t1 will be up to 93*15625 _smaller_
than the accurate number. This is taken into account in the next step.
*/
*/
t1 = ((time >> 13) * 0x8637bd0) >> 28; // ((time >> 13) * (2^41 / 15625)) >> (41 - 13)
t1 = ((time >> 13) * 0x8637bd0) >> 28; // ((time >> 13) * (2^41 / 15625)) >> (41 - 13)
result = t1 * 512;
t1 = time - t1 * 15625;
t1 = time - t1 * 15625;
/* This second step of the calculation is to find out how many RTC units there are
still left in the remaining microseconds.
@@ -130,9 +129,9 @@ static inline uint64_t NRF_802154_US_TO_RTC_TICKS(uint64_t time)
// ceil((time * (2^56 / 15625)) >> (56 - 9))
assert(t1 <= 1453125);
u1 = (t1 * 0x431bde82d7b); // (time * (2^56 / 15625))
u1 += 0x7fffffffffff; // round up
u1 >>= 47; // ceil(u1 >> (56 - 9))
u1 = (t1 * 0x431bde82d7b); // (time * (2^56 / 15625))
u1 += 0x7fffffffffff; // round up
u1 >>= 47; // ceil(u1 >> (56 - 9))
result += u1;
@@ -149,7 +148,8 @@ static inline uint64_t NRF_802154_US_TO_RTC_TICKS(uint64_t time)
*/
static inline uint32_t nrf_is_nvic_irq_enabled(IRQn_Type IRQn)
{
return (NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)]) & ((uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)));
return (NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)]) &
((uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)));
}
/**
@@ -49,20 +49,20 @@
#include "nrf_802154_config.h"
/**@brief Timer instance. */
#define TIMER NRF_TIMER0
#define TIMER NRF_TIMER0
/**@brief Timer compare channel definitions. */
#define TIMER_CC_CAPTURE NRF_TIMER_CC_CHANNEL1
#define TIMER_CC_CAPTURE_TASK NRF_TIMER_TASK_CAPTURE1
#define TIMER_CC_CAPTURE NRF_TIMER_CC_CHANNEL1
#define TIMER_CC_CAPTURE_TASK NRF_TIMER_TASK_CAPTURE1
#define TIMER_CC_SYNC NRF_TIMER_CC_CHANNEL2
#define TIMER_CC_SYNC_TASK NRF_TIMER_TASK_CAPTURE2
#define TIMER_CC_SYNC_EVENT NRF_TIMER_EVENT_COMPARE2
#define TIMER_CC_SYNC_INT NRF_TIMER_INT_COMPARE2_MASK
#define TIMER_CC_SYNC NRF_TIMER_CC_CHANNEL2
#define TIMER_CC_SYNC_TASK NRF_TIMER_TASK_CAPTURE2
#define TIMER_CC_SYNC_EVENT NRF_TIMER_EVENT_COMPARE2
#define TIMER_CC_SYNC_INT NRF_TIMER_INT_COMPARE2_MASK
#define TIMER_CC_EVT NRF_TIMER_CC_CHANNEL3
#define TIMER_CC_EVT_TASK NRF_TIMER_TASK_CAPTURE3
#define TIMER_CC_EVT_INT NRF_TIMER_INT_COMPARE3_MASK
#define TIMER_CC_EVT NRF_TIMER_CC_CHANNEL3
#define TIMER_CC_EVT_TASK NRF_TIMER_TASK_CAPTURE3
#define TIMER_CC_EVT_INT NRF_TIMER_INT_COMPARE3_MASK
/**@brief Unexpected value in the sync compare channel. */
static uint32_t m_unexpected_sync;
@@ -139,4 +139,3 @@ uint32_t nrf_802154_hp_timer_timestamp_get(void)
{
return nrf_timer_cc_read(TIMER, TIMER_CC_EVT);
}
@@ -134,7 +134,6 @@ uint32_t nrf_802154_hp_timer_timestamp_task_get(void);
*/
uint32_t nrf_802154_hp_timer_timestamp_get(void);
/**
*@}
**/
@@ -146,22 +146,22 @@ bool nrf_802154_lp_timer_is_running(void);
/**
* @brief Start one-shot synchronization timer that expires at nearest possible timepoint.
*
*
* On timer expiration @ref nrf_802154_lp_timer_synchronized function will be called and
* event returned by @ref nrf_802154_lp_timer_sync_event_get will be triggered.
*
*
* @note @ref nrf_802154_lp_timer_synchronized may be called multiple times.
*/
void nrf_802154_lp_timer_sync_start_now(void);
/**
* @brief Start one-shot synchronization timer that expires at specified time.
*
*
* Start one-shot synchronization timer that will expire @p dt microseconds after @p t0 time.
*
*
* On timer expiration @ref nrf_802154_lp_timer_synchronized function will be called and
* event returned by @ref nrf_802154_lp_timer_sync_event_get will be triggered.
*
*
* @param[in] t0 Number of microseconds representing timer start time.
* @param[in] dt Time of timer expiration as time elapsed from @p t0 [us].
*/
@@ -174,7 +174,7 @@ void nrf_802154_lp_timer_sync_stop(void);
/**
* @brief Get event used to synchronize this timer with HP Timer
*
*
* @return Address of the peripheral register corresponding to the event that
* should be used for timers synchronization.
*/
@@ -57,13 +57,12 @@
#define RTC_SYNC_COMPARE_EVENT NRF_RTC_EVENT_COMPARE_1
#define RTC_SYNC_COMPARE_EVENT_MASK RTC_EVTEN_COMPARE1_Msk
#define US_PER_OVERFLOW (512UL * NRF_802154_US_PER_S) ///< Time that has passed between overflow events. On full RTC speed, it occurs every 512 s.
#define MIN_RTC_COMPARE_EVENT_DT (2 * NRF_802154_US_PER_TICK) ///< Minimum time delta from now before RTC compare event is guaranteed to fire.
#define US_PER_OVERFLOW (512UL * NRF_802154_US_PER_S) ///< Time that has passed between overflow events. On full RTC speed, it occurs every 512 s.
#define MIN_RTC_COMPARE_EVENT_DT (2 * NRF_802154_US_PER_TICK) ///< Minimum time delta from now before RTC compare event is guaranteed to fire.
#define EPOCH_32BIT_US (1ULL << 32)
#define EPOCH_FROM_TIME(time) ((time) & ((uint64_t)UINT32_MAX << 32))
// Struct holding information about compare channel.
typedef struct
{
@@ -86,8 +85,7 @@ static const compare_channel_descriptor_t m_cmp_ch[CHANNEL_CNT] = {{RTC_LP_TIMER
RTC_SYNC_COMPARE_EVENT,
RTC_SYNC_COMPARE_EVENT_MASK}};
static uint64_t m_target_times[CHANNEL_CNT]; ///< Target time of given channel [us].
static uint64_t m_target_times[CHANNEL_CNT]; ///< Target time of given channel [us].
static volatile uint32_t m_offset_counter; ///< Counter of RTC overflows, incremented by 2 on each OVERFLOW event.
static volatile uint8_t m_mutex; ///< Mutex for write access to @ref m_offset_counter.
@@ -276,7 +274,8 @@ static uint32_t overflow_counter_get(void)
else
{
// Failed to acquire mutex.
if (nrf_rtc_event_pending(NRF_802154_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW) || (m_offset_counter & 0x01))
if (nrf_rtc_event_pending(NRF_802154_RTC_INSTANCE,
NRF_RTC_EVENT_OVERFLOW) || (m_offset_counter & 0x01))
{
// Lower priority context is currently incrementing m_offset_counter variable.
offset = (m_offset_counter + 2) / 2;
@@ -340,6 +339,7 @@ static uint64_t round_up_to_timer_ticks_multiply(uint64_t time)
{
uint64_t ticks = time_to_ticks(time);
uint64_t result = ticks_to_time(ticks);
return result;
}
@@ -396,7 +396,10 @@ void nrf_802154_lp_timer_init(void)
// Setup low frequency clock.
nrf_802154_clock_lfclk_start();
while (!m_clock_ready) { }
while (!m_clock_ready)
{
// Intentionally empty
}
// Setup RTC timer.
NVIC_SetPriority(NRF_802154_RTC_IRQN, NRF_802154_RTC_IRQ_PRIORITY);
@@ -517,7 +520,8 @@ void nrf_802154_lp_timer_sync_start_now(void)
offset_and_counter_get(&offset, &counter);
now = time_get(offset, counter);
timer_sync_start_at((uint32_t)now, MIN_RTC_COMPARE_EVENT_DT, &now);
} while (counter_get() != counter);
}
while (counter_get() != counter);
}
void nrf_802154_lp_timer_sync_start_at(uint32_t t0, uint32_t dt)
@@ -536,7 +540,8 @@ void nrf_802154_lp_timer_sync_stop(void)
uint32_t nrf_802154_lp_timer_sync_event_get(void)
{
return (uint32_t)nrf_rtc_event_address_get(NRF_802154_RTC_INSTANCE, m_cmp_ch[SYNC_CHANNEL].event);
return (uint32_t)nrf_rtc_event_address_get(NRF_802154_RTC_INSTANCE,
m_cmp_ch[SYNC_CHANNEL].event);
}
uint32_t nrf_802154_lp_timer_sync_time_get(void)
@@ -57,4 +57,3 @@ int8_t nrf_802154_temperature_get(void)
{
return DEFAULT_TEMPERATURE;
}
@@ -0,0 +1,456 @@
#include "nrf_802154_rsch.h"
#include <assert.h>
#include <stddef.h>
#include <nrf.h>
#include "nrf_802154_debug.h"
#include "nrf_802154_priority_drop.h"
#include "platform/clock/nrf_802154_clock.h"
#include "raal/nrf_raal_api.h"
#include "timer_scheduler/nrf_802154_timer_sched.h"
#define PREC_RAMP_UP_TIME 300 ///< Ramp-up time of preconditions [us]. 300 is worst case for HFclock
static volatile uint8_t m_ntf_mutex; ///< Mutex for notyfying core.
static volatile uint8_t m_ntf_mutex_monitor; ///< Mutex monitor, incremented every failed ntf mutex lock.
static volatile uint8_t m_req_mutex; ///< Mutex for requesting preconditions.
static volatile uint8_t m_req_mutex_monitor; ///< Mutex monitor, incremented every failed req mutex lock.
static volatile rsch_prio_t m_last_notified_prio; ///< Last reported approved priority level.
static volatile rsch_prio_t m_approved_prios[RSCH_PREC_CNT]; ///< Priority levels approved by each precondition.
static rsch_prio_t m_requested_prio; ///< Priority requested from all preconditions.
static rsch_prio_t m_cont_mode_prio; ///< Continuous mode priority level. If continuous mode is not requested equal to @ref RSCH_PRIO_IDLE.
typedef struct
{
rsch_prio_t prio; ///< Delayed timeslot priority level. If delayed timeslot is not scheduled equal to @ref RSCH_PRIO_IDLE.
uint32_t t0; ///< Time base of the delayed timeslot trigger time.
uint32_t dt; ///< Time delta of the delayed timeslot trigger time.
nrf_802154_timer_t timer; ///< Timer used to trigger delayed timeslot.
} dly_ts_t;
static dly_ts_t m_dly_ts[RSCH_DLY_TS_NUM];
/** @brief Non-blocking mutex for notifying core.
*
* @param[inout] p_mutex Pointer to the mutex data.
* @param[inout] p_mutex_monitor Pointer to the mutex monitor counter.
*
* @retval true Mutex was acquired.
* @retval false Mutex could not be acquired.
*/
static inline bool mutex_trylock(volatile uint8_t * p_mutex, volatile uint8_t * p_mutex_monitor)
{
do
{
uint8_t mutex_value = __LDREXB(p_mutex);
if (mutex_value)
{
__CLREX();
(*p_mutex_monitor)++;
return false;
}
}
while (__STREXB(1, p_mutex));
__DMB();
return true;
}
/** @brief Release mutex. */
static inline void mutex_unlock(volatile uint8_t * p_mutex)
{
__DMB();
*p_mutex = 0;
}
/** @brief Check maximal priority level required by any of delayed timeslots at the moment.
*
* To meet delayed timeslot timing requirements there is a time window in which radio
* preconditions should be requested. This function is used to prevent releasing preconditions
* in this time window.
*
* @return Maximal priority level required by delayed timeslots.
*/
static rsch_prio_t max_prio_for_delayed_timeslot_get(void)
{
rsch_prio_t result = RSCH_PRIO_IDLE;
uint32_t now = nrf_802154_timer_sched_time_get();
for (uint32_t i = 0; i < RSCH_DLY_TS_NUM; i++)
{
dly_ts_t * p_dly_ts = &m_dly_ts[i];
uint32_t t0 = p_dly_ts->t0;
uint32_t dt = p_dly_ts->dt - PREC_RAMP_UP_TIME -
nrf_802154_timer_sched_granularity_get();
if ((p_dly_ts->prio > result) && !nrf_802154_timer_sched_time_is_in_future(now, t0, dt))
{
result = p_dly_ts->prio;
}
}
return result;
}
static rsch_prio_t required_prio_lvl_get(void)
{
rsch_prio_t result = max_prio_for_delayed_timeslot_get();
if (m_cont_mode_prio > result)
{
result = m_cont_mode_prio;
}
return result;
}
/** @brief Set approved priority level @p prio on given precondition @p prec.
*
* When requested priority level equals to the @ref RSCH_PRIO_IDLE this function will approve only
* the @ref RSCH_PRIO_IDLE priority level and drop other approved levels silently.
*
* @param[in] prec Precondition which state will be changed.
* @param[in] prio Approved priority level for given precondition.
*/
static inline void prec_approved_prio_set(rsch_prec_t prec, rsch_prio_t prio)
{
assert(prec <= RSCH_PREC_CNT);
if ((m_requested_prio == RSCH_PRIO_IDLE) && (prio != RSCH_PRIO_IDLE))
{
// Ignore approved precondition - it was not requested.
return;
}
assert((m_approved_prios[prec] != prio) || (prio == RSCH_PRIO_IDLE));
m_approved_prios[prec] = prio;
}
/** @brief Request all preconditions.
*/
static inline void all_prec_update(void)
{
rsch_prio_t prev_prio;
rsch_prio_t new_prio;
uint8_t monitor;
do
{
if (!mutex_trylock(&m_req_mutex, &m_req_mutex_monitor))
{
return;
}
monitor = m_req_mutex_monitor;
prev_prio = m_requested_prio;
new_prio = required_prio_lvl_get();
if (prev_prio != new_prio)
{
m_requested_prio = new_prio;
if (new_prio == RSCH_PRIO_IDLE)
{
nrf_802154_priority_drop_hfclk_stop();
prec_approved_prio_set(RSCH_PREC_HFCLK, RSCH_PRIO_IDLE);
nrf_raal_continuous_mode_exit();
prec_approved_prio_set(RSCH_PREC_RAAL, RSCH_PRIO_IDLE);
}
else
{
nrf_802154_priority_drop_hfclk_stop_terminate();
nrf_802154_clock_hfclk_start();
nrf_raal_continuous_mode_enter();
}
}
mutex_unlock(&m_req_mutex);
}
while (monitor != m_req_mutex_monitor);
}
/** @brief Get currently approved priority level.
*
* @return Maximal priority level approved by all radio preconditions.
*/
static inline rsch_prio_t approved_prio_lvl_get(void)
{
rsch_prio_t result = RSCH_PRIO_MAX;
for (uint32_t i = 0; i < RSCH_PREC_CNT; i++)
{
if (m_approved_prios[i] < result)
{
result = m_approved_prios[i];
}
}
return result;
}
/** @brief Check if all preconditions are requested or met at given priority level or higher.
*
* @param[in] prio Minimal priority level requested from preconditions.
*
* @retval true All preconditions are requested or met at given or higher level.
* @retval false At least one precondition is requested at lower level than required.
*/
static inline bool requested_prio_lvl_is_at_least(rsch_prio_t prio)
{
return m_requested_prio >= prio;
}
/** @brief Notify core if preconditions are approved or denied if current state differs from last reported.
*/
static inline void notify_core(void)
{
rsch_prio_t approved_prio_lvl;
uint8_t temp_mon;
do
{
if (!mutex_trylock(&m_ntf_mutex, &m_ntf_mutex_monitor))
{
return;
}
/* It is possible that preemption is not detected (m_ntf_mutex_monitor is read after
* acquiring mutex). It is not a problem because we will call proper handler function
* requested by preempting context. Avoiding this race would generate one additional
* iteration without any effect.
*/
temp_mon = m_ntf_mutex_monitor;
approved_prio_lvl = approved_prio_lvl_get();
if ((m_cont_mode_prio > RSCH_PRIO_IDLE) && (m_last_notified_prio != approved_prio_lvl))
{
m_last_notified_prio = approved_prio_lvl;
nrf_802154_rsch_continuous_prio_changed(approved_prio_lvl);
}
mutex_unlock(&m_ntf_mutex);
}
while (temp_mon != m_ntf_mutex_monitor);
}
/** Timer callback used to trigger delayed timeslot.
*
* @param[in] p_context Index of the delayed timeslot operation (TX or RX).
*/
static void delayed_timeslot_start(void * p_context)
{
rsch_dly_ts_id_t dly_ts_id = (rsch_dly_ts_id_t)(uint32_t)p_context;
dly_ts_t * p_dly_ts = &m_dly_ts[dly_ts_id];
rsch_prio_t req_prio_lvl;
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RSCH_TIMER_DELAYED_START);
req_prio_lvl = p_dly_ts->prio;
p_dly_ts->prio = RSCH_PRIO_IDLE;
if (approved_prio_lvl_get() >= req_prio_lvl)
{
nrf_802154_rsch_delayed_timeslot_started(dly_ts_id);
}
else
{
nrf_802154_rsch_delayed_timeslot_failed(dly_ts_id);
}
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RSCH_TIMER_DELAYED_START);
}
/** Timer callback used to request preconditions for delayed timeslot.
*
* @param[in] p_context Index of the delayed timeslot operation (TX or RX).
*/
static void delayed_timeslot_prec_request(void * p_context)
{
rsch_dly_ts_id_t dly_ts_id = (rsch_dly_ts_id_t)(uint32_t)p_context;
dly_ts_t * p_dly_ts = &m_dly_ts[dly_ts_id];
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RSCH_TIMER_DELAYED_PREC);
all_prec_update();
p_dly_ts->timer.t0 = p_dly_ts->t0;
p_dly_ts->timer.dt = p_dly_ts->dt;
p_dly_ts->timer.callback = delayed_timeslot_start;
p_dly_ts->timer.p_context = p_context;
nrf_802154_timer_sched_add(&p_dly_ts->timer, true);
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RSCH_TIMER_DELAYED_PREC);
}
/***************************************************************************************************
* Public API
**************************************************************************************************/
void nrf_802154_rsch_init(void)
{
nrf_raal_init();
m_ntf_mutex = 0;
m_req_mutex = 0;
m_last_notified_prio = RSCH_PRIO_IDLE;
m_cont_mode_prio = RSCH_PRIO_IDLE;
m_requested_prio = RSCH_PRIO_IDLE;
for (uint32_t i = 0; i < RSCH_DLY_TS_NUM; i++)
{
m_dly_ts[i].prio = RSCH_PRIO_IDLE;
}
for (uint32_t i = 0; i < RSCH_PREC_CNT; i++)
{
m_approved_prios[i] = RSCH_PRIO_IDLE;
}
}
void nrf_802154_rsch_uninit(void)
{
for (uint32_t i = 0; i < RSCH_DLY_TS_NUM; i++)
{
nrf_802154_timer_sched_remove(&m_dly_ts[i].timer);
}
nrf_raal_uninit();
}
void nrf_802154_rsch_continuous_mode_priority_set(rsch_prio_t prio)
{
nrf_802154_log(EVENT_TRACE_ENTER, (prio > RSCH_PRIO_IDLE) ? FUNCTION_RSCH_CONTINUOUS_ENTER :
FUNCTION_RSCH_CONTINUOUS_EXIT);
m_cont_mode_prio = prio;
__DMB();
all_prec_update();
notify_core();
if (prio == RSCH_PRIO_IDLE)
{
m_last_notified_prio = RSCH_PRIO_IDLE;
}
nrf_802154_log(EVENT_TRACE_EXIT, (prio > RSCH_PRIO_IDLE) ? FUNCTION_RSCH_CONTINUOUS_ENTER :
FUNCTION_RSCH_CONTINUOUS_EXIT);
}
void nrf_802154_rsch_continuous_ended(void)
{
nrf_raal_continuous_ended();
}
bool nrf_802154_rsch_timeslot_request(uint32_t length_us)
{
return nrf_raal_timeslot_request(length_us);
}
bool nrf_802154_rsch_delayed_timeslot_request(uint32_t t0,
uint32_t dt,
uint32_t length,
rsch_prio_t prio,
rsch_dly_ts_id_t dly_ts_id)
{
(void)length;
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RSCH_DELAYED_TIMESLOT_REQ);
assert(dly_ts_id < RSCH_DLY_TS_NUM);
dly_ts_t * p_dly_ts = &m_dly_ts[dly_ts_id];
uint32_t now = nrf_802154_timer_sched_time_get();
uint32_t req_dt = dt - PREC_RAMP_UP_TIME;
bool result;
assert(!nrf_802154_timer_sched_is_running(&p_dly_ts->timer));
assert(p_dly_ts->prio == RSCH_PRIO_IDLE);
assert(prio != RSCH_PRIO_IDLE);
if (nrf_802154_timer_sched_time_is_in_future(now, t0, req_dt))
{
p_dly_ts->prio = prio;
p_dly_ts->t0 = t0;
p_dly_ts->dt = dt;
p_dly_ts->timer.t0 = t0;
p_dly_ts->timer.dt = req_dt;
p_dly_ts->timer.callback = delayed_timeslot_prec_request;
p_dly_ts->timer.p_context = (void *)dly_ts_id;
nrf_802154_timer_sched_add(&p_dly_ts->timer, false);
result = true;
}
else if (requested_prio_lvl_is_at_least(RSCH_PRIO_MAX) &&
nrf_802154_timer_sched_time_is_in_future(now, t0, dt))
{
p_dly_ts->prio = prio;
p_dly_ts->t0 = t0;
p_dly_ts->dt = dt;
p_dly_ts->timer.t0 = t0;
p_dly_ts->timer.dt = dt;
p_dly_ts->timer.callback = delayed_timeslot_start;
p_dly_ts->timer.p_context = (void *)dly_ts_id;
nrf_802154_timer_sched_add(&p_dly_ts->timer, true);
result = true;
}
else
{
result = false;
}
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RSCH_DELAYED_TIMESLOT_REQ);
return result;
}
bool nrf_802154_rsch_prec_is_approved(rsch_prec_t prec, rsch_prio_t prio)
{
assert(prec < RSCH_PREC_CNT);
return m_approved_prios[prec] >= prio;
}
uint32_t nrf_802154_rsch_timeslot_us_left_get(void)
{
return nrf_raal_timeslot_us_left_get();
}
// External handlers
void nrf_raal_timeslot_started(void)
{
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RSCH_TIMESLOT_STARTED);
prec_approved_prio_set(RSCH_PREC_RAAL, RSCH_PRIO_MAX);
notify_core();
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RSCH_TIMESLOT_STARTED);
}
void nrf_raal_timeslot_ended(void)
{
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RSCH_TIMESLOT_ENDED);
prec_approved_prio_set(RSCH_PREC_RAAL, RSCH_PRIO_IDLE);
notify_core();
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RSCH_TIMESLOT_ENDED);
}
void nrf_802154_clock_hfclk_ready(void)
{
prec_approved_prio_set(RSCH_PREC_HFCLK, RSCH_PRIO_MAX);
notify_core();
}
@@ -67,6 +67,32 @@ typedef enum
RSCH_PREC_CNT,
} rsch_prec_t;
/**
* @brief Priorities of the 802.15.4 radio operations.
*/
typedef enum
{
RSCH_PRIO_IDLE, ///< Priority used in the sleep state. With this priority RSCH releases all preconditions.
RSCH_PRIO_IDLE_LISTENING, ///< Priority used during the idle listening procedure.
RSCH_PRIO_RX, ///< Priority used when a frame is being received.
RSCH_PRIO_DETECT, ///< Priority used to detect channel conditions (CCA, ED).
RSCH_PRIO_TX, ///< Priority used to transmit a frame.
RSCH_PRIO_MIN_APPROVED = RSCH_PRIO_IDLE_LISTENING, ///< Minimal priority indicating that given precondition is approved.
RSCH_PRIO_MAX = RSCH_PRIO_TX, ///< Maximal priority available in the RSCH module.
} rsch_prio_t;
/**
* @brief Enumeration of delayed timeslots ids.
*/
typedef enum
{
RSCH_DLY_TX, ///< Timeslot for delayed tx operation.
RSCH_DLY_RX, ///< Timeslot for delayed rx operation.
RSCH_DLY_TS_NUM, ///< Number of delayed timeslots.
} rsch_dly_ts_id_t;
/**
* @brief Initialize Radio Scheduler.
*
@@ -87,25 +113,28 @@ void nrf_802154_rsch_init(void);
void nrf_802154_rsch_uninit(void);
/**
* @brief Enter continuous radio mode.
* @brief Set priority for the continuous radio mode.
*
* In the continuous mode the radio scheduler should try to satisfy all preconditions as long as
* possible in order to give to the radio driver core as much radio time as possible while
* disturbing the other activities as little as possible.
*
* @note The start of a timeslot will be indicated by @ref nrf_802154_rsch_prec_approved call.
* @note To disable the continuous radio mode, the @ref RSCH_PRIO_IDLE should be used.
*
* @param[in] prio Priority level used in the continuous radio mode.
*
*/
void nrf_802154_rsch_continuous_mode_enter(void);
void nrf_802154_rsch_continuous_mode_priority_set(rsch_prio_t prio);
/**
* @brief Exit continuous radio mode.
* @brief Confirm that current part of continuous timeslot is ended by the core.
*
* In this mode the radio scheduler should not try to satisfy any of radio activity preconditions
* unless it was requested by other functionalities of this module.
* This confirmation is used by the core to synchronize ending of continuous timeslot parts with
* the RSCH module.
*
*/
void nrf_802154_rsch_continuous_mode_exit(void);
void nrf_802154_rsch_continuous_ended(void);
/**
* @brief Request timeslot for radio communication immediately.
@@ -135,21 +164,28 @@ bool nrf_802154_rsch_timeslot_request(uint32_t length_us);
* @param[in] t0 Base time of the timestamp of the timeslot start [us].
* @param[in] dt Time delta between @p t0 and the timestamp of the timeslot start [us].
* @param[in] length Requested radio timeslot length [us].
* @param[in] prio Priority level required for the delayed timeslot.
* @param[in] dly_ts Type of the requested timeslot.
*
* @retval true Requested timeslot has been scheduled.
* @retval false Requested timeslot cannot be scheduled and will not be granted.
*/
bool nrf_802154_rsch_delayed_timeslot_request(uint32_t t0, uint32_t dt, uint32_t length);
bool nrf_802154_rsch_delayed_timeslot_request(uint32_t t0,
uint32_t dt,
uint32_t length,
rsch_prio_t prio,
rsch_dly_ts_id_t dly_ts);
/**
* @brief Check if the RSCH precondition is satisfied.
*
* @param[in] prec RSCH precondition to be checked.
*
* @param[in] prio Minimal required priority level of given precondition.
*
* @retval true Precondition @p prec is currently granted.
* @retval false Precondition @p prec is not currently granted.
*/
bool nrf_802154_rsch_prec_is_approved(rsch_prec_t prec);
bool nrf_802154_rsch_prec_is_approved(rsch_prec_t prec, rsch_prio_t prio);
/**
* @brief Get left time of currently granted timeslot [us].
@@ -159,50 +195,33 @@ bool nrf_802154_rsch_prec_is_approved(rsch_prec_t prec);
uint32_t nrf_802154_rsch_timeslot_us_left_get(void);
/**
* @brief The Radio Scheduler calls this function to notify the core
* about granting all preconditions.
* @brief This function is called to notify the core about changes of approved priority level.
*
* The radio driver now has exclusive access to the peripherals until
* @ref nrf_802154_rsch_prec_denied is called.
* If the @p prio is greater than @ref RSCH_PRIO_IDLE, the radio driver has exclusive access to the
* peripherals until this function is called with the @p prio equal to @ref RSCH_PRIO_IDLE.
*
* @note The end of the timeslot will be indicated by @ref nrf_802154_rsch_prec_denied function.
* @note The end of the timeslot is indicated by @p prio equal to the @ref RSCH_PRIO_IDLE.
*
* @param[in] prio Currently approved priority level.
*/
extern void nrf_802154_rsch_prec_approved(void);
/**
* @brief The Radio Scheduler calls this function to notify the core
* about denial of one or all preconditions.
*
* Depending on the preconditions configuration, radio driver has NRF_RAAL_MAX_CLEAN_UP_TIME_US
* microseconds to do any clean-up actions on RADIO peripheral and stop using it completely.
* Thus the Radio Scheduler has to call this function NRF_RAAL_MAX_CLEAN_UP_TIME_US microseconds
* before the timeslot is finished.
*
* If the Radio Scheduler is in the continuous mode, the next timeslot will be indicated again by
* the @ref nrf_802154_rsch_prec_approved.
*
* @note Because the radio driver core needs to stop any operation on the RADIO peripheral within
* NRF_RAAL_MAX_CLEAN_UP_TIME_US microseconds, this function should be called with high
* interrupt priority level to avoid unwanted delays.
*
* @note This function may be called after @ref nrf_802154_rsch_continuous_mode_exit is called.
*
*/
extern void nrf_802154_rsch_prec_denied(void);
extern void nrf_802154_rsch_continuous_prio_changed(rsch_prio_t prio);
/**
* @brief Notification that previously requested delayed timeslot has started just now.
*
* @param[in] dly_ts_id Type of the started timeslot.
*/
extern void nrf_802154_rsch_delayed_timeslot_started(void);
extern void nrf_802154_rsch_delayed_timeslot_started(rsch_dly_ts_id_t dly_ts_id);
/**
* @brief Notification that previously requested delayed timeslot cannot be started.
*
* This function may be called when any of radio activity precondition is not satisfied at the
* time when the timeslot should start.
*
* @param[in] dly_ts_id Type of the failed timeslot.
*/
extern void nrf_802154_rsch_delayed_timeslot_failed(void);
extern void nrf_802154_rsch_delayed_timeslot_failed(rsch_dly_ts_id_t dly_ts_id);
/**
*@}
@@ -0,0 +1,154 @@
/* Copyright (c) 2018, Nordic Semiconductor ASA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**
* @file
* This file implements critical sections for the RSCH module.
*
*/
#include "nrf_802154_rsch_crit_sect.h"
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include "nrf_802154_critical_section.h"
#include "nrf_802154_rsch.h"
#include <nrf.h>
#define RSCH_EVT_NONE (rsch_prio_t)UINT8_MAX
static volatile uint8_t m_rsch_pending_evt; ///< Indicator of pending RSCH event.
/***************************************************************************************************
* @section RSCH pending events management
**************************************************************************************************/
static void rsch_pending_evt_set(rsch_prio_t prio)
{
volatile uint8_t rsch_pending_evt; // Dummy variable to prevent compilers from removing ldrex
do
{
rsch_pending_evt = __LDREXB(&m_rsch_pending_evt);
(void)rsch_pending_evt;
}
while (__STREXB((uint8_t)prio, &m_rsch_pending_evt));
}
static rsch_prio_t rsch_pending_evt_clear(void)
{
uint8_t evt_value;
do
{
evt_value = __LDREXB(&m_rsch_pending_evt);
}
while (__STREXB(RSCH_EVT_NONE, &m_rsch_pending_evt));
return (rsch_prio_t)evt_value;
}
static bool rsch_pending_evt_is_none(void)
{
return m_rsch_pending_evt == (uint8_t)RSCH_EVT_NONE;
}
static void rsch_evt_process(rsch_prio_t evt)
{
if (evt != RSCH_EVT_NONE)
{
nrf_802154_rsch_crit_sect_prio_changed(evt);
}
}
/***************************************************************************************************
* @section Public API
**************************************************************************************************/
void nrf_802154_rsch_crit_sect_init(void)
{
m_rsch_pending_evt = RSCH_EVT_NONE;
}
void nrf_802154_rsch_crit_sect_prio_request(rsch_prio_t prio)
{
nrf_802154_rsch_continuous_mode_priority_set(prio);
}
/***************************************************************************************************
* @section RSCH callbacks
**************************************************************************************************/
void nrf_802154_rsch_continuous_prio_changed(rsch_prio_t prio)
{
bool crit_sect_success = false;
crit_sect_success = nrf_802154_critical_section_enter();
// If we managed to enter critical section, but there is already a pending event,
// it means that the Critical Section module is about to make one more iteration of the
// critical section exit procedure. To prevent race in continuous mode priorities notification,
// we do not notify directly, but just update the pending event.
if (crit_sect_success && rsch_pending_evt_is_none())
{
nrf_802154_rsch_crit_sect_prio_changed(prio);
}
else
{
rsch_pending_evt_set(prio);
}
if (crit_sect_success)
{
nrf_802154_critical_section_exit();
}
}
/***************************************************************************************************
* @section Critical section callbacks
**************************************************************************************************/
void nrf_802154_critical_section_rsch_enter(void)
{
// Intentionally empty
}
void nrf_802154_critical_section_rsch_exit(void)
{
rsch_evt_process(rsch_pending_evt_clear());
}
bool nrf_802154_critical_section_rsch_event_is_pending(void)
{
return !rsch_pending_evt_is_none();
}
@@ -0,0 +1,71 @@
/* Copyright (c) 2018, Nordic Semiconductor ASA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef NRF_802154_RSCH_CRIT_SECT_H__
#define NRF_802154_RSCH_CRIT_SECT_H__
#include <stdbool.h>
#include "nrf_802154_rsch.h"
/**
* @defgroup nrf_802154_rsch_crit_sect RSCH event queue used during critical sections
* @{
* @ingroup nrf_802154_rsch
* @brief Critical section implementation for the RSCH module.
*/
/**
* @brief Initialize the RSCH critical section module.
*/
void nrf_802154_rsch_crit_sect_init(void);
/**
* @brief Request priority level from RSCH through the critical section module.
*
* @param[in] prio Requested priority level.
*/
void nrf_802154_rsch_crit_sect_prio_request(rsch_prio_t prio);
/**
* @brief This function is called to notify the core that approved RSCH priority has changed.
*
* @note This function is called from critical section context and does not preempt other critical
* sections.
*
* @param[in] prio Approved priority level.
*/
extern void nrf_802154_rsch_crit_sect_prio_changed(rsch_prio_t prio);
/**
*@}
**/
#endif // NRF_802154_RSCH_CRIT_SECT_H__
@@ -0,0 +1,108 @@
/* Copyright (c) 2018, Nordic Semiconductor ASA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**
* @brief This module defines the Wifi coexistence module.
*
*/
#ifndef NRF_802154_WIFI_COEX_H_
#define NRF_802154_WIFI_COEX_H_
#include "nrf_802154_rsch.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup nrf_wifi_coex Wifi Coexistence
* @{
* @ingroup nrf_802154
* @brief Wifi Coexistence module.
*
* Wifi Coexistence module is a client of the PTA (defined in the 802.15.2). It manages GPIO
* to assert pins and respond to pin state changes.
*/
/**
* @brief Initialize the Wifi Coexistence module.
*
* @note This function shall be called once, before any other function from this module.
*
*/
void nrf_802154_wifi_coex_init(void);
/**
* @brief Uninitialize the Wifi Coexistence module.
*
*/
void nrf_802154_wifi_coex_uninit(void);
/**
* @brief Request given priority from the Wifi Coexistence module.
*
* @note The approval of requested priority is notified asynchronously by the
* @ref nrf_802154_wifi_coex_prio_changed call.
*
* @param[in] priority Requested priority level.
*
*/
void nrf_802154_wifi_coex_prio_req(rsch_prio_t priority);
/**
* @brief Get priority denial event address.
*
* Get an address of a hardware event that notifies about denial of the previously approved
* priority.
*
* @return Address of a priority denial event.
*/
void * nrf_802154_wifi_coex_deny_event_addr_get(void);
/**
* @biref Approved priority change notification.
*
* The Wifi Coexistence module calls this function to notify the RSCH of currently approved
* priority level.
*
* @param[in] priority Approved priority level.
*/
extern void nrf_802154_wifi_coex_prio_changed(rsch_prio_t priority);
/**
*@}
**/
#ifdef __cplusplus
}
#endif
#endif /* NRF_802154_WIFI_COEX_H_ */
@@ -85,13 +85,20 @@ void nrf_raal_uninit(void);
void nrf_raal_continuous_mode_enter(void);
/**
* @brief Exit arbiter from continous mode.
* @brief Exit arbiter from continuous mode.
*
* In this mode radio arbiter will not extend or allocate any more timeslots for radio driver.
*
*/
void nrf_raal_continuous_mode_exit(void);
/**
* @brief Confirm to RAAL that current part of the continuous timeslot is ended.
*
* The core cannot use the RADIO peripheral after this call until the timeslot is started again.
*/
void nrf_raal_continuous_ended(void);
/**
* @brief Request timeslot for radio communication.
*
@@ -56,7 +56,7 @@ extern "C" {
*
*/
#ifndef NRF_RAAL_MAX_CLEAN_UP_TIME_US
#define NRF_RAAL_MAX_CLEAN_UP_TIME_US 91
#define NRF_RAAL_MAX_CLEAN_UP_TIME_US 91
#endif
/**
@@ -95,11 +95,11 @@ void nrf_raal_init(void)
NVIC_ClearPendingIRQ(MWU_IRQn);
NVIC_EnableIRQ(MWU_IRQn);
NRF_TIMER0->MODE = TIMER_MODE_MODE_Timer;
NRF_TIMER0->BITMODE = TIMER_BITMODE_BITMODE_24Bit;
NRF_TIMER0->PRESCALER = 4;
NRF_TIMER0->INTENSET = TIMER_INTENSET_COMPARE0_Msk;
NRF_TIMER0->CC[0] = m_started_timestamp;
NRF_TIMER0->MODE = TIMER_MODE_MODE_Timer;
NRF_TIMER0->BITMODE = TIMER_BITMODE_BITMODE_24Bit;
NRF_TIMER0->PRESCALER = 4;
NRF_TIMER0->INTENSET = TIMER_INTENSET_COMPARE0_Msk;
NRF_TIMER0->CC[0] = m_started_timestamp;
NVIC_SetPriority(TIMER0_IRQn, 1);
NVIC_ClearPendingIRQ(TIMER0_IRQn);
@@ -155,6 +155,11 @@ void nrf_raal_continuous_mode_exit(void)
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_CONTINUOUS_EXIT);
}
void nrf_raal_continuous_ended(void)
{
// Intentionally empty.
}
bool nrf_raal_timeslot_request(uint32_t length_us)
{
uint32_t timer;
@@ -69,9 +69,14 @@ void nrf_raal_continuous_mode_exit(void)
m_continuous = false;
}
void nrf_raal_continuous_ended(void)
{
// Intentionally empty.
}
bool nrf_raal_timeslot_request(uint32_t length_us)
{
(void) length_us;
(void)length_us;
assert(m_continuous);
@@ -82,4 +87,3 @@ uint32_t nrf_raal_timeslot_us_left_get(void)
{
return UINT32_MAX;
}
@@ -45,46 +45,69 @@
#include <hal/nrf_timer.h>
#include <nrf_raal_api.h>
#include <nrf_802154.h>
#include <nrf_802154_const.h>
#include <nrf_802154_debug.h>
#include <nrf_802154_procedures_duration.h>
#include <nrf_802154_utils.h>
#if defined(__GNUC__)
_Pragma("GCC diagnostic push")
_Pragma("GCC diagnostic ignored \"-Wreturn-type\"")
_Pragma("GCC diagnostic ignored \"-Wunused-parameter\"")
_Pragma("GCC diagnostic ignored \"-Wpedantic\"")
_Pragma("GCC diagnostic push")
_Pragma("GCC diagnostic ignored \"-Wreturn-type\"")
_Pragma("GCC diagnostic ignored \"-Wunused-parameter\"")
_Pragma("GCC diagnostic ignored \"-Wpedantic\"")
#endif
#include <ble.h>
#include <nrf_mbr.h>
#include <nrf_sdm.h>
#include <nrf_soc.h>
#if defined(__GNUC__)
_Pragma("GCC diagnostic pop")
_Pragma("GCC diagnostic pop")
#endif
/***************************************************************************************************
* @section Defines and typedefs.
**************************************************************************************************/
/*
* @brief Defines the minimum version of the SoftDevice that supports configuration of BLE advertising
* role scheduling.
*
* The first SoftDevice that supports this option is S140 6.1.1 (6001001). The full version
* number for the SoftDevice binary is a decimal number in the form Mmmmbbb, where:
* - M is major version (one or more digits)
* - mmm is minor version (three digits)
* - bbb is bugfix version (three digits).
*/
#define BLE_ADV_SCHED_CFG_SUPPORT_MIN_SD_VERSION (6001001)
/**@brief Enable Request and End on timeslot safety interrupt. */
#define ENABLE_REQUEST_AND_END_ON_TIMESLOT_END 0
#define ENABLE_REQUEST_AND_END_ON_TIMESLOT_END 0
/**@brief RAAL Timer instance. */
#define RAAL_TIMER NRF_TIMER0
#define RAAL_TIMER NRF_TIMER0
/**@brief RAAL Timer interrupt number. */
#define RAAL_TIMER_IRQn TIMER0_IRQn
#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 Minimum time prior safe margin reached by RTC when TIMER reports reached margin in microseconds. */
#define MIN_TIME_PRIOR_MARGIN_IS_REACHED_US 31
/**@brief Timer compare channel definitions. */
#define TIMER_CC_ACTION NRF_TIMER_CC_CHANNEL0
#define TIMER_CC_ACTION_EVENT NRF_TIMER_EVENT_COMPARE0
#define TIMER_CC_ACTION_INT NRF_TIMER_INT_COMPARE0_MASK
#define TIMER_CC_ACTION NRF_TIMER_CC_CHANNEL0
#define TIMER_CC_ACTION_EVENT NRF_TIMER_EVENT_COMPARE0
#define TIMER_CC_ACTION_INT NRF_TIMER_INT_COMPARE0_MASK
#define TIMER_CC_CAPTURE NRF_TIMER_CC_CHANNEL1
#define TIMER_CC_CAPTURE_TASK NRF_TIMER_TASK_CAPTURE1
#define TIMER_CC_CAPTURE NRF_TIMER_CC_CHANNEL1
#define TIMER_CC_CAPTURE_TASK NRF_TIMER_TASK_CAPTURE1
#define NRF_RADIO_MINIMUM_TIMESLOT_LENGTH_EXTENSION_TIME_TICKS NRF_802154_US_TO_RTC_TICKS(NRF_RADIO_MINIMUM_TIMESLOT_LENGTH_EXTENSION_TIME_US)
#define MINIMUM_TIMESLOT_LENGTH_EXTENSION_TIME_TICKS NRF_802154_US_TO_RTC_TICKS( \
NRF_RADIO_MINIMUM_TIMESLOT_LENGTH_EXTENSION_TIME_US)
/**@brief PPM constants. */
#define PPM_UNIT 1000000UL
#define MAX_HFCLK_PPM 40
/**@brief Defines states of timeslot. */
typedef enum
@@ -129,9 +152,31 @@ static timer_action_t m_timer_action;
/**@brief Current timeslot length. */
static uint16_t m_timeslot_length;
/**@brief Previously granted timeslot length. */
static uint16_t m_prev_timeslot_length;
/**@brief Interval between successive timeslot extensions. */
static uint16_t m_extension_interval;
/**@brief Number of already performed extentions tries on failed event. */
static volatile uint16_t m_timeslot_extend_tries;
/***************************************************************************************************
* @section Drift calculations
**************************************************************************************************/
static uint32_t time_corrected_for_drift_get(uint32_t time)
{
uint32_t ppm = m_config.lf_clk_accuracy_ppm + MAX_HFCLK_PPM;
return time - NRF_802154_DIVIDE_AND_CEIL(time * ppm, PPM_UNIT);
}
static void calculate_config(void)
{
m_extension_interval = time_corrected_for_drift_get(m_config.timeslot_length);
}
/***************************************************************************************************
* @section Operations on RAAL TIMER.
**************************************************************************************************/
@@ -185,7 +230,7 @@ static inline uint32_t ticks_to_timeslot_end_get(void)
static inline uint32_t safe_time_to_timeslot_end_get(void)
{
uint32_t margin = m_config.timeslot_safe_margin + TIMER_TO_SIGNAL_JITTER_US;
uint32_t margin = m_config.timeslot_safe_margin + NRF_RADIO_START_JITTER_US;
uint32_t timeslot_end = NRF_802154_RTC_TICKS_TO_US(ticks_to_timeslot_end_get());
if (timeslot_end > margin)
@@ -201,7 +246,10 @@ static inline uint32_t safe_time_to_timeslot_end_get(void)
/**@brief Get timeslot margin. */
static uint32_t timer_get_cc_margin(void)
{
return timer_time_get() + safe_time_to_timeslot_end_get();
uint32_t corrected_time_to_margin = time_corrected_for_drift_get(
safe_time_to_timeslot_end_get());
return timer_time_get() + corrected_time_to_margin;
}
/**@brief Set timer action to the timeslot margin. */
@@ -219,7 +267,8 @@ static inline void timer_to_margin_set(void)
/**@brief Check if margin is already reached. */
static inline bool timer_is_margin_reached(void)
{
return timer_is_set_to_margin() && nrf_timer_event_check(RAAL_TIMER, TIMER_CC_ACTION_EVENT);
return timer_is_set_to_margin() && nrf_timer_event_check(RAAL_TIMER, TIMER_CC_ACTION_EVENT) &&
safe_time_to_timeslot_end_get() <= MIN_TIME_PRIOR_MARGIN_IS_REACHED_US;
}
/**@brief Set timer on extend event. */
@@ -230,13 +279,18 @@ static void timer_on_extend_update(void)
if (timer_is_set_to_margin())
{
uint32_t margin_cc = nrf_timer_cc_read(RAAL_TIMER, TIMER_CC_ACTION);
margin_cc += m_timeslot_length;
nrf_timer_cc_write(RAAL_TIMER, TIMER_CC_ACTION, margin_cc);
}
else
{
uint16_t extension_interval = (m_prev_timeslot_length == m_config.timeslot_length) ?
m_extension_interval :
time_corrected_for_drift_get(m_prev_timeslot_length);
nrf_timer_cc_write(RAAL_TIMER, TIMER_CC_ACTION,
nrf_timer_cc_read(RAAL_TIMER, TIMER_CC_ACTION) + m_timeslot_length);
nrf_timer_cc_read(RAAL_TIMER, TIMER_CC_ACTION) + extension_interval);
nrf_timer_int_enable(RAAL_TIMER, TIMER_CC_ACTION_INT);
}
}
@@ -355,27 +409,30 @@ static void timer_irq_handle(void)
{
if (timer_is_set_to_margin())
{
// Safe margin exceeded.
nrf_802154_pin_clr(PIN_DBG_TIMESLOT_ACTIVE);
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_MARGIN);
if (timer_is_margin_reached())
{
// Safe margin exceeded.
nrf_802154_pin_clr(PIN_DBG_TIMESLOT_ACTIVE);
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_MARGIN);
m_timeslot_state = TIMESLOT_STATE_IDLE;
timeslot_ended_notify();
m_timeslot_state = TIMESLOT_STATE_IDLE;
timeslot_ended_notify();
// Ignore any other events.
timer_reset();
// Ignore any other events.
timer_reset();
#if (ENABLE_REQUEST_AND_END_ON_TIMESLOT_END == 1)
timeslot_data_init();
timeslot_request_prepare();
m_ret_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_REQUEST_AND_END;
m_ret_param.params.request.p_next = &m_request;
#else
// Return and wait for NRF_EVT_RADIO_SESSION_IDLE event.
m_ret_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE;
#endif
// Return and wait for NRF_EVT_RADIO_SESSION_IDLE event.
m_ret_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE;
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_EVENT_MARGIN);
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_EVENT_MARGIN);
}
else
{
// Move safety margin a little further to suppress clocks drift
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_MARGIN_MOVE);
timer_to_margin_set();
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_EVENT_MARGIN_MOVE);
}
}
else
{
@@ -387,7 +444,7 @@ static void timer_irq_handle(void)
if (m_continuous &&
(nrf_timer_cc_read(RAAL_TIMER, TIMER_CC_ACTION) +
m_config.timeslot_length < m_config.timeslot_max_length))
m_config.timeslot_length < m_config.timeslot_max_length))
{
// Try to extend timeslot.
timeslot_extend(m_config.timeslot_length);
@@ -415,7 +472,7 @@ static void timer_irq_handle(void)
**************************************************************************************************/
/**@brief Signal handler. */
static nrf_radio_signal_callback_return_param_t *signal_handler(uint8_t signal_type)
static nrf_radio_signal_callback_return_param_t * signal_handler(uint8_t signal_type)
{
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_HANDLER);
@@ -427,7 +484,7 @@ static nrf_radio_signal_callback_return_param_t *signal_handler(uint8_t signal_t
nrf_802154_pin_clr(PIN_DBG_TIMESLOT_ACTIVE);
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_ENDED);
m_timeslot_state = TIMESLOT_STATE_IDLE;
m_timeslot_state = TIMESLOT_STATE_IDLE;
// TODO: Change to NRF_RADIO_SIGNAL_CALLBACK_ACTION_END (KRKNWK-937)
m_ret_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE;
@@ -440,97 +497,107 @@ static nrf_radio_signal_callback_return_param_t *signal_handler(uint8_t signal_t
switch (signal_type)
{
case NRF_RADIO_CALLBACK_SIGNAL_TYPE_START: /**< This signal indicates the start of the radio timeslot. */
{
nrf_802154_pin_set(PIN_DBG_TIMESLOT_ACTIVE);
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_START);
assert(m_timeslot_state == TIMESLOT_STATE_REQUESTED);
m_timeslot_state = TIMESLOT_STATE_GRANTED;
// Set up timer first with requested timeslot length.
timer_start();
// Re-initialize timeslot data for future extensions.
timeslot_data_init();
timeslot_started_notify();
// Try to extend right after start.
timeslot_extend(m_timeslot_length);
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_EVENT_START);
break;
}
case NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0: /**< This signal indicates the TIMER0 interrupt. */
timer_irq_handle();
break;
case NRF_RADIO_CALLBACK_SIGNAL_TYPE_RADIO: /**< This signal indicates the NRF_RADIO interrupt. */
nrf_802154_pin_set(PIN_DBG_TIMESLOT_RADIO_IRQ);
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_RADIO);
if (timeslot_is_granted())
case NRF_RADIO_CALLBACK_SIGNAL_TYPE_START: /**< This signal indicates the start of the radio timeslot. */
{
if (!timer_is_margin_reached())
{
nrf_802154_radio_irq_handler();
}
else
{
// Handle margin exceeded event.
timer_irq_handle();
}
}
else
{
NVIC_DisableIRQ(RADIO_IRQn);
}
nrf_802154_pin_set(PIN_DBG_TIMESLOT_ACTIVE);
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_START);
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_EVENT_RADIO);
nrf_802154_pin_clr(PIN_DBG_TIMESLOT_RADIO_IRQ);
break;
assert(m_timeslot_state == TIMESLOT_STATE_REQUESTED);
case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_FAILED: /**< This signal indicates extend action failed. */
nrf_802154_pin_tgl(PIN_DBG_TIMESLOT_FAILED);
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_EXTEND_FAIL);
// Set up timer first with requested timeslot length.
timer_start();
if (!timer_is_set_to_margin())
{
timer_to_margin_set();
}
// Re-initialize timeslot data for future extensions.
m_prev_timeslot_length = m_timeslot_length;
timeslot_data_init();
timeslot_next_extend();
// Try to extend right after start.
timeslot_extend(m_timeslot_length);
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_EVENT_EXTEND_FAIL);
break;
// Do not notify started timeslot here. Notify after successful extend to make sure
// enough timeslot length is available before notification.
case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_SUCCEEDED: /**< This signal indicates extend action succeeded. */
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_EXTEND_SUCCESS);
if ((!timer_is_set_to_margin()) && (ticks_to_timeslot_end_get() < NRF_RADIO_MINIMUM_TIMESLOT_LENGTH_EXTENSION_TIME_TICKS))
{
timer_to_margin_set();
m_ret_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE;
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_EVENT_START);
break;
}
timer_on_extend_update();
case NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0: /**< This signal indicates the TIMER0 interrupt. */
timer_irq_handle();
break;
case NRF_RADIO_CALLBACK_SIGNAL_TYPE_RADIO: /**< This signal indicates the NRF_RADIO interrupt. */
nrf_802154_pin_set(PIN_DBG_TIMESLOT_RADIO_IRQ);
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_RADIO);
if (timeslot_is_granted())
{
if (!timer_is_margin_reached())
{
nrf_802154_radio_irq_handler();
}
else
{
// Handle margin exceeded event.
timer_irq_handle();
}
}
else
{
NVIC_DisableIRQ(RADIO_IRQn);
}
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_EVENT_RADIO);
nrf_802154_pin_clr(PIN_DBG_TIMESLOT_RADIO_IRQ);
break;
case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_FAILED: /**< This signal indicates extend action failed. */
nrf_802154_pin_tgl(PIN_DBG_TIMESLOT_FAILED);
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_EXTEND_FAIL);
if (!timer_is_set_to_margin())
{
timer_to_margin_set();
}
// Request futher extension only if any of previous one failed.
if (m_timeslot_extend_tries != 0)
{
timeslot_next_extend();
}
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_EVENT_EXTEND_SUCCESS);
break;
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_EVENT_EXTEND_FAIL);
break;
default:
break;
case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_SUCCEEDED: /**< This signal indicates extend action succeeded. */
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_SIG_EVENT_EXTEND_SUCCESS);
if ((!timer_is_set_to_margin()) &&
(ticks_to_timeslot_end_get() <
MINIMUM_TIMESLOT_LENGTH_EXTENSION_TIME_TICKS))
{
timer_to_margin_set();
m_ret_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE;
}
else
{
timer_on_extend_update();
m_prev_timeslot_length = m_timeslot_length;
// Request further extension only if any of previous one failed.
if (m_timeslot_extend_tries != 0)
{
timeslot_next_extend();
}
}
if (!timeslot_is_granted())
{
m_timeslot_state = TIMESLOT_STATE_GRANTED;
timeslot_started_notify();
}
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_EVENT_EXTEND_SUCCESS);
break;
default:
break;
}
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_SIG_HANDLER);
@@ -542,55 +609,55 @@ void nrf_raal_softdevice_soc_evt_handler(uint32_t evt_id)
{
switch (evt_id)
{
case NRF_EVT_RADIO_BLOCKED:
case NRF_EVT_RADIO_CANCELED:
{
nrf_802154_pin_tgl(PIN_DBG_TIMESLOT_BLOCKED);
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_EVT_BLOCKED);
assert(!timeslot_is_granted());
m_timeslot_state = TIMESLOT_STATE_IDLE;
if (m_continuous)
case NRF_EVT_RADIO_BLOCKED:
case NRF_EVT_RADIO_CANCELED:
{
if (m_timeslot_extend_tries < m_config.timeslot_alloc_iters)
nrf_802154_pin_tgl(PIN_DBG_TIMESLOT_BLOCKED);
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_EVT_BLOCKED);
assert(!timeslot_is_granted());
m_timeslot_state = TIMESLOT_STATE_IDLE;
if (m_continuous)
{
timeslot_length_decrease();
if (m_timeslot_extend_tries < m_config.timeslot_alloc_iters)
{
timeslot_length_decrease();
}
timeslot_request();
}
timeslot_request();
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_EVT_BLOCKED);
break;
}
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_EVT_BLOCKED);
case NRF_EVT_RADIO_SIGNAL_CALLBACK_INVALID_RETURN:
assert(false);
break;
break;
}
case NRF_EVT_RADIO_SESSION_IDLE:
case NRF_EVT_RADIO_SIGNAL_CALLBACK_INVALID_RETURN:
assert(false);
break;
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_EVT_SESSION_IDLE);
nrf_802154_pin_tgl(PIN_DBG_TIMESLOT_SESSION_IDLE);
case NRF_EVT_RADIO_SESSION_IDLE:
if (m_continuous && timeslot_is_idle())
{
timeslot_data_init();
timeslot_request();
}
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_RAAL_EVT_SESSION_IDLE);
nrf_802154_pin_tgl(PIN_DBG_TIMESLOT_SESSION_IDLE);
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_EVT_SESSION_IDLE);
if (m_continuous && timeslot_is_idle())
{
timeslot_data_init();
timeslot_request();
}
break;
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_EVT_SESSION_IDLE);
case NRF_EVT_RADIO_SESSION_CLOSED:
break;
break;
case NRF_EVT_RADIO_SESSION_CLOSED:
break;
default:
break;
default:
break;
}
}
@@ -605,25 +672,48 @@ void nrf_raal_softdevice_config(const nrf_raal_softdevice_cfg_t * p_cfg)
assert(p_cfg);
m_config = *p_cfg;
calculate_config();
}
void nrf_raal_init(void)
{
assert(!m_initialized);
m_continuous = false;
m_timeslot_state = TIMESLOT_STATE_IDLE;
m_continuous = false;
m_timeslot_state = TIMESLOT_STATE_IDLE;
m_config.timeslot_length = NRF_RAAL_TIMESLOT_DEFAULT_LENGTH;
m_config.timeslot_alloc_iters = NRF_RAAL_TIMESLOT_DEFAULT_ALLOC_ITERS;
m_config.timeslot_safe_margin = NRF_RAAL_TIMESLOT_DEFAULT_SAFE_MARGIN;
m_config.timeslot_max_length = NRF_RAAL_TIMESLOT_DEFAULT_MAX_LENGTH;
m_config.timeslot_timeout = NRF_RAAL_TIMESLOT_DEFAULT_TIMEOUT;
m_config.lf_clk_accuracy_ppm = NRF_RAAL_DEFAULT_LF_CLK_ACCURACY_PPM;
calculate_config();
uint32_t err_code = sd_radio_session_open(signal_handler);
assert(err_code == NRF_SUCCESS);
(void)err_code;
#if (SD_VERSION >= BLE_ADV_SCHED_CFG_SUPPORT_MIN_SD_VERSION)
// Ensure that correct SoftDevice version is flashed.
if (SD_VERSION_GET(MBR_SIZE) >= BLE_ADV_SCHED_CFG_SUPPORT_MIN_SD_VERSION)
{
// Use improved Advertiser Role Scheduling configuration.
ble_opt_t opt;
memset(&opt, 0, sizeof(opt));
opt.common_opt.adv_sched_cfg.sched_cfg = ADV_SCHED_CFG_IMPROVED;
err_code = sd_ble_opt_set(BLE_COMMON_OPT_ADV_SCHED_CFG, &opt);
assert(err_code == NRF_SUCCESS);
(void)err_code;
}
#endif
m_initialized = true;
}
@@ -632,11 +722,12 @@ void nrf_raal_uninit(void)
assert(m_initialized);
uint32_t err_code = sd_radio_session_close();
assert(err_code == NRF_SUCCESS);
(void)err_code;
m_continuous = false;
m_timeslot_state = TIMESLOT_STATE_IDLE;
m_continuous = false;
m_timeslot_state = TIMESLOT_STATE_IDLE;
nrf_802154_pin_clr(PIN_DBG_TIMESLOT_ACTIVE);
}
@@ -677,14 +768,26 @@ void nrf_raal_continuous_mode_exit(void)
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_RAAL_CONTINUOUS_EXIT);
}
void nrf_raal_continuous_ended(void)
{
// Intentionally empty.
}
bool nrf_raal_timeslot_request(uint32_t length_us)
{
uint32_t us_left;
if (!m_continuous || !timeslot_is_granted())
{
return false;
}
return length_us < nrf_raal_timeslot_us_left_get();
us_left = nrf_raal_timeslot_us_left_get();
assert((us_left >= nrf_802154_rx_duration_get(MAX_PACKET_SIZE,
true)) || timer_is_set_to_margin());
return length_us < us_left;
}
uint32_t nrf_raal_timeslot_us_left_get(void)
@@ -46,30 +46,35 @@ extern "C" {
#endif
/** @brief RAAL Softdevice default parameters. */
#define NRF_RAAL_TIMESLOT_DEFAULT_LENGTH 6400
#define NRF_RAAL_TIMESLOT_DEFAULT_ALLOC_ITERS 5
#define NRF_RAAL_TIMESLOT_DEFAULT_SAFE_MARGIN nrf_raal_softdevice_safe_margin_calc(NRF_RAAL_DEFAULT_LF_CLK_ACCURACY_PPM)
#define NRF_RAAL_TIMESLOT_DEFAULT_TIMEOUT 6400
#define NRF_RAAL_TIMESLOT_DEFAULT_MAX_LENGTH 120000000
#define NRF_RAAL_DEFAULT_LF_CLK_ACCURACY_PPM 500
#define NRF_RAAL_TIMESLOT_DEFAULT_LENGTH 6400
#define NRF_RAAL_TIMESLOT_DEFAULT_ALLOC_ITERS 5
#define NRF_RAAL_TIMESLOT_DEFAULT_SAFE_MARGIN nrf_raal_softdevice_safe_margin_calc( \
NRF_RAAL_DEFAULT_LF_CLK_ACCURACY_PPM)
#define NRF_RAAL_TIMESLOT_DEFAULT_TIMEOUT 4500
#define NRF_RAAL_TIMESLOT_DEFAULT_MAX_LENGTH 120000000
#define NRF_RAAL_DEFAULT_LF_CLK_ACCURACY_PPM 500
#define NRF_RAAL_TIMESLOT_DEFAULT_SAFE_MARGIN_LFRC_TICKS 4
#define NRF_RAAL_TIMESLOT_DEFAULT_SAFE_MARGIN_CRYSTAL_TICKS 3
#define NRF_RAAL_TIMESLOT_DEFAULT_SAFE_MARGIN_US 3
#define NRF_RAAL_PPM_THRESHOLD 500
#define NRF_RAAL_PPM_THRESHOLD 500
#define NRF_RAAL_TIMESLOT_SAFE_MARGIN_TICKS(ppm) ((ppm >= NRF_RAAL_PPM_THRESHOLD) ? \
NRF_RAAL_TIMESLOT_DEFAULT_SAFE_MARGIN_LFRC_TICKS : \
NRF_RAAL_TIMESLOT_DEFAULT_SAFE_MARGIN_CRYSTAL_TICKS)
#define NRF_RAAL_TIMESLOT_SAFE_MARGIN_TICKS(ppm) ((ppm >= NRF_RAAL_PPM_THRESHOLD) ? \
NRF_RAAL_TIMESLOT_DEFAULT_SAFE_MARGIN_LFRC_TICKS \
: \
NRF_RAAL_TIMESLOT_DEFAULT_SAFE_MARGIN_CRYSTAL_TICKS)
/**
* @brief Function used to calculate safe margin from LF clock accuracy in ppm unit.
*
* @param[in] ppm LF clock accuracy in ppm unit.
*/
#define nrf_raal_softdevice_safe_margin_calc(ppm) (NRF_802154_RTC_TICKS_TO_US(NRF_RAAL_TIMESLOT_SAFE_MARGIN_TICKS(ppm)) \
+ NRF_RAAL_TIMESLOT_DEFAULT_SAFE_MARGIN_US)
#define nrf_raal_softdevice_safe_margin_calc(ppm) (NRF_802154_RTC_TICKS_TO_US( \
NRF_RAAL_TIMESLOT_SAFE_MARGIN_TICKS( \
ppm)) \
+ \
NRF_RAAL_TIMESLOT_DEFAULT_SAFE_MARGIN_US)
/** @brief RAAL Softdevice configuration parameters. */
typedef struct
@@ -99,12 +104,10 @@ typedef struct
* @ref nrf_raal_softdevice_safe_margin_calc can be used to calculate proper value based on clock accuracy.
* This value can also be selected experimentally.
*/
uint16_t timeslot_safe_margin;
uint16_t timeslot_safe_margin;
/**
* @brief @deprecated Clock accuracy in ppm unit.
* This value is not used anymore.
* Clock accuracy is embedded into timeslot_safe_margin.
* @brief Clock accuracy in ppm unit.
*/
uint16_t lf_clk_accuracy_ppm;
} nrf_raal_softdevice_cfg_t;
@@ -51,7 +51,7 @@
#include "platform/lp_timer/nrf_802154_lp_timer.h"
#if defined(__ICCARM__)
_Pragma("diag_suppress=Pe167")
_Pragma("diag_suppress=Pe167")
#endif
static volatile uint8_t m_timer_mutex; ///< Mutex for starting the timer.
@@ -75,7 +75,8 @@ static inline bool mutex_trylock(volatile uint8_t * p_mutex)
__CLREX();
return false;
}
} while (__STREXB(1, p_mutex));
}
while (__STREXB(1, p_mutex));
__DMB();
@@ -97,7 +98,8 @@ static inline void queue_cntr_bump(void)
do
{
cntr = __LDREXB(&m_queue_changed_cntr);
} while (__STREXB(cntr + 1, &m_queue_changed_cntr));
}
while (__STREXB(cntr + 1, &m_queue_changed_cntr));
__DMB();
}
@@ -165,7 +167,8 @@ static inline void handle_timer(void)
mutex_unlock(&m_timer_mutex);
}
} while (queue_cntr != m_queue_changed_cntr);
}
while (queue_cntr != m_queue_changed_cntr);
}
/**
@@ -259,7 +262,8 @@ static bool timer_remove(nrf_802154_timer_t * p_timer)
// This assignment is used to prevent compiler from removing exclusive load during optimization (IAR).
temp = __LDREXW((uint32_t *)&p_cur->p_next);
assert((void *)temp != p_cur);
} while (__STREXW(temp, (uint32_t *)&p_cur->p_next));
}
while (__STREXW(temp, (uint32_t *)&p_cur->p_next));
}
return (timer_start || timer_stop);
@@ -298,6 +302,24 @@ bool nrf_802154_timer_sched_time_is_in_future(uint32_t now, uint32_t t0, uint32_
return difference > 0;
}
uint32_t nrf_802154_timer_sched_remaining_time_get(const nrf_802154_timer_t * p_timer)
{
assert(p_timer != NULL);
uint32_t now = nrf_802154_lp_timer_time_get();
uint32_t expiration = p_timer->t0 + p_timer->dt;
int32_t remaining = expiration - now;
if (remaining > 0)
{
return (uint32_t)remaining;
}
else
{
return 0ul;
}
}
void nrf_802154_timer_sched_add(nrf_802154_timer_t * p_timer, bool round_up)
{
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_TSCH_ADD);
@@ -316,7 +338,7 @@ void nrf_802154_timer_sched_add(nrf_802154_timer_t * p_timer, bool round_up)
}
nrf_802154_timer_t ** pp_item;
nrf_802154_timer_t * p_next;
nrf_802154_timer_t * p_next;
uint8_t queue_cntr;
while (true)
@@ -402,7 +424,8 @@ bool nrf_802154_timer_sched_is_running(nrf_802154_timer_t * p_timer)
break;
}
}
} while (queue_cntr != m_queue_changed_cntr);
}
while (queue_cntr != m_queue_changed_cntr);
return result;
}
@@ -413,7 +436,7 @@ void nrf_802154_lp_timer_fired(void)
if (mutex_trylock(&m_fired_mutex))
{
nrf_802154_timer_t * p_timer = (nrf_802154_timer_t *) mp_head;
nrf_802154_timer_t * p_timer = (nrf_802154_timer_t *)mp_head;
if (p_timer != NULL)
{
@@ -76,11 +76,11 @@ typedef struct nrf_802154_timer_s nrf_802154_timer_t;
*/
struct nrf_802154_timer_s
{
uint32_t t0; ///< Base time of the timer [us]
uint32_t dt; ///< Timer expiration delta from @p t0 [us]
nrf_802154_timer_callback_t callback; ///< Callback function called when timer expires
void * p_context; ///< User-defined context passed to callback function
nrf_802154_timer_t * p_next; ///< A pointer to the next running timer
uint32_t t0; ///< Base time of the timer [us]
uint32_t dt; ///< Timer expiration delta from @p t0 [us]
nrf_802154_timer_callback_t callback; ///< Callback function called when timer expires
void * p_context; ///< User-defined context passed to callback function
nrf_802154_timer_t * p_next; ///< A pointer to the next running timer
};
/**
@@ -121,6 +121,15 @@ uint32_t nrf_802154_timer_sched_granularity_get(void);
*/
bool nrf_802154_timer_sched_time_is_in_future(uint32_t now, uint32_t t0, uint32_t dt);
/**
* @brief Get timer time remaining to expiration.
*
* @param[in] p_timer Pointer to the timer to check remaining time.
*
* @retval remaining time [us] or 0 if timer has already expired.
*/
uint32_t nrf_802154_timer_sched_remaining_time_get(const nrf_802154_timer_t * p_timer);
/**
* @brief Start given timer and add it to the scheduler.
*