mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-08-29 13:20:04 +00:00
nimble/phy/nrf53: Add PA/LNA support
This is basically port of 9ef71450 to nRF53 and DPPI.
This commit is contained in:
@@ -27,6 +27,7 @@
|
||||
#include <nimble/nimble_opt.h>
|
||||
#include <nimble/nimble_npl.h>
|
||||
#include <controller/ble_phy.h>
|
||||
#include "controller/ble_ll_plna.h"
|
||||
|
||||
#include <ble/xcvr.h>
|
||||
#include <controller/ble_phy_trace.h>
|
||||
@@ -39,13 +40,9 @@
|
||||
#define DPPI_CH_UNSUB(_ch) (((DPPI_CH_ ## _ch) & 0xff) | (0 << 31))
|
||||
#define DPPI_CH_MASK(_ch) (1 << (DPPI_CH_ ## _ch))
|
||||
|
||||
/*
|
||||
* NOTE: This code uses 0-5 DPPI channels so care should be taken when using
|
||||
* DPPI somewhere else.
|
||||
* TODO maybe we could reduce number of used channels if we reuse same channel
|
||||
* for mutually exclusive events but for now make it simpler to debug.
|
||||
*
|
||||
* Optionally channels 6,7,8 are used for GPIO DBG.
|
||||
/* Channels 0..5 are always used.
|
||||
* Channels 6 and 7 are used for PA/LNA (optionally).
|
||||
* Channels 6..8 are used for GPIO debugging (optionally).
|
||||
*/
|
||||
|
||||
#define DPPI_CH_TIMER0_EVENTS_COMPARE_0 0
|
||||
@@ -54,14 +51,16 @@
|
||||
#define DPPI_CH_RADIO_EVENTS_BCMATCH 3
|
||||
#define DPPI_CH_RADIO_EVENTS_ADDRESS 4
|
||||
#define DPPI_CH_RTC0_EVENTS_COMPARE_0 5
|
||||
/* used for GPIO DBG */
|
||||
#define DPPI_CH_RADIO_EVENTS_READY 6
|
||||
#define DPPI_CH_RADIO_EVENTS_RXREADY 7
|
||||
#define DPPI_CH_RADIO_EVENTS_DISABLED 8
|
||||
#define DPPI_CH_RADIO_EVENTS_DISABLED 7
|
||||
#define DPPI_CH_RADIO_EVENTS_RXREADY 8
|
||||
|
||||
#define DPPI_CH_ENABLE_ALL (DPPIC_CHEN_CH0_Msk | DPPIC_CHEN_CH1_Msk | DPPIC_CHEN_CH2_Msk | \
|
||||
DPPIC_CHEN_CH3_Msk | DPPIC_CHEN_CH4_Msk | DPPIC_CHEN_CH5_Msk)
|
||||
|
||||
#define DPPI_CH_MASK_PLNA (DPPI_CH_MASK(RADIO_EVENTS_READY) | \
|
||||
DPPI_CH_MASK(RADIO_EVENTS_DISABLED))
|
||||
|
||||
extern uint8_t g_nrf_num_irks;
|
||||
extern uint32_t g_nrf_irk_list[];
|
||||
|
||||
@@ -242,6 +241,27 @@ struct nrf_ccm_data {
|
||||
static struct nrf_ccm_data nrf_ccm_data;
|
||||
#endif
|
||||
|
||||
static int g_ble_phy_gpiote_idx;
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_PA) || MYNEWT_VAL(BLE_LL_LNA)
|
||||
|
||||
#define PLNA_SINGLE_GPIO \
|
||||
(!MYNEWT_VAL(BLE_LL_PA) || !MYNEWT_VAL(BLE_LL_LNA) || \
|
||||
(MYNEWT_VAL(BLE_LL_PA_GPIO) == MYNEWT_VAL(BLE_LL_LNA_GPIO)))
|
||||
|
||||
#if PLNA_SINGLE_GPIO
|
||||
static uint8_t plna_idx;
|
||||
#else
|
||||
#if MYNEWT_VAL(BLE_LL_PA)
|
||||
static uint8_t plna_pa_idx;
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_LNA)
|
||||
static uint8_t plna_lna_idx;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN) >= 0
|
||||
static uint8_t phy_dbg_txrxen_ready_idx;
|
||||
#endif
|
||||
@@ -307,6 +327,62 @@ ble_phy_mode_set(uint8_t tx_phy_mode, uint8_t rx_phy_mode)
|
||||
g_ble_phy_data.phy_rx_phy_mode = rx_phy_mode;
|
||||
}
|
||||
|
||||
static void
|
||||
ble_phy_plna_enable_pa(void)
|
||||
{
|
||||
#if MYNEWT_VAL(BLE_LL_PA)
|
||||
ble_ll_plna_pa_enable();
|
||||
|
||||
#if PLNA_SINGLE_GPIO
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_SET[plna_idx] = DPPI_CH_SUB(RADIO_EVENTS_READY);
|
||||
#else
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_SET[plna_pa_idx] = DPPI_CH_SUB(RADIO_EVENTS_READY);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
ble_phy_plna_disable_pa(void)
|
||||
{
|
||||
#if MYNEWT_VAL(BLE_LL_PA)
|
||||
ble_ll_plna_pa_disable();
|
||||
|
||||
#if PLNA_SINGLE_GPIO
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_SET[plna_idx] = DPPI_CH_UNSUB(RADIO_EVENTS_READY);
|
||||
#else
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_SET[plna_pa_idx] = DPPI_CH_UNSUB(RADIO_EVENTS_READY);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
ble_phy_plna_enable_lna(void)
|
||||
{
|
||||
#if MYNEWT_VAL(BLE_LL_LNA)
|
||||
ble_ll_plna_lna_enable();
|
||||
|
||||
#if PLNA_SINGLE_GPIO
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_SET[plna_idx] = DPPI_CH_SUB(RADIO_EVENTS_READY);
|
||||
#else
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_SET[plna_lna_idx] = DPPI_CH_SUB(RADIO_EVENTS_READY);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
ble_phy_plna_disable_lna(void)
|
||||
{
|
||||
#if MYNEWT_VAL(BLE_LL_LNA)
|
||||
ble_ll_plna_lna_disable();
|
||||
|
||||
#if PLNA_SINGLE_GPIO
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_SET[plna_idx] = DPPI_CH_UNSUB(RADIO_EVENTS_READY);
|
||||
#else
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_SET[plna_lna_idx] = DPPI_CH_UNSUB(RADIO_EVENTS_READY);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
ble_phy_get_cur_phy(void)
|
||||
{
|
||||
@@ -814,6 +890,7 @@ ble_phy_tx_end_isr(void)
|
||||
/* Start radio on timer */
|
||||
NRF_RADIO_NS->SUBSCRIBE_RXEN = DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_0);
|
||||
|
||||
ble_phy_plna_enable_lna();
|
||||
} else {
|
||||
NRF_TIMER0_NS->TASKS_STOP = 1;
|
||||
NRF_TIMER0_NS->TASKS_SHUTDOWN = 1;
|
||||
@@ -943,6 +1020,8 @@ ble_phy_rx_end_isr(void)
|
||||
/* Enable automatic TX */
|
||||
NRF_RADIO_NS->SUBSCRIBE_TXEN = DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_0);
|
||||
|
||||
ble_phy_plna_enable_pa();
|
||||
|
||||
/*
|
||||
* XXX: Hack warning!
|
||||
*
|
||||
@@ -1145,6 +1224,7 @@ ble_phy_isr(void)
|
||||
|
||||
switch (g_ble_phy_data.phy_state) {
|
||||
case BLE_PHY_STATE_RX:
|
||||
ble_phy_plna_disable_lna();
|
||||
if (g_ble_phy_data.phy_rx_started) {
|
||||
ble_phy_rx_end_isr();
|
||||
} else {
|
||||
@@ -1152,6 +1232,7 @@ ble_phy_isr(void)
|
||||
}
|
||||
break;
|
||||
case BLE_PHY_STATE_TX:
|
||||
ble_phy_plna_disable_pa();
|
||||
ble_phy_tx_end_isr();
|
||||
break;
|
||||
default:
|
||||
@@ -1167,13 +1248,17 @@ ble_phy_isr(void)
|
||||
}
|
||||
|
||||
#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
|
||||
static inline void
|
||||
ble_phy_dbg_time_setup_gpiote(int index, int pin)
|
||||
MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0 || \
|
||||
MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0 || \
|
||||
MYNEWT_VAL(BLE_LL_PA) || \
|
||||
MYNEWT_VAL(BLE_LL_LNA)
|
||||
static int
|
||||
ble_phy_gpiote_configure(int pin)
|
||||
{
|
||||
NRF_GPIO_Type *port;
|
||||
|
||||
g_ble_phy_gpiote_idx--;
|
||||
|
||||
port = pin > 31 ? NRF_P1_NS : NRF_P0_NS;
|
||||
pin &= 0x1f;
|
||||
|
||||
@@ -1181,17 +1266,21 @@ ble_phy_dbg_time_setup_gpiote(int index, int pin)
|
||||
port->DIRSET = (1 << pin);
|
||||
port->OUTCLR = (1 << pin);
|
||||
|
||||
NRF_GPIOTE_NS->CONFIG[index] =
|
||||
(GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) |
|
||||
((pin & 0x1F) << GPIOTE_CONFIG_PSEL_Pos) |
|
||||
((port == NRF_P1_NS) << GPIOTE_CONFIG_PORT_Pos);
|
||||
NRF_GPIOTE_NS->CONFIG[g_ble_phy_gpiote_idx] =
|
||||
(GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) |
|
||||
((pin & 0x1F) << GPIOTE_CONFIG_PSEL_Pos) |
|
||||
((port == NRF_P1_NS) << GPIOTE_CONFIG_PORT_Pos);
|
||||
|
||||
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 gpiote_idx __attribute__((unused)) = 8;
|
||||
int idx __attribute__((unused)) = 8;
|
||||
|
||||
/*
|
||||
* We setup GPIOTE starting from last configuration index to minimize risk
|
||||
@@ -1200,12 +1289,11 @@ ble_phy_dbg_time_setup(void)
|
||||
*/
|
||||
|
||||
#if MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN) >= 0
|
||||
phy_dbg_txrxen_ready_idx = --gpiote_idx;
|
||||
ble_phy_dbg_time_setup_gpiote(gpiote_idx,
|
||||
MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN));
|
||||
idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN));
|
||||
phy_dbg_txrxen_ready_idx = idx;
|
||||
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_SET[gpiote_idx] = DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_0);
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_CLR[gpiote_idx] = DPPI_CH_SUB(RADIO_EVENTS_READY);
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_SET[idx] = DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_0);
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_CLR[idx] = DPPI_CH_SUB(RADIO_EVENTS_READY);
|
||||
|
||||
/* Publish RADIO->EVENTS_READY */
|
||||
NRF_RADIO_NS->PUBLISH_READY = DPPI_CH_PUB(RADIO_EVENTS_READY);
|
||||
@@ -1214,28 +1302,26 @@ ble_phy_dbg_time_setup(void)
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0
|
||||
phy_dbg_address_end_idx = --gpiote_idx;
|
||||
ble_phy_dbg_time_setup_gpiote(gpiote_idx,
|
||||
MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN));
|
||||
idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN));
|
||||
phy_dbg_address_end_idx = idx;
|
||||
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_SET[gpiote_idx] = DPPI_CH_SUB(RADIO_EVENTS_ADDRESS);
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_CLR[gpiote_idx] = DPPI_CH_SUB(RADIO_EVENTS_END);
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_SET[idx] = DPPI_CH_SUB(RADIO_EVENTS_ADDRESS);
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_CLR[idx] = DPPI_CH_SUB(RADIO_EVENTS_END);
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0
|
||||
phy_dbg_wfr_idx = --gpiote_idx;
|
||||
ble_phy_dbg_time_setup_gpiote(gpiote_idx,
|
||||
MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN));
|
||||
idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN));
|
||||
phy_dbg_wfr_idx = idx;
|
||||
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_SET[gpiote_idx] = DPPI_CH_SUB(RADIO_EVENTS_RXREADY);
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_SET[idx] = DPPI_CH_SUB(RADIO_EVENTS_RXREADY);
|
||||
|
||||
/* TODO figure out how (if?) to subscribe task to multiple DPPI channels
|
||||
* Currently only last one is working. Also using multiple GPIOTE for same
|
||||
* PIN doesn't work...
|
||||
*/
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_CLR[gpiote_idx] = DPPI_CH_SUB(RADIO_EVENTS_DISABLED);
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_CLR[gpiote_idx] = DPPI_CH_SUB(RADIO_EVENTS_ADDRESS);
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_CLR[gpiote_idx] = DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_3);
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_CLR[idx] = DPPI_CH_SUB(RADIO_EVENTS_DISABLED);
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_CLR[idx] = DPPI_CH_SUB(RADIO_EVENTS_ADDRESS);
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_CLR[idx] = DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_3);
|
||||
|
||||
/* Publish RADIO->EVENTS_RXREADY */
|
||||
NRF_RADIO_NS->PUBLISH_RXREADY = DPPI_CH_PUB(RADIO_EVENTS_READY);
|
||||
@@ -1252,6 +1338,8 @@ 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;
|
||||
@@ -1341,6 +1429,35 @@ ble_phy_init(void)
|
||||
NRF_TIMER0_NS->SUBSCRIBE_CAPTURE[1] = DPPI_CH_SUB(RADIO_EVENTS_ADDRESS);
|
||||
NRF_TIMER0_NS->SUBSCRIBE_CAPTURE[2] = DPPI_CH_SUB(RADIO_EVENTS_END);
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_PA) || MYNEWT_VAL(BLE_LL_LNA)
|
||||
/* We keep both channels enabled and CLR task subscribed all the time. It's
|
||||
* enough to just (un)subscribe SET task when needed.
|
||||
* TODO: figure out if this affects power consumption
|
||||
*/
|
||||
|
||||
#if PLNA_SINGLE_GPIO
|
||||
plna_idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_LL_PA_GPIO));
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_SET[plna_idx] = DPPI_CH_UNSUB(RADIO_EVENTS_READY);
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_CLR[plna_idx] = DPPI_CH_SUB(RADIO_EVENTS_DISABLED);
|
||||
NRF_GPIOTE_NS->TASKS_CLR[plna_idx] = 1;
|
||||
#else
|
||||
#if MYNEWT_VAL(BLE_LL_PA)
|
||||
plna_pa_idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_LL_PA_GPIO));
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_SET[plna_pa_idx] = DPPI_CH_UNSUB(RADIO_EVENTS_READY);
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_CLR[plna_pa_idx] = DPPI_CH_SUB(RADIO_EVENTS_DISABLED);
|
||||
NRF_GPIOTE_NS->TASKS_CLR[plna_pa_idx] = 1;
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_LNA)
|
||||
plna_lna_idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_LL_LNA_GPIO));
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_SET[plna_lna_idx] = DPPI_CH_UNSUB(RADIO_EVENTS_READY);
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_CLR[plna_lna_idx] = DPPI_CH_SUB(RADIO_EVENTS_DISABLED);
|
||||
NRF_GPIOTE_NS->TASKS_CLR[plna_lna_idx] = 1;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
NRF_DPPIC_NS->CHENSET = DPPI_CH_MASK_PLNA;
|
||||
#endif
|
||||
|
||||
/* Set isr in vector table and enable interrupt */
|
||||
#ifndef RIOT_VERSION
|
||||
NVIC_SetPriority(RADIO_IRQn, 0);
|
||||
@@ -1471,6 +1588,8 @@ ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
|
||||
/* Enable PPI to automatically start TXEN */
|
||||
NRF_RADIO_NS->SUBSCRIBE_TXEN = DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_0);
|
||||
rc = 0;
|
||||
|
||||
ble_phy_plna_enable_pa();
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -1503,6 +1622,8 @@ ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
|
||||
/* Enable PPI to automatically start RXEN */
|
||||
NRF_RADIO_NS->SUBSCRIBE_RXEN = DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_0);
|
||||
|
||||
ble_phy_plna_enable_lna();
|
||||
|
||||
/* Start rx */
|
||||
rc = ble_phy_rx();
|
||||
|
||||
@@ -1778,6 +1899,17 @@ ble_phy_disable_irq_and_ppi(void)
|
||||
NRF_AAR_NS->SUBSCRIBE_START = DPPI_CH_UNSUB(RADIO_EVENTS_BCMATCH);
|
||||
NRF_CCM_NS->SUBSCRIBE_CRYPT = DPPI_CH_UNSUB(RADIO_EVENTS_ADDRESS);
|
||||
|
||||
#if PLNA_SINGLE_GPIO
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_SET[plna_idx] = DPPI_CH_UNSUB(RADIO_EVENTS_READY);
|
||||
#else
|
||||
#if MYNEWT_VAL(BLE_LL_PA)
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_SET[plna_pa_idx] = DPPI_CH_UNSUB(RADIO_EVENTS_READY);
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_LNA)
|
||||
NRF_GPIOTE_NS->SUBSCRIBE_SET[plna_lna_idx] = DPPI_CH_UNSUB(RADIO_EVENTS_READY);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
NVIC_ClearPendingIRQ(RADIO_IRQn);
|
||||
g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user