[nrf528xx] update nrf_802154_radio_driver to version 1.6.0 (#4324)

This commit is contained in:
Duda, Lukasz
2019-11-14 20:31:00 +01:00
committed by Jonathan Hui
parent e3737a915d
commit ca7d0c1dec
40 changed files with 3244 additions and 1326 deletions
+29 -23
View File
@@ -171,7 +171,7 @@ RADIO_DRIVER_SOURCES
drivers/radio/mac_features/nrf_802154_filter.c \
drivers/radio/mac_features/nrf_802154_frame_parser.c \
drivers/radio/mac_features/nrf_802154_precise_ack_timeout.c \
drivers/radio/fem/simple_gpio/nrf_fem_simple_gpio.c \
drivers/radio/fem/simple_gpio/nrf_fem_simple_gpio.c \
drivers/radio/nrf_802154_core_hooks.c \
drivers/radio/nrf_802154_core.c \
drivers/radio/nrf_802154_critical_section.c \
@@ -181,7 +181,8 @@ RADIO_DRIVER_SOURCES
drivers/radio/nrf_802154_rx_buffer.c \
drivers/radio/nrf_802154_timer_coord.c \
drivers/radio/nrf_802154.c \
drivers/radio/platform/clock/nrf_802154_clock_ot.c \
drivers/radio/platform/coex/nrf_802154_wifi_coex_none.c \
drivers/radio/platform/clock/nrf_802154_clock_ot.c \
drivers/radio/platform/hp_timer/nrf_802154_hp_timer.c \
drivers/radio/rsch/nrf_802154_rsch_crit_sect.c \
drivers/radio/rsch/nrf_802154_rsch.c \
@@ -343,48 +344,53 @@ noinst_HEADERS
$(top_srcdir)/third_party/NordicSemiconductor/drivers/systick/nrf_drv_systick.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/usbd/nrf_drv_usbd_errata.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/usbd/nrf_drv_usbd.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_core.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_core_hooks.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/fal/nrf_802154_fal.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/fem/none/nrf_fem_config.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_config.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_protocol_api.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_protocol_legacy_api.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/fem/simple_gpio/nrf_fem_config.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/fem/three_pin_gpio/nrf_fem_config.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/mac_features/ack_generator/nrf_802154_ack_data.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/mac_features/ack_generator/nrf_802154_ack_generator.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/mac_features/ack_generator/nrf_802154_enh_ack_generator.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/mac_features/ack_generator/nrf_802154_imm_ack_generator.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_ack_timeout.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_csma_ca.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_delayed_trx.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_filter.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_frame_parser.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_config.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_const.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_core.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_core_hooks.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_critical_section.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_debug.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_debug_core.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_debug.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_notification.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_peripherals.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_pib.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_priority_drop.h \
$(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_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 \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_swi.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_timer_coord.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_types.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/nrf_802154_utils.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/fal/nrf_802154_fal.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_protocol_api.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_control_config.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/fem/nrf_fem_protocol_legacy_api.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_ack_timeout.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_csma_ca.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_filter.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_delayed_trx.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_filter.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_frame_parser.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/mac_features/ack_generator/nrf_802154_ack_data.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/mac_features/ack_generator/nrf_802154_ack_generator.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/mac_features/ack_generator/nrf_802154_enh_ack_generator.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/mac_features/ack_generator/nrf_802154_imm_ack_generator.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/platform/clock/nrf_802154_clock.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/platform/coex/nrf_802154_wifi_coex.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/platform/random/nrf_802154_random.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/platform/temperature/nrf_802154_temperature.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/nrf_802154_rsch.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/simulator/nrf_802154_debug.h \
$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/rsch/raal/softdevice/nrf_802154_debug.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 \
@@ -1,3 +0,0 @@
# nRF 802.15.4 radio driver.
Copy of [the nRF52840 IEEE 802.15.4 radio driver](https://github.com/NordicSemiconductor/nRF-IEEE-802.15.4-radio-driver).
@@ -1,4 +1,4 @@
/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA
/* Copyright (c) 2017 - 2019, Nordic Semiconductor ASA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,41 +28,34 @@
*
*/
/**
* @brief Module that contains helpers for checking the nRF SoC revision.
*
*/
#ifndef NRF_FEM_CONFIG_H_
#define NRF_FEM_CONFIG_H_
#ifndef NRF_802154_REVISION_H_
#define NRF_802154_REVISION_H_
#include <stdbool.h>
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initializes the module by reading the nRF52840 revision from the registers and storing it
* for convenient access.
*
* @note If the chip revision is not recognized, this module assumes that it is running on a newer
* chip revision that has all of the features compared to the features of the most recent
* known revision.
* @brief Configuration parameters for pins that enable or disable (or both) either Power Amplifier (PA) or Low Noise Amplifier (LNA).
*/
void nrf_802154_revision_init(void);
typedef struct
{
} nrf_fem_gpiote_pin_config_t;
/**
* @brief Checks if the program is running on the nRF52840 revision that supports the PHYEND event.
*
* @retval true The PHYEND event is supported.
* @retval false The PHYEND event is not supported.
* @brief Configuration parameters for the PA/LNA interface.
*/
bool nrf_802154_revision_has_phyend_event(void);
typedef struct
{
} nrf_fem_interface_config_t;
#ifdef __cplusplus
}
#endif
#endif /* NRF_802154_REVISION_H_ */
#endif /* NRF_FEM_CONFIG_H_ */
@@ -1,401 +0,0 @@
/* Copyright (c) 2017 - 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 common function for Front End Module control of the nRF 802.15.4 radio driver.
*
*/
#include "nrf_fem_control_api.h"
#include <assert.h>
#include "compiler_abstraction.h"
#include "nrf_fem_control_config.h"
#include "nrf_802154_config.h"
#include "nrf.h"
#include "nrf_gpio.h"
#include "nrf_gpiote.h"
#include "nrf_ppi.h"
#include "nrf_radio.h"
#include "nrf_timer.h"
#define NRF_FEM_TIMER_INSTANCE NRF_802154_TIMER_INSTANCE
#if ENABLE_FEM
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)
{
switch (pin)
{
case NRF_FEM_CONTROL_LNA_PIN:
return m_nrf_fem_control_cfg.lna_cfg.enable;
case NRF_FEM_CONTROL_PA_PIN:
return m_nrf_fem_control_cfg.pa_cfg.enable;
case NRF_FEM_CONTROL_ANY_PIN:
return m_nrf_fem_control_cfg.lna_cfg.enable || m_nrf_fem_control_cfg.pa_cfg.enable;
default:
assert(false);
return false;
}
}
/**
* @section GPIO control.
*/
/** Initialize GPIO according to configuration provided. */
static void gpio_init(void)
{
if (m_nrf_fem_control_cfg.pa_cfg.enable)
{
nrf_gpio_cfg_output(m_nrf_fem_control_cfg.pa_cfg.gpio_pin);
nrf_gpio_pin_write(m_nrf_fem_control_cfg.pa_cfg.gpio_pin,
!m_nrf_fem_control_cfg.pa_cfg.active_high);
}
if (m_nrf_fem_control_cfg.lna_cfg.enable)
{
nrf_gpio_cfg_output(m_nrf_fem_control_cfg.lna_cfg.gpio_pin);
nrf_gpio_pin_write(m_nrf_fem_control_cfg.lna_cfg.gpio_pin,
!m_nrf_fem_control_cfg.lna_cfg.active_high);
}
}
/** Configure GPIOTE module. */
static void gpiote_configure(void)
{
if (m_nrf_fem_control_cfg.lna_cfg.enable)
{
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_task_enable(m_nrf_fem_control_cfg.lna_gpiote_ch_id);
}
if (m_nrf_fem_control_cfg.pa_cfg.enable)
{
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_task_enable(m_nrf_fem_control_cfg.pa_gpiote_ch_id);
}
}
/**
* @section PPI control.
*/
/** Initialize PPI according to configuration provided. */
static void ppi_init(void)
{
/* RADIO DISABLED --> clr LNA & clr PA PPI */
if (m_nrf_fem_control_cfg.lna_cfg.enable && m_nrf_fem_control_cfg.pa_cfg.enable)
{
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])));
}
else if (m_nrf_fem_control_cfg.lna_cfg.enable)
{
nrf_ppi_channel_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])));
}
else if (m_nrf_fem_control_cfg.pa_cfg.enable)
{
nrf_ppi_channel_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.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])));
}
else
{
// Intentionally empty
}
}
/** Setup PPI to set LNA pin on a timer event. */
static void ppi_lna_enable_setup(nrf_timer_cc_channel_t timer_cc_channel)
{
/* TIMER0->COMPARE --> set LNA PPI */
nrf_ppi_channel_endpoint_setup(
(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])));
}
/** Setup PPI to set PA pin on a timer event. */
static void ppi_pa_enable_setup(nrf_timer_cc_channel_t timer_cc_channel)
{
/* TIMER2->COMPARE --> set PA PPI */
nrf_ppi_channel_endpoint_setup(
(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])));
}
/**
* @section FEM API functions.
*/
void nrf_fem_control_cfg_set(const nrf_fem_control_cfg_t * p_cfg)
{
m_nrf_fem_control_cfg = *p_cfg;
if (m_nrf_fem_control_cfg.pa_cfg.enable || m_nrf_fem_control_cfg.lna_cfg.enable)
{
gpio_init();
gpiote_configure();
ppi_init();
nrf_ppi_channel_enable((nrf_ppi_channel_t)m_nrf_fem_control_cfg.ppi_ch_id_clr);
}
}
void nrf_fem_control_cfg_get(nrf_fem_control_cfg_t * p_cfg)
{
*p_cfg = m_nrf_fem_control_cfg;
}
void nrf_fem_control_activate(void)
{
if (m_nrf_fem_control_cfg.pa_cfg.enable || m_nrf_fem_control_cfg.lna_cfg.enable)
{
nrf_ppi_channel_enable((nrf_ppi_channel_t)m_nrf_fem_control_cfg.ppi_ch_id_clr);
}
}
void nrf_fem_control_deactivate(void)
{
if (m_nrf_fem_control_cfg.pa_cfg.enable || m_nrf_fem_control_cfg.lna_cfg.enable)
{
nrf_ppi_channel_disable((nrf_ppi_channel_t)m_nrf_fem_control_cfg.ppi_ch_id_clr);
nrf_ppi_channel_disable((nrf_ppi_channel_t)m_nrf_fem_control_cfg.ppi_ch_id_set);
}
}
void nrf_fem_control_ppi_enable(nrf_fem_control_pin_t pin, nrf_timer_cc_channel_t timer_cc_channel)
{
if (pin_is_enabled(pin))
{
switch (pin)
{
case NRF_FEM_CONTROL_LNA_PIN:
ppi_lna_enable_setup(timer_cc_channel);
nrf_ppi_channel_enable((nrf_ppi_channel_t)m_nrf_fem_control_cfg.ppi_ch_id_set);
break;
case NRF_FEM_CONTROL_PA_PIN:
ppi_pa_enable_setup(timer_cc_channel);
nrf_ppi_channel_enable((nrf_ppi_channel_t)m_nrf_fem_control_cfg.ppi_ch_id_set);
break;
default:
assert(false);
break;
}
}
}
void nrf_fem_control_ppi_disable(nrf_fem_control_pin_t pin)
{
if (pin_is_enabled(pin))
{
nrf_ppi_channel_disable((nrf_ppi_channel_t)m_nrf_fem_control_cfg.ppi_ch_id_set);
}
}
uint32_t nrf_fem_control_delay_get(nrf_fem_control_pin_t pin)
{
uint32_t target_time = 1;
if (pin_is_enabled(pin))
{
switch (pin)
{
case NRF_FEM_CONTROL_LNA_PIN:
target_time = NRF_FEM_RADIO_RX_STARTUP_LATENCY_US - NRF_FEM_LNA_TIME_IN_ADVANCE;
break;
case NRF_FEM_CONTROL_PA_PIN:
target_time = NRF_FEM_RADIO_TX_STARTUP_LATENCY_US - NRF_FEM_PA_TIME_IN_ADVANCE;
break;
default:
assert(false);
break;
}
}
return target_time;
}
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);
}
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);
}
}
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);
}
}
void nrf_fem_control_timer_reset(nrf_fem_control_pin_t pin, nrf_timer_short_mask_t short_mask)
{
if (pin_is_enabled(pin))
{
// Anomaly 78: use SHUTDOWN instead of STOP and CLEAR.
nrf_timer_task_trigger(NRF_FEM_TIMER_INSTANCE, NRF_TIMER_TASK_SHUTDOWN);
nrf_timer_shorts_disable(NRF_FEM_TIMER_INSTANCE, short_mask);
}
}
void nrf_fem_control_ppi_fork_setup(nrf_fem_control_pin_t pin,
nrf_ppi_channel_t ppi_channel,
uint32_t task_addr)
{
if (pin_is_enabled(pin))
{
nrf_ppi_fork_endpoint_setup(ppi_channel, task_addr);
}
}
void nrf_fem_control_ppi_task_setup(nrf_fem_control_pin_t pin,
nrf_ppi_channel_t ppi_channel,
uint32_t event_addr,
uint32_t task_addr)
{
if (pin_is_enabled(pin))
{
nrf_ppi_channel_endpoint_setup(ppi_channel, event_addr, task_addr);
nrf_ppi_channel_enable(ppi_channel);
}
}
void nrf_fem_control_ppi_fork_clear(nrf_fem_control_pin_t pin, nrf_ppi_channel_t ppi_channel)
{
if (pin_is_enabled(pin))
{
nrf_ppi_fork_endpoint_setup(ppi_channel, 0);
}
}
void nrf_fem_control_ppi_pin_task_setup(nrf_ppi_channel_t ppi_channel,
uint32_t event_addr,
bool lna_pin_set,
bool pa_pin_set)
{
uint32_t lna_task_addr = 0;
uint32_t pa_task_addr = 0;
if (m_nrf_fem_control_cfg.lna_cfg.enable)
{
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]);
}
else
{
lna_task_addr =
(uint32_t)(&NRF_GPIOTE->TASKS_CLR[m_nrf_fem_control_cfg.lna_gpiote_ch_id]);
}
}
if (m_nrf_fem_control_cfg.pa_cfg.enable)
{
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]);
}
else
{
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_enable(ppi_channel);
}
}
#endif // ENABLE_FEM
@@ -1,272 +0,0 @@
/* Copyright (c) 2017 - 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 Frontend Module control for the nRF 802.15.4 radio driver.
*
*/
#ifndef NRF_FEM_CONTROL_API_H_
#define NRF_FEM_CONTROL_API_H_
#include <stdint.h>
#include <stdbool.h>
#include "nrf_ppi.h"
#include "nrf_timer.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @section Resource configuration.
*/
#ifdef NRF52811_XXAA
/** Default Power Amplifier pin. */
#define NRF_FEM_CONTROL_DEFAULT_PA_PIN 19
/** Default Low Noise Amplifier pin. */
#define NRF_FEM_CONTROL_DEFAULT_LNA_PIN 20
#else
/** Default Power Amplifier pin. */
#define NRF_FEM_CONTROL_DEFAULT_PA_PIN 15
/** Default Low Noise Amplifier pin. */
#define NRF_FEM_CONTROL_DEFAULT_LNA_PIN 16
#endif
/** Default PPI channel for pin setting. */
#define NRF_FEM_CONTROL_DEFAULT_SET_PPI_CHANNEL 15
/** Default PPI channel for pin clearing. */
#define NRF_FEM_CONTROL_DEFAULT_CLR_PPI_CHANNEL 16
/** Default GPIOTE channel for FEM control. */
#define NRF_FEM_CONTROL_DEFAULT_LNA_GPIOTE_CHANNEL 6
/** Default GPIOTE channel for FEM control. */
#define NRF_FEM_CONTROL_DEFAULT_PA_GPIOTE_CHANNEL 7
#if ENABLE_FEM
/**
* @brief Configuration parameters for the Power Amplifier and Low Noise Amplifier.
*/
typedef struct
{
uint8_t enable : 1; /**< Enable/disable this amplifier. */
uint8_t active_high : 1; /**< GPIO pin active state for this amplifier. */
uint8_t gpio_pin : 6; /**< GPIO pin to be toggled for this amplifier. */
} nrf_fem_control_pa_lna_cfg_t;
/**
* @brief PA & LNA GPIO toggle configuration.
*
* This option configures the nRF 802.15.4 radio driver to toggle pins when the radio
* is active for use with a Power Amplifier or a Low Noise Amplifier, or both.
*
* Toggling the pins is achieved by using two PPI channels and a GPIOTE channel.
* The hardware channel IDs are provided by the application and must be regarded as reserved
* for as long as any PA/LNA toggling is enabled.
*
* @note Changing this configuration while the radio is in use can have undefined
* consequences and must be avoided by the application.
*/
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 the Power Amplifier pin toggling. */
uint8_t lna_gpiote_ch_id; /**< GPIOTE channel used for the Low Noise Amplifier pin toggling. */
uint8_t ppi_ch_id_set; /**< PPI channel used for radio Power Amplifier and Low Noise Amplifier pin settings. */
uint8_t ppi_ch_id_clr; /**< PPI channel used for radio pin clearing. */
} nrf_fem_control_cfg_t;
/**
* @brief Hardware pins controlled by the Frontend Module.
*/
typedef enum
{
NRF_FEM_CONTROL_PA_PIN,
NRF_FEM_CONTROL_LNA_PIN,
NRF_FEM_CONTROL_ANY_PIN,
} nrf_fem_control_pin_t;
/**@brief Sets the PA & LNA GPIO toggle configuration.
*
* @note Do not call this function when the radio is in use.
*
* @param[in] p_cfg Pointer to the PA & LNA GPIO toggle configuration.
*
*/
void nrf_fem_control_cfg_set(const nrf_fem_control_cfg_t * p_cfg);
/**@brief Gets the PA & LNA GPIO toggle configuration.
*
* @param[out] p_cfg Pointer to the structure for the PA & LNA GPIO toggle configuration.
*
*/
void nrf_fem_control_cfg_get(nrf_fem_control_cfg_t * p_cfg);
/**@brief Activates the Frontend Module controller.
*
* This function is to be called when the radio wakes up.
*/
void nrf_fem_control_activate(void);
/**@brief Deactivates the Frontend Module controller.
*
* This function is to be called when the radio goes to sleep.
*/
void nrf_fem_control_deactivate(void);
/**@brief Configures PPI to activate one of the Frontend Module pins on an appropriate timer event.
*
* @param[in] pin Pin controlled by Frontend Module to be connected to the PPI.
* @param[in] timer_cc_channel Timer CC channel that triggers the @p pin activation through the PPI.
*
*/
void nrf_fem_control_ppi_enable(nrf_fem_control_pin_t pin, nrf_timer_cc_channel_t timer_cc_channel);
/**@brief Clears the PPI configuration used to activate one of Frontend Module pins.
*
* @param[in] pin Pin controlled by Frontend Module to be disconnected from the PPI.
*
*/
void nrf_fem_control_ppi_disable(nrf_fem_control_pin_t pin);
/**@brief Calculates the target time for a timer that activates one of the Frontend Module pins.
*
* @param[in] pin Pin controlled by Frontend Module that is to be activated.
*
* @returns Activation delay of @p pin in microseconds.
*
*/
uint32_t nrf_fem_control_delay_get(nrf_fem_control_pin_t pin);
/**@brief Clears the Power Amplifier and the Low Noise Amplifier pins immediately.
*
*/
void nrf_fem_control_pin_clear(void);
/**@brief Configures and sets a timer for activation of one of the Frontend Module pins.
*
* @param[in] pin Pin controlled by Frontend Module to be activated.
* @param[in] timer_cc_channel Timer CC channel to be set.
* @param[in] short_mask Mask of timer shortcuts to be enabled.
*
*/
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);
/**@brief Clears the timer configuration after the deactivation of one of the Frontend Module pins.
*
* @param[in] pin Pin controlled by Frontend Module to be deactivated.
* @param[in] short_mask Mask of timer shortcuts to be disabled.
*
*/
void nrf_fem_control_timer_reset(nrf_fem_control_pin_t pin, nrf_timer_short_mask_t short_mask);
/**@brief Sets up a PPI fork task necessary for one of the Frontend Module pins.
*
* @param[in] pin Pin controlled by Frontend Module that was deactivated.
* @param[in] ppi_channel PPI channel to connect the fork task to.
*
*/
void nrf_fem_control_ppi_fork_setup(nrf_fem_control_pin_t pin,
nrf_ppi_channel_t ppi_channel,
uint32_t task_addr);
/**@brief Sets up a PPI task necessary for one of the Frontend Module pins.
*
* @param[in] pin Pin controlled by Frontend Module 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.
* @param[in] task_addr Address of the task to be connected to the PPI.
*
*/
void nrf_fem_control_ppi_task_setup(nrf_fem_control_pin_t pin,
nrf_ppi_channel_t ppi_channel,
uint32_t event_addr,
uint32_t task_addr);
/**@brief Clears a PPI fork task configuration for one of the Frontend Module pins.
*
* @param[in] pin Pin controlled by Frontend Module that was deactivated.
* @param[in] ppi_channel PPI channel to disconnect the fork task from.
*
*/
void nrf_fem_control_ppi_fork_clear(nrf_fem_control_pin_t pin, nrf_ppi_channel_t ppi_channel);
/**@brief Sets up a PPI task and a PPI fork that set or clear Frontend 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 @p event_addr.
* Otherwise, it will be cleared.
* @param[in] pa_pin_set If true, the Power Amplifier pin will be set on @p event_addr.
* Otherwise, it will be cleared.
*
*/
void nrf_fem_control_ppi_pin_task_setup(nrf_ppi_channel_t ppi_channel,
uint32_t event_addr,
bool lna_pin_set,
bool pa_pin_set);
#else // ENABLE_FEM
#define nrf_fem_control_cfg_set(...)
#define nrf_fem_control_cfg_get(...)
#define nrf_fem_control_activate(...)
#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_pin_clear(...)
#define nrf_fem_control_timer_set(...)
#define nrf_fem_control_timer_reset(...)
#define nrf_fem_control_ppi_fork_setup(...)
#define nrf_fem_control_ppi_task_setup(...)
#define nrf_fem_control_ppi_task_and_fork_setup(...)
#define nrf_fem_control_ppi_fork_clear(...)
#define nrf_fem_control_ppi_pin_task_setup(...)
#endif // ENABLE_FEM
#ifdef __cplusplus
}
#endif
#endif /* NRF_FEM_CONTROL_API_H_ */
@@ -1,4 +1,4 @@
/* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA
/* Copyright (c) 2017 - 2019, Nordic Semiconductor ASA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,37 +31,74 @@
#ifndef NRF_FEM_CONTROL_CONFIG_H_
#define NRF_FEM_CONTROL_CONFIG_H_
#if ENABLE_FEM
#include "nrf_fem_config.h"
#endif // ENABLE_FEM
#include <stdint.h>
#include <stdbool.h>
#include "nrf_error.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @section Timings.
* @section Configuration
*/
/** Time in microseconds when PA GPIO is activated before the radio is ready for transmission. */
#define NRF_FEM_PA_TIME_IN_ADVANCE 23
#if ENABLE_FEM
/** Time in microseconds when LNA GPIO is activated before the radio is ready for reception. */
#define NRF_FEM_LNA_TIME_IN_ADVANCE 5
/**
* @brief Configures the PA and LNA device interface.
*
* This function sets device interface parameters for the PA/LNA module.
* The module can then be used to control a power amplifier or a low noise amplifier (or both) through the given interface and resources.
*
* The function also sets the PPI and GPIOTE channels to be configured for the PA/LNA interface.
*
* @param[in] p_config Pointer to the interface parameters for the PA/LNA device.
*
* @retval ::NRF_SUCCESS PA/LNA control successfully configured.
* @retval ::NRF_ERROR_NOT_SUPPORTED PA/LNA is not available.
*
*/
int32_t nrf_fem_interface_configuration_set(nrf_fem_interface_config_t const * const p_config);
#if defined(NRF52840_XXAA) || \
defined(NRF52840_AAAA) || \
defined(NRF52840_AABA) || \
defined(NRF52840_AACX) || \
defined(NRF52811_XXAA)
/**
* @brief Retrieves the configuration of PA and LNA device interface.
*
* This function gets device interface parameters for the PA/LNA module.
* The module can then be used to control a power amplifier or a low noise amplifier (or both) through the given interface and resources.
*
*
* @param[in] p_config Pointer to the interface parameters for the PA/LNA device to be populated.
*
* @retval ::NRF_SUCCESS PA/LNA control successfully configured.
* @retval ::NRF_ERROR_NOT_SUPPORTED PA/LNA is not available.
*
*/
int32_t nrf_fem_interface_configuration_get(nrf_fem_interface_config_t * p_config);
/** Radio ramp-up time in TX mode, in microseconds. */
#define NRF_FEM_RADIO_TX_STARTUP_LATENCY_US 40
#else // ENABLE_FEM
/** Radio ramp-up time in RX mode, in microseconds. */
#define NRF_FEM_RADIO_RX_STARTUP_LATENCY_US 40
typedef void nrf_fem_interface_config_t;
#else
static inline int32_t nrf_fem_interface_configuration_set(
nrf_fem_interface_config_t const * const p_config)
{
(void)p_config;
return NRF_ERROR_NOT_SUPPORTED;
}
#error "Device not supported."
static inline int32_t nrf_fem_interface_configuration_get(nrf_fem_interface_config_t * p_config)
{
(void)p_config;
return NRF_ERROR_NOT_SUPPORTED;
}
#endif
#endif // ENABLE_FEM
#ifdef __cplusplus
}
@@ -0,0 +1,303 @@
/* Copyright (c) 2017 - 2019, 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 Protocol interface for Power Amplifier (PA) and Low Noise Amplifier (LNA).
*
* This module enables toggling of GPIO pins before and after the radio transmission and the radio reception
* in order to control a Power Amplifier or a Low Noise Amplifier, or both.
*
* The application must first provide PA and LNA device-specific configuration parameters to this module.
* The protocol must then provide PA and LNA protocol configuration parameters before it can use the functionality.
*
* When the PA/LNA module is configured, the stack can call the provided enable functions before radio activity
* to enable the PA or LNA timer configurations for the upcoming radio activity.
* By default, PA/LNA is automatically deactivated on the radio DISABLED event.
* This can be disabled, so that a manual deactivation can be performed instead.
*/
#ifndef NRF_FEM_PROTOCOL_API_H__
#define NRF_FEM_PROTOCOL_API_H__
#include "nrf_fem_control_config.h"
#include "nrf_fem_protocol_legacy_api.h"
#include "nrf_error.h"
#include "nrf_ppi.h"
#include "nrf_timer.h"
typedef enum
{
NRF_802154_FAL_PA = 1 << 0,
NRF_802154_FAL_LNA = 1 << 1,
NRF_802154_FAL_ALL = NRF_802154_FAL_PA | NRF_802154_FAL_LNA
} nrf_fal_functionality_t;
/**
* @brief PA and LNA activation event types.
*/
typedef enum
{
NRF_802154_FAL_EVENT_TYPE_TIMER,
NRF_802154_FAL_EVENT_TYPE_GENERIC,
NRF_802154_FAL_EVENT_TYPE_PPI,
} nrf_802154_fal_event_type_t;
/**
* @brief Frontend Abstraction Layer event.
*
* The event can be a Timer Compare event or an Any event.
* Register value is only used for the Timer Compare event and should only contain the timer value relative to the Timer Compare event.
*/
typedef struct
{
union
{
struct
{
NRF_TIMER_Type * p_timer_instance; /* Pointer to a 1-us resolution timer instance. */
uint32_t counter_value; /* Timer value when the radio activity starts. */
uint8_t compare_channel_mask; /* Mask of the compare channels that can be used by the FEM to schedule its own tasks. */
} timer;
struct
{
uint32_t register_address; /* Address of event register. */
} generic;
struct
{
uint8_t ch_id; /* Number of the PPI which was provided. */
} ppi;
} event;
bool override_ppi; /* False to ignore the PPI channel below and use the one set by application. True to use the PPI channel below. */
uint8_t ppi_ch_id; /* PPI channel to be used for this event. */
nrf_802154_fal_event_type_t type; /* Type of event source. */
} nrf_802154_fal_event_t;
#if ENABLE_FEM
/**
* @brief Sets up PA using the provided events for the upcoming radio transmission.
*
* Multiple configurations can be provided by repeating calls to this function (that is, you can set the activate and the deactivate events in multiple calls,
* and the configuration is preserved between calls).
*
* If a NRF_802154_PA_LNA_EVENT_TYPE_TIMER timer event is provided, the PA will be configured to activate or deactivate at the application-configured time gap
* before the timer instance reaches the given register_value. The time gap is set via @ref nrf_fem_interface_configuration_set.
*
* If a NRF_802154_PA_LNA_EVENT_TYPE_GENERIC event is provided, the PA will be configured to activate or deactivate when an event occurs.
*
* The function sets up the PPIs and the GPIOTE channel to activate PA for the upcoming radio transmission.
* The PA pin will be active until deactivated, which can happen either by encountering a configured deactivation event or by using @ref nrf_802154_fal_deactivate_now.
*
* @param[in] p_activate_event Pointer to the activation event structure.
* @param[in] p_deactivate_event Pointer to the deactivation event structure.
*
* @pre To activate PA, nrf_fem_interface_configuration_set() must have been called first.
*
* @note If a timer event is provided, the caller of this function is responsible for starting the timer and its shorts.
* Moreover, the caller is responsible for stopping the timer no earlier than the provided compare channel expires.
*
* @retval ::NRF_SUCCESS PA activate setup is successful.
* @retval ::NRF_ERROR_FORBIDDEN PA is currently disabled.
* @retval ::NRF_ERROR_INVALID_STATE PA activate setup could not be performed due to invalid or missing configuration parameters
* in p_activate_event or p_deactivate_event, or both.
*/
int32_t nrf_802154_fal_pa_configuration_set(const nrf_802154_fal_event_t * const p_activate_event,
const nrf_802154_fal_event_t * const p_deactivate_event);
/**
* @brief Clears up the configuration provided by the @ref nrf_802154_fal_pa_configuration_set function.
*
* @param[in] p_activate_event Pointer to the activation event structure.
* @param[in] p_deactivate_event Pointer to the deactivation event structure.
*
* @retval ::NRF_SUCCESS PA activate setup purge is successful.
* @retval ::NRF_ERROR_FORBIDDEN PA is currently disabled.
* @retval ::NRF_ERROR_INVALID_STATE PA activate setup purge could not be performed due to invalid or missing configuration parameters
* in p_activate_event or p_deactivate_event, or both.
*/
int32_t nrf_802154_fal_pa_configuration_clear(const nrf_802154_fal_event_t * const p_activate_event,
const nrf_802154_fal_event_t * const p_deactivate_event);
/**
* @brief Sets up LNA using the provided event for the upcoming radio reception.
*
* Multiple configurations can be provided by repeating calls to this function (that is, you can set the activate and the deactivate event in multiple calls,
* and the configuration is preserved between calls).
*
* If a NRF_802154_PA_LNA_EVENT_TYPE_TIMER timer event is provided, the LNA will be configured to activate or deactivate at the application-configured time gap
* before the timer instance reaches the given register_value. The time gap is set via @ref nrf_fem_interface_configuration_set.
*
* If a NRF_802154_PA_LNA_EVENT_TYPE_GENERIC event is provided, the LNA will be configured to activate or deactivate when an event occurs.
*
* The function sets up the PPIs and the GPIOTE channel to activate LNA for the upcoming radio transmission.
* The LNA pin will be active until deactivated, which can happen either by encountering a configured deactivation event or by using @ref nrf_802154_fal_deactivate_now.
*
* @param[in] p_activate_event Pointer to the activation event structure.
* @param[in] p_deactivate_event Pointer to the deactivation event structure.
*
* @pre To activate LNA, nrf_fem_interface_configuration_set() must have been called first.
*
* @note If a timer event is provided, the caller of this function is responsible for starting the timer and its shorts.
* Moreover, the caller is responsible for stopping the timer no earlier than the provided compare channel expires.
*
* @retval ::NRF_SUCCESS LNA activate setup is successful.
* @retval ::NRF_ERROR_FORBIDDEN LNA is currently disabled.
* @retval ::NRF_ERROR_INVALID_STATE LNA activate setup could not be performed due to invalid or missing configuration parameters
* in p_activate_event or p_deactivate_event, or both.
*/
int32_t nrf_802154_fal_lna_configuration_set(const nrf_802154_fal_event_t * const p_activate_event,
const nrf_802154_fal_event_t * const p_deactivate_event);
/**
* @brief Clears up the configuration provided by the @ref nrf_802154_fal_lna_configuration_set function.
*
* @param[in] p_activate_event Pointer to the activation event structure.
* @param[in] p_deactivate_event Pointer to the deactivation event structure.
*
* @retval ::NRF_SUCCESS LNA activate setup purge is successful.
* @retval ::NRF_ERROR_FORBIDDEN LNA is currently disabled.
* @retval ::NRF_ERROR_INVALID_STATE LNA activate setup purge could not be performed due to invalid or missing configuration parameters
* in p_activate_event or p_deactivate_event, or both.
*/
int32_t nrf_802154_fal_lna_configuration_clear(
const nrf_802154_fal_event_t * const p_activate_event,
const nrf_802154_fal_event_t * const p_deactivate_event);
/**
* @brief Deactivates PA/LNA pins with immediate effect.
*/
void nrf_802154_fal_deactivate_now(nrf_fal_functionality_t type);
/**
* @brief Cleans up the configured PA/LNA timer/radio instance and resources of PPI and GPIOTE.
* The function resets the hardware that has been set up for the PA/LNA activation. The PA and LNA module control configuration parameters are not deleted.
* The function is intended to be called after the radio disable signal.
*/
void nrf_802154_fal_cleanup(void);
/**
* @brief Checks if the PA signaling is configured and enabled, and gets the configured gain in dB.
*
* @param[out] p_gain The configured gain in dB if PA is configured and enabled.
If there is no PA present or the PA does not affect the signal gain, returns 0 dB.
*
*/
void nrf_802154_fal_pa_is_configured(int8_t * const p_gain);
/**
* @brief Prepares the FEM module to switch to the Power Down state.
*
* @param[in] p_instance Timer instance that is used to schedule the transition to the Power Down state.
* @param[in] compare_channel Compare channel to hold a value for the timer.
* @param[in] ppi_id ID of the PPI channel used to switch to the Power Down state.
*
* @return bool Whether the scheduling of the transition was successful or not.
*
*/
bool nrf_fem_prepare_powerdown(NRF_TIMER_Type * p_instance,
uint32_t compare_channel,
nrf_ppi_channel_t ppi_id);
#else // ENABLE_FEM
static inline int32_t nrf_802154_fal_pa_configuration_set(
const nrf_802154_fal_event_t * const p_activate_event,
const nrf_802154_fal_event_t * const p_deactivate_event)
{
(void)p_activate_event;
(void)p_deactivate_event;
return NRF_ERROR_FORBIDDEN;
}
static inline int32_t nrf_802154_fal_pa_configuration_clear(
const nrf_802154_fal_event_t * const p_activate_event,
const nrf_802154_fal_event_t * const p_deactivate_event)
{
(void)p_activate_event;
(void)p_deactivate_event;
return NRF_ERROR_FORBIDDEN;
}
static inline int32_t nrf_802154_fal_lna_configuration_set(
const nrf_802154_fal_event_t * const p_activate_event,
const nrf_802154_fal_event_t * const p_deactivate_event)
{
(void)p_activate_event;
(void)p_deactivate_event;
return NRF_ERROR_FORBIDDEN;
}
static inline int32_t nrf_802154_fal_lna_configuration_clear(
const nrf_802154_fal_event_t * const p_activate_event,
const nrf_802154_fal_event_t * const p_deactivate_event)
{
(void)p_activate_event;
(void)p_deactivate_event;
return NRF_ERROR_FORBIDDEN;
}
static inline void nrf_802154_fal_deactivate_now(nrf_fal_functionality_t type)
{
(void)type;
}
static inline void nrf_802154_fal_cleanup(void)
{
}
static inline bool nrf_fem_prepare_powerdown(NRF_TIMER_Type * p_instance,
uint32_t compare_channel,
nrf_ppi_channel_t ppi_id)
{
(void)p_instance;
(void)compare_channel;
(void)ppi_id;
return false;
}
static inline void nrf_802154_fal_pa_is_configured(int8_t * const p_gain)
{
*p_gain = 0;
}
#define NRF_802154_FEM_PINS_USED_MASK 0
#define NRF_802154_FEM_PPI_CHANNELS_USED_MASK 0
#define NRF_802154_FEM_GPIOTE_CHANNELS_USED_MASK 0
#endif // ENABLE_FEM
#endif // NRF_FEM_PROTOCOL_API_H__
/**
@}
@}
*/
@@ -0,0 +1,63 @@
/* Copyright (c) 2017 - 2019, 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.
*
*/
#include <stdint.h>
/**
* @brief Configuration parameters for PA and LNA.
*/
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 be toggled for this amplifier. */
} nrf_fem_control_pa_lna_cfg_t;
/**
* @brief PA and LNA GPIO toggle configuration.
*
* This option configures the nRF 802.15.4 radio driver to toggle pins when the radio
* is active and ready for use with a Power Amplifier (PA) or a Low Noise Amplifier (LNA), or both.
*
* Pins can be toggled by using two PPI channels and a GPIOTE channel. The hardware channel IDs are provided
* by the application and are to be regarded as reserved for as long as there is no PA/LNA toggling enabled.
*
* @note Avoid changing this configuration while the radio is in use, as this can lead to undefined consequences.
*
*/
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_cfg_t;
@@ -0,0 +1,127 @@
/* Copyright (c) 2017 - 2019, 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_FEM_CONFIG_H_
#define NRF_FEM_CONFIG_H_
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Configuration parameters for pins that enable or disable (or both) either Power Amplifier (PA) or Low Noise Amplifier (LNA).
*/
typedef struct
{
bool enable; /* Enable toggling for this pin. */
bool active_high; /* If true, the pin will be active high. Otherwise, the pin will be active low. */
uint8_t gpio_pin; /* GPIO pin number for the pin. */
uint8_t gpiote_ch_id; /* GPIOTE channel to be used for toggling pins. */
} nrf_fem_gpiote_pin_config_t;
/**
* @brief Configuration parameters for the PA/LNA interface.
*/
typedef struct
{
struct
{
uint32_t pa_time_gap_us; /* Time between the activation of the PA pin and the start of the radio transmission. */
uint32_t lna_time_gap_us; /* Time between the activation of the LNA pin and the start of the radio reception. */
int8_t pa_gain_db; /* Configurable PA gain. Ignored if the amplifier is not supporting this feature. */
int8_t lna_gain_db; /* Configurable LNA gain. Ignored if the amplifier is not supporting this feature. */
} fem_config;
nrf_fem_gpiote_pin_config_t pa_pin_config; /* Power Amplifier pin configuration. */
nrf_fem_gpiote_pin_config_t lna_pin_config; /* Low Noise Amplifier pin configuration. */
uint8_t ppi_ch_id_set; /* PPI channel to be used for setting pins. */
uint8_t ppi_ch_id_clr; /* PPI channel to be used for clearing pins. */
} nrf_fem_interface_config_t;
/**
* @section Timings.
*/
/** Time in microseconds when PA GPIO is activated before the radio is ready for transmission. */
#define NRF_FEM_PA_TIME_IN_ADVANCE_US 23
/** Time in microseconds when LNA GPIO is activated before the radio is ready for reception. */
#define NRF_FEM_LNA_TIME_IN_ADVANCE_US 5
#ifdef NRF52811_XXAA
/** Default Power Amplifier pin. */
#define NRF_FEM_CONTROL_DEFAULT_PA_PIN 19
/** Default Low Noise Amplifier pin. */
#define NRF_FEM_CONTROL_DEFAULT_LNA_PIN 20
#else
/** Default Power Amplifier pin. */
#define NRF_FEM_CONTROL_DEFAULT_PA_PIN 15
/** Default Low Noise Amplifier pin. */
#define NRF_FEM_CONTROL_DEFAULT_LNA_PIN 16
#endif
/** Default PPI channel for pin setting. */
#define NRF_FEM_CONTROL_DEFAULT_SET_PPI_CHANNEL 15
/** Default PPI channel for pin clearing. */
#define NRF_FEM_CONTROL_DEFAULT_CLR_PPI_CHANNEL 16
/** Default GPIOTE channel for FEM control. */
#define NRF_FEM_CONTROL_DEFAULT_LNA_GPIOTE_CHANNEL 6
/** Default GPIOTE channel for FEM control. */
#define NRF_FEM_CONTROL_DEFAULT_PA_GPIOTE_CHANNEL 7
/** Mask of GPIO pins used for FEM control. */
#define NRF_802154_FEM_PINS_USED_MASK ((1 << NRF_FEM_CONTROL_DEFAULT_PA_PIN) | \
(1 << NRF_FEM_CONTROL_DEFAULT_LNA_PIN))
/** Mask of PPI channels used for FEM control. */
#define NRF_802154_FEM_PPI_CHANNELS_USED_MASK ((1 << NRF_FEM_CONTROL_DEFAULT_SET_PPI_CHANNEL) | \
(1 << NRF_FEM_CONTROL_DEFAULT_CLR_PPI_CHANNEL))
/** Mask of GPIOTE channels used for FEM control. */
#define NRF_802154_FEM_GPIOTE_CHANNELS_USED_MASK ( \
(1 << NRF_FEM_CONTROL_DEAFULT_LNA_GPIOTE_CHANNEL) | \
(1 << NRF_FEM_CONTROL_DEFAULT_PA_GPIOTE_CHANNEL))
#ifdef __cplusplus
}
#endif
#endif /* NRF_FEM_CONFIG_H_ */
@@ -0,0 +1,470 @@
/* Copyright (c) 2017 - 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 common function for Front End Module control of the nRF 802.15.4 radio driver.
*
*/
#include "nrf_fem_protocol_api.h"
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include "compiler_abstraction.h"
#include "nrf_802154_config.h"
#include "nrf.h"
#include "nrf_error.h"
#include "nrf_gpio.h"
#include "nrf_gpiote.h"
#include "nrf_ppi.h"
#include "nrf_radio.h"
#include "nrf_timer.h"
#if ENABLE_FEM
#define PPI_INVALID_CHANNEL 0xFF /**< Default value for the PPI holder variable. */
static nrf_fem_interface_config_t m_nrf_fem_interface_config = /**< FEM controller configuration. */
{
.fem_config =
{
.pa_time_gap_us = NRF_FEM_PA_TIME_IN_ADVANCE_US,
.lna_time_gap_us = NRF_FEM_LNA_TIME_IN_ADVANCE_US
},
.pa_pin_config =
{
.enable = 1,
.active_high = 1,
.gpio_pin = NRF_FEM_CONTROL_DEFAULT_PA_PIN,
.gpiote_ch_id = NRF_FEM_CONTROL_DEFAULT_PA_GPIOTE_CHANNEL
},
.lna_pin_config =
{
.enable = 1,
.active_high = 1,
.gpio_pin = NRF_FEM_CONTROL_DEFAULT_LNA_PIN,
.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
};
static uint8_t m_ppi_channel_ext = PPI_INVALID_CHANNEL; /**< PPI channel provided by the `override_ppi = true` functionality. */
/** Map the mask bits with the Compare Channels. */
static uint32_t get_first_available_compare_channel(uint8_t mask)
{
if (mask & (1 << 0))
return NRF_TIMER_CC_CHANNEL0;
if (mask & (1 << 1))
return NRF_TIMER_CC_CHANNEL1;
if (mask & (1 << 2))
return NRF_TIMER_CC_CHANNEL2;
if (mask & (1 << 3))
return NRF_TIMER_CC_CHANNEL3;
assert(false);
return 0;
}
/** Configure GPIOTE module. */
static void gpiote_configure(void)
{
if (m_nrf_fem_interface_config.pa_pin_config.enable)
{
nrf_gpiote_task_configure(m_nrf_fem_interface_config.pa_pin_config.gpiote_ch_id,
m_nrf_fem_interface_config.pa_pin_config.gpio_pin,
(nrf_gpiote_polarity_t)GPIOTE_CONFIG_POLARITY_None,
(nrf_gpiote_outinit_t) !m_nrf_fem_interface_config.pa_pin_config.active_high);
nrf_gpiote_task_enable(m_nrf_fem_interface_config.pa_pin_config.gpiote_ch_id);
}
if (m_nrf_fem_interface_config.lna_pin_config.enable)
{
nrf_gpiote_task_configure(m_nrf_fem_interface_config.lna_pin_config.gpiote_ch_id,
m_nrf_fem_interface_config.lna_pin_config.gpio_pin,
(nrf_gpiote_polarity_t)GPIOTE_CONFIG_POLARITY_None,
(nrf_gpiote_outinit_t) !m_nrf_fem_interface_config.lna_pin_config.active_high);
nrf_gpiote_task_enable(m_nrf_fem_interface_config.lna_pin_config.gpiote_ch_id);
}
}
/** Configure the event with the provided values. */
static int32_t event_configuration_set(const nrf_802154_fal_event_t * const p_event,
nrf_fem_gpiote_pin_config_t * p_pin_config,
bool activate,
uint32_t time_delay)
{
uint32_t task_addr;
uint8_t ppi_ch;
assert(p_event);
assert(p_pin_config);
if (p_event->override_ppi)
{
assert(p_event->ppi_ch_id != PPI_INVALID_CHANNEL);
if (m_ppi_channel_ext == PPI_INVALID_CHANNEL)
{
/* External PPI channel placeholder is free. */
m_ppi_channel_ext = ppi_ch = p_event->ppi_ch_id;
}
else if ((m_ppi_channel_ext == p_event->ppi_ch_id) &&
(!NRF_PPI->FORK[(uint32_t)m_ppi_channel_ext].TEP))
{
/* PPI is equal to the already set, but the one set has a free fork endpoint. */
ppi_ch = p_event->ppi_ch_id;
}
else
{
return NRF_ERROR_INVALID_STATE;
}
}
else
{
ppi_ch =
activate ? m_nrf_fem_interface_config.ppi_ch_id_set : m_nrf_fem_interface_config.
ppi_ch_id_clr;
}
if (p_pin_config->active_high ^ activate)
{
task_addr = (uint32_t)(&NRF_GPIOTE->TASKS_CLR[p_pin_config->gpiote_ch_id]);
}
else
{
task_addr = (uint32_t)(&NRF_GPIOTE->TASKS_SET[p_pin_config->gpiote_ch_id]);
}
switch (p_event->type)
{
case NRF_802154_FAL_EVENT_TYPE_GENERIC:
{
if (NRF_PPI->CH[(uint32_t)ppi_ch].TEP)
{
nrf_ppi_fork_endpoint_setup((nrf_ppi_channel_t)ppi_ch, task_addr);
}
else
{
nrf_ppi_channel_endpoint_setup((nrf_ppi_channel_t)ppi_ch,
p_event->event.generic.register_address,
task_addr);
}
nrf_ppi_channel_enable((nrf_ppi_channel_t)ppi_ch);
}
break;
case NRF_802154_FAL_EVENT_TYPE_TIMER:
{
assert(p_event->event.timer.compare_channel_mask);
uint32_t compare_channel = get_first_available_compare_channel(
p_event->event.timer.compare_channel_mask);
nrf_ppi_channel_endpoint_setup((nrf_ppi_channel_t)ppi_ch,
(uint32_t)(&(p_event->event.timer.p_timer_instance->
EVENTS_COMPARE[compare_channel])),
task_addr);
nrf_ppi_channel_enable((nrf_ppi_channel_t)ppi_ch);
nrf_timer_cc_write(p_event->event.timer.p_timer_instance,
(nrf_timer_cc_channel_t)compare_channel,
p_event->event.timer.counter_value - time_delay);
}
break;
default:
assert(false);
break;
}
return NRF_SUCCESS;
}
/** Deconfigure the event with the provided values. */
static int32_t event_configuration_clear(const nrf_802154_fal_event_t * const p_event,
bool activate)
{
uint8_t ppi_ch;
assert(p_event);
if (p_event->override_ppi)
{
ppi_ch = p_event->ppi_ch_id;
}
else
{
ppi_ch =
activate ? m_nrf_fem_interface_config.ppi_ch_id_set : m_nrf_fem_interface_config.
ppi_ch_id_clr;
}
nrf_ppi_channel_disable((nrf_ppi_channel_t)ppi_ch);
nrf_ppi_channel_endpoint_setup((nrf_ppi_channel_t)ppi_ch, 0, 0);
nrf_ppi_fork_endpoint_setup((nrf_ppi_channel_t)ppi_ch, 0);
switch (p_event->type)
{
case NRF_802154_FAL_EVENT_TYPE_GENERIC:
break;
case NRF_802154_FAL_EVENT_TYPE_TIMER:
break;
default:
assert(false);
break;
}
return NRF_SUCCESS;
}
int32_t nrf_802154_fal_pa_configuration_set(const nrf_802154_fal_event_t * const p_activate_event,
const nrf_802154_fal_event_t * const p_deactivate_event)
{
int32_t ret_code;
if (!m_nrf_fem_interface_config.pa_pin_config.enable)
{
return NRF_ERROR_FORBIDDEN;
}
if (p_activate_event)
{
ret_code = event_configuration_set(p_activate_event,
&m_nrf_fem_interface_config.pa_pin_config,
true,
m_nrf_fem_interface_config.fem_config.pa_time_gap_us);
if (ret_code != NRF_SUCCESS)
{
return ret_code;
}
}
if (p_deactivate_event)
{
ret_code = event_configuration_set(p_deactivate_event,
&m_nrf_fem_interface_config.pa_pin_config,
false,
m_nrf_fem_interface_config.fem_config.pa_time_gap_us);
if (ret_code != NRF_SUCCESS)
{
return ret_code;
}
}
return NRF_SUCCESS;
}
int32_t nrf_802154_fal_lna_configuration_set(const nrf_802154_fal_event_t * const p_activate_event,
const nrf_802154_fal_event_t * const p_deactivate_event)
{
int32_t ret_code;
if (!m_nrf_fem_interface_config.lna_pin_config.enable)
{
return NRF_ERROR_FORBIDDEN;
}
if (p_activate_event)
{
ret_code = event_configuration_set(p_activate_event,
&m_nrf_fem_interface_config.lna_pin_config,
true,
m_nrf_fem_interface_config.fem_config.lna_time_gap_us);
if (ret_code != NRF_SUCCESS)
{
return ret_code;
}
}
if (p_deactivate_event)
{
ret_code = event_configuration_set(p_deactivate_event,
&m_nrf_fem_interface_config.lna_pin_config,
false,
m_nrf_fem_interface_config.fem_config.lna_time_gap_us);
if (ret_code != NRF_SUCCESS)
{
return ret_code;
}
}
return NRF_SUCCESS;
}
int32_t nrf_802154_fal_pa_configuration_clear(const nrf_802154_fal_event_t * const p_activate_event,
const nrf_802154_fal_event_t * const p_deactivate_event)
{
int32_t ret_code;
if (!m_nrf_fem_interface_config.pa_pin_config.enable)
{
return NRF_ERROR_FORBIDDEN;
}
if (p_activate_event)
{
ret_code = event_configuration_clear(p_activate_event, true);
if (ret_code != NRF_SUCCESS)
{
return ret_code;
}
}
if (p_deactivate_event)
{
ret_code = event_configuration_clear(p_deactivate_event, false);
if (ret_code != NRF_SUCCESS)
{
return ret_code;
}
}
return NRF_SUCCESS;
}
int32_t nrf_802154_fal_lna_configuration_clear(
const nrf_802154_fal_event_t * const p_activate_event,
const nrf_802154_fal_event_t * const p_deactivate_event)
{
int32_t ret_code;
if (!m_nrf_fem_interface_config.lna_pin_config.enable)
{
return NRF_ERROR_FORBIDDEN;
}
if (p_activate_event)
{
ret_code = event_configuration_clear(p_activate_event, true);
if (ret_code != NRF_SUCCESS)
{
return ret_code;
}
}
if (p_deactivate_event)
{
ret_code = event_configuration_clear(p_deactivate_event, false);
if (ret_code != NRF_SUCCESS)
{
return ret_code;
}
}
return NRF_SUCCESS;
}
void nrf_802154_fal_deactivate_now(nrf_fal_functionality_t type)
{
if (m_nrf_fem_interface_config.pa_pin_config.enable && (type & NRF_802154_FAL_PA))
{
if (m_nrf_fem_interface_config.pa_pin_config.active_high)
{
nrf_gpiote_task_force(m_nrf_fem_interface_config.pa_pin_config.gpiote_ch_id,
NRF_GPIOTE_INITIAL_VALUE_LOW);
}
else
{
nrf_gpiote_task_force(m_nrf_fem_interface_config.pa_pin_config.gpiote_ch_id,
NRF_GPIOTE_INITIAL_VALUE_HIGH);
}
}
if (m_nrf_fem_interface_config.lna_pin_config.enable && (type & NRF_802154_FAL_LNA))
{
if (m_nrf_fem_interface_config.lna_pin_config.active_high)
{
nrf_gpiote_task_force(m_nrf_fem_interface_config.lna_pin_config.gpiote_ch_id,
NRF_GPIOTE_INITIAL_VALUE_LOW);
}
else
{
nrf_gpiote_task_force(m_nrf_fem_interface_config.lna_pin_config.gpiote_ch_id,
NRF_GPIOTE_INITIAL_VALUE_HIGH);
}
}
}
int32_t nrf_fem_interface_configuration_set(nrf_fem_interface_config_t const * const p_config)
{
m_nrf_fem_interface_config = *p_config;
if (m_nrf_fem_interface_config.pa_pin_config.enable ||
m_nrf_fem_interface_config.lna_pin_config.enable)
{
gpiote_configure();
}
return NRF_SUCCESS;
}
int32_t nrf_fem_interface_configuration_get(nrf_fem_interface_config_t * p_config)
{
*p_config = m_nrf_fem_interface_config;
return NRF_SUCCESS;
}
void nrf_802154_fal_cleanup(void)
{
nrf_ppi_channel_disable((nrf_ppi_channel_t)m_nrf_fem_interface_config.ppi_ch_id_set);
nrf_ppi_channel_endpoint_setup((nrf_ppi_channel_t)m_nrf_fem_interface_config.ppi_ch_id_set, 0,
0);
nrf_ppi_fork_endpoint_setup((nrf_ppi_channel_t)m_nrf_fem_interface_config.ppi_ch_id_set, 0);
nrf_ppi_channel_disable((nrf_ppi_channel_t)m_nrf_fem_interface_config.ppi_ch_id_clr);
nrf_ppi_channel_endpoint_setup((nrf_ppi_channel_t)m_nrf_fem_interface_config.ppi_ch_id_clr, 0,
0);
nrf_ppi_fork_endpoint_setup((nrf_ppi_channel_t)m_nrf_fem_interface_config.ppi_ch_id_clr, 0);
if (m_ppi_channel_ext != PPI_INVALID_CHANNEL)
{
nrf_ppi_channel_disable((nrf_ppi_channel_t)m_ppi_channel_ext);
nrf_ppi_channel_endpoint_setup((nrf_ppi_channel_t)m_ppi_channel_ext, 0, 0);
nrf_ppi_fork_endpoint_setup((nrf_ppi_channel_t)m_ppi_channel_ext, 0);
m_ppi_channel_ext = PPI_INVALID_CHANNEL;
}
}
bool nrf_fem_prepare_powerdown(NRF_TIMER_Type * p_instance,
uint32_t compare_channel,
nrf_ppi_channel_t ppi_id)
{
(void)p_instance;
(void)compare_channel;
(void)ppi_id;
return false;
}
#endif // ENABLE_FEM
@@ -0,0 +1,149 @@
/* Copyright (c) 2017 - 2019, 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_FEM_CONFIG_H_
#define NRF_FEM_CONFIG_H_
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Configuration parameters for pins that enable or disable (or both) either Power Amplifier (PA) or Low Noise Amplifier (LNA).
*/
typedef struct
{
bool enable; /* Enable toggling for this pin. */
bool active_high; /* If true, the pin will be active high. Otherwise, the pin will be active low. */
uint8_t gpio_pin; /* GPIO pin number for the pin. */
uint8_t gpiote_ch_id; /* GPIOTE channel to be used for toggling pins. */
} nrf_fem_gpiote_pin_config_t;
/**
* @brief Configuration parameters for the PA/LNA interface.
*/
typedef struct
{
struct
{
uint32_t pa_time_gap_us; /* Time between the activation of the PA pin and the start of the radio transmission. */
uint32_t lna_time_gap_us; /* Time between the activation of the LNA pin and the start of the radio reception. */
uint32_t pdn_settle_us; /* The time between activating the PDN and asserting the PA/LNA pin. */
uint32_t trx_hold_us; /* The time between deasserting the PA/LNA pin and deactivating PDN. */
int8_t pa_gain_db; /* Configurable PA gain. Ignored if the amplifier is not supporting this feature. */
int8_t lna_gain_db; /* Configurable LNA gain. Ignored if the amplifier is not supporting this feature. */
} fem_config;
nrf_fem_gpiote_pin_config_t pa_pin_config; /* Power Amplifier pin configuration. */
nrf_fem_gpiote_pin_config_t lna_pin_config; /* Low Noise Amplifier pin configuration. */
nrf_fem_gpiote_pin_config_t pdn_pin_config; /* Power Down pin configuration. */
uint8_t ppi_ch_id_set; /* PPI channel to be used for setting pins. */
uint8_t ppi_ch_id_clr; /* PPI channel to be used for clearing pins. */
uint8_t ppi_ch_id_pdn; /* PPI channel to handle PDN pin. */
} nrf_fem_interface_config_t;
/**
* @section Timings.
*/
/** Time in microseconds when PA GPIO is activated before the radio is ready for transmission. */
#define NRF_FEM_PA_TIME_IN_ADVANCE_US 13
/** Time in microseconds when LNA GPIO is activated before the radio is ready for reception. */
#define NRF_FEM_LNA_TIME_IN_ADVANCE_US 13
/** The time between activating the PDN and asserting the RX_EN/TX_EN. */
#define NRF_FEM_PDN_SETTLE_US 18
/** The time between deasserting the RX_EN/TX_EN and deactivating PDN. */
#define NRF_FEM_TRX_HOLD_US 5
#ifdef NRF52811_XXAA
/** Default Power Amplifier pin. */
#define NRF_FEM_CONTROL_DEFAULT_PA_PIN 19
/** Default Low Noise Amplifier pin. */
#define NRF_FEM_CONTROL_DEFAULT_LNA_PIN 20
#else
/** Default Power Amplifier pin. */
#define NRF_FEM_CONTROL_DEFAULT_PA_PIN 15
/** Default Low Noise Amplifier pin. */
#define NRF_FEM_CONTROL_DEFAULT_LNA_PIN 16
#endif
/** Default Eagle PDN pin. */
#define NRF_FEM_CONTROL_DEFAULT_PDN_PIN 24
/** Default PPI channel for pin setting. */
#define NRF_FEM_CONTROL_DEFAULT_SET_PPI_CHANNEL 15
/** Default PPI channel for pin clearing. */
#define NRF_FEM_CONTROL_DEFAULT_CLR_PPI_CHANNEL 16
/** Default PPI channel for PDN pin handling. */
#define NRF_FEM_CONTROL_DEFAULT_PDN_PPI_CHANNEL 5
/** Default GPIOTE channel for PDN control. */
#define NRF_FEM_CONTROL_DEFAULT_PDN_GPIOTE_CHANNEL 5
/** Default GPIOTE channel for LNA control. */
#define NRF_FEM_CONTROL_DEFAULT_LNA_GPIOTE_CHANNEL 6
/** Default GPIOTE channel for PA control. */
#define NRF_FEM_CONTROL_DEFAULT_PA_GPIOTE_CHANNEL 7
/** Mask of GPIO pins used for FEM control. */
#define NRF_802154_FEM_PINS_USED_MASK ((1 << NRF_FEM_CONTROL_DEFAULT_PA_PIN) | \
(1 << NRF_FEM_CONTROL_DEFAULT_LNA_PIN) | \
(1 << NRF_FEM_CONTROL_DEFAULT_PDN_PIN))
/** Mask of PPI channels used for FEM control. */
#define NRF_802154_FEM_PPI_CHANNELS_USED_MASK ((1 << NRF_FEM_CONTROL_DEFAULT_SET_PPI_CHANNEL) | \
(1 << NRF_FEM_CONTROL_DEFAULT_CLR_PPI_CHANNEL) | \
(1 << NRF_FEM_CONTROL_DEFAULT_PDN_PPI_CHANNEL))
/** Mask of GPIOTE channels used for FEM control. */
#define NRF_802154_FEM_GPIOTE_CHANNELS_USED_MASK ( \
(1 << NRF_FEM_CONTROL_DEFAULT_PDN_GPIOTE_CHANNEL) | \
(1 << NRF_FEM_CONTROL_DEFAULT_LNA_GPIOTE_CHANNEL) | \
(1 << NRF_FEM_CONTROL_DEFAULT_PA_GPIOTE_CHANNEL))
#ifdef __cplusplus
}
#endif
#endif /* NRF_FEM_CONFIG_H_ */
@@ -0,0 +1,574 @@
/* Copyright (c) 2017 - 2019, 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 common function for Front End Module control of the nRF 802.15.4 radio driver.
*
*/
#include "nrf_fem_protocol_api.h"
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include "compiler_abstraction.h"
#include "nrf_802154_config.h"
#include "nrf.h"
#include "nrf_error.h"
#include "nrf_gpio.h"
#include "nrf_gpiote.h"
#include "nrf_ppi.h"
#include "nrf_radio.h"
#include "nrf_timer.h"
#if ENABLE_FEM
#define PPI_INVALID_CHANNEL 0xFF /**< Default value for the PPI holder variable. */
static nrf_fem_interface_config_t m_nrf_fem_interface_config = /**< FEM controller configuration. */
{
.fem_config =
{
.pa_time_gap_us = NRF_FEM_PA_TIME_IN_ADVANCE_US,
.lna_time_gap_us = NRF_FEM_LNA_TIME_IN_ADVANCE_US,
.pdn_settle_us = NRF_FEM_PDN_SETTLE_US,
.trx_hold_us = NRF_FEM_TRX_HOLD_US,
},
.pa_pin_config =
{
.enable = 1,
.active_high = 1,
.gpio_pin = NRF_FEM_CONTROL_DEFAULT_PA_PIN,
.gpiote_ch_id = NRF_FEM_CONTROL_DEFAULT_PA_GPIOTE_CHANNEL
},
.lna_pin_config =
{
.enable = 1,
.active_high = 1,
.gpio_pin = NRF_FEM_CONTROL_DEFAULT_LNA_PIN,
.gpiote_ch_id = NRF_FEM_CONTROL_DEFAULT_LNA_GPIOTE_CHANNEL
},
.pdn_pin_config =
{
.enable = 1,
.gpio_pin = NRF_FEM_CONTROL_DEFAULT_PDN_PIN,
.active_high = 1,
.gpiote_ch_id = NRF_FEM_CONTROL_DEFAULT_PDN_GPIOTE_CHANNEL
},
.ppi_ch_id_set = NRF_FEM_CONTROL_DEFAULT_SET_PPI_CHANNEL,
.ppi_ch_id_clr = NRF_FEM_CONTROL_DEFAULT_CLR_PPI_CHANNEL,
.ppi_ch_id_pdn = NRF_FEM_CONTROL_DEFAULT_PDN_PPI_CHANNEL
};
static uint8_t m_ppi_channel_ext = PPI_INVALID_CHANNEL; /**< PPI channel provided by the `override_ppi = true` functionality. */
/** Map the mask bits with the Compare Channels. */
static uint32_t get_available_compare_channel(uint8_t mask, uint32_t number)
{
uint32_t i;
for (i = 0; i < 4; i++)
{
if (mask & (1 << i))
{
if (number == 0)
{
break;
}
else
{
number--;
}
}
}
if (i == 0)
return NRF_TIMER_CC_CHANNEL0;
if (i == 1)
return NRF_TIMER_CC_CHANNEL1;
if (i == 2)
return NRF_TIMER_CC_CHANNEL2;
if (i == 3)
return NRF_TIMER_CC_CHANNEL3;
assert(false);
return 0;
}
/** Configure GPIOTE module. */
static void gpiote_configure(void)
{
if (m_nrf_fem_interface_config.pa_pin_config.enable)
{
nrf_gpiote_task_configure(m_nrf_fem_interface_config.pa_pin_config.gpiote_ch_id,
m_nrf_fem_interface_config.pa_pin_config.gpio_pin,
(nrf_gpiote_polarity_t)GPIOTE_CONFIG_POLARITY_None,
(nrf_gpiote_outinit_t) !m_nrf_fem_interface_config.pa_pin_config.active_high);
nrf_gpiote_task_enable(m_nrf_fem_interface_config.pa_pin_config.gpiote_ch_id);
}
if (m_nrf_fem_interface_config.lna_pin_config.enable)
{
nrf_gpiote_task_configure(m_nrf_fem_interface_config.lna_pin_config.gpiote_ch_id,
m_nrf_fem_interface_config.lna_pin_config.gpio_pin,
(nrf_gpiote_polarity_t)GPIOTE_CONFIG_POLARITY_None,
(nrf_gpiote_outinit_t) !m_nrf_fem_interface_config.lna_pin_config.active_high);
nrf_gpiote_task_enable(m_nrf_fem_interface_config.lna_pin_config.gpiote_ch_id);
}
if (m_nrf_fem_interface_config.pdn_pin_config.enable)
{
nrf_gpiote_task_configure(m_nrf_fem_interface_config.pdn_pin_config.gpiote_ch_id,
m_nrf_fem_interface_config.pdn_pin_config.gpio_pin,
(nrf_gpiote_polarity_t)GPIOTE_CONFIG_POLARITY_None,
(nrf_gpiote_outinit_t) !m_nrf_fem_interface_config.pdn_pin_config.active_high);
nrf_gpiote_task_enable(m_nrf_fem_interface_config.pdn_pin_config.gpiote_ch_id);
}
}
/** Configure the event with the provided values. */
static int32_t event_configuration_set(const nrf_802154_fal_event_t * const p_event,
nrf_fem_gpiote_pin_config_t * p_pin_config,
bool activate,
uint32_t time_delay)
{
uint32_t task_addr;
uint8_t ppi_ch;
assert(p_event);
assert(p_pin_config);
if (p_event->override_ppi)
{
assert(p_event->ppi_ch_id != PPI_INVALID_CHANNEL);
if (m_ppi_channel_ext == PPI_INVALID_CHANNEL)
{
/* External PPI channel placeholder is free. */
m_ppi_channel_ext = ppi_ch = p_event->ppi_ch_id;
}
else if ((m_ppi_channel_ext == p_event->ppi_ch_id) &&
(!NRF_PPI->FORK[(uint32_t)m_ppi_channel_ext].TEP))
{
/* PPI is equal to the already set, but the one set has a free fork endpoint. */
ppi_ch = p_event->ppi_ch_id;
}
else
{
return NRF_ERROR_INVALID_STATE;
}
}
else
{
ppi_ch =
activate ? m_nrf_fem_interface_config.ppi_ch_id_set : m_nrf_fem_interface_config.
ppi_ch_id_clr;
}
if (p_pin_config->active_high ^ activate)
{
task_addr = (uint32_t)(&NRF_GPIOTE->TASKS_CLR[p_pin_config->gpiote_ch_id]);
}
else
{
task_addr = (uint32_t)(&NRF_GPIOTE->TASKS_SET[p_pin_config->gpiote_ch_id]);
}
switch (p_event->type)
{
case NRF_802154_FAL_EVENT_TYPE_GENERIC:
{
if (NRF_PPI->CH[(uint32_t)ppi_ch].TEP)
{
nrf_ppi_fork_endpoint_setup((nrf_ppi_channel_t)ppi_ch, task_addr);
}
else
{
nrf_ppi_channel_endpoint_setup((nrf_ppi_channel_t)ppi_ch,
p_event->event.generic.register_address,
task_addr);
}
nrf_ppi_channel_enable((nrf_ppi_channel_t)ppi_ch);
}
break;
case NRF_802154_FAL_EVENT_TYPE_TIMER:
{
assert(p_event->event.timer.compare_channel_mask);
uint32_t compare_channel;
uint32_t pdn_task_addr;
/* EN pin */
compare_channel = get_available_compare_channel(
p_event->event.timer.compare_channel_mask,
0);
nrf_ppi_channel_endpoint_setup((nrf_ppi_channel_t)ppi_ch,
(uint32_t)(&(p_event->event.timer.p_timer_instance->
EVENTS_COMPARE[compare_channel])),
task_addr);
nrf_ppi_channel_enable((nrf_ppi_channel_t)ppi_ch);
nrf_timer_cc_write(p_event->event.timer.p_timer_instance,
(nrf_timer_cc_channel_t)compare_channel,
p_event->event.timer.counter_value - time_delay);
/* PDN pin */
if (m_nrf_fem_interface_config.pdn_pin_config.active_high)
{
pdn_task_addr =
(uint32_t)(&NRF_GPIOTE->TASKS_SET[m_nrf_fem_interface_config.pdn_pin_config.
gpiote_ch_id]);
}
else
{
pdn_task_addr =
(uint32_t)(&NRF_GPIOTE->TASKS_CLR[m_nrf_fem_interface_config.pdn_pin_config.
gpiote_ch_id]);
}
compare_channel = get_available_compare_channel(
p_event->event.timer.compare_channel_mask,
1);
nrf_ppi_channel_endpoint_setup(m_nrf_fem_interface_config.ppi_ch_id_pdn,
(uint32_t)(&(p_event->event.timer.p_timer_instance->
EVENTS_COMPARE[compare_channel])),
pdn_task_addr);
nrf_ppi_channel_enable(m_nrf_fem_interface_config.ppi_ch_id_pdn);
nrf_timer_cc_write(p_event->event.timer.p_timer_instance,
(nrf_timer_cc_channel_t)compare_channel,
p_event->event.timer.counter_value - time_delay -
m_nrf_fem_interface_config.fem_config.pdn_settle_us);
break;
}
default:
assert(false);
break;
}
return NRF_SUCCESS;
}
/** Deconfigure the event with the provided values. */
static int32_t event_configuration_clear(const nrf_802154_fal_event_t * const p_event,
bool activate)
{
uint8_t ppi_ch;
assert(p_event);
if (p_event->override_ppi)
{
ppi_ch = p_event->ppi_ch_id;
}
else
{
ppi_ch =
activate ? m_nrf_fem_interface_config.ppi_ch_id_set : m_nrf_fem_interface_config.
ppi_ch_id_clr;
}
nrf_ppi_channel_disable((nrf_ppi_channel_t)ppi_ch);
nrf_ppi_channel_endpoint_setup((nrf_ppi_channel_t)ppi_ch, 0, 0);
nrf_ppi_fork_endpoint_setup((nrf_ppi_channel_t)ppi_ch, 0);
switch (p_event->type)
{
case NRF_802154_FAL_EVENT_TYPE_GENERIC:
case NRF_802154_FAL_EVENT_TYPE_TIMER:
break;
default:
assert(false);
break;
}
return NRF_SUCCESS;
}
int32_t nrf_802154_fal_pa_configuration_set(const nrf_802154_fal_event_t * const p_activate_event,
const nrf_802154_fal_event_t * const p_deactivate_event)
{
int32_t ret_code;
if (!m_nrf_fem_interface_config.pa_pin_config.enable)
{
return NRF_ERROR_FORBIDDEN;
}
if (p_activate_event)
{
ret_code = event_configuration_set(p_activate_event,
&m_nrf_fem_interface_config.pa_pin_config,
true,
m_nrf_fem_interface_config.fem_config.pa_time_gap_us);
if (ret_code != NRF_SUCCESS)
{
return ret_code;
}
}
if (p_deactivate_event)
{
ret_code = event_configuration_set(p_deactivate_event,
&m_nrf_fem_interface_config.pa_pin_config,
false,
m_nrf_fem_interface_config.fem_config.pa_time_gap_us);
if (ret_code != NRF_SUCCESS)
{
return ret_code;
}
}
return NRF_SUCCESS;
}
int32_t nrf_802154_fal_lna_configuration_set(const nrf_802154_fal_event_t * const p_activate_event,
const nrf_802154_fal_event_t * const p_deactivate_event)
{
int32_t ret_code;
if (!m_nrf_fem_interface_config.lna_pin_config.enable)
{
return NRF_ERROR_FORBIDDEN;
}
if (p_activate_event)
{
ret_code = event_configuration_set(p_activate_event,
&m_nrf_fem_interface_config.lna_pin_config,
true,
m_nrf_fem_interface_config.fem_config.lna_time_gap_us);
if (ret_code != NRF_SUCCESS)
{
return ret_code;
}
}
if (p_deactivate_event)
{
ret_code = event_configuration_set(p_deactivate_event,
&m_nrf_fem_interface_config.lna_pin_config,
false,
m_nrf_fem_interface_config.fem_config.lna_time_gap_us);
if (ret_code != NRF_SUCCESS)
{
return ret_code;
}
}
return NRF_SUCCESS;
}
int32_t nrf_802154_fal_pa_configuration_clear(const nrf_802154_fal_event_t * const p_activate_event,
const nrf_802154_fal_event_t * const p_deactivate_event)
{
int32_t ret_code;
if (!m_nrf_fem_interface_config.pa_pin_config.enable)
{
return NRF_ERROR_FORBIDDEN;
}
if (p_activate_event)
{
ret_code = event_configuration_clear(p_activate_event, true);
if (ret_code != NRF_SUCCESS)
{
return ret_code;
}
}
if (p_deactivate_event)
{
ret_code = event_configuration_clear(p_deactivate_event, false);
if (ret_code != NRF_SUCCESS)
{
return ret_code;
}
}
return NRF_SUCCESS;
}
int32_t nrf_802154_fal_lna_configuration_clear(
const nrf_802154_fal_event_t * const p_activate_event,
const nrf_802154_fal_event_t * const p_deactivate_event)
{
int32_t ret_code;
if (!m_nrf_fem_interface_config.lna_pin_config.enable)
{
return NRF_ERROR_FORBIDDEN;
}
if (p_activate_event)
{
ret_code = event_configuration_clear(p_activate_event, true);
if (ret_code != NRF_SUCCESS)
{
return ret_code;
}
}
if (p_deactivate_event)
{
ret_code = event_configuration_clear(p_deactivate_event, false);
if (ret_code != NRF_SUCCESS)
{
return ret_code;
}
}
return NRF_SUCCESS;
}
void nrf_802154_fal_deactivate_now(nrf_fal_functionality_t type)
{
if (m_nrf_fem_interface_config.pa_pin_config.enable && (type & NRF_802154_FAL_PA))
{
if (m_nrf_fem_interface_config.pa_pin_config.active_high)
{
nrf_gpiote_task_force(m_nrf_fem_interface_config.pa_pin_config.gpiote_ch_id,
NRF_GPIOTE_INITIAL_VALUE_LOW);
}
else
{
nrf_gpiote_task_force(m_nrf_fem_interface_config.pa_pin_config.gpiote_ch_id,
NRF_GPIOTE_INITIAL_VALUE_HIGH);
}
}
if (m_nrf_fem_interface_config.lna_pin_config.enable && (type & NRF_802154_FAL_LNA))
{
if (m_nrf_fem_interface_config.lna_pin_config.active_high)
{
nrf_gpiote_task_force(m_nrf_fem_interface_config.lna_pin_config.gpiote_ch_id,
NRF_GPIOTE_INITIAL_VALUE_LOW);
}
else
{
nrf_gpiote_task_force(m_nrf_fem_interface_config.lna_pin_config.gpiote_ch_id,
NRF_GPIOTE_INITIAL_VALUE_HIGH);
}
}
}
int32_t nrf_fem_interface_configuration_set(nrf_fem_interface_config_t const * const p_config)
{
m_nrf_fem_interface_config = *p_config;
if (m_nrf_fem_interface_config.pa_pin_config.enable ||
m_nrf_fem_interface_config.lna_pin_config.enable)
{
gpiote_configure();
}
return NRF_SUCCESS;
}
int32_t nrf_fem_interface_configuration_get(nrf_fem_interface_config_t * p_config)
{
*p_config = m_nrf_fem_interface_config;
return NRF_SUCCESS;
}
void nrf_802154_fal_cleanup(void)
{
nrf_ppi_channel_disable((nrf_ppi_channel_t)m_nrf_fem_interface_config.ppi_ch_id_set);
nrf_ppi_channel_endpoint_setup((nrf_ppi_channel_t)m_nrf_fem_interface_config.ppi_ch_id_set, 0,
0);
nrf_ppi_fork_endpoint_setup((nrf_ppi_channel_t)m_nrf_fem_interface_config.ppi_ch_id_set, 0);
nrf_ppi_channel_disable((nrf_ppi_channel_t)m_nrf_fem_interface_config.ppi_ch_id_clr);
nrf_ppi_channel_endpoint_setup((nrf_ppi_channel_t)m_nrf_fem_interface_config.ppi_ch_id_clr, 0,
0);
nrf_ppi_fork_endpoint_setup((nrf_ppi_channel_t)m_nrf_fem_interface_config.ppi_ch_id_clr, 0);
if (m_ppi_channel_ext != PPI_INVALID_CHANNEL)
{
nrf_ppi_channel_disable((nrf_ppi_channel_t)m_ppi_channel_ext);
nrf_ppi_channel_endpoint_setup((nrf_ppi_channel_t)m_ppi_channel_ext, 0, 0);
nrf_ppi_fork_endpoint_setup((nrf_ppi_channel_t)m_ppi_channel_ext, 0);
m_ppi_channel_ext = PPI_INVALID_CHANNEL;
}
}
bool nrf_fem_prepare_powerdown(NRF_TIMER_Type * p_instance,
uint32_t compare_channel,
nrf_ppi_channel_t ppi_id)
{
uint32_t pdn_task_addr;
if (!m_nrf_fem_interface_config.pdn_pin_config.enable)
{
return false;
}
if (m_nrf_fem_interface_config.pdn_pin_config.active_high)
{
pdn_task_addr =
(uint32_t)(&NRF_GPIOTE->TASKS_CLR[m_nrf_fem_interface_config.pdn_pin_config.gpiote_ch_id
]);
}
else
{
pdn_task_addr =
(uint32_t)(&NRF_GPIOTE->TASKS_SET[m_nrf_fem_interface_config.pdn_pin_config.gpiote_ch_id
]);
}
nrf_timer_cc_write(p_instance,
compare_channel,
m_nrf_fem_interface_config.fem_config.trx_hold_us + 1);
nrf_ppi_channel_endpoint_setup(m_nrf_fem_interface_config.ppi_ch_id_pdn,
(uint32_t)(&(p_instance->EVENTS_COMPARE[compare_channel])),
pdn_task_addr);
uint32_t event_addr = (uint32_t)nrf_radio_event_address_get(NRF_RADIO_EVENT_DISABLED);
uint32_t task_addr = (uint32_t)nrf_timer_task_address_get(p_instance, NRF_TIMER_TASK_START);
nrf_timer_shorts_enable(p_instance, NRF_TIMER_SHORT_COMPARE0_STOP_MASK);
nrf_ppi_channel_endpoint_setup(ppi_id, event_addr, task_addr);
nrf_ppi_fork_endpoint_setup(ppi_id, 0);
nrf_ppi_channel_enable(ppi_id);
nrf_timer_event_clear(p_instance, NRF_TIMER_EVENT_COMPARE0);
return true;
}
#endif // ENABLE_FEM
@@ -43,7 +43,6 @@
#include "mac_features/nrf_802154_frame_parser.h"
#include "nrf_802154_config.h"
#include "nrf_802154_const.h"
#include "nrf_802154_types.h"
/// Maximum number of Short Addresses of nodes for which there is ACK data to set.
#define NUM_SHORT_ADDRESSES NRF_802154_PENDING_SHORT_ADDRESSES
@@ -91,8 +90,9 @@ typedef struct
} ie_arrays_t;
// TODO: Combine below arrays to perform binary search only once per Ack generation.
static pending_bit_arrays_t m_pending_bit;
static ie_arrays_t m_ie;
static pending_bit_arrays_t m_pending_bit;
static ie_arrays_t m_ie;
static nrf_802154_src_addr_match_t m_src_matching_method;
/***************************************************************************************************
* @section Array handling helper functions
@@ -321,6 +321,106 @@ static bool addr_index_find(const uint8_t * p_addr,
return addr_binary_search(p_addr, p_addr_array, p_location, data_type, extended);
}
/**
* @brief Thread implementation of the address matching algorithm.
*
* @param[in] p_frame Pointer to the frame for which the ACK frame is being prepared.
*
* @retval true Pending bit is to be set.
* @retval false Pending bit is to be cleared.
*/
static bool addr_match_thread(const uint8_t * p_frame)
{
bool extended;
uint32_t location;
const uint8_t * p_src_addr = nrf_802154_frame_parser_src_addr_get(p_frame, &extended);
// The pending bit is set by default.
if (!m_pending_bit.enabled || (NULL == p_src_addr))
{
return true;
}
return addr_index_find(p_src_addr, &location, NRF_802154_ACK_DATA_PENDING_BIT, extended);
}
/**
* @brief Zigbee implementation of the address matching algorithm.
*
* @param[in] p_frame Pointer to the frame for which the ACK frame is being prepared.
*
* @retval true Pending bit is to be set.
* @retval false Pending bit is to be cleared.
*/
static bool addr_match_zigbee(const uint8_t * p_frame)
{
uint8_t frame_type;
nrf_802154_frame_parser_mhr_data_t mhr_fields;
uint32_t location;
const uint8_t * p_cmd = p_frame;
bool ret = false;
// If ack data generator module is disabled do not perform check, return true by default.
if (!m_pending_bit.enabled)
{
return true;
}
// Check the frame type.
frame_type = (p_frame[FRAME_TYPE_OFFSET] & FRAME_TYPE_MASK);
// Parse the MAC header and retrieve the command type.
if (nrf_802154_frame_parser_mhr_parse(p_frame, &mhr_fields))
{
// Note: Security header is not included in the offset.
// If security is to be used at any point, additional calculation
// in nrf_802154_frame_parser_mhr_parse needs to be implemented.
p_cmd += mhr_fields.addressing_end_offset;
}
else
{
// If invalid source or destination addressing mode is detected, assume unknown device.
// Command type cannot be checked, as addressing_end_offset value will be invalid.
return true;
}
// Check frame type and command type.
if ((frame_type == FRAME_TYPE_COMMAND) && (*p_cmd == MAC_CMD_DATA_REQ))
{
// Check addressing type - in long case address, pb should always be 1.
if (mhr_fields.src_addr_size == SHORT_ADDRESS_SIZE)
{
// Return true if address is not found on the m_pending_bits list.
ret = !addr_index_find(mhr_fields.p_src_addr,
&location,
NRF_802154_ACK_DATA_PENDING_BIT,
false);
}
else
{
ret = true;
}
}
return ret;
}
/**
* @brief Standard-compliant implementation of the address matching algorithm.
*
* Function always returns true. It is IEEE 802.15.4 compliant, as per 6.7.3.
* Higher layer should ensure empty data frame with no AR is sent afterwards.
*
* @param[in] p_frame Pointer to the frame for which the ACK frame is being prepared.
*
* @retval true Pending bit is to be set.
*/
static bool addr_match_standard_compliant(const uint8_t * p_frame)
{
(void)p_frame;
return true;
}
/**
* @brief Add an address to the address list in ascending order.
*
@@ -491,6 +591,7 @@ void nrf_802154_ack_data_init(void)
memset(&m_ie, 0, sizeof(m_ie));
m_pending_bit.enabled = true;
m_src_matching_method = NRF_802154_SRC_ADDR_MATCH_THREAD;
}
void nrf_802154_ack_data_enable(bool enabled)
@@ -567,19 +668,45 @@ void nrf_802154_ack_data_reset(bool extended, uint8_t data_type)
}
}
bool nrf_802154_ack_data_pending_bit_should_be_set(const uint8_t * p_frame)
void nrf_802154_ack_data_src_addr_matching_method_set(nrf_802154_src_addr_match_t match_method)
{
bool extended;
uint32_t location;
const uint8_t * p_src_addr = nrf_802154_frame_parser_src_addr_get(p_frame, &extended);
// The pending bit is set by default.
if (!m_pending_bit.enabled || NULL == p_src_addr)
switch (match_method)
{
return true;
case NRF_802154_SRC_ADDR_MATCH_THREAD:
case NRF_802154_SRC_ADDR_MATCH_ZIGBEE:
case NRF_802154_SRC_ADDR_MATCH_ALWAYS_1:
m_src_matching_method = match_method;
break;
default:
assert(false);
}
return addr_index_find(p_src_addr, &location, NRF_802154_ACK_DATA_PENDING_BIT, extended);
}
bool nrf_802154_ack_data_pending_bit_should_be_set(const uint8_t * p_frame)
{
bool ret;
switch (m_src_matching_method)
{
case NRF_802154_SRC_ADDR_MATCH_THREAD:
ret = addr_match_thread(p_frame);
break;
case NRF_802154_SRC_ADDR_MATCH_ZIGBEE:
ret = addr_match_zigbee(p_frame);
break;
case NRF_802154_SRC_ADDR_MATCH_ALWAYS_1:
ret = addr_match_standard_compliant(p_frame);
break;
default:
assert(false);
}
return ret;
}
const uint8_t * nrf_802154_ack_data_ie_get(const uint8_t * p_src_addr,
@@ -40,6 +40,8 @@
#include <stdbool.h>
#include <stdint.h>
#include "nrf_802154_types.h"
/**
* @brief Initializes the ACK data generator module.
*/
@@ -99,6 +101,19 @@ bool nrf_802154_ack_data_for_addr_clear(const uint8_t * p_addr, bool extended, u
*/
void nrf_802154_ack_data_reset(bool extended, uint8_t data_type);
/**
* @brief Select the source matching algorithm.
*
* @note This function is to be called after the driver initialization, but before the transceiver is enabled.
*
* When calling @ref nrf_802154_ack_data_pending_bit_should_be_set, one of several algorithms
* for source address matching will be chosen. To ensure a specific algorithm is selected,
* call this function before @ref rf_802154_ack_data_pending_bit_should_be_set.
*
* @param[in] match_method Source matching method to be used.
*/
void nrf_802154_ack_data_src_addr_matching_method_set(nrf_802154_src_addr_match_t match_method);
/**
* @brief Checks if a pending bit is to be set in the ACK frame sent in response to a given frame.
*
+42 -6
View File
@@ -51,7 +51,6 @@
#include "nrf_802154_pib.h"
#include "nrf_802154_priority_drop.h"
#include "nrf_802154_request.h"
#include "nrf_802154_revision.h"
#include "nrf_802154_rssi.h"
#include "nrf_802154_rx_buffer.h"
#include "nrf_802154_timer_coord.h"
@@ -70,7 +69,7 @@
#include "mac_features/ack_generator/nrf_802154_ack_data.h"
#if ENABLE_FEM
#include "fem/nrf_fem_control_api.h"
#include "fem/nrf_fem_protocol_api.h"
#endif
#define RAW_LENGTH_OFFSET 0
@@ -214,7 +213,6 @@ void nrf_802154_init(void)
nrf_802154_priority_drop_init();
nrf_802154_random_init();
nrf_802154_request_init();
nrf_802154_revision_init();
nrf_802154_rsch_crit_sect_init();
nrf_802154_rsch_init();
nrf_802154_rx_buffer_init();
@@ -244,14 +242,47 @@ void nrf_802154_radio_irq_handler(void)
#endif // !NRF_802154_INTERNAL_RADIO_IRQ_HANDLING
#if ENABLE_FEM
void nrf_802154_fem_control_cfg_set(const nrf_802154_fem_control_cfg_t * p_cfg)
void nrf_802154_fem_control_cfg_set(nrf_802154_fem_control_cfg_t const * const p_cfg)
{
nrf_fem_control_cfg_set(p_cfg);
nrf_fem_interface_config_t config;
nrf_fem_interface_configuration_get(&config);
config.lna_pin_config.active_high = p_cfg->lna_cfg.active_high;
config.lna_pin_config.enable = p_cfg->lna_cfg.enable;
config.lna_pin_config.gpio_pin = p_cfg->lna_cfg.gpio_pin;
config.lna_pin_config.gpiote_ch_id = p_cfg->lna_gpiote_ch_id;
config.pa_pin_config.active_high = p_cfg->pa_cfg.active_high;
config.pa_pin_config.enable = p_cfg->pa_cfg.enable;
config.pa_pin_config.gpio_pin = p_cfg->pa_cfg.gpio_pin;
config.pa_pin_config.gpiote_ch_id = p_cfg->pa_gpiote_ch_id;
config.ppi_ch_id_set = p_cfg->ppi_ch_id_set;
config.ppi_ch_id_clr = p_cfg->ppi_ch_id_clr;
nrf_fem_interface_configuration_set(&config);
}
void nrf_802154_fem_control_cfg_get(nrf_802154_fem_control_cfg_t * p_cfg)
{
nrf_fem_control_cfg_get(p_cfg);
nrf_fem_interface_config_t config;
nrf_fem_interface_configuration_get(&config);
p_cfg->lna_cfg.active_high = config.lna_pin_config.active_high;
p_cfg->lna_cfg.enable = config.lna_pin_config.enable;
p_cfg->lna_cfg.gpio_pin = config.lna_pin_config.gpio_pin;
p_cfg->pa_cfg.active_high = config.pa_pin_config.active_high;
p_cfg->pa_cfg.enable = config.pa_pin_config.enable;
p_cfg->pa_cfg.gpio_pin = config.pa_pin_config.gpio_pin;
p_cfg->lna_gpiote_ch_id = config.lna_pin_config.gpiote_ch_id;
p_cfg->pa_gpiote_ch_id = config.pa_pin_config.gpiote_ch_id;
p_cfg->ppi_ch_id_clr = config.ppi_ch_id_clr;
p_cfg->ppi_ch_id_set = config.ppi_ch_id_set;
}
#endif // ENABLE_FEM
@@ -574,6 +605,11 @@ void nrf_802154_pan_coord_set(bool enabled)
nrf_802154_pib_pan_coord_set(enabled);
}
void nrf_802154_src_addr_matching_method_set(nrf_802154_src_addr_match_t match_method)
{
nrf_802154_ack_data_src_addr_matching_method_set(match_method);
}
bool nrf_802154_ack_data_set(const uint8_t * p_addr,
bool extended,
const void * p_data,
+73 -6
View File
@@ -43,8 +43,10 @@
#include "nrf_802154_config.h"
#include "nrf_802154_types.h"
#include "nrf_ppi.h"
#if ENABLE_FEM
#include "fem/nrf_fem_control_api.h"
#include "fem/nrf_fem_protocol_api.h"
#endif
#ifdef __cplusplus
@@ -151,16 +153,22 @@ typedef nrf_fem_control_cfg_t nrf_802154_fem_control_cfg_t;
*
* @note This function must not be called when the radio is in use.
*
* @note This function is deprecated. Only to be used with Skyworks module.
* Consider using nrf_fem_interface_configuration_set instead.
*
* @param[in] p_cfg Pointer to the PA & LNA GPIO toggle configuration.
*
*/
void nrf_802154_fem_control_cfg_set(const nrf_802154_fem_control_cfg_t * p_cfg);
void nrf_802154_fem_control_cfg_set(nrf_802154_fem_control_cfg_t const * const p_cfg);
/**
* @brief Get the PA & LNA GPIO toggle configuration.
*
* @param[out] p_cfg Pointer to the structure for the PA & LNA GPIO toggle configuration.
*
* @note This function is deprecated. Only to be used with Skyworks module.
* Consider using nrf_fem_interface_configuration_get instead.
*
*/
void nrf_802154_fem_control_cfg_get(nrf_802154_fem_control_cfg_t * p_cfg);
@@ -994,7 +1002,30 @@ void nrf_802154_pan_coord_set(bool enabled);
bool nrf_802154_pan_coord_get(void);
/**
* @brief Adds the address of a peer node for which the provided ACK data is to be set.
* @brief Select the source matching algorithm.
*
* @note This method should be called after driver initialization, but before transceiver is enabled.
*
* When calling @ref nrf_802154_ack_data_pending_bit_should_be_set, one of several algorithms
* for source address matching will be chosen. To ensure a specific algorithm is selected,
* call this function before @ref rf_802154_ack_data_pending_bit_should_be_set.
*
* @param[in] match_method Source address matching method to be used.
*/
void nrf_802154_src_addr_matching_method_set(nrf_802154_src_addr_match_t match_method);
/**
* @brief Adds the address of a peer node for which the provided ACK data
* is to be added to the pending bit list.
*
* The pending bit list works differently, depending on the upper layer for which the source
* address matching method is selected:
* - For Thread, @ref NRF_802154_SRC_ADDR_MATCH_THREAD
* - For Zigbee, @ref NRF_802154_SRC_ADDR_MATCH_ZIGBEE
* - For Standard-compliant, @ref NRF_802154_SRC_ADDR_MATCH_ALWAYS_1
* For more information, see @ref nrf_802154_src_addr_match_t.
*
* The method can be set during initialization phase by calling @ref nrf_802154_src_matching_method.
*
* @param[in] p_addr Array of bytes containing the address of the node (little-endian).
* @param[in] extended If the given address is an extended MAC address or a short MAC address.
@@ -1012,10 +1043,19 @@ bool nrf_802154_ack_data_set(const uint8_t * p_addr,
uint8_t data_type);
/**
* @brief Removes the address of a peer node for which the ACK data is set.
* @brief Removes the address of a peer node for which the ACK data is set from the pending bit list.
*
* The ACK data that was previously set for the given address is automatically removed.
*
* The pending bit list works differently, depending on the upper layer for which the source
* address matching method is selected:
* - For Thread, @ref NRF_802154_SRC_ADDR_MATCH_THREAD
* - For Zigbee, @ref NRF_802154_SRC_ADDR_MATCH_ZIGBEE
* - For Standard-compliant, @ref NRF_802154_SRC_ADDR_MATCH_ALWAYS_1
* For more information, see @ref nrf_802154_src_addr_match_t.
*
* The method can be set during initialization phase by calling @ref nrf_802154_src_matching_method.
*
* @param[in] p_addr Array of bytes containing the address of the node (little-endian).
* @param[in] extended If the given address is an extended MAC address or a short MAC address.
* @param[in] data_type Type of data to be removed. Refer to the @ref nrf_802154_ack_data_t type.
@@ -1047,7 +1087,16 @@ bool nrf_802154_ack_data_clear(const uint8_t * p_addr, bool extended, uint8_t da
void nrf_802154_auto_pending_bit_set(bool enabled);
/**
* @brief Adds address of a peer node for which there is pending data in the buffer.
* @brief Adds the address of a peer node to the pending bit list.
*
* The pending bit list works differently, depending on the upper layer for which the source
* address matching method is selected:
* - For Thread, @ref NRF_802154_SRC_ADDR_MATCH_THREAD
* - For Zigbee, @ref NRF_802154_SRC_ADDR_MATCH_ZIGBEE
* - For Standard-compliant, @ref NRF_802154_SRC_ADDR_MATCH_ALWAYS_1
* For more information, see @ref nrf_802154_src_addr_match_t.
*
* The method can be set during initialization phase by calling @ref nrf_802154_src_matching_method.
*
* @note This function makes a copy of the given address.
*
@@ -1060,7 +1109,16 @@ void nrf_802154_auto_pending_bit_set(bool enabled);
bool nrf_802154_pending_bit_for_addr_set(const uint8_t * p_addr, bool extended);
/**
* @brief Removes address of a peer node for which there is no more pending data in the buffer.
* @brief Removes address of a peer node from the pending bit list.
*
* The pending bit list works differently, depending on the upper layer for which the source
* address matching method is selected:
* - For Thread, @ref NRF_802154_SRC_ADDR_MATCH_THREAD
* - For Zigbee, @ref NRF_802154_SRC_ADDR_MATCH_ZIGBEE
* - For Standard-compliant, @ref NRF_802154_SRC_ADDR_MATCH_ALWAYS_1
* For more information, see @ref nrf_802154_src_addr_match_t.
*
* The method can be set during initialization phase by calling @ref nrf_802154_src_matching_method.
*
* @param[in] p_addr Array of bytes containing the address of the node (little-endian).
* @param[in] extended If the given address is an extended MAC address or a short MAC address.
@@ -1073,6 +1131,15 @@ bool nrf_802154_pending_bit_for_addr_clear(const uint8_t * p_addr, bool extended
/**
* @brief Removes all addresses of a given type from the pending bit list.
*
* The pending bit list works differently, depending on the upper layer for which the source
* address matching method is selected:
* - For Thread, @ref NRF_802154_SRC_ADDR_MATCH_THREAD
* - For Zigbee, @ref NRF_802154_SRC_ADDR_MATCH_ZIGBEE
* - For Standard-compliant, @ref NRF_802154_SRC_ADDR_MATCH_ALWAYS_1
* For more information, see @ref nrf_802154_src_addr_match_t.
*
* The method can be set during initialization phase by calling @ref nrf_802154_src_matching_method.
*
* @param[in] extended If the function is to remove all extended MAC addresses or all short
* addresses.
*/
@@ -124,71 +124,6 @@ extern "C" {
#define NRF_802154_IRQ_PRIORITY 0
#endif
/**
* @def NRF_802154_TIMER_INSTANCE
*
* The timer instance used both by the driver for ACK IFS and by the FEM module.
*
*/
#ifndef NRF_802154_TIMER_INSTANCE
#define NRF_802154_TIMER_INSTANCE NRF_TIMER1
#endif
/**
* @def NRF_802154_COUNTER_TIMER_INSTANCE
*
* The timer instance used by the driver for detecting when PSDU is being received.
*
* @note This configuration is used only when the NRF_RADIO_EVENT_BCMATCH event handling is disabled
* (see @ref NRF_802154_DISABLE_BCC_MATCHING).
*/
#ifndef NRF_802154_COUNTER_TIMER_INSTANCE
#define NRF_802154_COUNTER_TIMER_INSTANCE NRF_TIMER2
#endif
/**
* @def NRF_802154_SWI_EGU_INSTANCE
*
* The SWI EGU instance used by the driver to synchronize PPIs and for requests and notifications if
* SWI is in use.
*
* @note This option is used by the core module regardless of the driver configuration.
*
*/
#ifndef NRF_802154_SWI_EGU_INSTANCE
#ifdef NRF52811_XXAA
#define NRF_802154_SWI_EGU_INSTANCE NRF_EGU0
#else
#define NRF_802154_SWI_EGU_INSTANCE NRF_EGU3
#endif
#endif
/**
* @def NRF_802154_SWI_IRQ_HANDLER
*
* The SWI EGU IRQ handler used by the driver for requests and notifications if SWI is in use.
*
* @note This option is used when the driver uses SWI to process requests and notifications.
*
*/
#ifndef NRF_802154_SWI_IRQ_HANDLER
#define NRF_802154_SWI_IRQ_HANDLER SWI3_EGU3_IRQHandler
#endif
/**
* @def NRF_802154_SWI_IRQN
*
* The SWI EGU IRQ number used by the driver for requests and notifications if SWI is in use.
*
* @note This option is used when the driver uses SWI to process requests and notifications.
*
*/
#ifndef NRF_802154_SWI_IRQN
#define NRF_802154_SWI_IRQN SWI3_EGU3_IRQn
#endif
/**
* @def NRF_802154_SWI_PRIORITY
*
@@ -270,7 +205,7 @@ extern "C" {
* @def NRF_802154_FRAME_TIMESTAMP_ENABLED
*
* If timestamps are to be added to the frames received.
* Enabling this feature enables the functions @ref nrf_802154_received_timsestamp_raw,
* Enabling this feature enables the functions @ref nrf_802154_received_timestamp_raw,
* @ref nrf_802154_received_timestamp, @ref nrf_802154_transmitted_timestamp_raw, and
* @ref nrf_802154_transmitted_timestamp, which add timestamps to the frames received.
*
@@ -340,63 +275,6 @@ extern "C" {
#define NRF_802154_RTC_IRQ_PRIORITY 6
#endif
/**
* @def NRF_802154_RTC_INSTANCE
*
* The RTC instance used in the standalone timer driver implementation.
*
* @note This configuration is only applicable for the Low Power Timer Abstraction Layer
* implementation in nrf_802154_lp_timer_nodrv.c.
*
*/
#ifndef NRF_802154_RTC_INSTANCE
#ifdef NRF52811_XXAA
#define NRF_802154_RTC_INSTANCE NRF_RTC0
#else
#define NRF_802154_RTC_INSTANCE NRF_RTC2
#endif
#endif
/**
* @def NRF_802154_RTC_IRQ_HANDLER
*
* The RTC interrupt handler name used in the standalone timer driver implementation.
*
* @note This configuration is only applicable for Low Power Timer Abstraction Layer implementation
* in nrf_802154_lp_timer_nodrv.c.
*
*/
#ifndef NRF_802154_RTC_IRQ_HANDLER
#ifdef NRF52811_XXAA
#define NRF_802154_RTC_IRQ_HANDLER RTC0_IRQHandler
#else
#define NRF_802154_RTC_IRQ_HANDLER RTC2_IRQHandler
#endif
#endif
/**
* @def NRF_802154_RTC_IRQN
*
* The RTC Interrupt number used in the standalone timer driver implementation.
*
* @note This configuration is only applicable for the Low Power Timer Abstraction Layer implementation
* in nrf_802154_lp_timer_nodrv.c.
*
*/
#ifndef NRF_802154_RTC_IRQN
#ifdef NRF52811_XXAA
#define NRF_802154_RTC_IRQN RTC0_IRQn
#else
#define NRF_802154_RTC_IRQN RTC2_IRQn
#endif
#endif
/**
* @}
* @defgroup nrf_802154_config_csma CSMA/CA procedure configuration
@@ -88,6 +88,16 @@
#define KEY_ID_MODE_2 0x10 ///< Bits containing the 0x10 Key Identifier Mode.
#define KEY_ID_MODE_3 0x18 ///< Bits containing the 0x11 Key Identifier Mode.
#define MAC_CMD_ASSOC_REQ 0x01 ///< Command frame identifier for MAC Association request.
#define MAC_CMD_ASSOC_RESP 0x02 ///< Command frame identifier for MAC Association response.
#define MAC_CMD_DISASSOC_NOTIFY 0x03 ///< Command frame identifier for MAC Disaccociation notification.
#define MAC_CMD_DATA_REQ 0x04 ///< Command frame identifier for MAC Data Requests.
#define MAC_CMD_PANID_CONFLICT 0x05 ///< Command frame identifier for MAC PAN ID conflict notification.
#define MAC_CMD_ORPHAN_NOTIFY 0x06 ///< Command frame identifier for MAC Orphan notification.
#define MAC_CMD_BEACON_REQ 0x07 ///< Command frame identifier for MAC Beacon.
#define MAC_CMD_COORD_REALIGN 0x08 ///< Command frame identifier for MAC Coordinator realignment.
#define MAC_CMD_GTS_REQUEST 0x09 ///< Command frame identifier for MAC GTS request.
#define PAN_ID_COMPR_OFFSET 1 ///< Byte containing the PAN ID compression bit (+1 for the frame length byte).
#define PAN_ID_COMPR_MASK 0x40 ///< PAN ID compression bit.
+280 -177
View File
@@ -47,9 +47,9 @@
#include "nrf_802154_critical_section.h"
#include "nrf_802154_debug.h"
#include "nrf_802154_notification.h"
#include "nrf_802154_peripherals.h"
#include "nrf_802154_pib.h"
#include "nrf_802154_procedures_duration.h"
#include "nrf_802154_revision.h"
#include "nrf_802154_rssi.h"
#include "nrf_802154_rx_buffer.h"
#include "nrf_802154_utils.h"
@@ -57,10 +57,11 @@
#include "nrf_802154_types.h"
#include "nrf_802154_utils.h"
#include "nrf_egu.h"
#include "nrf_error.h"
#include "nrf_ppi.h"
#include "nrf_radio.h"
#include "nrf_timer.h"
#include "fem/nrf_fem_control_api.h"
#include "fem/nrf_fem_protocol_api.h"
#include "mac_features/nrf_802154_delayed_trx.h"
#include "mac_features/nrf_802154_filter.h"
#include "mac_features/nrf_802154_frame_parser.h"
@@ -73,40 +74,22 @@
#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 PPI_CHGRP0 NRF_802154_PPI_CORE_GROUP ///< 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 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 NRF_802154_PPI_RADIO_DISABLED_TO_EGU ///< PPI that connects RADIO DISABLED event with EGU task
#define PPI_EGU_RAMP_UP NRF_802154_PPI_EGU_TO_RADIO_RAMP_UP ///< PPI that connects EGU event with RADIO TXEN or RXEN task
#define PPI_EGU_TIMER_START NRF_802154_PPI_EGU_TO_TIMER_START ///< PPI that connects EGU event with TIMER START task
#define PPI_CRCERROR_CLEAR NRF_802154_PPI_RADIO_CRCERROR_TO_TIMER_CLEAR ///< PPI that connects RADIO CRCERROR event with TIMER CLEAR task
#define PPI_CCAIDLE_FEM NRF_802154_PPI_RADIO_CCAIDLE_TO_FEM_GPIOTE ///< PPI that connects RADIO CCAIDLE event with GPIOTE tasks used by FEM
#define PPI_TIMER_TX_ACK NRF_802154_PPI_TIMER_COMPARE_TO_RADIO_TXEN ///< PPI that connects TIMER COMPARE event with RADIO TXEN task
#define PPI_CRCOK_DIS_PPI NRF_802154_PPI_RADIO_CRCOK_TO_PPI_GRP_DISABLE ///< 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
#define PPI_ADDRESS_COUNTER_COUNT NRF_802154_PPI_RADIO_ADDR_TO_COUNTER_COUNT ///< PPI that connects RADIO ADDRESS event with TIMER COUNT task
#define PPI_CRCERROR_COUNTER_CLEAR NRF_802154_PPI_RADIO_CRCERROR_COUNTER_CLEAR ///< 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)
{
if (nrf_802154_revision_has_phyend_event())
{
return NRF_RADIO_SHORT_PHYEND_DISABLE_MASK;
}
return NRF_RADIO_SHORT_END_DISABLE_MASK;
}
#if NRF_802154_DISABLE_BCC_MATCHING
#define SHORT_ADDRESS_BCSTART 0UL
#else // NRF_802154_DISABLE_BCC_MATCHING
@@ -124,16 +107,16 @@ static inline uint32_t short_phyend_disable_mask_get(void)
#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())
NRF_RADIO_SHORT_PHYEND_DISABLE_MASK)
#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())
NRF_RADIO_SHORT_PHYEND_DISABLE_MASK)
#define SHORTS_TX (NRF_RADIO_SHORT_TXREADY_START_MASK | \
short_phyend_disable_mask_get())
NRF_RADIO_SHORT_PHYEND_DISABLE_MASK)
#define SHORTS_RX_ACK (NRF_RADIO_SHORT_ADDRESS_RSSISTART_MASK | \
NRF_RADIO_SHORT_END_DISABLE_MASK)
@@ -189,6 +172,47 @@ static uint8_t m_ed_result; ///< Result of the current energy detecti
static volatile radio_state_t m_state; ///< State of the radio driver.
/// Common parameters for the FAL handling.
static const nrf_802154_fal_event_t m_deactivate_on_disable =
{
.type = NRF_802154_FAL_EVENT_TYPE_GENERIC,
.override_ppi = false,
.event.generic.register_address =
((uint32_t)NRF_RADIO_BASE + (uint32_t)NRF_RADIO_EVENT_DISABLED)
};
static const nrf_802154_fal_event_t m_activate_rx_cc0 =
{
.type = NRF_802154_FAL_EVENT_TYPE_TIMER,
.override_ppi = false,
.event.timer =
{
.p_timer_instance = NRF_802154_TIMER_INSTANCE,
.counter_value = RX_RAMP_UP_TIME,
.compare_channel_mask = ((1 << NRF_TIMER_CC_CHANNEL0) | (1 << NRF_TIMER_CC_CHANNEL2)),
},
};
static const nrf_802154_fal_event_t m_activate_tx_cc0 =
{
.type = NRF_802154_FAL_EVENT_TYPE_TIMER,
.override_ppi = false,
.event.timer =
{
.p_timer_instance = NRF_802154_TIMER_INSTANCE,
.counter_value = TX_RAMP_UP_TIME,
.compare_channel_mask = ((1 << NRF_TIMER_CC_CHANNEL0) | (1 << NRF_TIMER_CC_CHANNEL2)),
},
};
static const nrf_802154_fal_event_t m_ccaidle =
{
.type = NRF_802154_FAL_EVENT_TYPE_GENERIC,
.override_ppi = true,
.ppi_ch_id = PPI_CCAIDLE_FEM,
.event.generic.register_address = ((uint32_t)NRF_RADIO_BASE + (uint32_t)NRF_RADIO_EVENT_CCAIDLE)
};
typedef struct
{
bool frame_filtered : 1; ///< If frame being received passed filtering operation.
@@ -784,96 +808,126 @@ static void ppis_for_egu_and_ramp_up_set(nrf_radio_task_t ramp_up_task, bool sel
}
/** Configure FEM to set LNA at appropriate time. */
static void fem_for_lna_set(nrf_timer_cc_channel_t cc_channel,
nrf_timer_short_mask_t short_mask)
static void fem_for_lna_set(void)
{
nrf_fem_control_ppi_enable(NRF_FEM_CONTROL_LNA_PIN, cc_channel);
nrf_fem_control_timer_set(NRF_FEM_CONTROL_LNA_PIN, cc_channel, short_mask);
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),
(uint32_t)nrf_timer_task_address_get(
NRF_802154_TIMER_INSTANCE,
NRF_TIMER_TASK_START));
if (nrf_802154_fal_lna_configuration_set(&m_activate_rx_cc0, NULL) == NRF_SUCCESS)
{
uint32_t event_addr = (uint32_t)nrf_egu_event_address_get(NRF_802154_SWI_EGU_INSTANCE,
EGU_EVENT);
uint32_t task_addr = (uint32_t)nrf_timer_task_address_get(NRF_802154_TIMER_INSTANCE,
NRF_TIMER_TASK_START);
nrf_timer_shorts_enable(m_activate_rx_cc0.event.timer.p_timer_instance,
NRF_TIMER_SHORT_COMPARE0_STOP_MASK);
nrf_ppi_channel_endpoint_setup(PPI_EGU_TIMER_START, event_addr, task_addr);
nrf_ppi_channel_enable(PPI_EGU_TIMER_START);
}
}
/** Reset FEM configuration for LNA.
*
* @param[in] timer_short_mask Mask of shorts that should be disabled on FEM timer.
*/
static void fem_for_lna_reset(nrf_timer_short_mask_t timer_short_mask)
static void fem_for_lna_reset(void)
{
nrf_fem_control_ppi_disable(NRF_FEM_CONTROL_LNA_PIN);
nrf_fem_control_timer_reset(NRF_FEM_CONTROL_LNA_PIN, timer_short_mask);
nrf_802154_fal_lna_configuration_clear(&m_activate_rx_cc0, NULL);
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_ppi_channel_disable(PPI_EGU_TIMER_START);
}
/** Configure FEM to set PA at appropriate time. */
static void fem_for_pa_set(void)
{
nrf_fem_control_ppi_enable(NRF_FEM_CONTROL_PA_PIN, NRF_TIMER_CC_CHANNEL2);
nrf_fem_control_timer_set(NRF_FEM_CONTROL_PA_PIN,
NRF_TIMER_CC_CHANNEL2,
NRF_TIMER_SHORT_COMPARE2_STOP_MASK);
nrf_fem_control_ppi_fork_setup(NRF_FEM_CONTROL_PA_PIN,
PPI_EGU_RAMP_UP,
(uint32_t)nrf_timer_task_address_get(
NRF_802154_TIMER_INSTANCE,
NRF_TIMER_TASK_START));
if (nrf_802154_fal_pa_configuration_set(&m_activate_tx_cc0, NULL) == NRF_SUCCESS)
{
uint32_t event_addr = (uint32_t)nrf_egu_event_address_get(NRF_802154_SWI_EGU_INSTANCE,
EGU_EVENT);
uint32_t task_addr = (uint32_t)nrf_timer_task_address_get(NRF_802154_TIMER_INSTANCE,
NRF_TIMER_TASK_START);
nrf_timer_shorts_enable(m_activate_tx_cc0.event.timer.p_timer_instance,
NRF_TIMER_SHORT_COMPARE0_STOP_MASK);
nrf_ppi_channel_endpoint_setup(PPI_EGU_TIMER_START, event_addr, task_addr);
nrf_ppi_channel_enable(PPI_EGU_TIMER_START);
}
}
/** Reset FEM configuration for PA. */
static void fem_for_pa_reset(void)
{
nrf_fem_control_ppi_disable(NRF_FEM_CONTROL_PA_PIN);
nrf_fem_control_timer_reset(NRF_FEM_CONTROL_PA_PIN, NRF_TIMER_SHORT_COMPARE2_STOP_MASK);
nrf_fem_control_ppi_fork_clear(NRF_FEM_CONTROL_PA_PIN, PPI_EGU_RAMP_UP);
nrf_802154_fal_pa_configuration_clear(&m_activate_tx_cc0, NULL);
nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_SHUTDOWN);
nrf_ppi_channel_disable(PPI_EGU_TIMER_START);
nrf_802154_fal_deactivate_now(NRF_802154_FAL_PA);
}
/** Configure FEM for TX procedure. */
static void fem_for_tx_set(bool cca)
{
bool success;
if (cca)
{
nrf_fem_control_ppi_enable(NRF_FEM_CONTROL_LNA_PIN, NRF_TIMER_CC_CHANNEL0);
nrf_fem_control_timer_set(NRF_FEM_CONTROL_LNA_PIN,
NRF_TIMER_CC_CHANNEL0,
NRF_TIMER_SHORT_COMPARE0_STOP_MASK);
nrf_fem_control_ppi_pin_task_setup(PPI_CCAIDLE_FEM,
(uint32_t)nrf_radio_event_address_get(
NRF_RADIO_EVENT_CCAIDLE),
false,
true);
bool pa_set = false;
bool lna_set = false;
if (nrf_802154_fal_lna_configuration_set(&m_activate_rx_cc0, &m_ccaidle) == NRF_SUCCESS)
{
lna_set = true;
}
if (nrf_802154_fal_pa_configuration_set(&m_ccaidle, NULL) == NRF_SUCCESS)
{
pa_set = true;
}
success = pa_set || lna_set;
}
else
{
nrf_fem_control_ppi_enable(NRF_FEM_CONTROL_PA_PIN, NRF_TIMER_CC_CHANNEL1);
nrf_fem_control_timer_set(NRF_FEM_CONTROL_PA_PIN,
NRF_TIMER_CC_CHANNEL1,
NRF_TIMER_SHORT_COMPARE1_STOP_MASK);
success = (nrf_802154_fal_pa_configuration_set(&m_activate_tx_cc0, NULL) == NRF_SUCCESS);
}
nrf_fem_control_ppi_task_setup(NRF_FEM_CONTROL_ANY_PIN,
PPI_EGU_TIMER_START,
(uint32_t)nrf_egu_event_address_get(
NRF_802154_SWI_EGU_INSTANCE,
EGU_EVENT),
(uint32_t)nrf_timer_task_address_get(
NRF_802154_TIMER_INSTANCE,
NRF_TIMER_TASK_START));
if (success)
{
nrf_timer_shorts_enable(NRF_802154_TIMER_INSTANCE, NRF_TIMER_SHORT_COMPARE0_STOP_MASK);
uint32_t egu_event_addr = (uint32_t)nrf_egu_event_address_get(NRF_802154_SWI_EGU_INSTANCE,
EGU_EVENT);
uint32_t timer_task_addr = (uint32_t)nrf_timer_task_address_get(NRF_802154_TIMER_INSTANCE,
NRF_TIMER_TASK_START);
nrf_ppi_channel_endpoint_setup(PPI_EGU_TIMER_START, egu_event_addr, timer_task_addr);
nrf_ppi_channel_enable(PPI_EGU_TIMER_START);
}
}
/** Reset FEM for TX procedure. */
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_fem_control_ppi_fork_clear(NRF_FEM_CONTROL_ANY_PIN, PPI_CCAIDLE_FEM);
nrf_ppi_channel_disable(PPI_CCAIDLE_FEM);
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_COMPARE1_STOP_MASK);
switch (m_state)
{
case RADIO_STATE_CCA_TX:
nrf_802154_fal_pa_configuration_clear(&m_activate_rx_cc0, &m_ccaidle);
break;
case RADIO_STATE_TX:
nrf_802154_fal_pa_configuration_clear(&m_activate_tx_cc0, NULL);
break;
default:
assert(false);
break;
}
nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_SHUTDOWN);
if (disable_ppi_egu_timer_start)
{
@@ -990,8 +1044,9 @@ static void rx_terminate(void)
nrf_ppi_channel_disable(PPI_CRCERROR_COUNTER_CLEAR);
#endif // NRF_802154_DISABLE_BCC_MATCHING
nrf_fem_control_ppi_disable(NRF_FEM_CONTROL_LNA_PIN);
// Disable LNA
nrf_802154_fal_lna_configuration_clear(&m_activate_rx_cc0, NULL);
nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_SHUTDOWN);
nrf_ppi_channel_remove_from_group(PPI_EGU_RAMP_UP, PPI_CHGRP0);
#if NRF_802154_DISABLE_BCC_MATCHING
@@ -1003,8 +1058,7 @@ static void rx_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_SHORT_COMPARE0_STOP_MASK);
#if NRF_802154_DISABLE_BCC_MATCHING
// Anomaly 78: use SHUTDOWN instead of STOP and CLEAR.
@@ -1023,7 +1077,21 @@ static void rx_terminate(void)
ints_to_disable |= NRF_RADIO_INT_CRCOK_MASK;
nrf_radio_int_disable(ints_to_disable);
nrf_radio_shorts_set(SHORTS_IDLE);
bool shutdown = nrf_fem_prepare_powerdown(NRF_802154_TIMER_INSTANCE,
NRF_TIMER_CC_CHANNEL0,
PPI_EGU_TIMER_START);
nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE);
if (shutdown)
{
while (!nrf_timer_event_check(NRF_802154_TIMER_INSTANCE, NRF_TIMER_EVENT_COMPARE0))
{
// Wait until the event is set.
}
nrf_timer_shorts_disable(NRF_802154_TIMER_INSTANCE, NRF_TIMER_SHORT_COMPARE0_STOP_MASK);
nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_SHUTDOWN);
nrf_ppi_channel_disable(PPI_EGU_TIMER_START);
}
}
}
@@ -1040,7 +1108,9 @@ static void tx_ack_terminate(void)
nrf_ppi_channel_disable(PPI_CRCOK_DIS_PPI);
#endif // NRF_802154_DISABLE_BCC_MATCHING
nrf_fem_control_ppi_disable(NRF_FEM_CONTROL_PA_PIN);
// Disable PA
nrf_802154_fal_pa_configuration_clear(&m_activate_tx_cc0, NULL);
nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_SHUTDOWN);
nrf_ppi_channel_remove_from_group(PPI_EGU_RAMP_UP, PPI_CHGRP0);
#if !NRF_802154_DISABLE_BCC_MATCHING
@@ -1050,8 +1120,7 @@ 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_SHORT_COMPARE0_STOP_MASK);
#if NRF_802154_DISABLE_BCC_MATCHING
// Anomaly 78: use SHUTDOWN instead of STOP and CLEAR.
@@ -1061,8 +1130,8 @@ 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;
ints_to_disable = NRF_RADIO_INT_PHYEND_MASK;
#if NRF_802154_TX_STARTED_NOTIFY_ENABLED
ints_to_disable |= NRF_RADIO_INT_ADDRESS_MASK;
#endif // NRF_802154_TX_STARTED_NOTIFY_ENABLED
@@ -1088,17 +1157,30 @@ 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;
ints_to_disable |= NRF_RADIO_INT_CCABUSY_MASK;
ints_to_disable = NRF_RADIO_INT_PHYEND_MASK | NRF_RADIO_INT_CCABUSY_MASK;
#if NRF_802154_TX_STARTED_NOTIFY_ENABLED
ints_to_disable |= NRF_RADIO_INT_ADDRESS_MASK;
#endif // NRF_802154_TX_STARTED_NOTIFY_ENABLED
nrf_radio_int_disable(ints_to_disable);
nrf_radio_shorts_set(SHORTS_IDLE);
bool shutdown = nrf_fem_prepare_powerdown(NRF_802154_TIMER_INSTANCE,
NRF_TIMER_CC_CHANNEL0,
PPI_EGU_TIMER_START);
nrf_radio_task_trigger(NRF_RADIO_TASK_CCASTOP);
nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE);
if (shutdown)
{
while (!nrf_timer_event_check(NRF_802154_TIMER_INSTANCE, NRF_TIMER_EVENT_COMPARE0))
{
// Wait until the event is set.
}
nrf_timer_shorts_disable(NRF_802154_TIMER_INSTANCE, NRF_TIMER_SHORT_COMPARE0_STOP_MASK);
nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_SHUTDOWN);
nrf_ppi_channel_disable(PPI_EGU_TIMER_START);
}
}
}
@@ -1110,7 +1192,7 @@ static void rx_ack_terminate(void)
nrf_ppi_channel_disable(PPI_DISABLED_EGU);
nrf_ppi_channel_disable(PPI_EGU_RAMP_UP);
fem_for_lna_reset(NRF_TIMER_SHORT_COMPARE2_STOP_MASK);
fem_for_lna_reset();
nrf_ppi_channel_remove_from_group(PPI_EGU_RAMP_UP, PPI_CHGRP0);
nrf_ppi_fork_endpoint_setup(PPI_EGU_RAMP_UP, 0);
@@ -1134,17 +1216,32 @@ static void ed_terminate(void)
nrf_ppi_channel_disable(PPI_DISABLED_EGU);
nrf_ppi_channel_disable(PPI_EGU_RAMP_UP);
fem_for_lna_reset(NRF_TIMER_SHORT_COMPARE0_STOP_MASK);
fem_for_lna_reset();
nrf_ppi_channel_remove_from_group(PPI_EGU_RAMP_UP, PPI_CHGRP0);
nrf_ppi_fork_endpoint_setup(PPI_EGU_RAMP_UP, 0);
if (timeslot_is_granted())
{
bool shutdown = nrf_fem_prepare_powerdown(NRF_802154_TIMER_INSTANCE,
NRF_TIMER_CC_CHANNEL0,
PPI_EGU_TIMER_START);
nrf_radio_int_disable(NRF_RADIO_INT_EDEND_MASK);
nrf_radio_shorts_set(SHORTS_IDLE);
nrf_radio_task_trigger(NRF_RADIO_TASK_EDSTOP);
nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE);
if (shutdown)
{
while (!nrf_timer_event_check(NRF_802154_TIMER_INSTANCE, NRF_TIMER_EVENT_COMPARE0))
{
// Wait until the event is set.
}
nrf_timer_shorts_disable(NRF_802154_TIMER_INSTANCE, NRF_TIMER_SHORT_COMPARE0_STOP_MASK);
nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_SHUTDOWN);
nrf_ppi_channel_disable(PPI_EGU_TIMER_START);
}
}
}
@@ -1154,17 +1251,32 @@ static void cca_terminate(void)
nrf_ppi_channel_disable(PPI_DISABLED_EGU);
nrf_ppi_channel_disable(PPI_EGU_RAMP_UP);
fem_for_lna_reset(NRF_TIMER_SHORT_COMPARE0_STOP_MASK);
fem_for_lna_reset();
nrf_ppi_channel_remove_from_group(PPI_EGU_RAMP_UP, PPI_CHGRP0);
nrf_ppi_fork_endpoint_setup(PPI_EGU_RAMP_UP, 0);
if (timeslot_is_granted())
{
bool shutdown = nrf_fem_prepare_powerdown(NRF_802154_TIMER_INSTANCE,
NRF_TIMER_CC_CHANNEL0,
PPI_EGU_TIMER_START);
nrf_radio_int_disable(NRF_RADIO_INT_CCABUSY_MASK | NRF_RADIO_INT_CCAIDLE_MASK);
nrf_radio_shorts_set(SHORTS_IDLE);
nrf_radio_task_trigger(NRF_RADIO_TASK_CCASTOP);
nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE);
if (shutdown)
{
while (!nrf_timer_event_check(NRF_802154_TIMER_INSTANCE, NRF_TIMER_EVENT_COMPARE0))
{
// Wait until the event is set.
}
nrf_timer_shorts_disable(NRF_802154_TIMER_INSTANCE, NRF_TIMER_SHORT_COMPARE0_STOP_MASK);
nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_SHUTDOWN);
nrf_ppi_channel_disable(PPI_EGU_TIMER_START);
}
}
}
@@ -1178,7 +1290,21 @@ static void continuous_carrier_terminate(void)
if (timeslot_is_granted())
{
bool shutdown = nrf_fem_prepare_powerdown(NRF_802154_TIMER_INSTANCE,
NRF_TIMER_CC_CHANNEL0,
PPI_EGU_TIMER_START);
nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE);
if (shutdown)
{
while (!nrf_timer_event_check(NRF_802154_TIMER_INSTANCE, NRF_TIMER_EVENT_COMPARE0))
{
// Wait until the event is set.
}
nrf_timer_shorts_disable(NRF_802154_TIMER_INSTANCE, NRF_TIMER_SHORT_COMPARE0_STOP_MASK);
nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_SHUTDOWN);
nrf_ppi_channel_disable(PPI_EGU_TIMER_START);
}
}
}
@@ -1374,10 +1500,8 @@ static void falling_asleep_init(void)
/** Initialize RX operation. */
static void rx_init(bool disabled_was_triggered)
{
bool free_buffer;
int32_t ints_to_enable = 0;
uint32_t lna_target_time;
uint32_t pa_target_time;
bool free_buffer;
int32_t ints_to_enable = 0;
if (!timeslot_is_granted())
{
@@ -1421,21 +1545,25 @@ static void rx_init(bool disabled_was_triggered)
nrf_radio_int_enable(ints_to_enable);
// Set FEM
nrf_fem_control_ppi_enable(NRF_FEM_CONTROL_LNA_PIN, NRF_TIMER_CC_CHANNEL0);
lna_target_time = nrf_fem_control_delay_get(NRF_FEM_CONTROL_LNA_PIN);
pa_target_time = nrf_fem_control_delay_get(NRF_FEM_CONTROL_PA_PIN);
// Set TIMER to transmit ACK
nrf_timer_shorts_enable(NRF_802154_TIMER_INSTANCE,
NRF_TIMER_SHORT_COMPARE0_STOP_MASK |
NRF_TIMER_SHORT_COMPARE2_STOP_MASK);
nrf_timer_cc_write(NRF_802154_TIMER_INSTANCE, NRF_TIMER_CC_CHANNEL0, lna_target_time);
NRF_TIMER_SHORT_COMPARE0_STOP_MASK);
uint32_t delta_time;
if (nrf_802154_fal_lna_configuration_set(&m_activate_rx_cc0, NULL) == NRF_SUCCESS)
{
delta_time = nrf_timer_cc_read(NRF_802154_TIMER_INSTANCE,
NRF_TIMER_CC_CHANNEL0);
}
else
{
delta_time = 1;
nrf_timer_cc_write(NRF_802154_TIMER_INSTANCE, NRF_TIMER_CC_CHANNEL0, delta_time);
}
nrf_timer_cc_write(NRF_802154_TIMER_INSTANCE,
NRF_TIMER_CC_CHANNEL1,
lna_target_time + ACK_IFS - TXRU_TIME - EVENT_LAT);
nrf_timer_cc_write(NRF_802154_TIMER_INSTANCE,
NRF_TIMER_CC_CHANNEL2,
lna_target_time + ACK_IFS - TXRU_TIME - EVENT_LAT + pa_target_time);
delta_time + ACK_IFS - TXRU_TIME - EVENT_LAT);
#if NRF_802154_DISABLE_BCC_MATCHING
nrf_timer_shorts_enable(NRF_802154_COUNTER_TIMER_INSTANCE, NRF_TIMER_SHORT_COMPARE1_STOP_MASK);
@@ -1565,16 +1693,8 @@ static bool tx_init(const uint8_t * p_data, bool cca, bool disabled_was_triggere
nrf_radio_shorts_set(cca ? SHORTS_CCA_TX : SHORTS_TX);
// Enable IRQs
if (nrf_802154_revision_has_phyend_event())
{
nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND);
ints_to_enable |= NRF_RADIO_INT_PHYEND_MASK;
}
else
{
nrf_radio_event_clear(NRF_RADIO_EVENT_END);
ints_to_enable |= NRF_RADIO_INT_END_MASK;
}
nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND);
ints_to_enable |= NRF_RADIO_INT_PHYEND_MASK;
if (cca)
{
@@ -1624,7 +1744,7 @@ static void ed_init(bool disabled_was_triggered)
nrf_radio_int_enable(NRF_RADIO_INT_EDEND_MASK);
// Set FEM
fem_for_lna_set(NRF_TIMER_CC_CHANNEL0, NRF_TIMER_SHORT_COMPARE0_STOP_MASK);
fem_for_lna_set();
// Clr event EGU
nrf_egu_event_clear(NRF_802154_SWI_EGU_INSTANCE, EGU_EVENT);
@@ -1655,7 +1775,7 @@ static void cca_init(bool disabled_was_triggered)
nrf_radio_int_enable(NRF_RADIO_INT_CCABUSY_MASK | NRF_RADIO_INT_CCAIDLE_MASK);
// Set FEM
fem_for_lna_set(NRF_TIMER_CC_CHANNEL0, NRF_TIMER_SHORT_COMPARE0_STOP_MASK);
fem_for_lna_set();
// Clr event EGU
nrf_egu_event_clear(NRF_802154_SWI_EGU_INSTANCE, EGU_EVENT);
@@ -1714,6 +1834,9 @@ static void cont_prec_approved(void)
m_rsch_timeslot_is_granted = true;
nrf_802154_timer_coord_start();
nrf_802154_fal_pa_configuration_set(NULL, &m_deactivate_on_disable);
nrf_802154_fal_lna_configuration_set(NULL, &m_deactivate_on_disable);
switch (m_state)
{
case RADIO_STATE_SLEEP:
@@ -1768,7 +1891,10 @@ static void cont_prec_denied(void)
nrf_radio_reset();
}
nrf_fem_control_pin_clear();
nrf_802154_fal_pa_configuration_clear(NULL, &m_deactivate_on_disable);
nrf_802154_fal_lna_configuration_clear(NULL, &m_deactivate_on_disable);
nrf_802154_fal_deactivate_now(NRF_802154_FAL_ALL);
nrf_802154_timer_coord_stop();
result = current_operation_terminate(NRF_802154_TERM_802154, REQ_ORIG_RSCH, false);
@@ -2052,8 +2178,14 @@ static void irq_crcok_state_rx(void)
#endif // !NRF_802154_DISABLE_BCC_MATCHING
// Set FEM PPIs
nrf_fem_control_ppi_disable(NRF_FEM_CONTROL_LNA_PIN);
nrf_fem_control_ppi_enable(NRF_FEM_CONTROL_PA_PIN, NRF_TIMER_CC_CHANNEL2);
uint32_t time_to_pa = nrf_timer_cc_read(NRF_802154_TIMER_INSTANCE,
NRF_TIMER_CC_CHANNEL1);
nrf_802154_fal_event_t timer = m_activate_tx_cc0;
timer.event.timer.counter_value += time_to_pa;
nrf_802154_fal_pa_configuration_set(&timer, NULL);
// Detect if PPI worked (timer is counting or TIMER event is marked)
nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_CAPTURE3);
@@ -2094,16 +2226,8 @@ static void irq_crcok_state_rx(void)
ints_to_disable |= NRF_RADIO_INT_CRCOK_MASK;
nrf_radio_int_disable(ints_to_disable);
if (nrf_802154_revision_has_phyend_event())
{
nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND);
ints_to_enable = NRF_RADIO_INT_PHYEND_MASK;
}
else
{
nrf_radio_event_clear(NRF_RADIO_EVENT_END);
ints_to_enable = NRF_RADIO_INT_END_MASK;
}
nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND);
ints_to_enable = NRF_RADIO_INT_PHYEND_MASK;
#if NRF_802154_TX_STARTED_NOTIFY_ENABLED
nrf_radio_event_clear(NRF_RADIO_EVENT_ADDRESS);
@@ -2192,8 +2316,9 @@ static void irq_phyend_state_tx_ack(void)
nrf_ppi_channel_disable(PPI_DISABLED_EGU);
// Set FEM PPIs
nrf_fem_control_ppi_disable(NRF_FEM_CONTROL_PA_PIN);
nrf_fem_control_ppi_enable(NRF_FEM_CONTROL_LNA_PIN, NRF_TIMER_CC_CHANNEL0);
nrf_802154_fal_pa_configuration_clear(&m_activate_tx_cc0, NULL);
nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_SHUTDOWN);
nrf_802154_fal_lna_configuration_set(&m_activate_rx_cc0, NULL);
nrf_radio_shorts_set(SHORTS_RX);
@@ -2202,8 +2327,7 @@ static void irq_phyend_state_tx_ack(void)
nrf_radio_bcc_set(BCC_INIT);
#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;
ints_to_disable = NRF_RADIO_INT_PHYEND_MASK;
#if NRF_802154_TX_STARTED_NOTIFY_ENABLED
ints_to_disable |= NRF_RADIO_INT_ADDRESS_MASK;
@@ -2325,12 +2449,9 @@ static void irq_phyend_state_tx_frame(void)
ints_to_disable |= NRF_RADIO_INT_ADDRESS_MASK;
#endif // NRF_802154_TX_STARTED_NOTIFY_ENABLED
if (nrf_802154_revision_has_phyend_event())
{
ints_to_disable |= NRF_RADIO_INT_PHYEND_MASK;
nrf_radio_event_clear(NRF_RADIO_EVENT_END);
ints_to_enable |= NRF_RADIO_INT_END_MASK;
}
ints_to_disable |= NRF_RADIO_INT_PHYEND_MASK;
nrf_radio_event_clear(NRF_RADIO_EVENT_END);
ints_to_enable |= NRF_RADIO_INT_END_MASK;
nrf_radio_int_disable(ints_to_disable);
@@ -2342,7 +2463,7 @@ static void irq_phyend_state_tx_frame(void)
// Clear FEM configuration set at the beginning of the transmission
fem_for_tx_reset(false);
// Set PPIs necessary in rx_ack state
fem_for_lna_set(NRF_TIMER_CC_CHANNEL2, NRF_TIMER_SHORT_COMPARE2_STOP_MASK);
fem_for_lna_set();
nrf_ppi_channel_and_fork_endpoint_setup(PPI_EGU_RAMP_UP,
(uint32_t)nrf_egu_event_address_get(
@@ -2505,7 +2626,7 @@ static void irq_edend_state_ed(void)
}
else
{
fem_for_lna_reset(NRF_TIMER_SHORT_COMPARE0_STOP_MASK);
fem_for_lna_reset();
}
}
else
@@ -2620,8 +2741,7 @@ static void irq_handler(void)
nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_EVENT_CRCOK);
}
if (nrf_802154_revision_has_phyend_event() &&
nrf_radio_int_enable_check(NRF_RADIO_INT_PHYEND_MASK) &&
if (nrf_radio_int_enable_check(NRF_RADIO_INT_PHYEND_MASK) &&
nrf_radio_event_check(NRF_RADIO_EVENT_PHYEND))
{
nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_EVENT_PHYEND);
@@ -2653,23 +2773,6 @@ static void irq_handler(void)
switch (m_state)
{
case RADIO_STATE_TX_ACK:
if (!nrf_802154_revision_has_phyend_event())
{
irq_phyend_state_tx_ack();
}
break;
case RADIO_STATE_CCA_TX:
case RADIO_STATE_TX:
if (!nrf_802154_revision_has_phyend_event())
{
irq_phyend_state_tx_frame();
}
break;
case RADIO_STATE_RX_ACK: // Ended receiving of ACK.
irq_end_state_rx_ack();
break;
@@ -2785,10 +2888,10 @@ void nrf_802154_core_deinit(void)
if (timeslot_is_granted())
{
nrf_radio_reset();
nrf_802154_fal_deactivate_now(NRF_802154_FAL_ALL);
}
nrf_fem_control_pin_clear();
nrf_fem_control_deactivate();
nrf_802154_fal_cleanup();
irq_deinit();
}
@@ -62,65 +62,55 @@ static void radio_event_gpio_toggle_init(void)
nrf_gpio_cfg_output(PIN_DBG_RADIO_EVT_READY);
nrf_gpio_cfg_output(PIN_DBG_RADIO_EVT_FRAMESTART);
nrf_gpio_cfg_output(PIN_DBG_RADIO_EVT_EDEND);
nrf_gpio_cfg_output(PIN_DBG_RADIO_EVT_PHYEND);
nrf_gpiote_task_configure(0,
nrf_gpiote_task_configure(GPIOTE_DBG_RADIO_EVT_END,
PIN_DBG_RADIO_EVT_END,
NRF_GPIOTE_POLARITY_TOGGLE,
NRF_GPIOTE_INITIAL_VALUE_HIGH);
nrf_gpiote_task_configure(1,
nrf_gpiote_task_configure(GPIOTE_DBG_RADIO_EVT_DISABLED,
PIN_DBG_RADIO_EVT_DISABLED,
NRF_GPIOTE_POLARITY_TOGGLE,
NRF_GPIOTE_INITIAL_VALUE_HIGH);
nrf_gpiote_task_configure(2,
nrf_gpiote_task_configure(GPIOTE_DBG_RADIO_EVT_READY,
PIN_DBG_RADIO_EVT_READY,
NRF_GPIOTE_POLARITY_TOGGLE,
NRF_GPIOTE_INITIAL_VALUE_HIGH);
nrf_gpiote_task_configure(3,
nrf_gpiote_task_configure(GPIOTE_DBG_RADIO_EVT_FRAMESTART,
PIN_DBG_RADIO_EVT_FRAMESTART,
NRF_GPIOTE_POLARITY_TOGGLE,
NRF_GPIOTE_INITIAL_VALUE_HIGH);
nrf_gpiote_task_configure(4,
nrf_gpiote_task_configure(GPIOTE_DBG_RADIO_EVT_EDEND,
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);
nrf_gpiote_task_enable(2);
nrf_gpiote_task_enable(3);
nrf_gpiote_task_enable(4);
nrf_gpiote_task_enable(5);
nrf_gpiote_task_enable(GPIOTE_DBG_RADIO_EVT_END);
nrf_gpiote_task_enable(GPIOTE_DBG_RADIO_EVT_DISABLED);
nrf_gpiote_task_enable(GPIOTE_DBG_RADIO_EVT_READY);
nrf_gpiote_task_enable(GPIOTE_DBG_RADIO_EVT_FRAMESTART);
nrf_gpiote_task_enable(GPIOTE_DBG_RADIO_EVT_EDEND);
nrf_ppi_channel_endpoint_setup(NRF_PPI_CHANNEL0,
nrf_ppi_channel_endpoint_setup((nrf_ppi_channel_t)PPI_DBG_RADIO_EVT_END,
(uint32_t)&NRF_RADIO->EVENTS_END,
nrf_gpiote_task_addr_get(NRF_GPIOTE_TASKS_OUT_0));
nrf_ppi_channel_endpoint_setup(NRF_PPI_CHANNEL1,
nrf_ppi_channel_endpoint_setup((nrf_ppi_channel_t)PPI_DBG_RADIO_EVT_DISABLED,
(uint32_t)&NRF_RADIO->EVENTS_DISABLED,
nrf_gpiote_task_addr_get(NRF_GPIOTE_TASKS_OUT_1));
nrf_ppi_channel_endpoint_setup(NRF_PPI_CHANNEL2,
nrf_ppi_channel_endpoint_setup((nrf_ppi_channel_t)PPI_DBG_RADIO_EVT_READY,
(uint32_t)&NRF_RADIO->EVENTS_READY,
nrf_gpiote_task_addr_get(NRF_GPIOTE_TASKS_OUT_2));
nrf_ppi_channel_endpoint_setup(NRF_PPI_CHANNEL3,
nrf_ppi_channel_endpoint_setup((nrf_ppi_channel_t)PPI_DBG_RADIO_EVT_FRAMESTART,
(uint32_t)&NRF_RADIO->EVENTS_FRAMESTART,
nrf_gpiote_task_addr_get(NRF_GPIOTE_TASKS_OUT_3));
nrf_ppi_channel_endpoint_setup(NRF_PPI_CHANNEL4,
nrf_ppi_channel_endpoint_setup((nrf_ppi_channel_t)PPI_DBG_RADIO_EVT_EDEND,
(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);
nrf_ppi_channel_enable(NRF_PPI_CHANNEL2);
nrf_ppi_channel_enable(NRF_PPI_CHANNEL3);
nrf_ppi_channel_enable(NRF_PPI_CHANNEL4);
nrf_ppi_channel_enable(NRF_PPI_CHANNEL5);
nrf_ppi_channel_enable((nrf_ppi_channel_t)PPI_DBG_RADIO_EVT_END);
nrf_ppi_channel_enable((nrf_ppi_channel_t)PPI_DBG_RADIO_EVT_DISABLED);
nrf_ppi_channel_enable((nrf_ppi_channel_t)PPI_DBG_RADIO_EVT_READY);
nrf_ppi_channel_enable((nrf_ppi_channel_t)PPI_DBG_RADIO_EVT_FRAMESTART);
nrf_ppi_channel_enable((nrf_ppi_channel_t)PPI_DBG_RADIO_EVT_EDEND);
}
/**
@@ -134,36 +124,6 @@ static void raal_simulator_gpio_init(void)
#endif
}
/**
* @brief Initialize PPI to toggle GPIO pins on Softdevice events. Initialize GPIO to set it
* according to Softdevice arbiter client events.
*/
static void raal_softdevice_event_gpio_toggle_init(void)
{
#if RAAL_SOFTDEVICE
nrf_gpio_cfg_output(PIN_DBG_TIMESLOT_ACTIVE);
nrf_gpio_cfg_output(PIN_DBG_TIMESLOT_EXTEND_REQ);
nrf_gpio_cfg_output(PIN_DBG_TIMESLOT_SESSION_IDLE);
nrf_gpio_cfg_output(PIN_DBG_TIMESLOT_RADIO_IRQ);
nrf_gpio_cfg_output(PIN_DBG_TIMESLOT_FAILED);
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_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_enable(NRF_PPI_CHANNEL5);
#endif // RAAL_SOFTDEVICE
}
#endif // ENABLE_DEBUG_GPIO
void nrf_802154_debug_init(void)
@@ -171,7 +131,6 @@ void nrf_802154_debug_init(void)
#if ENABLE_DEBUG_GPIO
radio_event_gpio_toggle_init();
raal_simulator_gpio_init();
raal_softdevice_event_gpio_toggle_init();
#endif // ENABLE_DEBUG_GPIO
}
@@ -141,6 +141,49 @@ extern "C" {
#endif
#define PPI_DBG_RADIO_EVT_END 0
#define PPI_DBG_RADIO_EVT_DISABLED 1
#define PPI_DBG_RADIO_EVT_READY 2
#define PPI_DBG_RADIO_EVT_FRAMESTART 3
#define PPI_DBG_RADIO_EVT_EDEND 4
#define GPIOTE_DBG_RADIO_EVT_END 0
#define GPIOTE_DBG_RADIO_EVT_DISABLED 1
#define GPIOTE_DBG_RADIO_EVT_READY 2
#define GPIOTE_DBG_RADIO_EVT_FRAMESTART 3
#define GPIOTE_DBG_RADIO_EVT_EDEND 4
#if ENABLE_DEBUG_GPIO
#define NRF_802154_DEBUG_PINS_USED_MASK ((1 << PIN_DBG_RADIO_EVT_END) | \
(1 << PIN_DBG_RADIO_EVT_DISABLED) | \
(1 << PIN_DBG_RADIO_EVT_READY) | \
(1 << PIN_DBG_RADIO_EVT_FRAMESTART) | \
(1 << PIN_DBG_RADIO_EVT_EDEND) | \
(1 << PIN_DBG_RADIO_EVT_PHYEND))
#define NRF_802154_DEBUG_PPI_CHANNELS_USED_MASK ((1 << PPI_DBG_RADIO_EVT_END) | \
(1 << PPI_DBG_RADIO_EVT_DISABLED) | \
(1 << PPI_DBG_RADIO_EVT_READY) | \
(1 << PPI_DBG_RADIO_EVT_FRAMESTART) | \
(1 << PPI_DBG_RADIO_EVT_EDEND) | \
(1 << PPI_DBG_RADIO_EVT_PHYEND))
#define NRF_802154_DEBUG_GPIOTE_CHANNELS_USED_MASK ((1 << GPIOTE_DBG_RADIO_EVT_END) | \
(1 << GPIOTE_DBG_RADIO_EVT_DISABLED) | \
(1 << GPIOTE_DBG_RADIO_EVT_READY) | \
(1 << GPIOTE_DBG_RADIO_EVT_FRAMESTART) | \
(1 << GPIOTE_DBG_RADIO_EVT_EDEND) | \
(1 << GPIOTE_DBG_RADIO_EVT_PHYEND))
#else // ENABLE_DEBUG_GPIO
#define NRF_802154_DEBUG_PINS_USED_MASK 0
#define NRF_802154_DEBUG_PPI_CHANNELS_USED_MASK 0
#define NRF_802154_DEBUG_GPIOTE_CHANNELS_USED_MASK 0
#endif // ENABLE_DEBUG_GPIO
#ifdef __cplusplus
}
#endif
@@ -57,8 +57,24 @@ extern "C" {
#define PIN_DBG_RTC0_EVT_REM 31
#if ENABLE_DEBUG_GPIO
#define NRF_802154_DEBUG_CORE_PINS_USED ((1 << PIN_DBG_TIMESLOT_ACTIVE) | \
(1 << PIN_DBG_TIMESLOT_EXTEND_REQ) | \
(1 << PIN_DBG_TIMESLOT_SESSION_IDLE) | \
(1 << PIN_DBG_TIMESLOT_RADIO_IRQ) | \
(1 << PIN_DBG_TIMESLOT_FAILED) | \
(1 << PIN_DBG_TIMESLOT_BLOCKED) | \
(1 << PIN_DBG_RAAL_CRITICAL_SECTION))
#else // ENABLE_DEBUG_GPIO
#define NRF_802154_DEBUG_CORE_PINS_USED 0
#endif
#ifndef DEBUG_VERBOSITY
#define DEBUG_VERBOSITY 1
#define DEBUG_VERBOSITY 1
#endif
#ifndef CU_TEST
@@ -0,0 +1,506 @@
/* Copyright (c) 2019, 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 Module that defines the 802.15.4 driver peripheral usage.
*
*/
#ifndef NRF_802154_PERIPHERALS_H__
#define NRF_802154_PERIPHERALS_H__
#include <nrf.h>
#include <nrfx.h>
#include "nrf_802154_config.h"
#include "nrf_802154_debug.h"
#include "nrf_802154_debug_core.h"
#include "fem/nrf_fem_protocol_api.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @def NRF_802154_HIGH_PRECISION_TIMER_INSTANCE_NO
*
* Number of the timer instance used for precise frame timestamps and synchronous radio operations.
*
*/
#ifndef NRF_802154_HIGH_PRECISION_TIMER_INSTANCE_NO
#define NRF_802154_HIGH_PRECISION_TIMER_INSTANCE_NO 0
#endif
/**
* @def NRF_802154_HIGH_PRECISION_TIMER_INSTANCE
*
* The timer instance used for precise frame timestamps and synchronous radio operations.
*
*/
#define NRF_802154_HIGH_PRECISION_TIMER_INSTANCE \
NRFX_CONCAT_2(NRF_TIMER, NRF_802154_HIGH_PRECISION_TIMER_INSTANCE_NO)
/**
* @def NRF_802154_TIMER_INSTANCE_NO
*
* Number of the timer instance used both by the driver for ACK IFS and by the FEM module.
*
*/
#ifndef NRF_802154_TIMER_INSTANCE_NO
#define NRF_802154_TIMER_INSTANCE_NO 1
#endif
/**
* @def NRF_802154_TIMER_INSTANCE
*
* The timer instance used both by the driver for ACK IFS and by the FEM module.
*
*/
#define NRF_802154_TIMER_INSTANCE \
NRFX_CONCAT_2(NRF_TIMER, NRF_802154_TIMER_INSTANCE_NO)
/**
* @def NRF_802154_COUNTER_TIMER_INSTANCE_NO
*
* Number of the timer instance used for detecting when PSDU is being received.
*
*/
#ifndef NRF_802154_COUNTER_TIMER_INSTANCE_NO
#define NRF_802154_COUNTER_TIMER_INSTANCE_NO 2
#endif
/**
* @def NRF_802154_COUNTER_TIMER_INSTANCE
*
* The timer instance used by the driver for detecting when PSDU is being received.
*
* @note This configuration is used only when the NRF_RADIO_EVENT_BCMATCH event handling is disabled
* (see @ref NRF_802154_DISABLE_BCC_MATCHING).
*/
#define NRF_802154_COUNTER_TIMER_INSTANCE \
NRFX_CONCAT_2(NRF_TIMER, NRF_802154_COUNTER_TIMER_INSTANCE_NO)
/**
* @def NRF_802154_SWI_EGU_INSTANCE_NO
*
* Number of the SWI EGU instance used by the driver to synchronize PPIs and for requests and
* notifications if SWI is in use.
*
*/
#ifndef NRF_802154_SWI_EGU_INSTANCE_NO
#ifdef NRF52811_XXAA
#define NRF_802154_SWI_EGU_INSTANCE_NO 0
#else
#define NRF_802154_SWI_EGU_INSTANCE_NO 3
#endif
#endif // NRF_802154_SWI_EGU_INSTANCE_NO
/**
* @def NRF_802154_SWI_EGU_INSTANCE
*
* The SWI EGU instance used by the driver to synchronize PPIs and for requests and notifications if
* SWI is in use.
*
* @note This option is used by the core module regardless of the driver configuration.
*
*/
#define NRF_802154_SWI_EGU_INSTANCE NRFX_CONCAT_2(NRF_EGU, NRF_802154_SWI_EGU_INSTANCE_NO)
/**
* @def NRF_802154_SWI_IRQ_HANDLER
*
* The SWI EGU IRQ handler used by the driver for requests and notifications if SWI is in use.
*
* @note This option is used when the driver uses SWI to process requests and notifications.
*
*/
#define NRF_802154_SWI_IRQ_HANDLER \
NRFX_CONCAT_3(NRFX_CONCAT_3(SWI, NRF_802154_SWI_EGU_INSTANCE_NO, _EGU), \
NRF_802154_SWI_EGU_INSTANCE_NO, \
_IRQHandler)
/**
* @def NRF_802154_SWI_IRQN
*
* The SWI EGU IRQ number used by the driver for requests and notifications if SWI is in use.
*
* @note This option is used when the driver uses SWI to process requests and notifications.
*
*/
#define NRF_802154_SWI_IRQN \
NRFX_CONCAT_3(NRFX_CONCAT_3(SWI, NRF_802154_SWI_EGU_INSTANCE_NO, _EGU), \
NRF_802154_SWI_EGU_INSTANCE_NO, \
_IRQn)
/**
* @def NRF_802154_RTC_INSTANCE_NO
*
* Number of the RTC instance used in the standalone timer driver implementation.
*
*/
#ifndef NRF_802154_RTC_INSTANCE_NO
#ifdef NRF52811_XXAA
#define NRF_802154_RTC_INSTANCE_NO 0
#else
#define NRF_802154_RTC_INSTANCE_NO 2
#endif
#endif // NRF_802154_RTC_INSTANCE_NO
/**
* @def NRF_802154_RTC_INSTANCE
*
* The RTC instance used in the standalone timer driver implementation.
*
* @note This configuration is only applicable for the Low Power Timer Abstraction Layer
* implementation in nrf_802154_lp_timer_nodrv.c.
*
*/
#define NRF_802154_RTC_INSTANCE NRFX_CONCAT_2(NRF_RTC, NRF_802154_RTC_INSTANCE_NO)
/**
* @def NRF_802154_RTC_IRQ_HANDLER
*
* The RTC interrupt handler name used in the standalone timer driver implementation.
*
* @note This configuration is only applicable for Low Power Timer Abstraction Layer implementation
* in nrf_802154_lp_timer_nodrv.c.
*
*/
#define NRF_802154_RTC_IRQ_HANDLER NRFX_CONCAT_3(RTC, NRF_802154_RTC_INSTANCE_NO, _IRQHandler)
/**
* @def NRF_802154_RTC_IRQN
*
* The RTC Interrupt number used in the standalone timer driver implementation.
*
* @note This configuration is only applicable for the Low Power Timer Abstraction Layer implementation
* in nrf_802154_lp_timer_nodrv.c.
*
*/
#define NRF_802154_RTC_IRQN NRFX_CONCAT_3(RTC, NRF_802154_RTC_INSTANCE_NO, _IRQn)
/**
* @def NRF_802154_PPI_RADIO_DISABLED_TO_EGU
*
* The PPI channel that connects RADIO_DISABLED event to EGU task.
*
* @note This option is used by the core module regardless of the driver configuration.
*
*/
#ifndef NRF_802154_PPI_RADIO_DISABLED_TO_EGU
#define NRF_802154_PPI_RADIO_DISABLED_TO_EGU NRF_PPI_CHANNEL6
#endif
/**
* @def NRF_802154_PPI_EGU_TO_RADIO_RAMP_UP
*
* The PPI channel that connects EGU event to RADIO_TXEN or RADIO_RXEN task.
*
* @note This option is used by the core module regardless of the driver configuration.
*
*/
#ifndef NRF_802154_PPI_EGU_TO_RADIO_RAMP_UP
#define NRF_802154_PPI_EGU_TO_RADIO_RAMP_UP NRF_PPI_CHANNEL7
#endif
/**
* @def NRF_802154_PPI_EGU_TO_TIMER_START
*
* The PPI channel that connects EGU event to TIMER_START task.
*
* @note This option is used by the core module regardless of the driver configuration.
*
*/
#ifndef NRF_802154_PPI_EGU_TO_TIMER_START
#define NRF_802154_PPI_EGU_TO_TIMER_START NRF_PPI_CHANNEL8
#endif
/**
* @def NRF_802154_PPI_RADIO_CRCERROR_TO_TIMER_CLEAR
*
* The PPI channel that connects RADIO_CRCERROR event to TIMER_CLEAR task.
*
* @note This option is used by the core module regardless of the driver configuration.
* The peripheral is shared with @ref NRF_802154_PPI_RADIO_CCAIDLE_TO_FEM_GPIOTE
* and @ref NRF_802154_PPI_TIMER_COMPARE_TO_RADIO_TXEN.
*
*/
#ifndef NRF_802154_PPI_RADIO_CRCERROR_TO_TIMER_CLEAR
#define NRF_802154_PPI_RADIO_CRCERROR_TO_TIMER_CLEAR NRF_PPI_CHANNEL9
#endif
/**
* @def NRF_802154_PPI_RADIO_CCAIDLE_TO_FEM_GPIOTE
*
* The PPI channel that connects RADIO_CCAIDLE event to the GPIOTE tasks used by the Frontend.
*
* @note This option is used by the core module regardless of the driver configuration.
* The peripheral is shared with @ref NRF_802154_PPI_RADIO_CRCERROR_TO_TIMER_CLEAR
* and @ref NRF_802154_PPI_TIMER_COMPARE_TO_RADIO_TXEN.
*
*/
#ifndef NRF_802154_PPI_RADIO_CCAIDLE_TO_FEM_GPIOTE
#define NRF_802154_PPI_RADIO_CCAIDLE_TO_FEM_GPIOTE NRF_PPI_CHANNEL9
#endif
/**
* @def NRF_802154_PPI_TIMER_COMPARE_TO_RADIO_TXEN
*
* The PPI channel that connects TIMER_COMPARE event to RADIO_TXEN task.
*
* @note This option is used by the core module regardless of the driver configuration.
* The peripheral is shared with @ref NRF_802154_PPI_RADIO_CRCERROR_TO_TIMER_CLEAR
* and @ref NRF_802154_PPI_RADIO_CCAIDLE_TO_FEM_GPIOTE.
*
*/
#ifndef NRF_802154_PPI_TIMER_COMPARE_TO_RADIO_TXEN
#define NRF_802154_PPI_TIMER_COMPARE_TO_RADIO_TXEN NRF_PPI_CHANNEL9
#endif
/**
* @def NRF_802154_PPI_RADIO_CRCOK_TO_PPI_GRP_DISABLE
*
* The PPI channel that connects RADIO_CRCOK event with the task that disables the whole PPI group.
*
* @note This option is used by the core module regardless of the driver configuration.
*
*/
#ifndef NRF_802154_PPI_RADIO_CRCOK_TO_PPI_GRP_DISABLE
#define NRF_802154_PPI_RADIO_CRCOK_TO_PPI_GRP_DISABLE NRF_PPI_CHANNEL10
#endif
#ifdef NRF_802154_DISABLE_BCC_MATCHING
/**
* @def NRF_802154_PPI_RADIO_ADDR_TO_COUNTER_COUNT
*
* The PPI channel that connects RADIO_ADDRESS event to TIMER_COUNT task.
*
* @note This configuration is used only when the NRF_RADIO_EVENT_BCMATCH event handling is disabled
* (see @ref NRF_802154_DISABLE_BCC_MATCHING).
*
*/
#ifndef NRF_802154_PPI_RADIO_ADDR_TO_COUNTER_COUNT
#define NRF_802154_PPI_RADIO_ADDR_TO_COUNTER_COUNT NRF_PPI_CHANNEL11
#endif
/**
* @def NRF_802154_PPI_RADIO_CRCERROR_TO_COUNTER_CLEAR
*
* The PPI channel that connects RADIO_CRCERROR event to TIMER_CLEAR task.
*
* @note This option is used only when the NRF_RADIO_EVENT_BCMATCH event handling is disabled
* (see @ref NRF_802154_DISABLE_BCC_MATCHING).
*
*/
#ifndef NRF_802154_PPI_RADIO_CRCERROR_COUNTER_CLEAR
#define NRF_802154_PPI_RADIO_CRCERROR_COUNTER_CLEAR NRF_PPI_CHANNEL12
#endif
/**
* @def NRF_802154_DISABLE_BCC_MATCHING_PPI_CHANNELS_USED_MASK
*
* Helper bit mask of PPI channels used additionally by the 802.15.4 driver when the BCC matching
* is disabled.
*/
#define NRF_802154_DISABLE_BCC_MATCHING_PPI_CHANNELS_USED_MASK \
((1 << NRF_802154_PPI_RADIO_ADDR_TO_COUNTER_COUNT) | \
(1 << NRF_802154_PPI_RADIO_CRCERROR_COUNTER_CLEAR))
#else // NRF_802154_DISABLE_BCC_MATCHING
#define NRF_802154_DISABLE_BCC_MATCHING_PPI_CHANNELS_USED_MASK 0
#endif // NRF_802154_DISABLE_BCC_MATCHING
#ifdef NRF_802154_FRAME_TIMESTAMP_ENABLED
/**
* @def NRF_802154_PPI_RTC_COMPARE_TO_TIMER_CAPTURE
*
* The PPI channel that connects LP timer's COMPARE event to HP timer's TIMER_CAPTURE task.
*
* @note This option is used only when the timestamping feature is enabled
* (see @ref NRF_802154_FRAME_TIMESTAMP_ENABLED).
*
*/
#ifndef NRF_802154_PPI_RTC_COMPARE_TO_TIMER_CAPTURE
#define NRF_802154_PPI_RTC_COMPARE_TO_TIMER_CAPTURE NRF_PPI_CHANNEL13
#endif
/**
* @def NRF_802154_PPI_TIMESTAMP_EVENT_TO_TIMER_CAPTURE
*
* The PPI channel that connects provided event to HP timer's TIMER_CAPTURE task.
*
* @note This option is used only when the timestamping feature is enabled
* (see @ref NRF_802154_FRAME_TIMESTAMP_ENABLED).
*
*/
#ifndef NRF_802154_PPI_TIMESTAMP_EVENT_TO_TIMER_CAPTURE
#define NRF_802154_PPI_TIMESTAMP_EVENT_TO_TIMER_CAPTURE NRF_PPI_CHANNEL14
#endif
/**
* @def NRF_802154_TIMESTAMP_PPI_CHANNELS_USED_MASK
*
* Helper bit mask of PPI channels used by the 802.15.4 driver for timestamping.
*/
#define NRF_802154_TIMESTAMP_PPI_CHANNELS_USED_MASK \
((1 << NRF_802154_PPI_RTC_COMPARE_TO_TIMER_CAPTURE) | \
(1 << NRF_802154_PPI_TIMESTAMP_EVENT_TO_TIMER_CAPTURE))
#else // NRF_802154_FRAME_TIMESTAMP_ENABLED
#define NRF_802154_TIMESTAMP_PPI_CHANNELS_USED_MASK 0
#endif // NRF_802154_FRAME_TIMESTAMP_ENABLED
/**
* @def NRF_802154_PPI_CORE_GROUP
*
* The PPI channel group used to disable self-disabling PPIs used by the core module.
*
* @note This option is used by the core module regardless of the driver configuration.
*
*/
#ifndef NRF_802154_PPI_CORE_GROUP
#define NRF_802154_PPI_CORE_GROUP NRF_PPI_CHANNEL_GROUP0
#endif
#ifdef NRF_802154_FRAME_TIMESTAMP_ENABLED
/**
* @def NRF_802154_PPI_TIMESTAMP_GROUP
*
* The PPI channel group used to control PPIs used for timestamping.
*
* @note This option is used only when the timestamping feature is enabled
* (see @ref NRF_802154_FRAME_TIMESTAMP_ENABLED).
*
*/
#ifndef NRF_802154_PPI_TIMESTAMP_GROUP
#define NRF_802154_PPI_TIMESTAMP_GROUP NRF_PPI_CHANNEL_GROUP1
#endif
#endif // NRF_802154_FRAME_TIMESTAMP_ENABLED
/**
* @def NRF_802154_TIMERS_USED_MASK
*
* Bit mask of instances of timer peripherals used by the 802.15.4 driver.
*/
#ifndef NRF_802154_TIMERS_USED_MASK
#define NRF_802154_TIMERS_USED_MASK ((1 << NRF_802154_HIGH_PRECISION_TIMER_INSTANCE_NO) | \
(1 << NRF_802154_TIMER_INSTANCE_NO) | \
(1 << NRF_802154_COUNTER_TIMER_INSTANCE_NO))
#endif // NRF_802154_TIMERS_USED_MASK
/**
* @def NRF_802154_SWI_EGU_USED_MASK
*
* Bit mask of instances of SWI/EGU peripherals used by the 802.15.4 driver.
*/
#ifndef NRF_802154_SWI_EGU_USED_MASK
#define NRF_802154_SWI_EGU_USED_MASK (1 << NRF_802154_SWI_EGU_INSTANCE_NO)
#endif
/**
* @def NRF_802154_RTC_USED_MASK
*
* Bit mask of instances of RTC peripherals used by the 802.15.4 driver.
*/
#ifndef NRF_802154_RTC_USED_MASK
#define NRF_802154_RTC_USED_MASK (1 << NRF_802154_RTC_INSTANCE_NO)
#endif
/**
* @def NRF_802154_GPIO_PINS_USED_MASK
*
* Bit mask of GPIO pins used by the 802.15.4 driver.
*/
#ifndef NRF_802154_GPIO_PINS_USED_MASK
#define NRF_802154_GPIO_PINS_USED_MASK (NRF_802154_FEM_PINS_USED_MASK | \
NRF_802154_DEBUG_PINS_USED_MASK)
#endif // NRF_802154_GPIO_PINS_USED_MASK
/**
* @def NRF_802154_GPIOTE_CHANNELS_USED_MASK
*
* Bit mask of GPIOTE peripherals used by the 802.15.4 driver.
*/
#ifndef NRF_802154_GPIOTE_CHANNELS_USED_MASK
#define NRF_802154_GPIOTE_CHANNELS_USED_MASK (NRF_802154_FEM_GPIOTE_CHANNELS_USED_MASK | \
NRF_802154_DEBUG_GPIOTE_CHANNELS_USED_MASK)
#endif // NRF_802154_GPIOTE_CHANNELS_USED_MASK
/**
* @def NRF_80254_PPI_CHANNELS_USED_MASK
*
* Bit mask of PPI channels used by the 802.15.4 driver.
*/
#ifndef NRF_802154_PPI_CHANNELS_USED_MASK
#define NRF_802154_PPI_CHANNELS_USED_MASK ((1 << NRF_802154_PPI_RADIO_DISABLED_TO_EGU) | \
(1 << NRF_802154_PPI_EGU_TO_RADIO_RAMP_UP) | \
(1 << NRF_802154_PPI_EGU_TO_TIMER_START) | \
(1 << NRF_802154_PPI_RADIO_CRCERROR_TO_TIMER_CLEAR) | \
(1 << NRF_802154_PPI_RADIO_CCAIDLE_TO_FEM_GPIOTE) | \
(1 << NRF_802154_PPI_TIMER_COMPARE_TO_RADIO_TXEN) | \
(1 << NRF_802154_PPI_RADIO_CRCOK_TO_PPI_GRP_DISABLE) | \
NRF_802154_DISABLE_BCC_MATCHING_PPI_CHANNELS_USED_MASK | \
NRF_802154_TIMESTAMP_PPI_CHANNELS_USED_MASK | \
NRF_802154_FEM_PPI_CHANNELS_USED_MASK | \
NRF_802154_DEBUG_PPI_CHANNELS_USED_MASK)
#endif // NRF_802154_PPI_CHANNELS_USED_MASK
/**
* @def NRF_802154_PPI_GROUPS_USED_MASK
*
* Bit mask of PPI groups identifiers used by the 802.15.4 driver.
*/
#ifndef NRF_802154_PPI_GROUPS_USED_MASK
#ifdef NRF_802154_FRAME_TIMESTAMP_ENABLED
#define NRF_802154_PPI_GROUPS_USED_MASK ((1 << NRF_802154_PPI_CORE_GROUP) | \
(1 << NRF_802154_PPI_TIMESTAMP_GROUP)
#else // NRF_802154_FRAME_TIMESTAMP_ENABLED
#define NRF_802154_PPI_GROUPS_USED_MASK (1 << NRF_802154_PPI_CORE_GROUP)
#endif // NRF_802154_FRAME_TIMESTAMP_ENABLED
#endif // NRF_802154_PPI_GROUPS_USED_MASK
#ifdef __cplusplus
}
#endif
#endif // NRF_802154_PERIPHERALS_H__
@@ -44,9 +44,10 @@
#include "nrf_802154_core.h"
#include "nrf_802154_critical_section.h"
#include "nrf_802154_debug.h"
#include "nrf_802154_utils.h"
#include "nrf_802154_peripherals.h"
#include "nrf_802154_rx_buffer.h"
#include "nrf_802154_swi.h"
#include "nrf_802154_utils.h"
#include "nrf_radio.h"
#include <nrf.h>
@@ -1,178 +0,0 @@
/* Copyright (c) 2017 - 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 helpers for checking nRF SoC revision.
*
*/
#include "nrf_802154_revision.h"
#include <assert.h>
/** @breif Types of nRF revisions. */
typedef enum
{
NRF52840_REVISION_AAAA,
NRF52840_REVISION_AABA,
NRF52840_REVISION_AACX,
NRF52811_REVISION,
NRF_REVISION_UNKNOWN,
} nrf_802154_chip_revision;
static nrf_802154_chip_revision m_nrf_revision = NRF_REVISION_UNKNOWN;
/**
* @brief Internal auxiliary function to check if the program is running on NRF52840 chip.
*
* @retval true If it is NRF52480 chip.
* @retval false If it is other chip.
*/
static inline bool nrf_revision_type_52840(void)
{
return ((((*(uint32_t *)0xF0000FE0) & 0xFF) == 0x08) &&
(((*(uint32_t *)0xF0000FE4) & 0x0F) == 0x00));
}
/**
* @brief Internal auxiliary function to check if the program is running
* on the AAAA revision of the nRF52840 chip.
*
* @retval true If it is NRF52480_AAAA chip revision.
* @retval false It is other chip revision.
*/
static inline bool nrf_revision_type_52840_aaaa(void)
{
return (nrf_revision_type_52840() &&
(((*(uint32_t *)0xF0000FE8) & 0xF0) == 0x00) && // revision
(((*(uint32_t *)0xF0000FEC) & 0xF0) == 0x00)); // sub-revision
}
/**
* @brief Internal auxiliary function to check if the program is running
* on the AABA revision of the nRF52840 chip.
*
* @retval true If it is NRF52480_AABA chip revision.
* @retval false It is other chip revision.
*/
static inline bool nrf_revision_type_52840_aaba(void)
{
return (nrf_revision_type_52840() &&
(((*(uint32_t *)0xF0000FE8) & 0xF0) == 0x10) && // revision
(((*(uint32_t *)0xF0000FEC) & 0xF0) == 0x00)); // sub-revision
}
/**
* @brief Internal auxiliary function to check if the program is running
* on the AACx revision of the nRF52840 chip.
*
* @retval true If it is NRF52480_AACx chip revision.
* @retval false It is other chip revision.
*/
static inline bool nrf_revision_type_52840_aacx(void)
{
return (nrf_revision_type_52840() &&
(((*(uint32_t *)0xF0000FE8) & 0xF0) == 0x20) && // revision
(((*(uint32_t *)0xF0000FEC) & 0xF0) == 0x00)); // sub-revision
}
/**
* @brief Internal auxiliary function to check if the program is running on NRF52811 chip.
*
* @retval true If it is NRF52411 chip.
* @retval false If it is other chip.
*/
static inline bool nrf_revision_type_52811(void)
{
return ((((*(uint32_t *)0xF0000FE0) & 0xFF) == 0x0E) &&
(((*(uint32_t *)0xF0000FE4) & 0x0F) == 0x00));
}
void nrf_802154_revision_init(void)
{
if (nrf_revision_type_52840_aaaa())
{
m_nrf_revision = NRF52840_REVISION_AAAA;
}
else if (nrf_revision_type_52840_aaba())
{
m_nrf_revision = NRF52840_REVISION_AABA;
}
else if (nrf_revision_type_52840_aacx())
{
m_nrf_revision = NRF52840_REVISION_AACX;
}
else if (nrf_revision_type_52811())
{
m_nrf_revision = NRF52811_REVISION;
}
else
{
m_nrf_revision = NRF_REVISION_UNKNOWN;
}
// This variable may be unused if revision is defined by the compiler.
(void)m_nrf_revision;
}
bool nrf_802154_revision_has_phyend_event(void)
{
#if defined(NRF52840_XXAA) || defined(NRF52840_AAAA)
return false;
#elif defined(NRF52840_AABA)
return true;
#elif defined(NRF52840_AACX)
return true;
#elif defined(NRF52811_XXAA)
return true;
#else
bool result = false;
switch (m_nrf_revision)
{
case NRF52840_REVISION_AAAA:
result = false;
break;
case NRF52840_REVISION_AABA:
case NRF52840_REVISION_AACX:
case NRF52811_REVISION:
case NRF_REVISION_UNKNOWN:
result = true;
break;
default:
assert(false);
}
return result;
#endif // NRF52840_AAAA
}
@@ -43,6 +43,7 @@
#include "nrf_802154.h"
#include "nrf_802154_config.h"
#include "nrf_802154_core.h"
#include "nrf_802154_peripherals.h"
#include "nrf_802154_rx_buffer.h"
#include "nrf_802154_utils.h"
#include "nrf_egu.h"
@@ -54,6 +55,7 @@
* detection.
*/
#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.
@@ -42,7 +42,7 @@
#include "nrf_802154_config.h"
#include "nrf_802154_debug.h"
#include "nrf_ppi.h"
#include "nrf_802154_peripherals.h"
#include "platform/hp_timer/nrf_802154_hp_timer.h"
#include "platform/lp_timer/nrf_802154_lp_timer.h"
@@ -57,13 +57,9 @@
#define RESYNC_TIME (4 * 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_SYNC PPI_CH0
#define PPI_TIMESTAMP PPI_CH1
#define PPI_TIMESTAMP_GROUP PPI_CHGRP0
#define PPI_SYNC NRF_802154_PPI_RTC_COMPARE_TO_TIMER_CAPTURE
#define PPI_TIMESTAMP NRF_802154_PPI_TIMESTAMP_EVENT_TO_TIMER_CAPTURE
#define PPI_TIMESTAMP_GROUP NRF_802154_PPI_TIMESTAMP_GROUP
#if NRF_802154_FRAME_TIMESTAMP_ENABLED
// Structure holding common timepoint from both timers.
@@ -138,6 +138,23 @@ typedef uint8_t nrf_802154_ack_data_t;
#define NRF_802154_ACK_DATA_PENDING_BIT 0x00
#define NRF_802154_ACK_DATA_IE 0x01
/**
* @brief Methods of source address matching.
*
* You can use one of the following methods that can be set during the initialization phase
* by calling @ref nrf_802154_src_matching_method:
* - For Thread: @ref NRF_802154_SRC_ADDR_MATCH_THREAD -- The pending bit is set only for the addresses found in the list.
* - For Zigbee: @ref NRF_802154_SRC_ADDR_MATCH_ZIGBEE -- The pending bit is cleared only for the short addresses found in the list.\n
* This method does not set pending bit in non-command and non-data-request frames.
* - For standard-compliant implementation: @ref NRF_802154_SRC_ADDR_MATCH_ALWAYS_1 -- The pending bit is always set to 1.\n
* This requires an empty data frame with AR set to 0 to be transmitted immediately afterwards.
*/
typedef uint8_t nrf_802154_src_addr_match_t;
#define NRF_802154_SRC_ADDR_MATCH_THREAD 0x00 // !< Implementation for the Thread protocol.
#define NRF_802154_SRC_ADDR_MATCH_ZIGBEE 0x01 // !< Implementation for the Zigbee protocol.
#define NRF_802154_SRC_ADDR_MATCH_ALWAYS_1 0x02 // !< Standard compliant implementation.
/**
* @brief RSSI measurement results.
*/
@@ -0,0 +1,114 @@
/* Copyright (c) 2017 - 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 the nrf 802.15.4 HF Clock abstraction with SDK driver.
*
* This implementation uses clock driver implementation from SDK.
*/
#include "nrf_802154_clock.h"
#include <stddef.h>
#include <compiler_abstraction.h>
#include <nrf_drv_clock.h>
static void clock_handler(nrf_drv_clock_evt_type_t event);
static nrf_drv_clock_handler_item_t m_clock_handler =
{
.p_next = NULL,
.event_handler = clock_handler,
};
static void clock_handler(nrf_drv_clock_evt_type_t event)
{
if (event == NRF_DRV_CLOCK_EVT_HFCLK_STARTED)
{
nrf_802154_clock_hfclk_ready();
}
if (event == NRF_DRV_CLOCK_EVT_LFCLK_STARTED)
{
nrf_802154_clock_lfclk_ready();
}
}
void nrf_802154_clock_init(void)
{
// Intentionally empty.
}
void nrf_802154_clock_deinit(void)
{
// Intentionally empty.
}
void nrf_802154_clock_hfclk_start(void)
{
nrf_drv_clock_hfclk_request(&m_clock_handler);
}
void nrf_802154_clock_hfclk_stop(void)
{
nrf_drv_clock_hfclk_release();
}
bool nrf_802154_clock_hfclk_is_running(void)
{
return nrf_drv_clock_hfclk_is_running();
}
void nrf_802154_clock_lfclk_start(void)
{
nrf_drv_clock_lfclk_request(&m_clock_handler);
}
void nrf_802154_clock_lfclk_stop(void)
{
nrf_drv_clock_lfclk_release();
}
bool nrf_802154_clock_lfclk_is_running(void)
{
return nrf_drv_clock_lfclk_is_running();
}
__WEAK void nrf_802154_clock_hfclk_ready(void)
{
// Intentionally empty.
}
__WEAK void nrf_802154_clock_lfclk_ready(void)
{
// Intentionally empty.
}
@@ -65,12 +65,12 @@ static void clock_handler(nrf_drv_clock_evt_type_t event)
void nrf_802154_clock_init(void)
{
// Intentionally empty.
nrf_drv_clock_init();
}
void nrf_802154_clock_deinit(void)
{
// Intentionally empty.
nrf_drv_clock_uninit();
}
void nrf_802154_clock_hfclk_start(void)
@@ -36,7 +36,7 @@
#ifndef NRF_802154_WIFI_COEX_H_
#define NRF_802154_WIFI_COEX_H_
#include "nrf_802154_rsch.h"
#include "rsch/nrf_802154_rsch.h"
#ifdef __cplusplus
extern "C" {
@@ -75,7 +75,7 @@ void nrf_802154_wifi_coex_uninit(void);
* @param[in] priority The requested priority level.
*
*/
void nrf_802154_wifi_coex_prio_req(rsch_prio_t priority);
void nrf_802154_wifi_coex_prio_request(rsch_prio_t priority);
/**
* @brief Gets the priority denial event address.
@@ -0,0 +1,69 @@
/* Copyright (c) 2017 - 2019, 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 the nrf 802.15.4 WiFi Coexitstence abstraction in case no implementation is used.
*
*/
#include "nrf_802154_wifi_coex.h"
#include "stddef.h"
#include <nrf.h>
void nrf_802154_wifi_coex_init(void)
{
// Intentionally empty
}
void nrf_802154_wifi_coex_uninit(void)
{
// Intentionally empty
}
void nrf_802154_wifi_coex_prio_request(rsch_prio_t priority)
{
(void)priority;
// Intentionally empty
}
void * nrf_802154_wifi_coex_deny_event_addr_get(void)
{
// Intentionally empty
return NULL;
}
__WEAK void nrf_802154_wifi_coex_prio_changed(rsch_prio_t priority)
{
(void)priority;
// Intentionally empty
}
@@ -47,9 +47,10 @@
#include <nrf_timer.h>
#include "nrf_802154_config.h"
#include "nrf_802154_peripherals.h"
/**@brief Timer instance. */
#define TIMER NRF_TIMER0
#define TIMER NRF_802154_HIGH_PRECISION_TIMER_INSTANCE
/**@brief Timer compare channel definitions. */
#define TIMER_CC_CAPTURE NRF_TIMER_CC_CHANNEL1
@@ -45,6 +45,7 @@
#include "platform/clock/nrf_802154_clock.h"
#include "nrf_802154_config.h"
#include "nrf_802154_peripherals.h"
#include "nrf_802154_utils.h"
#define RTC_LP_TIMER_COMPARE_CHANNEL 0
@@ -0,0 +1,82 @@
/* Copyright (c) 2019, 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 the pseudo-random number generator abstraction layer.
*
* This pseudo-random number abstraction layer uses newlib's rand_r() function.
*
*/
#define _POSIX_C_SOURCE 1 // Enable access to POSIX functions (rand_r is not from the std library)
#include "nrf_802154_random.h"
#include <stdlib.h>
#include <stdint.h>
#include "nrf.h"
#if RAAL_SOFTDEVICE
#include <nrf_soc.h>
#endif // RAAL_SOFTDEVICE
unsigned int m_seed;
void nrf_802154_random_init(void)
{
#if RAAL_SOFTDEVICE
uint32_t result;
do
{
result = sd_rand_application_vector_get((uint8_t *)&m_seed, sizeof(m_seed));
}
while (result != NRF_SUCCESS);
#else // RAAL_SOFTDEVICE
NRF_RNG->TASKS_START = 1;
while (!NRF_RNG->EVENTS_VALRDY);
NRF_RNG->EVENTS_VALRDY = 0;
m_seed = NRF_RNG->VALUE;
#endif // RAAL_SOFTDEVICE
}
void nrf_802154_random_deinit(void)
{
// Intentionally empty
}
uint32_t nrf_802154_random_get(void)
{
return (uint32_t)rand_r(&m_seed);
}
@@ -44,7 +44,7 @@
#include "nrf.h"
#if RAAL_SOFTDEVICE
#include <softdevice.h>
#include <nrf_soc.h>
#endif // RAAL_SOFTDEVICE
void nrf_802154_random_init(void)
@@ -7,6 +7,7 @@
#include "../nrf_802154_debug.h"
#include "nrf_802154_priority_drop.h"
#include "platform/clock/nrf_802154_clock.h"
#include "platform/coex/nrf_802154_wifi_coex.h"
#include "raal/nrf_raal_api.h"
#include "timer_scheduler/nrf_802154_timer_sched.h"
@@ -227,6 +228,9 @@ static inline void all_prec_update(void)
nrf_802154_clock_hfclk_start();
nrf_raal_continuous_mode_enter();
}
nrf_802154_wifi_coex_prio_request(new_prio);
prec_approved_prio_set(RSCH_PREC_COEX, new_prio);
}
mutex_unlock(&m_req_mutex);
@@ -363,6 +367,7 @@ static void delayed_timeslot_prec_request(void * p_context)
void nrf_802154_rsch_init(void)
{
nrf_raal_init();
nrf_802154_wifi_coex_init();
m_ntf_mutex = 0;
m_req_mutex = 0;
@@ -388,6 +393,7 @@ void nrf_802154_rsch_uninit(void)
nrf_802154_timer_sched_remove(&m_dly_ts[i].timer, NULL);
}
nrf_802154_wifi_coex_uninit();
nrf_raal_uninit();
}
@@ -64,6 +64,7 @@ typedef enum
{
RSCH_PREC_HFCLK,
RSCH_PREC_RAAL,
RSCH_PREC_COEX,
RSCH_PREC_CNT,
} rsch_prec_t;
@@ -117,7 +118,7 @@ void nrf_802154_rsch_uninit(void);
* possible to give the radio driver core as much radio time as possible while
* disturbing the other activities to the minimum extent.
*
* @note The start of a timeslot is indicated by the @ref nrf_802154_rsch_prec_approved call.
* @note The start of a timeslot is indicated by the @ref nrf_802154_rsch_prec_is_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.
@@ -137,7 +138,7 @@ void nrf_802154_rsch_continuous_ended(void);
/**
* @brief Immediately requests a timeslot for radio communication.
*
* This function is to be called only after @ref nrf_802154_rsch_prec_approved indicated the
* This function is to be called only after @ref nrf_802154_rsch_prec_is_approved indicated the
* start of a timeslot.
*
* @param[in] length_us Requested radio timeslot length in microseconds.
@@ -71,16 +71,16 @@ _Pragma("GCC diagnostic pop")
**************************************************************************************************/
/*
* @brief Defines the minimum version of the SoftDevice that supports configuration of BLE advertising
* @brief Defines the only 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
* The only 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)
#define BLE_ADV_SCHED_CFG_SUPPORT_SD_VERSION (6001001)
/*
* @brief Defines the minimum version of the SoftDevice that correctly handles timeslot releasing.
@@ -713,9 +713,9 @@ void nrf_raal_init(void)
assert(err_code == NRF_SUCCESS);
(void)err_code;
#if (SD_VERSION >= BLE_ADV_SCHED_CFG_SUPPORT_MIN_SD_VERSION)
#if (SD_VERSION == BLE_ADV_SCHED_CFG_SUPPORT_SD_VERSION)
// Ensure that correct SoftDevice version is flashed.
if (SD_VERSION_GET(MBR_SIZE) >= BLE_ADV_SCHED_CFG_SUPPORT_MIN_SD_VERSION)
if (SD_VERSION_GET(MBR_SIZE) == BLE_ADV_SCHED_CFG_SUPPORT_SD_VERSION)
{
// Use improved Advertiser Role Scheduling configuration.
ble_opt_t opt;
@@ -51,7 +51,7 @@ extern "C" {
#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_TIMEOUT 2500
#define NRF_RAAL_TIMESLOT_DEFAULT_MAX_LENGTH 120000000
#define NRF_RAAL_DEFAULT_LF_CLK_ACCURACY_PPM 500