nimble/phy/nrf5x: Move out nRF52 code

This moves most of code specific to nRF52 series to separate file and
creates private phy APIs to call that code.

The moved code is anything related to PPI: FEM, GPIO debug and PPI
itself.
This commit is contained in:
Andrzej Kaczmarek
2022-09-14 12:52:29 +02:00
parent a7b016ebac
commit 4d3b302fa6
4 changed files with 406 additions and 216 deletions
+49 -216
View File
@@ -25,7 +25,6 @@
#include <hal/nrf_ccm.h>
#include <hal/nrf_aar.h>
#include <hal/nrf_timer.h>
#include <hal/nrf_ppi.h>
#include <hal/nrf_rtc.h>
#include "syscfg/syscfg.h"
#include "os/os.h"
@@ -46,6 +45,7 @@
#else
#include "core_cm4.h"
#endif
#include "phy_priv.h"
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
#if !MYNEWT_VAL_CHOICE(MCU_TARGET, nRF52840) && !MYNEWT_VAL_CHOICE(MCU_TARGET, nRF52811)
@@ -319,27 +319,6 @@ struct nrf_ccm_data
struct nrf_ccm_data g_nrf_ccm_data;
#endif
static int g_ble_phy_gpiote_idx;
#if MYNEWT_VAL(BLE_LL_FEM_PA) || MYNEWT_VAL(BLE_LL_FEM_LNA)
#define FEM_SINGLE_GPIO \
(!MYNEWT_VAL(BLE_LL_FEM_PA) || !MYNEWT_VAL(BLE_LL_FEM_LNA) || \
(MYNEWT_VAL(BLE_LL_FEM_PA_GPIO) == MYNEWT_VAL(BLE_LL_FEM_LNA_GPIO)))
#if FEM_SINGLE_GPIO
static uint8_t fem_idx;
#else
#if MYNEWT_VAL(BLE_LL_FEM_PA)
static uint8_t fem_pa_idx;
#endif
#if MYNEWT_VAL(BLE_LL_FEM_LNA)
static uint8_t fem_lna_idx;
#endif
#endif
#endif
#ifndef BABBLESIM
static void
ble_phy_apply_errata_102_106_107(void)
@@ -465,36 +444,6 @@ ble_phy_mode_set(uint8_t tx_phy_mode, uint8_t rx_phy_mode)
}
#endif
static void
ble_phy_fem_enable_pa(void)
{
#if MYNEWT_VAL(BLE_LL_FEM_PA)
ble_ll_fem_pa_enable();
#if !FEM_SINGLE_GPIO
NRF_PPI->CH[6].TEP = (uint32_t) &(NRF_GPIOTE->TASKS_SET[fem_pa_idx]);
NRF_PPI->CH[7].TEP = (uint32_t) &(NRF_GPIOTE->TASKS_CLR[fem_pa_idx]);
#endif
NRF_PPI->CHENSET = PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk;
#endif
}
static void
ble_phy_fem_enable_lna(void)
{
#if MYNEWT_VAL(BLE_LL_FEM_LNA)
ble_ll_fem_lna_enable();
#if !FEM_SINGLE_GPIO
NRF_PPI->CH[6].TEP = (uint32_t) &(NRF_GPIOTE->TASKS_SET[fem_lna_idx]);
NRF_PPI->CH[7].TEP = (uint32_t) &(NRF_GPIOTE->TASKS_CLR[fem_lna_idx]);
#endif
NRF_PPI->CHENSET = PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk;
#endif
}
int
ble_phy_get_cur_phy(void)
{
@@ -741,7 +690,7 @@ ble_phy_set_start_time(uint32_t cputime, uint8_t rem_usecs, bool tx)
nrf_rtc_event_enable(NRF_RTC0, RTC_EVTENSET_COMPARE0_Msk);
/* Enable PPI */
nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH31_Msk);
phy_ppi_rtc0_compare0_to_timer0_start_enable();
/* Store the cputime at which we set the RTC */
g_ble_phy_data.phy_start_cputime = cputime;
@@ -777,7 +726,8 @@ ble_phy_set_start_now(void)
nrf_rtc_event_enable(NRF_RTC0, RTC_EVTENSET_COMPARE0_Msk);
/* Enable PPI */
nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH31_Msk);
phy_ppi_rtc0_compare0_to_timer0_start_enable();
/*
* Store the cputime at which we set the RTC
*
@@ -856,7 +806,7 @@ ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs)
NRF_TIMER0->EVENTS_COMPARE[3] = 0;
/* Enable wait for response PPI */
nrf_ppi_channels_enable(NRF_PPI, (PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk));
phy_ppi_wfr_enable();
/*
* It may happen that if CPU is halted for a brief moment (e.g. during flash
@@ -872,7 +822,7 @@ ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs)
*/
nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_CAPTURE1);
if (NRF_TIMER0->CC[1] > NRF_TIMER0->CC[3]) {
nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk);
phy_ppi_wfr_disable();
nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_DISABLE);
}
}
@@ -927,7 +877,7 @@ ble_phy_rx_xcvr_setup(void)
NRF_CCM->EVENTS_ERROR = 0;
NRF_CCM->EVENTS_ENDCRYPT = 0;
nrf_ccm_task_trigger(NRF_CCM, NRF_CCM_TASK_KSGEN);
nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH25_Msk);
phy_ppi_radio_address_to_ccm_crypt_enable();
} else {
NRF_RADIO->PACKETPTR = (uint32_t)dptr;
}
@@ -951,7 +901,8 @@ ble_phy_rx_xcvr_setup(void)
#endif
/* Turn off trigger TXEN on output compare match and AAR on bcmatch */
nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH20_Msk | PPI_CHEN_CH23_Msk);
phy_ppi_timer0_compare0_to_radio_txen_disable();
phy_ppi_radio_bcmatch_to_aar_start_disable();
/* Reset the rx started flag. Used for the wait for response */
g_ble_phy_data.phy_rx_started = 0;
@@ -1052,9 +1003,11 @@ ble_phy_tx_end_isr(void)
nrf_timer_cc_set(NRF_TIMER0, 0, rx_time);
NRF_TIMER0->EVENTS_COMPARE[0] = 0;
nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH21_Msk);
phy_ppi_timer0_compare0_to_radio_rxen_enable();
ble_phy_fem_enable_lna();
#if PHY_USE_FEM_LNA
phy_fem_enable_lna();
#endif
} else if (transition == BLE_PHY_TRANSITION_TX_TX) {
/* Schedule TX exactly T_IFS after TX end captured in CC[2] */
tx_time = NRF_TIMER0->CC[2] + ble_phy_tifs_get();
@@ -1067,11 +1020,11 @@ ble_phy_tx_end_isr(void)
nrf_timer_cc_set(NRF_TIMER0, 0, tx_time);
NRF_TIMER0->EVENTS_COMPARE[0] = 0;
nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH20_Msk);
phy_ppi_timer0_compare0_to_radio_txen_enable();
nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_CAPTURE3);
if (NRF_TIMER0->CC[3] > NRF_TIMER0->CC[0]) {
nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH20_Msk);
phy_ppi_timer0_compare0_to_radio_txen_disable();
g_ble_phy_data.phy_transition_late = 1;
}
} else {
@@ -1081,8 +1034,9 @@ ble_phy_tx_end_isr(void)
*/
nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_STOP);
NRF_TIMER0->TASKS_SHUTDOWN = 1;
nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk |
PPI_CHEN_CH20_Msk | PPI_CHEN_CH31_Msk);
phy_ppi_wfr_disable();
phy_ppi_timer0_compare0_to_radio_txen_disable();
phy_ppi_rtc0_compare0_to_timer0_start_disable();
assert(transition == BLE_PHY_TRANSITION_NONE);
}
}
@@ -1122,7 +1076,7 @@ ble_phy_rx_end_isr(void)
struct ble_mbuf_hdr *ble_hdr;
/* Disable automatic RXEN */
nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH21_Msk);
phy_ppi_timer0_compare0_to_radio_rxen_disable();
/* Set RSSI and CRC status flag in header */
ble_hdr = &g_ble_phy_data.rxhdr;
@@ -1194,9 +1148,11 @@ ble_phy_rx_end_isr(void)
nrf_timer_cc_set(NRF_TIMER0, 0, tx_time);
NRF_TIMER0->EVENTS_COMPARE[0] = 0;
nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH20_Msk);
phy_ppi_timer0_compare0_to_radio_txen_enable();
ble_phy_fem_enable_pa();
#if PHY_USE_FEM_PA
phy_fem_enable_pa();
#endif
/*
* XXX: Hack warning!
@@ -1212,7 +1168,7 @@ ble_phy_rx_end_isr(void)
*/
nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_CAPTURE3);
if (NRF_TIMER0->CC[3] > NRF_TIMER0->CC[0]) {
nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH20_Msk);
phy_ppi_timer0_compare0_to_radio_txen_disable();
g_ble_phy_data.phy_transition_late = 1;
}
@@ -1250,7 +1206,7 @@ ble_phy_rx_start_isr(void)
nrf_radio_int_disable(NRF_RADIO, RADIO_INTENCLR_ADDRESS_Msk);
/* Clear wfr timer channels */
nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk);
phy_ppi_wfr_disable();
/* Initialize the ble mbuf header */
ble_hdr = &g_ble_phy_data.rxhdr;
@@ -1332,7 +1288,7 @@ ble_phy_rx_start_isr(void)
/* Trigger AAR after last bit of AdvA is received */
NRF_RADIO->EVENTS_BCMATCH = 0;
nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH23_Msk);
phy_ppi_radio_bcmatch_to_aar_start_enable();
nrf_radio_bcc_set(NRF_RADIO, (BLE_LL_PDU_HDR_LEN + adva_offset +
BLE_DEV_ADDR_LEN) * 8 + g_ble_phy_data.phy_bcc_offset);
}
@@ -1409,7 +1365,7 @@ ble_phy_isr(void)
switch (g_ble_phy_data.phy_state) {
case BLE_PHY_STATE_RX:
#if MYNEWT_VAL(BLE_LL_FEM_LNA)
NRF_PPI->CHENCLR = PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk;
phy_ppi_fem_disable();
ble_ll_fem_lna_disable();
#endif
if (g_ble_phy_data.phy_rx_started) {
@@ -1420,7 +1376,7 @@ ble_phy_isr(void)
break;
case BLE_PHY_STATE_TX:
#if MYNEWT_VAL(BLE_LL_FEM_PA)
NRF_PPI->CHENCLR = PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk;
phy_ppi_fem_disable();
ble_ll_fem_pa_disable();
#endif
ble_phy_tx_end_isr();
@@ -1438,95 +1394,6 @@ ble_phy_isr(void)
os_trace_isr_exit();
}
#if MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN) >= 0 || \
MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0 || \
MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0 || \
MYNEWT_VAL(BLE_LL_FEM_PA) || \
MYNEWT_VAL(BLE_LL_FEM_LNA)
static int
ble_phy_gpiote_configure(int pin)
{
NRF_GPIO_Type *port;
g_ble_phy_gpiote_idx--;
#if NRF52840_XXAA
port = pin > 31 ? NRF_P1 : NRF_P0;
pin &= 0x1f;
#else
port = NRF_P0;
#endif
/* Configure GPIO directly to avoid dependency to hal_gpio (for porting) */
port->DIRSET = (1 << pin);
port->OUTCLR = (1 << pin);
NRF_GPIOTE->CONFIG[g_ble_phy_gpiote_idx] =
(GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) |
((pin & 0x1F) << GPIOTE_CONFIG_PSEL_Pos) |
#if NRF52840_XXAA
((port == NRF_P1) << GPIOTE_CONFIG_PORT_Pos);
#else
0;
#endif
BLE_LL_ASSERT(g_ble_phy_gpiote_idx >= 0);
return g_ble_phy_gpiote_idx;
}
#endif
static void
ble_phy_dbg_time_setup(void)
{
int idx __attribute__((unused));
/*
* We setup GPIOTE starting from last configuration index to minimize risk
* of conflict with GPIO setup via hal. It's not great solution, but since
* this is just debugging code we can live with this.
*/
#if MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN) >= 0
idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN));
nrf_ppi_channel_endpoint_setup(NRF_PPI, 17, (uint32_t)&(NRF_RADIO->EVENTS_READY),
(uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx]));
nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH17_Msk);
/* CH[20] and PPI CH[21] are on to trigger TASKS_TXEN or TASKS_RXEN */
nrf_ppi_fork_endpoint_setup(NRF_PPI, 20, (uint32_t)&(NRF_GPIOTE->TASKS_SET[idx]));
nrf_ppi_fork_endpoint_setup(NRF_PPI, 21, (uint32_t)&(NRF_GPIOTE->TASKS_SET[idx]));
#endif
#if MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0
idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN));
/* CH[26] and CH[27] are always on for EVENT_ADDRESS and EVENT_END */
nrf_ppi_fork_endpoint_setup(NRF_PPI, 26, (uint32_t)&(NRF_GPIOTE->TASKS_SET[idx]));
nrf_ppi_fork_endpoint_setup(NRF_PPI, 27, (uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx]));
#endif
#if MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0
idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN));
#if NRF52840_XXAA
nrf_ppi_channel_endpoint_setup(NRF_PPI, 18, (uint32_t)&(NRF_RADIO->EVENTS_RXREADY),
(uint32_t)&(NRF_GPIOTE->TASKS_SET[idx]));
#else
nrf_ppi_channel_endpoint_setup(NRF_PPI, 18, (uint32_t)&(NRF_RADIO->EVENTS_READY),
(uint32_t)&(NRF_GPIOTE->TASKS_SET[idx]));
#endif
nrf_ppi_channel_endpoint_setup(NRF_PPI, 19, (uint32_t)&(NRF_RADIO->EVENTS_DISABLED),
(uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx]));
nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH18_Msk | PPI_CHEN_CH19_Msk);
/* CH[4] and CH[5] are always on for wfr */
nrf_ppi_fork_endpoint_setup(NRF_PPI, 4, (uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx]));
nrf_ppi_fork_endpoint_setup(NRF_PPI, 5, (uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx]));
#endif
}
/**
* ble phy init
*
@@ -1539,8 +1406,6 @@ ble_phy_init(void)
{
int rc;
g_ble_phy_gpiote_idx = 8;
/* Default phy to use is 1M */
g_ble_phy_data.phy_cur_phy_mode = BLE_PHY_MODE_1M;
g_ble_phy_data.phy_tx_phy_mode = BLE_PHY_MODE_1M;
@@ -1589,9 +1454,6 @@ ble_phy_init(void)
/* Configure IFS */
NRF_RADIO->TIFS = BLE_LL_IFS;
/* Captures tx/rx start in timer0 cc 1 and tx/rx end in timer0 cc 2 */
nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH26_Msk | PPI_CHEN_CH27_Msk);
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
nrf_ccm_int_disable(NRF_CCM, 0xffffffff);
NRF_CCM->SHORTS = CCM_SHORTS_ENDKSGEN_CRYPT_Msk;
@@ -1616,39 +1478,13 @@ ble_phy_init(void)
NRF_TIMER0->MODE = 0; /* Timer mode */
NRF_TIMER0->PRESCALER = 4; /* gives us 1 MHz */
/*
* PPI setup.
* Channel 4: Captures TIMER0 in CC[3] when EVENTS_ADDRESS occurs. Used
* to cancel the wait for response timer.
* Channel 5: TIMER0 CC[3] to TASKS_DISABLE on radio. This is the wait
* for response timer.
*/
nrf_ppi_channel_endpoint_setup(NRF_PPI, NRF_PPI_CHANNEL4,
(uint32_t)&(NRF_RADIO->EVENTS_ADDRESS),
(uint32_t)&(NRF_TIMER0->TASKS_CAPTURE[3]));
nrf_ppi_channel_endpoint_setup(NRF_PPI, NRF_PPI_CHANNEL5,
(uint32_t)&(NRF_TIMER0->EVENTS_COMPARE[3]),
(uint32_t)&(NRF_RADIO->TASKS_DISABLE));
phy_ppi_init();
#if MYNEWT_VAL(BLE_LL_FEM_PA) || MYNEWT_VAL(BLE_LL_FEM_LNA)
#if FEM_SINGLE_GPIO
fem_idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_LL_FEM_PA_GPIO));
NRF_PPI->CH[6].TEP = (uint32_t) &(NRF_GPIOTE->TASKS_SET[fem_idx]);
NRF_PPI->CH[7].TEP = (uint32_t) &(NRF_GPIOTE->TASKS_CLR[fem_idx]);
#else
#if MYNEWT_VAL(BLE_LL_FEM_PA)
fem_pa_idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_LL_FEM_PA_GPIO));
NRF_GPIOTE->TASKS_CLR[fem_pa_idx] = 1;
#if PHY_USE_DEBUG
phy_debug_init();
#endif
#if MYNEWT_VAL(BLE_LL_FEM_LNA)
fem_lna_idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_LL_FEM_LNA_GPIO));
NRF_GPIOTE->TASKS_CLR[fem_lna_idx] = 1;
#endif
#endif
NRF_PPI->CH[6].EEP = (uint32_t)&(NRF_RADIO->EVENTS_READY);
NRF_PPI->CH[7].EEP = (uint32_t)&(NRF_RADIO->EVENTS_DISABLED);
NRF_PPI->CHENCLR = PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk;
#if PHY_USE_FEM
phy_fem_init();
#endif
/* Set isr in vector table and enable interrupt */
@@ -1674,8 +1510,6 @@ ble_phy_init(void)
g_ble_phy_data.phy_stats_initialized = 1;
}
ble_phy_dbg_time_setup();
return 0;
}
@@ -1715,9 +1549,6 @@ ble_phy_rx(void)
/* Setup for rx */
ble_phy_rx_xcvr_setup();
/* PPI to start radio automatically shall be set here */
assert(NRF_PPI->CHEN & PPI_CHEN_CH21_Msk);
return 0;
}
@@ -1756,7 +1587,7 @@ ble_phy_encrypt_set_pkt_cntr(uint64_t pkt_counter, int dir)
void
ble_phy_encrypt_disable(void)
{
nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH25_Msk);
phy_ppi_radio_address_to_ccm_crypt_disable();
nrf_ccm_task_trigger(NRF_CCM, NRF_CCM_TASK_STOP);
NRF_CCM->EVENTS_ERROR = 0;
NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Disabled;
@@ -1803,7 +1634,7 @@ ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
/* XXX: This should not be necessary, but paranoia is good! */
/* Clear timer0 compare to RXEN since we are transmitting */
nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH21_Msk);
phy_ppi_timer0_compare0_to_radio_rxen_disable();
if (ble_phy_set_start_time(cputime, rem_usecs, true) != 0) {
STATS_INC(ble_phy_stats, tx_late);
@@ -1811,10 +1642,12 @@ ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
rc = BLE_PHY_ERR_TX_LATE;
} else {
/* Enable PPI to automatically start TXEN */
nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH20_Msk);
phy_ppi_timer0_compare0_to_radio_txen_enable();
rc = 0;
ble_phy_fem_enable_pa();
#if PHY_USE_FEM_PA
phy_fem_enable_pa();
#endif
}
return rc;
@@ -1847,7 +1680,7 @@ ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
/* XXX: This should not be necessary, but paranoia is good! */
/* Clear timer0 compare to TXEN since we are transmitting */
nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH20_Msk);
phy_ppi_timer0_compare0_to_radio_txen_disable();
if (ble_phy_set_start_time(cputime, rem_usecs, false) != 0) {
STATS_INC(ble_phy_stats, rx_late);
@@ -1859,9 +1692,11 @@ ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
}
/* Enable PPI to automatically start RXEN */
nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH21_Msk);
phy_ppi_timer0_compare0_to_radio_rxen_enable();
ble_phy_fem_enable_lna();
#if PHY_USE_FEM_LNA
phy_fem_enable_lna();
#endif
/* Start rx */
rc = ble_phy_rx();
@@ -1907,8 +1742,9 @@ ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans)
* paranoid, and if you are going to clear one, might as well clear them
* all.
*/
nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk |
PPI_CHEN_CH23_Msk | PPI_CHEN_CH25_Msk);
phy_ppi_wfr_disable();
phy_ppi_radio_bcmatch_to_aar_start_disable();
phy_ppi_radio_address_to_ccm_crypt_disable();
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
if (g_ble_phy_data.phy_encrypted) {
@@ -2158,10 +1994,7 @@ ble_phy_disable_irq_and_ppi(void)
nrf_radio_int_disable(NRF_RADIO, NRF_RADIO_IRQ_MASK_ALL);
NRF_RADIO->SHORTS = 0;
nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_DISABLE);
nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk |
PPI_CHEN_CH20_Msk | PPI_CHEN_CH21_Msk | PPI_CHEN_CH23_Msk |
PPI_CHEN_CH25_Msk | PPI_CHEN_CH31_Msk);
nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk);
phy_ppi_disable();
NVIC_ClearPendingIRQ(RADIO_IRQn);
g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE;
}
@@ -2174,7 +2007,7 @@ ble_phy_restart_rx(void)
ble_phy_set_start_now();
/* Enable PPI to automatically start RXEN */
nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH21_Msk);
phy_ppi_timer0_compare0_to_radio_rxen_enable();
ble_phy_rx();
}
+165
View File
@@ -0,0 +1,165 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <stdint.h>
#include <nrfx.h>
#include <controller/ble_ll_fem.h>
#include "../phy_priv.h"
#if PHY_USE_DEBUG
void
phy_debug_init(void)
{
#if PHY_USE_DEBUG_1
phy_gpiote_configure(PHY_GPIOTE_DEBUG_1,
MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN));
nrf_ppi_channel_endpoint_setup(NRF_PPI, 17,
(uint32_t)&(NRF_RADIO->EVENTS_READY),
(uint32_t)&(NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_DEBUG_1]));
nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH17_Msk);
/* CH[20] and PPI CH[21] are on to trigger TASKS_TXEN or TASKS_RXEN */
nrf_ppi_fork_endpoint_setup(NRF_PPI, 20,
(uint32_t)&(NRF_GPIOTE->TASKS_SET[PHY_GPIOTE_DEBUG_1]));
nrf_ppi_fork_endpoint_setup(NRF_PPI, 21,
(uint32_t)&(NRF_GPIOTE->TASKS_SET[PHY_GPIOTE_DEBUG_1]));
#endif
#if PHY_USE_DEBUG_2
phy_gpiote_configure(PHY_GPIOTE_DEBUG_2,
MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN));
/* CH[26] and CH[27] are always on for EVENT_ADDRESS and EVENT_END */
nrf_ppi_fork_endpoint_setup(NRF_PPI, 26,
(uint32_t)&(NRF_GPIOTE->TASKS_SET[PHY_GPIOTE_DEBUG_2]));
nrf_ppi_fork_endpoint_setup(NRF_PPI, 27,
(uint32_t)&(NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_DEBUG_2]));
#endif
#if PHY_USE_DEBUG_3
phy_gpiote_configure(PHY_GPIOTE_DEBUG_3, MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN));
#if NRF52840_XXAA
nrf_ppi_channel_endpoint_setup(NRF_PPI, 18,
(uint32_t)&(NRF_RADIO->EVENTS_RXREADY),
(uint32_t)&(NRF_GPIOTE->TASKS_SET[PHY_GPIOTE_DEBUG_3]));
#else
nrf_ppi_channel_endpoint_setup(NRF_PPI, 18,
(uint32_t)&(NRF_RADIO->EVENTS_READY),
(uint32_t)&(NRF_GPIOTE->TASKS_SET[GIDX_DEBUG_3]));
#endif
nrf_ppi_channel_endpoint_setup(NRF_PPI, 19,
(uint32_t)&(NRF_RADIO->EVENTS_DISABLED),
(uint32_t)&(NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_DEBUG_3]));
nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH18_Msk | PPI_CHEN_CH19_Msk);
/* CH[4] and CH[5] are always on for wfr */
nrf_ppi_fork_endpoint_setup(NRF_PPI, 4,
(uint32_t)&(NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_DEBUG_3]));
nrf_ppi_fork_endpoint_setup(NRF_PPI, 5,
(uint32_t)&(NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_DEBUG_3]));
#endif
}
#endif /* PHY_USE_DEBUG */
#if PHY_USE_FEM
void
phy_fem_init(void)
{
#if PHY_USE_FEM_SINGLE_GPIO
#if PHY_USE_FEM_PA
phy_gpiote_configure(PHY_GPIOTE_FEM, MYNEWT_VAL(BLE_LL_FEM_PA_GPIO));
#else
phy_gpiote_configure(PHY_GPIOTE_FEM, MYNEWT_VAL(BLE_LL_FEM_LNA_GPIO));
#endif
NRF_PPI->CH[6].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[PHY_GPIOTE_FEM]);
NRF_PPI->CH[7].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_FEM]);
#else
#if PHY_USE_FEM_PA
phy_gpiote_configure(PHY_GPIOTE_FEM_PA, MYNEWT_VAL(BLE_LL_FEM_PA_GPIO));
NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_FEM_PA] = 1;
#endif
#if PHY_USE_FEM_LNA
phy_gpiote_configure(PHY_GPIOTE_FEM_LNA, MYNEWT_VAL(BLE_LL_FEM_LNA_GPIO));
NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_FEM_LNA] = 1;
#endif
#endif /* PHY_USE_FEM_SINGLE_GPIO */
NRF_PPI->CH[6].EEP = (uint32_t)&(NRF_RADIO->EVENTS_READY);
NRF_PPI->CH[7].EEP = (uint32_t)&(NRF_RADIO->EVENTS_DISABLED);
nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk);
}
#if PHY_USE_FEM_PA
void
phy_fem_enable_pa(void)
{
ble_ll_fem_pa_enable();
#if !PHY_USE_FEM_SINGLE_GPIO
/* Switch FEM channels to control PA */
NRF_PPI->CH[6].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[PHY_GPIOTE_FEM_PA]);
NRF_PPI->CH[7].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_FEM_PA]);
#endif
nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk);
}
#endif
#if PHY_USE_FEM_LNA
void
phy_fem_enable_lna(void)
{
ble_ll_fem_lna_enable();
#if !PHY_USE_FEM_SINGLE_GPIO
/* Switch FEM channels to control LNA */
NRF_PPI->CH[6].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[PHY_GPIOTE_FEM_LNA]);
NRF_PPI->CH[7].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_FEM_LNA]);
#endif
nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk);
}
#endif
#endif /* PHY_USE_FEM */
void
phy_ppi_init(void)
{
/* radio_address_to_timer0_capture1 */
nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH26_Msk);
/* radio_end_to_timer0_capture2 */
nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH27_Msk);
/*
* PPI setup.
* Channel 4: Captures TIMER0 in CC[3] when EVENTS_ADDRESS occurs. Used
* to cancel the wait for response timer.
* Channel 5: TIMER0 CC[3] to TASKS_DISABLE on radio. This is the wait
* for response timer.
*/
nrf_ppi_channel_endpoint_setup(NRF_PPI, NRF_PPI_CHANNEL4,
(uint32_t)&(NRF_RADIO->EVENTS_ADDRESS),
(uint32_t)&(NRF_TIMER0->TASKS_CAPTURE[3]));
nrf_ppi_channel_endpoint_setup(NRF_PPI, NRF_PPI_CHANNEL5,
(uint32_t)&(NRF_TIMER0->EVENTS_COMPARE[3]),
(uint32_t)&(NRF_RADIO->TASKS_DISABLE));
}
+113
View File
@@ -0,0 +1,113 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef H_PHY_PPI_
#define H_PHY_PPI_
#include <nrf_ppi.h>
static inline void
phy_ppi_rtc0_compare0_to_timer0_start_enable(void)
{
nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH31_Msk);
}
static inline void
phy_ppi_rtc0_compare0_to_timer0_start_disable(void)
{
nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH31_Msk);
}
static inline void
phy_ppi_timer0_compare0_to_radio_txen_enable(void)
{
nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH20_Msk);
}
static inline void
phy_ppi_timer0_compare0_to_radio_txen_disable(void)
{
nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH20_Msk);
}
static inline void
phy_ppi_timer0_compare0_to_radio_rxen_enable(void)
{
nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH21_Msk);
}
static inline void
phy_ppi_timer0_compare0_to_radio_rxen_disable(void)
{
nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH21_Msk);
}
static inline void
phy_ppi_radio_bcmatch_to_aar_start_enable(void)
{
nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH23_Msk);
}
static inline void
phy_ppi_radio_bcmatch_to_aar_start_disable(void)
{
nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH23_Msk);
}
static inline void
phy_ppi_radio_address_to_ccm_crypt_enable(void)
{
nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH25_Msk);
}
static inline void
phy_ppi_radio_address_to_ccm_crypt_disable(void)
{
nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH25_Msk);
}
static inline void
phy_ppi_wfr_enable(void)
{
nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk);
}
static inline void
phy_ppi_wfr_disable(void)
{
nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk);
}
static inline void
phy_ppi_fem_disable(void)
{
nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk);
}
static inline void
phy_ppi_disable(void)
{
nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk |
PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk |
PPI_CHEN_CH20_Msk | PPI_CHEN_CH21_Msk |
PPI_CHEN_CH23_Msk | PPI_CHEN_CH25_Msk |
PPI_CHEN_CH31_Msk);
}
#endif /* H_PHY_PPI_ */
+79
View File
@@ -0,0 +1,79 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef H_PHY_PRIV_
#define H_PHY_PRIV_
#include <nrf_gpio.h>
#include <nrf_gpiote.h>
#define PHY_USE_DEBUG_1 (MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN) >= 0)
#define PHY_USE_DEBUG_2 (MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0)
#define PHY_USE_DEBUG_3 (MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0)
#define PHY_USE_DEBUG (PHY_USE_DEBUG_1 || PHY_USE_DEBUG_2 || PHY_USE_DEBUG_3)
#define PHY_USE_FEM_PA (MYNEWT_VAL(BLE_LL_FEM_PA) != 0)
#define PHY_USE_FEM_LNA (MYNEWT_VAL(BLE_LL_FEM_LNA) != 0)
#define PHY_USE_FEM (PHY_USE_FEM_PA || PHY_USE_FEM_LNA)
#define PHY_USE_FEM_SINGLE_GPIO \
(PHY_USE_FEM && (!PHY_USE_FEM_PA || !PHY_USE_FEM_LNA || \
(MYNEWT_VAL(BLE_LL_FEM_PA_GPIO) == \
MYNEWT_VAL(BLE_LL_FEM_LNA_GPIO))))
/* GPIOTE indexes, start assigning from last one */
#define PHY_GPIOTE_DEBUG_1 (8 - PHY_USE_DEBUG_1)
#define PHY_GPIOTE_DEBUG_2 (PHY_GPIOTE_DEBUG_1 - PHY_USE_DEBUG_2)
#define PHY_GPIOTE_DEBUG_3 (PHY_GPIOTE_DEBUG_2 - PHY_USE_DEBUG_3)
#if PHY_USE_FEM_SINGLE_GPIO
#define PHY_GPIOTE_FEM (PHY_GPIOTE_DEBUG_3 - PHY_USE_FEM)
#else
#define PHY_GPIOTE_FEM_PA (PHY_GPIOTE_DEBUG_3 - PHY_USE_FEM_PA)
#define PHY_GPIOTE_FEM_LNA (PHY_GPIOTE_FEM_PA - PHY_USE_FEM_LNA)
#endif
static inline void
phy_gpiote_configure(int idx, int pin)
{
nrf_gpio_cfg_output(pin);
nrf_gpiote_task_configure(NRF_GPIOTE, idx, pin, NRF_GPIOTE_POLARITY_NONE,
NRF_GPIOTE_INITIAL_VALUE_LOW);
nrf_gpiote_task_enable(NRF_GPIOTE, idx);
}
#if PHY_USE_DEBUG
void phy_debug_init(void);
#endif
#if PHY_USE_FEM
void phy_fem_init(void);
#if PHY_USE_FEM_PA
void phy_fem_enable_pa(void);
#endif
#if PHY_USE_FEM_LNA
void phy_fem_enable_lna(void);
#endif
#endif
void phy_ppi_init(void);
#ifdef NRF52_SERIES
#include "nrf52/phy_ppi.h"
#endif
#endif /* H_PHY_PRIV_ */