Skip to content

Instantly share code, notes, and snippets.

@hieuv
Created July 15, 2024 21:45
Show Gist options
  • Save hieuv/06fb6b9609c59e3a57bb62340ccaf242 to your computer and use it in GitHub Desktop.
Save hieuv/06fb6b9609c59e3a57bb62340ccaf242 to your computer and use it in GitHub Desktop.
nRF52x - Two ways to connect RADIO events to GPIOTE with PPI
// Pro: The nrfx drivers keep track of which PPI and GPIOTE channels are in used.
static void alloc_assign_enable_nrfx_ppi(nrf_ppi_channel_t* p_channel,
uint32_t event_end_point,
uint32_t task_end_point)
{
#if (!NRFX_PPI_ENABLED)
#error "Require enabling NRFX_PPI_ENABLED in sdk_config.h. In nRF5 SDK, also check PPI_ENABLED (refer to apply_old_config.h)"
#endif
nrfx_err_t err;
if (!nrfx_gpiote_is_init())
{
APP_ERROR_CHECK(NRFX_ERROR_INVALID_STATE);
}
err = nrfx_ppi_channel_alloc(p_channel);
APP_ERROR_CHECK(err);
err = nrfx_ppi_channel_assign(*p_channel,
event_end_point,
task_end_point
);
APP_ERROR_CHECK(err);
err = nrfx_ppi_channel_enable(*p_channel);
APP_ERROR_CHECK(err);
}
static void config_then_enable_gpiote_via_nrfx(uint8_t port, uint8_t pin)
{
#if (!NRFX_GPIOTE_ENABLED)
#error "Require enabling NRFX_GPIOTE_ENABLED in sdk_config.h. In nRF5 SDK, also check GPIOTE_ENABLED (refer to apply_old_config.h)"
#endif
nrfx_err_t err;
nrfx_gpiote_out_config_t nrfx_gpiote_out_config_led_common = {
.action = NRF_GPIOTE_POLARITY_TOGGLE,
.init_state = NRF_GPIOTE_INITIAL_VALUE_LOW,
.task_pin = true
};
err = nrfx_gpiote_out_init(NRF_GPIO_PIN_MAP(port, pin), &nrfx_gpiote_out_config_led_common);
APP_ERROR_CHECK(err);
nrfx_gpiote_out_task_enable(NRF_GPIO_PIN_MAP(port, pin));
}
static void radio_ppi_gpiote_setup_nrfx(void)
{
nrfx_err_t err;
err = nrfx_gpiote_init();
APP_ERROR_CHECK(err);
config_then_enable_gpiote_via_nrfx(LED_PORT, LED1_PIN);
config_then_enable_gpiote_via_nrfx(LED_PORT, LED2_PIN);
nrf_ppi_channel_t nrf_ppi_channel_set_led1;
nrf_ppi_channel_t nrf_ppi_channel_clr_led1;
nrf_ppi_channel_t nrf_ppi_channel_set_led2;
nrf_ppi_channel_t nrf_ppi_channel_clr_led2;
alloc_assign_enable_nrfx_ppi(
&nrf_ppi_channel_clr_led1,
nrf_radio_event_address_get(NRF_RADIO_EVENT_TXREADY),
nrfx_gpiote_clr_task_addr_get(NRF_GPIO_PIN_MAP(LED_PORT, LED1_PIN))
);
alloc_assign_enable_nrfx_ppi(
&nrf_ppi_channel_set_led1,
nrf_radio_event_address_get(NRF_RADIO_EVENT_END),
nrfx_gpiote_set_task_addr_get(NRF_GPIO_PIN_MAP(LED_PORT, LED1_PIN))
);
alloc_assign_enable_nrfx_ppi(
&nrf_ppi_channel_clr_led2,
nrf_radio_event_address_get(NRF_RADIO_EVENT_RXREADY),
nrfx_gpiote_clr_task_addr_get(NRF_GPIO_PIN_MAP(LED_PORT, LED2_PIN))
);
alloc_assign_enable_nrfx_ppi(
&nrf_ppi_channel_set_led2,
nrf_radio_event_address_get(NRF_RADIO_EVENT_END),
nrfx_gpiote_set_task_addr_get(NRF_GPIO_PIN_MAP(LED_PORT, LED2_PIN))
);
}
// Con: need to keep track of which PPI and GPIOTE channels are in used.
static void radio_ppi_gpiote_setup_direct_register_macro(void)
{
#define LED_PORT 0
#define LED1_PIN 13
#define LED2_PIN 14
#define GPIOTE_CHANNEL_FOR_LED1 0 /* 0..7, can't reuse */
#define GPIOTE_CHANNEL_FOR_LED2 1 /* 0..7, can't reuse */
#define PPI_CHANNEL_FOR_LED1_SET 0 /* 0..19 for nRF52840, can't reuse */
#define PPI_CHANNEL_FOR_LED2_SET 1 /* 0..19 for nRF52840, can't reuse */
#define PPI_CHANNEL_FOR_LED1_CLR 2 /* 0..19 for nRF52840, can't reuse */
#define PPI_CHANNEL_FOR_LED2_CLR 3 /* 0..19 for nRF52840, can't reuse */
NRF_GPIOTE->CONFIG[GPIOTE_CHANNEL_FOR_LED1] = (uint32_t)
( GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos ) |
( LED_PORT << GPIOTE_CONFIG_PORT_Pos ) |
( LED1_PIN << GPIOTE_CONFIG_PSEL_Pos ) |
//( GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos ) |
( GPIOTE_CONFIG_OUTINIT_High << GPIOTE_CONFIG_OUTINIT_Pos );
NRF_GPIOTE->CONFIG[GPIOTE_CHANNEL_FOR_LED2] = (uint32_t)
( GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos ) |
( LED_PORT << GPIOTE_CONFIG_PORT_Pos ) |
( LED2_PIN << GPIOTE_CONFIG_PSEL_Pos ) |
//( GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos ) |
( GPIOTE_CONFIG_OUTINIT_High << GPIOTE_CONFIG_OUTINIT_Pos );
NRF_PPI->CH[PPI_CHANNEL_FOR_LED1_CLR].EEP =
(uint32_t) (&NRF_RADIO->EVENTS_TXREADY);
NRF_PPI->CH[PPI_CHANNEL_FOR_LED1_CLR].TEP =
(uint32_t) (&NRF_GPIOTE->TASKS_CLR[GPIOTE_CHANNEL_FOR_LED1]);
NRF_PPI->CH[PPI_CHANNEL_FOR_LED1_SET].EEP =
(uint32_t) (&NRF_RADIO->EVENTS_END);
NRF_PPI->CH[PPI_CHANNEL_FOR_LED1_SET].TEP =
(uint32_t) (&NRF_GPIOTE->TASKS_SET[GPIOTE_CHANNEL_FOR_LED1]);
NRF_PPI->CH[PPI_CHANNEL_FOR_LED2_CLR].EEP =
(uint32_t) (&NRF_RADIO->EVENTS_RXREADY);
NRF_PPI->CH[PPI_CHANNEL_FOR_LED2_CLR].TEP =
(uint32_t) (&NRF_GPIOTE->TASKS_CLR[GPIOTE_CHANNEL_FOR_LED2]);
NRF_PPI->CH[PPI_CHANNEL_FOR_LED2_SET].EEP =
(uint32_t) (&NRF_RADIO->EVENTS_END);
NRF_PPI->CH[PPI_CHANNEL_FOR_LED2_SET].TEP =
(uint32_t) (&NRF_GPIOTE->TASKS_SET[GPIOTE_CHANNEL_FOR_LED2]);
NRF_PPI->CHENSET = (0x1 << PPI_CHANNEL_FOR_LED1_CLR) |
(0x1 << PPI_CHANNEL_FOR_LED1_SET) |
(0x1 << PPI_CHANNEL_FOR_LED2_CLR) |
(0x1 << PPI_CHANNEL_FOR_LED2_SET);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment