drivers: arm: stm32: adc: Added Shared IRQ

Certain stm32 soc's have a single shared irq for all adc channels
on those soc's only a single channel is supported.

Added a Kconfig that enables a shared irq for stm32f2x, stm32f4x,
stm32f7x soc's. The shared IRQ uses a flag to limit the number of
interrupts defined to only 1. A shared irq handler is added which
determines which ADC instance the interrupt is for, it then calls
into the existing interrupt.

Signed-off-by: Marius Scholtz <mariuss@ricelectronics.com>
This commit is contained in:
Marius Scholtz 2021-09-01 09:24:24 -07:00 committed by Carles Cufí
commit 14e15df00f
3 changed files with 102 additions and 16 deletions

View file

@ -3,6 +3,7 @@
# Copyright (c) 2019 Intel Corporation
# Copyright (c) 2019 Endre Karlson
# Copyright (c) 2019 Song Qiang <songqiang1304521@gmail.com>
# 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

View file

@ -3,6 +3,7 @@
* Copyright (c) 2019 Song Qiang <songqiang1304521@gmail.com>
* 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)

View file

@ -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>;