Skip to content

Commit

Permalink
mpsl: Support mpsl_pin_debug on nRF54L DK
Browse files Browse the repository at this point in the history
This commit adds support for using pin debug on nRF54L.
The code has been extracted out to a separate file because has a
couple of things that are different compared to nRF52 and nRF53:
- It needs to setup a PPI bridge between two domains.
  This is done through `nrfx_gppi_edge_connection_setup()`
- It needs to allocate DPPI channels in the domain where the
  GPIO pin is located.

The code hardcodes to use PORT1. We should consider moving
the pin allocations to device tree to make this more flexible.

The code should be reusable for nRF54H as well.

Signed-off-by: Rubin Gerritsen <[email protected]>
  • Loading branch information
rugeGerritsen authored and nordicjm committed Dec 11, 2024
1 parent c382665 commit db3c544
Show file tree
Hide file tree
Showing 3 changed files with 241 additions and 3 deletions.
1 change: 1 addition & 0 deletions subsys/mpsl/pin_debug/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
zephyr_library()
zephyr_library_sources_ifdef(CONFIG_MPSL_PIN_DEBUG_APP_CORE mpsl_pin_debug_app_core.c)
zephyr_library_sources_ifdef(CONFIG_MPSL_PIN_DEBUG_RADIO_CORE mpsl_pin_debug_radio_core.c)
zephyr_library_sources_ifdef(CONFIG_SOC_COMPATIBLE_NRF54LX mpsl_pin_debug_nrf54.c)
14 changes: 11 additions & 3 deletions subsys/mpsl/pin_debug/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ config MPSL_PIN_DEBUG
BOARD_NRF52833DK_NRF52833 || \
BOARD_NRF52840DK_NRF52840 || \
BOARD_NRF5340DK_NRF5340_CPUNET || \
BOARD_NRF5340DK_NRF5340_CPUAPP)
BOARD_NRF5340DK_NRF5340_CPUAPP || \
BOARD_NRF54L15DK)
help
Set this option to enable toggling of GPIO pins upon radio
events. This can be useful for debugging purposes to figure
Expand All @@ -27,6 +28,7 @@ config MPSL_PIN_DEBUG_RADIO_CORE
bool
depends on MPSL_PIN_DEBUG
select NRFX_GPIOTE
select NRFX_GPPI
select NRFX_PPI if HAS_HW_NRF_PPI
select NRFX_DPPI if HAS_HW_NRF_DPPIC
default y if (SOC_COMPATIBLE_NRF52X || SOC_COMPATIBLE_NRF5340_CPUNET)
Expand All @@ -36,13 +38,19 @@ config MPSL_PIN_DEBUG_RADIO_READY_AND_DISABLED_PIN
depends on MPSL_PIN_DEBUG
default 3 if SOC_COMPATIBLE_NRF52X
default 4 if SOC_COMPATIBLE_NRF53X
default 43 if SOC_COMPATIBLE_NRF54LX
help
Only PORT0 can be used.
For nRF52 and nRF53 only PORT0 can be used.
For nRF54L only PORT1 can be used. Here the pin number
is 43 - 32 = 11.

config MPSL_PIN_DEBUG_RADIO_ADDRESS_AND_END_PIN
int "Pin toggled upon the events RADIO->EVENTS_ADDRESS and RADIO->EVENTS_END"
depends on MPSL_PIN_DEBUG
default 4 if SOC_COMPATIBLE_NRF52X
default 5 if SOC_COMPATIBLE_NRF53X
default 44 if SOC_COMPATIBLE_NRF54LX
help
Only PORT0 can be used.
For nRF52 and nRF53 only PORT0 can be used.
For nRF54L only PORT1 can be used. Here the pin number
is 44 - 32 = 12.
229 changes: 229 additions & 0 deletions subsys/mpsl/pin_debug/mpsl_pin_debug_nrf54.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

#include <zephyr/init.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <mpsl_dppi_protocol_api.h>
#include <nrfx_gpiote.h>
#include <helpers/nrfx_gppi.h>
#include <nrfx_dppi.h>
#include <hal/nrf_radio.h>
#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>

const nrfx_gpiote_t gpiote = NRFX_GPIOTE_INSTANCE(20);
const nrfx_dppi_t dppi_radio_domain = NRFX_DPPI_INSTANCE(10);
const nrfx_dppi_t dppi_gpio_domain = NRFX_DPPI_INSTANCE(20);
LOG_MODULE_REGISTER(mpsl_radio_pin_debug, CONFIG_MPSL_LOG_LEVEL);

