From 9886bdc0c87de5b4d56454dbdef6edec2ec1e80e Mon Sep 17 00:00:00 2001 From: Krzysztof Chruscinski Date: Wed, 24 Nov 2021 08:05:05 +0100 Subject: [PATCH] drivers: pwm: pwm_nrf5_sw: Use runtime resources allocation Use nrfx_gpiote and nrfx_ppi allocators to allocate channels at runtime instead of fixed, device-tree based allocation which is harder to maintain. Signed-off-by: Krzysztof Chruscinski --- drivers/pwm/Kconfig.nrf5_sw | 4 +- drivers/pwm/pwm_nrf5_sw.c | 76 ++++++++++++------- dts/arm/nordic/nrf51822.dtsi | 2 - dts/arm/nordic/nrf52805.dtsi | 2 - dts/arm/nordic/nrf52810.dtsi | 2 - dts/arm/nordic/nrf52811.dtsi | 2 - dts/arm/nordic/nrf52820.dtsi | 2 - dts/arm/nordic/nrf52832.dtsi | 2 - dts/arm/nordic/nrf52833.dtsi | 2 - dts/arm/nordic/nrf52840.dtsi | 2 - dts/bindings/pwm/nordic,nrf-sw-pwm.yaml | 10 --- modules/hal_nordic/nrfx/nrfx_glue.h | 24 +----- .../ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h | 6 -- .../nordic/hal/nrf5/radio/radio_nrf5_dppi.h | 5 -- .../nordic/hal/nrf5/radio/radio_nrf5_ppi.h | 5 -- 15 files changed, 55 insertions(+), 91 deletions(-) diff --git a/drivers/pwm/Kconfig.nrf5_sw b/drivers/pwm/Kconfig.nrf5_sw index e2e28d6aadf4..f590f38fd8c6 100644 --- a/drivers/pwm/Kconfig.nrf5_sw +++ b/drivers/pwm/Kconfig.nrf5_sw @@ -6,7 +6,9 @@ config PWM_NRF5_SW bool "Nordic Semiconductor nRF5x series S/W PWM" default y if !PWM_NRFX - depends on SOC_FAMILY_NRF + depends on HAS_HW_NRF_PPI + select NRFX_GPIOTE + select NRFX_PPI help Enable driver to utilize PWM on the Nordic Semiconductor nRF5x series. diff --git a/drivers/pwm/pwm_nrf5_sw.c b/drivers/pwm/pwm_nrf5_sw.c index 7a62a2192dd2..083937b0c182 100644 --- a/drivers/pwm/pwm_nrf5_sw.c +++ b/drivers/pwm/pwm_nrf5_sw.c @@ -7,6 +7,8 @@ #define DT_DRV_COMPAT nordic_nrf_sw_pwm #include +#include +#include #include #include @@ -35,13 +37,14 @@ BUILD_ASSERT(DT_INST_PROP(0, clock_prescaler) == 0, #endif #define PWM_0_MAP_SIZE DT_INST_PROP(0, channel_count) +/* When RTC is used, one more PPI channel is required. */ +#define PPI_PER_CH (2 + USE_RTC) + struct pwm_config { union { NRF_RTC_Type *rtc; NRF_TIMER_Type *timer; }; - uint8_t gpiote_base; - uint8_t ppi_base; uint8_t map_size; uint8_t prescaler; }; @@ -53,6 +56,8 @@ struct chan_map { struct pwm_data { uint32_t period_cycles; + uint8_t ppi_ch[PWM_0_MAP_SIZE][PPI_PER_CH]; + uint8_t gpiote_ch[PWM_0_MAP_SIZE]; struct chan_map map[PWM_0_MAP_SIZE]; }; @@ -128,9 +133,10 @@ static int pwm_nrf5_sw_pin_set(const struct device *dev, uint32_t pwm, NRF_TIMER_Type *timer = pwm_config_timer(config); NRF_RTC_Type *rtc = pwm_config_rtc(config); struct pwm_data *data = dev->data; - uint8_t ppi_index; uint32_t ppi_mask; uint8_t channel; + uint8_t gpiote_ch; + const uint8_t *ppi_chs; uint32_t ret; if (flags) { @@ -167,6 +173,8 @@ static int pwm_nrf5_sw_pin_set(const struct device *dev, uint32_t pwm, /* map pwm pin to GPIOTE config/channel */ channel = pwm_channel_map(data, config->map_size, pwm); + gpiote_ch = data->gpiote_ch[channel]; + ppi_chs = data->ppi_ch[channel]; if (channel >= config->map_size) { LOG_ERR("No more channels available"); return -ENOMEM; @@ -176,17 +184,10 @@ static int pwm_nrf5_sw_pin_set(const struct device *dev, uint32_t pwm, period_cycles, pulse_cycles); /* clear GPIOTE config */ - NRF_GPIOTE->CONFIG[config->gpiote_base + channel] = 0; + NRF_GPIOTE->CONFIG[gpiote_ch] = 0; /* clear PPI used */ - if (USE_RTC) { - ppi_index = config->ppi_base + (channel * 3); - ppi_mask = BIT(ppi_index) | BIT(ppi_index + 1) | - BIT(ppi_index + 2); - } else { - ppi_index = config->ppi_base + (channel * 2); - ppi_mask = BIT(ppi_index) | BIT(ppi_index + 1); - } + ppi_mask = BIT(ppi_chs[0]) | BIT(ppi_chs[1]) | (USE_RTC ? BIT(ppi_chs[2]) : 0); NRF_PPI->CHENCLR = ppi_mask; /* configure GPIO pin as output */ @@ -229,31 +230,30 @@ static int pwm_nrf5_sw_pin_set(const struct device *dev, uint32_t pwm, } /* configure GPIOTE, toggle with initialise output high */ - NRF_GPIOTE->CONFIG[config->gpiote_base + channel] = 0x00130003 | - (pwm << 8); + NRF_GPIOTE->CONFIG[gpiote_ch] = 0x00130003 | (pwm << 8); /* setup PPI */ if (USE_RTC) { - NRF_PPI->CH[ppi_index].EEP = + NRF_PPI->CH[ppi_chs[0]].EEP = (uint32_t) &(rtc->EVENTS_COMPARE[channel]); - NRF_PPI->CH[ppi_index].TEP = + NRF_PPI->CH[ppi_chs[0]].TEP = (uint32_t) &(NRF_GPIOTE->TASKS_OUT[channel]); - NRF_PPI->CH[ppi_index + 1].EEP = + NRF_PPI->CH[ppi_chs[1]].EEP = (uint32_t) &(rtc->EVENTS_COMPARE[config->map_size]); - NRF_PPI->CH[ppi_index + 1].TEP = + NRF_PPI->CH[ppi_chs[1]].TEP = (uint32_t) &(NRF_GPIOTE->TASKS_OUT[channel]); - NRF_PPI->CH[ppi_index + 2].EEP = + NRF_PPI->CH[ppi_chs[2]].EEP = (uint32_t) &(rtc->EVENTS_COMPARE[config->map_size]); - NRF_PPI->CH[ppi_index + 2].TEP = + NRF_PPI->CH[ppi_chs[2]].TEP = (uint32_t) &(rtc->TASKS_CLEAR); } else { - NRF_PPI->CH[ppi_index].EEP = + NRF_PPI->CH[ppi_chs[0]].EEP = (uint32_t) &(timer->EVENTS_COMPARE[channel]); - NRF_PPI->CH[ppi_index].TEP = + NRF_PPI->CH[ppi_chs[0]].TEP = (uint32_t) &(NRF_GPIOTE->TASKS_OUT[channel]); - NRF_PPI->CH[ppi_index + 1].EEP = + NRF_PPI->CH[ppi_chs[1]].EEP = (uint32_t) &(timer->EVENTS_COMPARE[config->map_size]); - NRF_PPI->CH[ppi_index + 1].TEP = + NRF_PPI->CH[ppi_chs[1]].TEP = (uint32_t) &(NRF_GPIOTE->TASKS_OUT[channel]); } NRF_PPI->CHENSET = ppi_mask; @@ -327,9 +327,35 @@ static const struct pwm_driver_api pwm_nrf5_sw_drv_api_funcs = { static int pwm_nrf5_sw_init(const struct device *dev) { const struct pwm_config *config = dev->config; + struct pwm_data *data = dev->data; NRF_TIMER_Type *timer = pwm_config_timer(config); NRF_RTC_Type *rtc = pwm_config_rtc(config); + /* Allocate resources. */ + for (uint32_t i = 0; i < config->map_size; i++) { + nrfx_err_t err; + + for (uint32_t j = 0; j < PPI_PER_CH; j++) { + err = nrfx_ppi_channel_alloc(&data->ppi_ch[i][j]); + if (err != NRFX_SUCCESS) { + /* Do not free allocated resource. It is a fatal condition, + * system requires reconfiguration. + */ + LOG_ERR("Failed to allocate PPI channel"); + return -ENOMEM; + } + } + + err = nrfx_gpiote_channel_alloc(&data->gpiote_ch[i]); + if (err != NRFX_SUCCESS) { + /* Do not free allocated resource. It is a fatal condition, + * system requires reconfiguration. + */ + LOG_ERR("Failed to allocate GPIOTE channel"); + return -ENOMEM; + } + } + if (USE_RTC) { /* setup RTC */ rtc->PRESCALER = 0; @@ -361,8 +387,6 @@ static int pwm_nrf5_sw_init(const struct device *dev) static const struct pwm_config pwm_nrf5_sw_0_config = { COND_CODE_1(USE_RTC, (.rtc), (.timer)) = GENERATOR_ADDR, - .ppi_base = DT_INST_PROP(0, ppi_base), - .gpiote_base = DT_INST_PROP(0, gpiote_base), .map_size = PWM_0_MAP_SIZE, .prescaler = DT_INST_PROP(0, clock_prescaler), }; diff --git a/dts/arm/nordic/nrf51822.dtsi b/dts/arm/nordic/nrf51822.dtsi index b20a9841b49a..02005e5e8da7 100644 --- a/dts/arm/nordic/nrf51822.dtsi +++ b/dts/arm/nordic/nrf51822.dtsi @@ -251,8 +251,6 @@ generator = <&timer1>; channel-count = <3>; clock-prescaler = <0>; - ppi-base = <0>; - gpiote-base = <0>; #pwm-cells = <1>; }; }; diff --git a/dts/arm/nordic/nrf52805.dtsi b/dts/arm/nordic/nrf52805.dtsi index 581ac666c8e1..a39b611f8bf8 100644 --- a/dts/arm/nordic/nrf52805.dtsi +++ b/dts/arm/nordic/nrf52805.dtsi @@ -256,8 +256,6 @@ generator = <&timer2>; channel-count = <3>; clock-prescaler = <0>; - ppi-base = <0>; - gpiote-base = <0>; #pwm-cells = <1>; }; }; diff --git a/dts/arm/nordic/nrf52810.dtsi b/dts/arm/nordic/nrf52810.dtsi index 90a8bc81c333..9c436c69ea58 100644 --- a/dts/arm/nordic/nrf52810.dtsi +++ b/dts/arm/nordic/nrf52810.dtsi @@ -269,8 +269,6 @@ generator = <&timer2>; channel-count = <3>; clock-prescaler = <0>; - ppi-base = <0>; - gpiote-base = <0>; #pwm-cells = <1>; }; }; diff --git a/dts/arm/nordic/nrf52811.dtsi b/dts/arm/nordic/nrf52811.dtsi index f14fcaf33106..10b2b6041e13 100644 --- a/dts/arm/nordic/nrf52811.dtsi +++ b/dts/arm/nordic/nrf52811.dtsi @@ -295,8 +295,6 @@ generator = <&timer2>; channel-count = <3>; clock-prescaler = <0>; - ppi-base = <0>; - gpiote-base = <0>; #pwm-cells = <1>; }; }; diff --git a/dts/arm/nordic/nrf52820.dtsi b/dts/arm/nordic/nrf52820.dtsi index dea0333af058..b692811706b6 100644 --- a/dts/arm/nordic/nrf52820.dtsi +++ b/dts/arm/nordic/nrf52820.dtsi @@ -335,8 +335,6 @@ generator = <&timer2>; channel-count = <3>; clock-prescaler = <0>; - ppi-base = <0>; - gpiote-base = <0>; #pwm-cells = <1>; }; }; diff --git a/dts/arm/nordic/nrf52832.dtsi b/dts/arm/nordic/nrf52832.dtsi index 744c5a8bf40b..166e0c1e9217 100644 --- a/dts/arm/nordic/nrf52832.dtsi +++ b/dts/arm/nordic/nrf52832.dtsi @@ -406,8 +406,6 @@ generator = <&timer2>; channel-count = <3>; clock-prescaler = <0>; - ppi-base = <0>; - gpiote-base = <0>; #pwm-cells = <1>; }; }; diff --git a/dts/arm/nordic/nrf52833.dtsi b/dts/arm/nordic/nrf52833.dtsi index 7dd378c9e656..befbafe2afab 100644 --- a/dts/arm/nordic/nrf52833.dtsi +++ b/dts/arm/nordic/nrf52833.dtsi @@ -464,8 +464,6 @@ generator = <&timer2>; channel-count = <3>; clock-prescaler = <0>; - ppi-base = <0>; - gpiote-base = <0>; #pwm-cells = <1>; }; }; diff --git a/dts/arm/nordic/nrf52840.dtsi b/dts/arm/nordic/nrf52840.dtsi index e3f84a7088d7..b6b658bb938a 100644 --- a/dts/arm/nordic/nrf52840.dtsi +++ b/dts/arm/nordic/nrf52840.dtsi @@ -484,8 +484,6 @@ generator = <&timer2>; channel-count = <3>; clock-prescaler = <0>; - ppi-base = <0>; - gpiote-base = <0>; #pwm-cells = <1>; }; }; diff --git a/dts/bindings/pwm/nordic,nrf-sw-pwm.yaml b/dts/bindings/pwm/nordic,nrf-sw-pwm.yaml index 9770a75d1511..2eb15f86d4ca 100644 --- a/dts/bindings/pwm/nordic,nrf-sw-pwm.yaml +++ b/dts/bindings/pwm/nordic,nrf-sw-pwm.yaml @@ -29,16 +29,6 @@ properties: TIMER: 16 MHz / 2^prescaler base clock is used for PWM generation. required: true - ppi-base: - type: int - description: PPI base used for PPI index calculation used for PWM output generation - required: true - - gpiote-base: - type: int - description: GPIOTE base used for GPIOTE index calculation used for PWM output generation - required: true - "#pwm-cells": const: 1 diff --git a/modules/hal_nordic/nrfx/nrfx_glue.h b/modules/hal_nordic/nrfx/nrfx_glue.h index c79305654b87..5b45edc2987c 100644 --- a/modules/hal_nordic/nrfx/nrfx_glue.h +++ b/modules/hal_nordic/nrfx/nrfx_glue.h @@ -229,8 +229,7 @@ void nrfx_busy_wait(uint32_t usec_to_wait); /** @brief Bitmask that defines PPI channels that are reserved for use outside of the nrfx library. */ #define NRFX_PPI_CHANNELS_USED (NRFX_PPI_CHANNELS_USED_BY_BT_CTLR | \ NRFX_PPI_CHANNELS_USED_BY_802154_DRV | \ - NRFX_PPI_CHANNELS_USED_BY_MPSL | \ - NRFX_PPI_CHANNELS_USED_BY_PWM_SW) + NRFX_PPI_CHANNELS_USED_BY_MPSL) /** @brief Bitmask that defines PPI groups that are reserved for use outside of the nrfx library. */ #define NRFX_PPI_GROUPS_USED (NRFX_PPI_GROUPS_USED_BY_BT_CTLR | \ @@ -238,7 +237,7 @@ void nrfx_busy_wait(uint32_t usec_to_wait); NRFX_PPI_GROUPS_USED_BY_MPSL) /** @brief Bitmask that defines GPIOTE channels that are reserved for use outside of the nrfx library. */ -#define NRFX_GPIOTE_CHANNELS_USED NRFX_GPIOTE_CHANNELS_USED_BY_PWM_SW +#define NRFX_GPIOTE_CHANNELS_USED 0 #if defined(CONFIG_BT_CTLR) extern const uint32_t z_bt_ctlr_used_nrf_ppi_channels; @@ -271,25 +270,6 @@ extern const uint32_t z_mpsl_used_nrf_ppi_groups; #define NRFX_PPI_GROUPS_USED_BY_MPSL 0 #endif -#if defined(CONFIG_PWM_NRF5_SW) -#define PWM_NRF5_SW_NODE DT_INST(0, nordic_nrf_sw_pwm) -#define PWM_NRF5_SW_GENERATOR_NODE DT_PHANDLE(PWM_NRF5_SW_NODE, generator) -#if DT_NODE_HAS_COMPAT(PWM_NRF5_SW_GENERATOR_NODE, nordic_nrf_rtc) -#define PWM_NRF5_SW_PPI_CHANNELS_PER_PIN 3 -#else -#define PWM_NRF5_SW_PPI_CHANNELS_PER_PIN 2 -#endif /* DT_NODE_HAS_COMPAT(PWM_NRF5_SW_GENERATOR_NODE, nordic_nrf_rtc) */ -#define NRFX_PPI_CHANNELS_USED_BY_PWM_SW \ - (BIT_MASK(DT_PROP(PWM_NRF5_SW_NODE, channel_count) * \ - PWM_NRF5_SW_PPI_CHANNELS_PER_PIN) \ - << DT_PROP(PWM_NRF5_SW_NODE, ppi_base)) -#define NRFX_GPIOTE_CHANNELS_USED_BY_PWM_SW \ - DT_PROP(PWM_NRF5_SW_NODE, channel_count) -#else -#define NRFX_PPI_CHANNELS_USED_BY_PWM_SW 0 -#define NRFX_GPIOTE_CHANNELS_USED_BY_PWM_SW 0 -#endif - /** @brief Bitmask that defines EGU instances that are reserved for use outside of the nrfx library. */ #define NRFX_EGUS_USED 0 diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h index 46fc2a5c981b..fb21672d2743 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h @@ -50,15 +50,9 @@ #include -#if defined(CONFIG_PWM_NRF5_SW) -#define HAL_PALNA_GPIOTE_CHAN 3 -#define HAL_PDN_GPIOTE_CHAN 4 -#define HAL_CSN_GPIOTE_CHAN 5 -#else #define HAL_PALNA_GPIOTE_CHAN 0 #define HAL_PDN_GPIOTE_CHAN 1 #define HAL_CSN_GPIOTE_CHAN 2 -#endif /* This has to come before the ppi/dppi includes below. */ #include "radio_nrf5_fem.h" diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h index 7e42bf1cc50a..c8019cc16bcd 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_dppi.h @@ -691,11 +691,6 @@ static inline void hal_radio_group_task_disable_ppi_setup(void) #define HAL_USED_PPI_CHANNELS_6 0 #endif -BUILD_ASSERT( - (HAL_USED_PPI_CHANNELS & NRFX_PPI_CHANNELS_USED_BY_PWM_SW) == 0, - "PPI channels used by the Bluetooth controller overlap with those " - "assigned to the pwm_nrf5_sw driver."); - #if defined(SW_SWITCH_TIMER_TASK_GROUP_BASE) #define HAL_USED_PPI_GROUPS \ (BIT(SW_SWITCH_TIMER_TASK_GROUP_BASE) | \ diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi.h index e5704dccb661..1701ce72ba52 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi.h @@ -709,11 +709,6 @@ static inline void hal_radio_sw_switch_ppi_group_setup(void) #define HAL_USED_PPI_CHANNELS_6 0 #endif -BUILD_ASSERT( - (HAL_USED_PPI_CHANNELS & NRFX_PPI_CHANNELS_USED_BY_PWM_SW) == 0, - "PPI channels used by the Bluetooth controller overlap with those " - "assigned to the pwm_nrf5_sw driver."); - #if defined(SW_SWITCH_TIMER_TASK_GROUP_BASE) #define HAL_USED_PPI_GROUPS \ (BIT(SW_SWITCH_TIMER_TASK_GROUP_BASE) | \