-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Toggling pins on radio events is something that can be useful for debugging purposes. By defining Kconfig entries, this becomes simpler to setup. The default configuration will setup two pins to toggle on (RADIO->EVENTS_READY, RADIO->EVENTS_DISABLED) and (RADIO->EVENTS_ADDRESS, RADIO->EVENTS_END). The implementation may require code to be run on both the application core and radio core. As Kconfig entries are not propagated to child images, this entry needs to be set for both cores. For example like this: ``` west build -b nrf5340dk_nrf5340_cpuapp -- -DCONFIG_MPSL_PIN_DEBUG=y -Dhci_ipc_CONFIG_MPSL_PIN_DEBUG=y ``` The entry is marked as experimental because the implementation is not necessarily stable nor tested properly. Signed-off-by: Rubin Gerritsen <[email protected]>
- Loading branch information
1 parent
6ba10cb
commit 7e318ac
Showing
6 changed files
with
290 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# | ||
# Copyright (c) 2024 Nordic Semiconductor ASA | ||
# | ||
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause | ||
# | ||
|
||
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# | ||
# Copyright (c) 2024 Nordic Semiconductor ASA | ||
# | ||
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause | ||
# | ||
|
||
config MPSL_PIN_DEBUG | ||
bool "Toggle MPSL debug pins [EXPERIMENTAL]" | ||
select EXPERIMENTAL | ||
depends on (BOARD_NRF52DK_NRF52832 || \ | ||
BOARD_NRF52833DK_NRF52833 || \ | ||
BOARD_NRF52840DK_NRF52840 || \ | ||
BOARD_NRF5340DK_NRF5340_CPUNET || \ | ||
BOARD_NRF5340DK_NRF5340_CPUAPP) | ||
help | ||
Set this option to enable toggling of GPIO pins upon radio | ||
events. This can be useful for debugging purposes to figure | ||
out when the radio is used. | ||
|
||
config MPSL_PIN_DEBUG_APP_CORE | ||
bool | ||
depends on MPSL_PIN_DEBUG | ||
depends on SOC_COMPATIBLE_NRF5340_CPUAPP | ||
default y if SOC_COMPATIBLE_NRF5340_CPUAPP | ||
|
||
config MPSL_PIN_DEBUG_RADIO_CORE | ||
bool | ||
depends on MPSL_PIN_DEBUG | ||
select NRFX_GPIOTE | ||
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) | ||
|
||
config MPSL_PIN_DEBUG_RADIO_READY_AND_DISABLED_PIN | ||
int "Pin toggled upon the events RADIO->EVENTS_READY and RADIO->EVENTS_DISABLED" | ||
depends on MPSL_PIN_DEBUG | ||
default 3 if SOC_COMPATIBLE_NRF52X | ||
default 4 if SOC_COMPATIBLE_NRF53X | ||
help | ||
Only PORT0 can be used. | ||
|
||
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 | ||
help | ||
Only PORT0 can be used. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/* | ||
* Copyright (c) 2024 Nordic Semiconductor ASA | ||
* | ||
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause | ||
*/ | ||
|
||
#include <zephyr/init.h> | ||
#include <zephyr/kernel.h> | ||
|
||
/* Only PORT 0 can be used. */ | ||
BUILD_ASSERT(CONFIG_MPSL_PIN_DEBUG_RADIO_READY_AND_DISABLED_PIN < | ||
ARRAY_SIZE(NRF_P0_S->PIN_CNF)); | ||
BUILD_ASSERT(CONFIG_MPSL_PIN_DEBUG_RADIO_ADDRESS_AND_END_PIN < | ||
ARRAY_SIZE(NRF_P0_S->PIN_CNF)); | ||
|
||
static const uint8_t pins_used[] = {CONFIG_MPSL_PIN_DEBUG_RADIO_READY_AND_DISABLED_PIN, | ||
CONFIG_MPSL_PIN_DEBUG_RADIO_ADDRESS_AND_END_PIN}; | ||
|
||
/** @brief Allow access to specific GPIOs for the network core. */ | ||
static int network_gpio_allow(void) | ||
{ | ||
for (uint32_t i = 0; i < ARRAY_SIZE(pins_used); i++) { | ||
uint8_t pin = pins_used[i]; | ||
|
||
NRF_P0_S->PIN_CNF[pin] = | ||
(GPIO_PIN_CNF_MCUSEL_NetworkMCU << GPIO_PIN_CNF_MCUSEL_Pos); | ||
} | ||
|
||
return 0; | ||
} | ||
SYS_INIT(network_gpio_allow, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
/* | ||
* 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 <nrfx_gpiote.h> | ||
#include <helpers/nrfx_gppi.h> | ||
#include <hal/nrf_radio.h> | ||
|
||
#ifdef PPI_PRESENT | ||
#include <nrfx_ppi.h> | ||
#elif defined(DPPI_PRESENT) | ||
#include <nrfx_dppi.h> | ||
#include <mpsl_dppi_protocol_api.h> | ||
#include <hal/nrf_egu.h> | ||
#endif | ||
|
||
LOG_MODULE_REGISTER(mpsl_radio_pin_debug, CONFIG_MPSL_LOG_LEVEL); | ||
|
||
static int m_ppi_config(void) | ||
{ | ||
#if defined(PPI_PRESENT) | ||
uint8_t ppi_chan_radio_ready; | ||
uint8_t ppi_chan_radio_address; | ||
uint8_t ppi_chan_radio_end; | ||
uint8_t ppi_chan_radio_disabled; | ||
|
||
if (nrfx_ppi_channel_alloc(&ppi_chan_radio_ready) != NRFX_SUCCESS) { | ||
LOG_ERR("Failed allocating PPI chan"); | ||
return -ENOMEM; | ||
} | ||
|
||
if (nrfx_ppi_channel_alloc(&ppi_chan_radio_address) != NRFX_SUCCESS) { | ||
LOG_ERR("Failed allocating PPI chan"); | ||
return -ENOMEM; | ||
} | ||
|
||
if (nrfx_ppi_channel_alloc(&ppi_chan_radio_end) != NRFX_SUCCESS) { | ||
LOG_ERR("Failed allocating PPI chan"); | ||
return -ENOMEM; | ||
} | ||
|
||
if (nrfx_ppi_channel_alloc(&ppi_chan_radio_disabled) != NRFX_SUCCESS) { | ||
LOG_ERR("Failed allocating PPI chan"); | ||
return -ENOMEM; | ||
} | ||
|
||
nrfx_gppi_channel_endpoints_setup( | ||
ppi_chan_radio_ready, nrf_radio_event_address_get(NRF_RADIO, NRF_RADIO_EVENT_READY), | ||
nrfx_gpiote_out_task_address_get( | ||
CONFIG_MPSL_PIN_DEBUG_RADIO_READY_AND_DISABLED_PIN)); | ||
|
||
nrfx_gppi_channel_endpoints_setup( | ||
ppi_chan_radio_disabled, | ||
nrf_radio_event_address_get(NRF_RADIO, NRF_RADIO_EVENT_DISABLED), | ||
nrfx_gpiote_out_task_address_get( | ||
CONFIG_MPSL_PIN_DEBUG_RADIO_READY_AND_DISABLED_PIN)); | ||
|
||
nrfx_gppi_channel_endpoints_setup( | ||
ppi_chan_radio_address, | ||
nrf_radio_event_address_get(NRF_RADIO, NRF_RADIO_EVENT_ADDRESS), | ||
nrfx_gpiote_out_task_address_get(CONFIG_MPSL_PIN_DEBUG_RADIO_ADDRESS_AND_END_PIN)); | ||
|
||
nrfx_gppi_channel_endpoints_setup( | ||
ppi_chan_radio_end, nrf_radio_event_address_get(NRF_RADIO, NRF_RADIO_EVENT_END), | ||
nrfx_gpiote_out_task_address_get(CONFIG_MPSL_PIN_DEBUG_RADIO_ADDRESS_AND_END_PIN)); | ||
|
||
if (nrfx_ppi_channel_enable(ppi_chan_radio_ready) != NRFX_SUCCESS) { | ||
LOG_ERR("Failed enabling channel"); | ||
return -ENOMEM; | ||
} | ||
if (nrfx_ppi_channel_enable(ppi_chan_radio_address) != NRFX_SUCCESS) { | ||
LOG_ERR("Failed enabling channel"); | ||
return -ENOMEM; | ||
} | ||
if (nrfx_ppi_channel_enable(ppi_chan_radio_end) != NRFX_SUCCESS) { | ||
LOG_ERR("Failed enabling channel"); | ||
return -ENOMEM; | ||
} | ||
if (nrfx_ppi_channel_enable(ppi_chan_radio_disabled) != NRFX_SUCCESS) { | ||
LOG_ERR("Failed enabling channel"); | ||
return -ENOMEM; | ||
} | ||
|
||
#elif defined(DPPI_PRESENT) | ||
/* Radio events are published on predefined channels. | ||
*/ | ||
uint8_t ppi_chan_radio_ready = MPSL_DPPI_RADIO_PUBLISH_READY_CHANNEL_IDX; | ||
uint8_t ppi_chan_radio_address = MPSL_DPPI_RADIO_PUBLISH_ADDRESS_CHANNEL_IDX; | ||
uint8_t ppi_chan_radio_end = MPSL_DPPI_RADIO_PUBLISH_END_CHANNEL_IDX; | ||
uint8_t ppi_chan_radio_disabled = MPSL_DPPI_RADIO_PUBLISH_DISABLED_CH_IDX; | ||
|
||
/* Because the GPIOTE needs to subscribe to only two DPPI channels, | ||
* we use an EGU to route events together. | ||
*/ | ||
uint8_t dppi_chan_ready_disabled; | ||
uint8_t dppi_chan_address_end; | ||
|
||
if (nrfx_dppi_channel_alloc(&dppi_chan_ready_disabled) != NRFX_SUCCESS) { | ||
LOG_ERR("Failed allocating DPPI chan"); | ||
return -ENOMEM; | ||
} | ||
|
||
if (nrfx_dppi_channel_alloc(&dppi_chan_address_end) != NRFX_SUCCESS) { | ||
LOG_ERR("Failed allocating DPPI chan"); | ||
return -ENOMEM; | ||
} | ||
nrf_egu_subscribe_set(NRF_EGU0, NRF_EGU_TASK_TRIGGER0, ppi_chan_radio_ready); | ||
nrf_egu_subscribe_set(NRF_EGU0, NRF_EGU_TASK_TRIGGER1, ppi_chan_radio_disabled); | ||
nrf_egu_subscribe_set(NRF_EGU0, NRF_EGU_TASK_TRIGGER2, ppi_chan_radio_address); | ||
nrf_egu_subscribe_set(NRF_EGU0, NRF_EGU_TASK_TRIGGER3, ppi_chan_radio_end); | ||
|
||
nrf_egu_publish_set(NRF_EGU0, NRF_EGU_EVENT_TRIGGERED0, dppi_chan_ready_disabled); | ||
nrf_egu_publish_set(NRF_EGU0, NRF_EGU_EVENT_TRIGGERED1, dppi_chan_ready_disabled); | ||
nrf_egu_publish_set(NRF_EGU0, NRF_EGU_EVENT_TRIGGERED2, dppi_chan_address_end); | ||
nrf_egu_publish_set(NRF_EGU0, NRF_EGU_EVENT_TRIGGERED3, dppi_chan_address_end); | ||
|
||
nrfx_gppi_task_endpoint_setup(dppi_chan_ready_disabled, | ||
nrfx_gpiote_out_task_address_get( | ||
CONFIG_MPSL_PIN_DEBUG_RADIO_READY_AND_DISABLED_PIN)); | ||
|
||
nrfx_gppi_task_endpoint_setup( | ||
dppi_chan_address_end, | ||
nrfx_gpiote_out_task_address_get(CONFIG_MPSL_PIN_DEBUG_RADIO_ADDRESS_AND_END_PIN)); | ||
|
||
if (nrfx_dppi_channel_enable(dppi_chan_ready_disabled) != NRFX_SUCCESS) { | ||
LOG_ERR("Failed enabling channel"); | ||
return -ENOMEM; | ||
} | ||
|
||
if (nrfx_dppi_channel_enable(dppi_chan_address_end) != NRFX_SUCCESS) { | ||
LOG_ERR("Failed enabling channel"); | ||
return -ENOMEM; | ||
} | ||
#else | ||
#error "Expect either PPI or DPPI to be present." | ||
#endif | ||
|
||
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(&radio_ready_radio_disabled_gpiote_channel) != NRFX_SUCCESS) { | ||
LOG_ERR("Failed allocating GPIOTE chan"); | ||
return -ENOMEM; | ||
} | ||
|
||
if (nrfx_gpiote_channel_alloc(&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(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(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(CONFIG_MPSL_PIN_DEBUG_RADIO_READY_AND_DISABLED_PIN); | ||
nrfx_gpiote_out_task_enable(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); |