static int m_ppi_config(void)
{
uint8_t gppi_chan_radio_ready;
uint8_t gppi_chan_radio_disabled;
uint8_t gppi_chan_radio_address;
uint8_t gppi_chan_radio_end;

uint8_t dppi_chan_gpio_ready;
uint8_t dppi_chan_gpio_disabled;
uint8_t dppi_chan_gpio_address;
uint8_t dppi_chan_gpio_end;

if (nrfx_gppi_channel_alloc(&gppi_chan_radio_ready) !=
NRFX_SUCCESS) {
LOG_ERR("Failed allocating gppi_chan_radio_ready");
return -ENOMEM;
}

if (nrfx_gppi_channel_alloc(&gppi_chan_radio_disabled) !=
NRFX_SUCCESS) {
LOG_ERR("Failed allocating gppi_chan_radio_disabled");
return -ENOMEM;
}

if (nrfx_gppi_channel_alloc(&gppi_chan_radio_address) !=
NRFX_SUCCESS) {
LOG_ERR("Failed allocating gppi_chan_radio_address");
return -ENOMEM;
}

if (nrfx_gppi_channel_alloc(&gppi_chan_radio_end) !=
NRFX_SUCCESS) {
LOG_ERR("Failed allocating gppi_chan_radio_end");
return -ENOMEM;
}

if (nrfx_dppi_channel_alloc(&dppi_gpio_domain, &dppi_chan_gpio_ready) !=
NRFX_SUCCESS) {
LOG_ERR("Failed allocating dppi_chan_gpio_ready");
return -ENOMEM;
}

if (nrfx_dppi_channel_alloc(&dppi_gpio_domain, &dppi_chan_gpio_disabled) !=
NRFX_SUCCESS) {
LOG_ERR("Failed allocating dppi_chan_gpio_disabled");
return -ENOMEM;
}

if (nrfx_dppi_channel_alloc(&dppi_gpio_domain, &dppi_chan_gpio_address) !=
NRFX_SUCCESS) {
LOG_ERR("Failed allocating dppi_chan_gpio_address");
return -ENOMEM;
}

if (nrfx_dppi_channel_alloc(&dppi_gpio_domain, &dppi_chan_gpio_end) !=
NRFX_SUCCESS) {
LOG_ERR("Failed allocating dppi_chan_gpio_end");
return -ENOMEM;
}

if (nrfx_gppi_edge_connection_setup(gppi_chan_radio_ready,
&dppi_radio_domain,
MPSL_DPPI_RADIO_PUBLISH_READY_CHANNEL_IDX,
&dppi_gpio_domain,
dppi_chan_gpio_ready) != NRFX_SUCCESS) {
LOG_ERR("Failed edge setup chan ready");
return -ENOMEM;
}

if (nrfx_gppi_edge_connection_setup(gppi_chan_radio_disabled,
&dppi_radio_domain,
MPSL_DPPI_RADIO_PUBLISH_DISABLED_CH_IDX,
&dppi_gpio_domain,
dppi_chan_gpio_disabled) != NRFX_SUCCESS) {
LOG_ERR("Failed edge setup chan disabled");
return -ENOMEM;
}

if (nrfx_gppi_edge_connection_setup(gppi_chan_radio_address,
&dppi_radio_domain,
MPSL_DPPI_RADIO_PUBLISH_ADDRESS_CHANNEL_IDX,
&dppi_gpio_domain,
dppi_chan_gpio_address) != NRFX_SUCCESS) {
LOG_ERR("Failed edge setup chan address");
return -ENOMEM;
}

/* Setup a PPI bridge between the radio domain and the domain of the GPIO pin. */
if (nrfx_gppi_edge_connection_setup(gppi_chan_radio_address,
&dppi_radio_domain,
MPSL_DPPI_RADIO_PUBLISH_END_CHANNEL_IDX,
&dppi_gpio_domain,
dppi_chan_gpio_end) != NRFX_SUCCESS) {
LOG_ERR("Failed edge setup chan end");
return -ENOMEM;
}

nrf_gpiote_subscribe_set(
gpiote.p_reg,
nrfx_gpiote_set_task_address_get(
&gpiote, CONFIG_MPSL_PIN_DEBUG_RADIO_READY_AND_DISABLED_PIN),
dppi_chan_gpio_ready);

nrf_gpiote_subscribe_set(
gpiote.p_reg,
nrfx_gpiote_clr_task_address_get(
&gpiote, CONFIG_MPSL_PIN_DEBUG_RADIO_READY_AND_DISABLED_PIN),
dppi_chan_gpio_disabled);

nrf_gpiote_subscribe_set(
gpiote.p_reg,
nrfx_gpiote_set_task_address_get(&gpiote,
CONFIG_MPSL_PIN_DEBUG_RADIO_ADDRESS_AND_END_PIN),
dppi_chan_gpio_address);

nrf_gpiote_subscribe_set(
gpiote.p_reg,
nrfx_gpiote_clr_task_address_get(&gpiote,
CONFIG_MPSL_PIN_DEBUG_RADIO_ADDRESS_AND_END_PIN),
dppi_chan_gpio_end);

nrfx_gppi_channels_enable(NRFX_BIT(gppi_chan_radio_ready) |
NRFX_BIT(gppi_chan_radio_disabled) |
NRFX_BIT(gppi_chan_radio_address) |
NRFX_BIT(gppi_chan_radio_end));

if (nrfx_dppi_channel_enable(&dppi_gpio_domain, dppi_chan_gpio_ready) != NRFX_SUCCESS) {
LOG_ERR("Failed chan enable gpio_ready");
return -ENOMEM;
}

if (nrfx_dppi_channel_enable(&dppi_gpio_domain, dppi_chan_gpio_disabled) != NRFX_SUCCESS) {
LOG_ERR("Failed chan enable gpio_disabled");
return -ENOMEM;
}

if (nrfx_dppi_channel_enable(&dppi_gpio_domain, dppi_chan_gpio_address) != NRFX_SUCCESS) {
LOG_ERR("Failed chan enable gpio_address");
return -ENOMEM;
}

if (nrfx_dppi_channel_enable(&dppi_gpio_domain, dppi_chan_gpio_end) != NRFX_SUCCESS) {
LOG_ERR("Failed chan enable gpio_end");
return -ENOMEM;
}

return 0;
}

