diff --git a/drivers/adc/Kconfig.stm32 b/drivers/adc/Kconfig.stm32 index a5da9656f14..cb763cdf7fc 100644 --- a/drivers/adc/Kconfig.stm32 +++ b/drivers/adc/Kconfig.stm32 @@ -3,6 +3,7 @@ # Copyright (c) 2019 Intel Corporation # Copyright (c) 2019 Endre Karlson # Copyright (c) 2019 Song Qiang +# Copyright (c) 2021 Marius Scholtz, RIC Electronics # SPDX-License-Identifier: Apache-2.0 config ADC_STM32 @@ -10,3 +11,13 @@ config ADC_STM32 depends on SOC_FAMILY_STM32 help Enable the driver implementation for the stm32xx ADC + +if SOC_SERIES_STM32F2X || SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X + +config ADC_STM32_SHARED_IRQS + bool "STM32 ADC shared interrupts" + default y + depends on ADC_STM32 + help + Enable the use of shared interrupts for families that only have a single interrupt for all ADC's +endif diff --git a/drivers/adc/adc_stm32.c b/drivers/adc/adc_stm32.c index 8ea29999b37..471d91b49e2 100644 --- a/drivers/adc/adc_stm32.c +++ b/drivers/adc/adc_stm32.c @@ -3,6 +3,7 @@ * Copyright (c) 2019 Song Qiang * Copyright (c) 2019 Endre Karlson * Copyright (c) 2020 Teslabs Engineering S.L. + * Copyright (c) 2021 Marius Scholtz, RIC Electronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -262,6 +263,10 @@ struct adc_stm32_cfg { const struct pinctrl_dev_config *pcfg; }; +#ifdef CONFIG_ADC_STM32_SHARED_IRQS +static bool init_irq = true; +#endif + static int check_buffer_size(const struct adc_sequence *sequence, uint8_t active_channels) { @@ -666,7 +671,7 @@ static void adc_stm32_isr(const struct device *dev) adc_context_on_sampling_done(&data->ctx, dev); - LOG_DBG("ISR triggered."); + LOG_DBG("%s ISR triggered.", dev->name); } static int adc_stm32_read(const struct device *dev, @@ -1048,11 +1053,60 @@ static const struct adc_driver_api api_stm32_driver_api = { #endif }; -#define STM32_ADC_INIT(index) \ - \ -static void adc_stm32_cfg_func_##index(void); \ - \ -PINCTRL_DT_INST_DEFINE(index); \ +#ifdef CONFIG_ADC_STM32_SHARED_IRQS + +bool adc_stm32_is_irq_active(ADC_TypeDef *adc) +{ + return LL_ADC_IsActiveFlag_EOCS(adc) || + LL_ADC_IsActiveFlag_OVR(adc) || + LL_ADC_IsActiveFlag_JEOS(adc) || + LL_ADC_IsActiveFlag_AWD1(adc); +} + +#define HANDLE_IRQS(index) \ + static const struct device *dev_##index = DEVICE_DT_INST_GET(index); \ + const struct adc_stm32_cfg *cfg_##index = dev_##index->config; \ + ADC_TypeDef *adc_##index = (ADC_TypeDef *)(cfg_##index->base); \ + \ + if (adc_stm32_is_irq_active(adc_##index)) { \ + adc_stm32_isr(dev_##index); \ + } + +static void adc_stm32_shared_irq_handler(void) +{ + DT_INST_FOREACH_STATUS_OKAY(HANDLE_IRQS); +} + +static void adc_stm32_irq_init(void) +{ + if (init_irq) { + init_irq = false; + IRQ_CONNECT(DT_INST_IRQN(0), + DT_INST_IRQ(0, priority), + adc_stm32_shared_irq_handler, NULL, 0); + irq_enable(DT_INST_IRQN(0)); + } +} + +#define ADC_STM32_CONFIG(index) \ +static const struct adc_stm32_cfg adc_stm32_cfg_##index = { \ + .base = (ADC_TypeDef *)DT_INST_REG_ADDR(index), \ + .irq_cfg_func = adc_stm32_irq_init, \ + .pclken = { \ + .enr = DT_INST_CLOCKS_CELL(index, bits), \ + .bus = DT_INST_CLOCKS_CELL(index, bus), \ + }, \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(index), \ +}; +#else +#define ADC_STM32_CONFIG(index) \ +static void adc_stm32_cfg_func_##index(void) \ +{ \ + IRQ_CONNECT(DT_INST_IRQN(index), \ + DT_INST_IRQ(index, priority), \ + adc_stm32_isr, DEVICE_DT_INST_GET(index), 0); \ + irq_enable(DT_INST_IRQN(index)); \ +} \ \ static const struct adc_stm32_cfg adc_stm32_cfg_##index = { \ .base = (ADC_TypeDef *)DT_INST_REG_ADDR(index), \ @@ -1062,7 +1116,15 @@ static const struct adc_stm32_cfg adc_stm32_cfg_##index = { \ .bus = DT_INST_CLOCKS_CELL(index, bus), \ }, \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(index), \ -}; \ +}; +#endif /* CONFIG_ADC_STM32_SHARED_IRQS */ + +#define STM32_ADC_INIT(index) \ + \ +PINCTRL_DT_INST_DEFINE(index); \ + \ +ADC_STM32_CONFIG(index) \ + \ static struct adc_stm32_data adc_stm32_data_##index = { \ ADC_CONTEXT_INIT_TIMER(adc_stm32_data_##index, ctx), \ ADC_CONTEXT_INIT_LOCK(adc_stm32_data_##index, ctx), \ @@ -1073,14 +1135,6 @@ DEVICE_DT_INST_DEFINE(index, \ &adc_stm32_init, NULL, \ &adc_stm32_data_##index, &adc_stm32_cfg_##index, \ POST_KERNEL, CONFIG_ADC_INIT_PRIORITY, \ - &api_stm32_driver_api); \ - \ -static void adc_stm32_cfg_func_##index(void) \ -{ \ - IRQ_CONNECT(DT_INST_IRQN(index), \ - DT_INST_IRQ(index, priority), \ - adc_stm32_isr, DEVICE_DT_INST_GET(index), 0); \ - irq_enable(DT_INST_IRQN(index)); \ -} + &api_stm32_driver_api); DT_INST_FOREACH_STATUS_OKAY(STM32_ADC_INIT) diff --git a/dts/arm/st/f4/stm32f405.dtsi b/dts/arm/st/f4/stm32f405.dtsi index fc6e3bfe501..266db3d62ed 100644 --- a/dts/arm/st/f4/stm32f405.dtsi +++ b/dts/arm/st/f4/stm32f405.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2017 Linaro Limited + * Copyright (c) 2021 Marius Scholtz, RIC Electronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -257,6 +258,26 @@ status = "disabled"; }; + adc2: adc@40012100 { + compatible = "st,stm32-adc"; + reg = <0x40012100 0x050>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00000200>; + interrupts = <18 0>; + status = "disabled"; + label = "ADC_2"; + #io-channel-cells = <1>; + }; + + adc3: adc@40012200 { + compatible = "st,stm32-adc"; + reg = <0x40012200 0x050>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00000400>; + interrupts = <18 0>; + status = "disabled"; + label = "ADC_3"; + #io-channel-cells = <1>; + }; + dac1: dac@40007400 { compatible = "st,stm32-dac"; reg = <0x40007400 0x400>;