From db3c5448e6730e3474090b7be4bf1f59ddb61791 Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Tue, 10 Dec 2024 08:43:58 +0100 Subject: [PATCH] mpsl: Support mpsl_pin_debug on nRF54L DK 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 --- subsys/mpsl/pin_debug/CMakeLists.txt | 1 + subsys/mpsl/pin_debug/Kconfig | 14 +- subsys/mpsl/pin_debug/mpsl_pin_debug_nrf54.c | 229 +++++++++++++++++++ 3 files changed, 241 insertions(+), 3 deletions(-) create mode 100644 subsys/mpsl/pin_debug/mpsl_pin_debug_nrf54.c diff --git a/subsys/mpsl/pin_debug/CMakeLists.txt b/subsys/mpsl/pin_debug/CMakeLists.txt index df8231088c37..8bbf9dbdb568 100644 --- a/subsys/mpsl/pin_debug/CMakeLists.txt +++ b/subsys/mpsl/pin_debug/CMakeLists.txt @@ -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) diff --git a/subsys/mpsl/pin_debug/Kconfig b/subsys/mpsl/pin_debug/Kconfig index 2f8e0fa07d66..c363b92f6758 100644 --- a/subsys/mpsl/pin_debug/Kconfig +++ b/subsys/mpsl/pin_debug/Kconfig @@ -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 @@ -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) @@ -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. diff --git a/subsys/mpsl/pin_debug/mpsl_pin_debug_nrf54.c b/subsys/mpsl/pin_debug/mpsl_pin_debug_nrf54.c new file mode 100644 index 000000000000..ae9e0bc51ada --- /dev/null +++ b/subsys/mpsl/pin_debug/mpsl_pin_debug_nrf54.c @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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);