static int mpsl_radio_pin_debug_init(void)
{
uint8_t radio_ready_radio_disabled_gpiote_channel;
uint8_t radio_address_radio_end_gpiote_channel;

const nrfx_gpiote_output_config_t gpiote_output_cfg = NRFX_GPIOTE_DEFAULT_OUTPUT_CONFIG;

if (nrfx_gpiote_channel_alloc(&gpiote, &radio_ready_radio_disabled_gpiote_channel) !=
NRFX_SUCCESS) {
LOG_ERR("Failed allocating GPIOTE chan");
return -ENOMEM;
}

if (nrfx_gpiote_channel_alloc(&gpiote, &radio_address_radio_end_gpiote_channel) !=
NRFX_SUCCESS) {
LOG_ERR("Failed allocating GPIOTE chan");
return -ENOMEM;
}

const nrfx_gpiote_task_config_t task_cfg_ready_disabled = {
.task_ch = radio_ready_radio_disabled_gpiote_channel,
.polarity = NRF_GPIOTE_POLARITY_TOGGLE,
.init_val = NRF_GPIOTE_INITIAL_VALUE_LOW,
};

if (nrfx_gpiote_output_configure(&gpiote,
CONFIG_MPSL_PIN_DEBUG_RADIO_READY_AND_DISABLED_PIN,
&gpiote_output_cfg,
&task_cfg_ready_disabled)
!= NRFX_SUCCESS) {
LOG_ERR("Failed configuring GPIOTE chan");
return -ENOMEM;
}

const nrfx_gpiote_task_config_t task_cfg_address_end = {
.task_ch = radio_address_radio_end_gpiote_channel,
.polarity = NRF_GPIOTE_POLARITY_TOGGLE,
.init_val = NRF_GPIOTE_INITIAL_VALUE_LOW,
};

if (nrfx_gpiote_output_configure(&gpiote, CONFIG_MPSL_PIN_DEBUG_RADIO_ADDRESS_AND_END_PIN,
&gpiote_output_cfg,
&task_cfg_address_end) != NRFX_SUCCESS) {
LOG_ERR("Failed configuring GPIOTE chan");
return -ENOMEM;
}

if (m_ppi_config() != 0) {
return -ENOMEM;
}

nrfx_gpiote_out_task_enable(&gpiote, CONFIG_MPSL_PIN_DEBUG_RADIO_READY_AND_DISABLED_PIN);
nrfx_gpiote_out_task_enable(&gpiote, CONFIG_MPSL_PIN_DEBUG_RADIO_ADDRESS_AND_END_PIN);

return 0;
}

SYS_INIT(mpsl_radio_pin_debug_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);

0 comments on commit db3c544

Please sign in to comment.