From abcaedb9909edc50914a55983fae1bc164aeee93 Mon Sep 17 00:00:00 2001 From: Juha Niskanen Date: Wed, 20 Sep 2017 12:20:45 +0000 Subject: [PATCH] Merged in juniskane/nuttx_stm32l4/dfsdm_adc_work_pr (pull request #487) STM32L4 ADC, DFSDM: add routing of ADC data to DFSDM filters * configs/nucleo-l496zg: add DFSDM initialization * STM32L4 ADC: add option for routing ADC data to DFSDM, fix DFSDM DMA Approved-by: Gregory Nutt --- arch/arm/src/stm32l4/Kconfig | 22 +++ arch/arm/src/stm32l4/chip/stm32l4_adc.h | 3 +- arch/arm/src/stm32l4/stm32l4_adc.c | 82 +++++++++- arch/arm/src/stm32l4/stm32l4_adc.h | 32 ++++ arch/arm/src/stm32l4/stm32l4_dfsdm.c | 23 ++- arch/arm/src/stm32l4/stm32l4_dfsdm.h | 9 ++ configs/nucleo-l496zg/include/board.h | 11 +- configs/nucleo-l496zg/src/Makefile | 5 +- configs/nucleo-l496zg/src/nucleo-144.h | 12 ++ .../nucleo-l496zg/src/stm32_appinitialize.c | 11 ++ configs/nucleo-l496zg/src/stm32_dfsdm.c | 143 ++++++++++++++++++ 11 files changed, 335 insertions(+), 18 deletions(-) create mode 100644 configs/nucleo-l496zg/src/stm32_dfsdm.c diff --git a/arch/arm/src/stm32l4/Kconfig b/arch/arm/src/stm32l4/Kconfig index 00aa03f2634..3b3c0afb24d 100644 --- a/arch/arm/src/stm32l4/Kconfig +++ b/arch/arm/src/stm32l4/Kconfig @@ -3308,6 +3308,28 @@ config STM32L4_ADC3_DMA DMA transfer, which is necessary if multiple channels are read or if very high trigger frequencies are used. +config STM32L4_ADC1_OUTPUT_DFSDM + bool "ADC1 output to DFSDM" + depends on STM32L4_ADC1 && STM32L4_DFSDM1 && (STM32L4_STM32L496XX || \ + STM32L4_STM32L451XX || STM32L4_STM32L452XX || STM32L4_STM32L462XX) + default n + ---help--- + Route ADC1 output directly to DFSDM parallel inputs. + +config STM32L4_ADC2_OUTPUT_DFSDM + bool "ADC2 output to DFSDM" + depends on STM32L4_ADC2 && STM32L4_DFSDM1 && STM32L4_STM32L496XX + default n + ---help--- + Route ADC2 output directly to DFSDM parallel inputs. + +config STM32L4_ADC3_OUTPUT_DFSDM + bool "ADC3 output to DFSDM" + depends on STM32L4_ADC3 && STM32L4_DFSDM1 && STM32L4_STM32L496XX + default n + ---help--- + Route ADC3 output directly to DFSDM parallel inputs. + endmenu menu "DAC Configuration" diff --git a/arch/arm/src/stm32l4/chip/stm32l4_adc.h b/arch/arm/src/stm32l4/chip/stm32l4_adc.h index b6d2997071f..657dfac82e9 100644 --- a/arch/arm/src/stm32l4/chip/stm32l4_adc.h +++ b/arch/arm/src/stm32l4/chip/stm32l4_adc.h @@ -73,7 +73,7 @@ #define STM32L4_ADC_OFR1_OFFSET 0x0060 /* ADC offset register 1 */ #define STM32L4_ADC_OFR2_OFFSET 0x0064 /* ADC offset register 2 */ #define STM32L4_ADC_OFR3_OFFSET 0x0068 /* ADC offset register 3 */ -#define STM32L4_ADC_OFR4_OFFSET 0x006c /* ADC data offset register 4 */ +#define STM32L4_ADC_OFR4_OFFSET 0x006c /* ADC offset register 4 */ #define STM32L4_ADC_JDR1_OFFSET 0x0080 /* ADC injected data register 1 */ #define STM32L4_ADC_JDR2_OFFSET 0x0084 /* ADC injected data register 2 */ #define STM32L4_ADC_JDR3_OFFSET 0x0088 /* ADC injected data register 3 */ @@ -220,6 +220,7 @@ #define ADC_CFGR_DMAEN (1 << 0) /* Bit 0: Direct memory access enable */ #define ADC_CFGR_DMACFG (1 << 1) /* Bit 1: Direct memory access configuration */ +#define ADC_CFGR_DFSDMCFG (1 << 2) /* Bit 2: DFSDM mode configuration */ #define ADC_CFGR_RES_SHIFT (3) /* Bits 3-4: Data resolution */ #define ADC_CFGR_RES_MASK (3 << ADC_CFGR_RES_SHIFT) # define ADC_CFGR_RES_12BIT (0 << ADC_CFGR_RES_SHIFT) /* 12-bit resolution */ diff --git a/arch/arm/src/stm32l4/stm32l4_adc.c b/arch/arm/src/stm32l4/stm32l4_adc.c index c023a32a068..ff9511550ca 100644 --- a/arch/arm/src/stm32l4/stm32l4_adc.c +++ b/arch/arm/src/stm32l4/stm32l4_adc.c @@ -176,11 +176,14 @@ struct stm32_dev_s uint8_t current; /* Current ADC channel being converted */ #ifdef ADC_HAVE_DMA uint8_t dmachan; /* DMA channel needed by this ADC */ - bool hasdma; /* True: This channel supports DMA */ + bool hasdma; /* True: This ADC supports DMA */ +#endif +#ifdef ADC_HAVE_DFSDM + bool hasdfsdm; /* True: This ADC routes its output to DFSDM */ #endif #ifdef ADC_HAVE_TIMER uint8_t trigger; /* Timer trigger channel: 0=CC1, 1=CC2, 2=CC3, - * 3=CC4, 4=TRGO */ + * 3=CC4, 4=TRGO, 5=TRGO2 */ #endif xcpt_t isr; /* Interrupt handler for this ADC block */ uint32_t base; /* Base address of registers unique to this ADC @@ -248,6 +251,11 @@ static void adc_dmaconvcallback(DMA_HANDLE handle, uint8_t isr, FAR void *arg); #endif +#ifdef ADC_HAVE_DFSDM +static int adc_setoffset(FAR struct stm32_dev_s *priv, uint8_t ch, uint8_t i, + uint16_t offset); +#endif + static void adc_startconv(FAR struct stm32_dev_s *priv, bool enable); /* ADC Interrupt Handler */ @@ -306,6 +314,9 @@ static struct stm32_dev_s g_adcpriv1 = .dmachan = ADC1_DMA_CHAN, .hasdma = true, #endif +#ifdef ADC1_HAVE_DFSDM + .hasdfsdm = true, +#endif }; static struct adc_dev_s g_adcdev1 = @@ -335,6 +346,9 @@ static struct stm32_dev_s g_adcpriv2 = .dmachan = ADC2_DMA_CHAN, .hasdma = true, #endif +#ifdef ADC2_HAVE_DFSDM + .hasdfsdm = true, +#endif }; static struct adc_dev_s g_adcdev2 = @@ -364,6 +378,9 @@ static struct stm32_dev_s g_adcpriv3 = .dmachan = ADC3_DMA_CHAN, .hasdma = true, #endif +#ifdef ADC3_HAVE_DFSDM + .hasdfsdm = true, +#endif }; static struct adc_dev_s g_adcdev3 = @@ -1230,6 +1247,19 @@ static int adc_setup(FAR struct adc_dev_s *dev) } #endif +#ifdef ADC_HAVE_DFSDM + if (priv->hasdfsdm) + { + /* Disable DMA */ + + clrbits |= ADC_CFGR_DMAEN; + + /* Enable routing to DFSDM */ + + setbits |= ADC_CFGR_DFSDMCFG; + } +#endif + /* Disable continuous mode and set align to right */ clrbits |= ADC_CFGR_CONT | ADC_CFGR_ALIGN; @@ -1455,6 +1485,35 @@ static bool adc_internal(FAR struct stm32_dev_s * priv, uint32_t *adc_ccr) return internal; } +/**************************************************************************** + * Name: adc_set_offset + ****************************************************************************/ + +#ifdef ADC_HAVE_DFSDM +static int adc_setoffset(FAR struct stm32_dev_s *priv, uint8_t ch, uint8_t i, + uint16_t offset) +{ + uint32_t reg; + uint32_t regval; + + if (i >= 4) + { + /* There are only four offset registers. */ + + return -E2BIG; + } + + reg = STM32L4_ADC_OFR1_OFFSET + i * 4; + + regval = ADC_OFR_OFFSETY_EN; + adc_putreg(priv, reg, regval); + + regval |= ADC_OFR_OFFSETY_CH(ch) | ADC_OFR_OFFSETY(offset); + adc_putreg(priv, reg, regval); + return OK; +} +#endif + /**************************************************************************** * Name: adc_set_ch * @@ -1509,6 +1568,25 @@ static int adc_set_ch(FAR struct adc_dev_s *dev, uint8_t ch) adc_sqrbits(priv, ADC_SQR1_FIRST, ADC_SQR1_LAST, ADC_SQR1_SQ_OFFSET); adc_modifyreg(priv, STM32L4_ADC_SQR1_OFFSET, ~ADC_SQR1_RESERVED, bits); +#ifdef ADC_HAVE_DFSDM + if (priv->hasdfsdm) + { + /* Convert 12-bit ADC result to signed 16-bit. */ + + if (ch == 0) + { + for (i = 0; i < priv->cchannels; i++) + { + adc_setoffset(priv, priv->chanlist[i], i, 0x800); + } + } + else + { + adc_setoffset(priv, priv->current, 0, 0x800); + } + } +#endif + return OK; } diff --git a/arch/arm/src/stm32l4/stm32l4_adc.h b/arch/arm/src/stm32l4/stm32l4_adc.h index 39f7d665b6a..d75aad0d39a 100644 --- a/arch/arm/src/stm32l4/stm32l4_adc.h +++ b/arch/arm/src/stm32l4/stm32l4_adc.h @@ -120,6 +120,38 @@ #if defined(CONFIG_STM32L4_ADC1) || defined(CONFIG_STM32L4_ADC2) || \ defined(CONFIG_STM32L4_ADC3) +/* ADC output to DFSDM support. Note that DFSDM and DMA are + * mutually exclusive. + */ + +#undef ADC_HAVE_DFSDM +#if defined(CONFIG_STM32L4_ADC1_OUTPUT_DFSDM) || \ + defined(CONFIG_STM32L4_ADC2_OUTPUT_DFSDM) || \ + defined(CONFIG_STM32L4_ADC3_OUTPUT_DFSDM) +# define ADC_HAVE_DFSDM +#endif + +#if defined(CONFIG_STM32L4_ADC1_OUTPUT_DFSDM) +# define ADC1_HAVE_DFSDM 1 +# undef CONFIG_STM32L4_ADC1_DMA +#else +# undef ADC1_HAVE_DFSDM +#endif + +#if defined(CONFIG_STM32L4_ADC2_OUTPUT_DFSDM) +# define ADC2_HAVE_DFSDM 1 +# undef CONFIG_STM32L4_ADC2_DMA +#else +# undef ADC2_HAVE_DFSDM +#endif + +#if defined(CONFIG_STM32L4_ADC3_OUTPUT_DFSDM) +# define ADC3_HAVE_DFSDM 1 +# undef CONFIG_STM32L4_ADC3_DMA +#else +# undef ADC3_HAVE_DFSDM +#endif + /* DMA support */ #undef ADC_HAVE_DMA diff --git a/arch/arm/src/stm32l4/stm32l4_dfsdm.c b/arch/arm/src/stm32l4/stm32l4_dfsdm.c index b1f780cfb96..89a57ea86ec 100644 --- a/arch/arm/src/stm32l4/stm32l4_dfsdm.c +++ b/arch/arm/src/stm32l4/stm32l4_dfsdm.c @@ -152,8 +152,8 @@ * parallel inputs to DFSDM_CHyDATINR register. */ -#define DFSDM_DMA_CONTROL_WORD (DMA_CCR_MSIZE_16BITS | \ - DMA_CCR_PSIZE_16BITS | \ +#define DFSDM_DMA_CONTROL_WORD (DMA_CCR_MSIZE_32BITS | \ + DMA_CCR_PSIZE_32BITS | \ DMA_CCR_MINC | \ DMA_CCR_CIRC) @@ -1371,13 +1371,16 @@ static int dfsdm_set_ch(FAR struct adc_dev_s *dev, uint8_t ch) regval |= DFSDM_FLTCR1_RCH(priv->current); dfsdm_putreg(priv, FLTCR1_OFFSET(priv), regval); -#if 0 /* TODO: for testing */ /* Set CHCFGR1 input data configuration */ regval = dfsdm_getreg(priv, CHCFGR1_OFFSET(priv)); - regval |= DFSDM_CHCFGR1_DATMPX_DATINR; - dfsdm_putreg(priv, CHCFGR1_OFFSET(priv), regval); +#ifdef ADC_HAVE_DFSDM + regval |= DFSDM_CHCFGR1_DATMPX_ADC; +#else + regval |= DFSDM_CHCFGR1_DATMPX_EXT; + // regval |= DFSDM_CHCFGR1_DATMPX_DATINR; #endif + dfsdm_putreg(priv, CHCFGR1_OFFSET(priv), regval); /* Enable the channel */ @@ -1488,7 +1491,7 @@ static int dfsdm_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg) static int dfsdm_interrupt(FAR struct adc_dev_s *dev, uint32_t isr) { FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv; - int32_t value; + uint32_t value; /* Identifies the interruption AWD or OVR */ @@ -1516,6 +1519,7 @@ static int dfsdm_interrupt(FAR struct adc_dev_s *dev, uint32_t isr) dfsdm_putreg(priv, FLTAWCFR_OFFSET(priv), DFSDM_INT_ROVR); } +#if 0 if ((isr & DFSDM_INT_JOVR) != 0) { awarn("WARNING: Injected conversion overrun has occurred!\n"); @@ -1524,6 +1528,7 @@ static int dfsdm_interrupt(FAR struct adc_dev_s *dev, uint32_t isr) dfsdm_putreg(priv, FLTAWCFR_OFFSET(priv), DFSDM_INT_JOVR); } +#endif /* EOC: End of conversion */ @@ -1689,6 +1694,7 @@ static void dfsdm_dmaconvcallback(DMA_HANDLE handle, uint8_t isr, FAR void *arg) { FAR struct adc_dev_s *dev = (FAR struct adc_dev_s *)arg; FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv; + uint32_t value; int i; /* Verify that the upper-half driver has bound its callback functions */ @@ -1699,7 +1705,10 @@ static void dfsdm_dmaconvcallback(DMA_HANDLE handle, uint8_t isr, FAR void *arg) for (i = 0; i < priv->nchannels; i++) { - priv->cb->au_receive(dev, priv->chanlist[priv->current], priv->dmabuffer[priv->current]); + value = priv->dmabuffer[priv->current]; + value = (value & DFSDM_FLTRDATAR_RDATA_MASK) >> DFSDM_FLTRDATAR_RDATA_SHIFT; + + priv->cb->au_receive(dev, priv->chanlist[priv->current], value); priv->current++; if (priv->current >= priv->nchannels) { diff --git a/arch/arm/src/stm32l4/stm32l4_dfsdm.h b/arch/arm/src/stm32l4/stm32l4_dfsdm.h index 06f87852f6a..b751f187767 100644 --- a/arch/arm/src/stm32l4/stm32l4_dfsdm.h +++ b/arch/arm/src/stm32l4/stm32l4_dfsdm.h @@ -89,6 +89,15 @@ # define DFSDM_HAVE_DMA 1 #endif +/* ADC output to DFSDM support */ + +#undef ADC_HAVE_DFSDM +#if defined(CONFIG_STM32L4_ADC1_OUTPUT_DFSDM) || \ + defined(CONFIG_STM32L4_ADC2_OUTPUT_DFSDM) || \ + defined(CONFIG_STM32L4_ADC3_OUTPUT_DFSDM) +# define ADC_HAVE_DFSDM +#endif + /* Timer configuration: If a timer trigger is specified, then get * information about the timer. */ diff --git a/configs/nucleo-l496zg/include/board.h b/configs/nucleo-l496zg/include/board.h index e85d94a17f2..f1f205c70c1 100644 --- a/configs/nucleo-l496zg/include/board.h +++ b/configs/nucleo-l496zg/include/board.h @@ -74,13 +74,10 @@ * LSE: 32.768 kHz */ - -#define STM32_BOARD_XTAL 8000000ul - -#define STM32_HSI_FREQUENCY 16000000ul -#define STM32_LSI_FREQUENCY 32000 -#define STM32_HSE_FREQUENCY STM32_BOARD_XTAL -#define STM32_LSE_FREQUENCY 32768 +#define STM32L4_HSI_FREQUENCY 16000000ul +#define STM32L4_LSI_FREQUENCY 32000 +#define STM32L4_HSE_FREQUENCY 8000000ul /* 8 MHz from MCO output */ +#define STM32L4_LSE_FREQUENCY 32768 #define HSI_CLOCK_CONFIG diff --git a/configs/nucleo-l496zg/src/Makefile b/configs/nucleo-l496zg/src/Makefile index 1ae9cc1d70c..7cfaf9f5a03 100644 --- a/configs/nucleo-l496zg/src/Makefile +++ b/configs/nucleo-l496zg/src/Makefile @@ -46,7 +46,7 @@ CSRCS += stm32_userleds.c endif ifeq ($(CONFIG_ARCH_BUTTONS),y) -CSRCS += stm32_buttons.c +CSRCS += stm32_buttons.c endif ifeq ($(CONFIG_LIB_BOARDCTL),y) @@ -59,6 +59,9 @@ endif ifeq ($(CONFIG_ADC),y) CSRCS += stm32_adc.c + ifeq ($(CONFIG_STM32L4_DFSDM),y) + CSRCS += stm32_dfsdm.c + endif endif ifeq ($(CONFIG_DAC),y) diff --git a/configs/nucleo-l496zg/src/nucleo-144.h b/configs/nucleo-l496zg/src/nucleo-144.h index 74ff14a0cc5..728d38b1ba5 100644 --- a/configs/nucleo-l496zg/src/nucleo-144.h +++ b/configs/nucleo-l496zg/src/nucleo-144.h @@ -293,5 +293,17 @@ int stm32_adc_setup(void); int stm32_dac_setup(void); #endif +/************************************************************************************ + * Name: stm32_dfsdm_setup + * + * Description: + * Initialize DFSDM and register the ADC drivers for DFSDM filters. + * + ************************************************************************************/ + +#if defined(CONFIG_ADC) && defined(CONFIG_STM32L4_DFSDM) +int stm32_dfsdm_setup(void); +#endif + #endif /* __ASSEMBLY__ */ #endif /* __CONFIGS_NUCLEO_L496ZG_SRC_NUCLEO_144_H */ diff --git a/configs/nucleo-l496zg/src/stm32_appinitialize.c b/configs/nucleo-l496zg/src/stm32_appinitialize.c index 0d21b280e39..a874b0ee35b 100644 --- a/configs/nucleo-l496zg/src/stm32_appinitialize.c +++ b/configs/nucleo-l496zg/src/stm32_appinitialize.c @@ -130,7 +130,18 @@ int board_app_initialize(uintptr_t arg) { syslog(LOG_ERR, "ERROR: stm32_adc_setup failed: %d\n", ret); } + +#ifdef CONFIG_STM32L4_DFSDM + /* Initialize DFSDM and register its filters as additional ADC devices. */ + + ret = stm32_dfsdm_setup(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: stm32_dfsdm_setup failed: %d\n", ret); + } + #endif +#endif /* CONFIG_ADC */ #ifdef CONFIG_DAC /* Initialize DAC and register the DAC driver. */ diff --git a/configs/nucleo-l496zg/src/stm32_dfsdm.c b/configs/nucleo-l496zg/src/stm32_dfsdm.c new file mode 100644 index 00000000000..43b02d8bfcf --- /dev/null +++ b/configs/nucleo-l496zg/src/stm32_dfsdm.c @@ -0,0 +1,143 @@ +/***************************************************************************** + * configs/nucleo-l496zg/src/stm32_dfsdm.c + * + * Copyright (C) 2017 Haltian Ltd. All rights reserved. + * Authors: Juha Niskanen + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include "stm32l4_gpio.h" +#include "stm32l4_dfsdm.h" +#include "nucleo-144.h" + +#if defined(CONFIG_ADC) && defined(CONFIG_STM32L4_DFSDM) + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_dfsdm_setup + ************************************************************************************/ + +int stm32_dfsdm_setup(void) +{ + static bool initialized = false; + + if (!initialized) + { + int ret; + struct adc_dev_s *adc; + + ainfo("Initializing DFSDM\n"); + + /* TODO: just some arbitrary channels selected, missing input pin + * configuration and DFSDM mode selection: SPI/Manchester or internal + * parallel inputs (CPU/DMA/ADC). + */ + +#ifdef CONFIG_STM32L4_DFSDM1_FLT0 + adc = stm32l4_dfsdm_initialize(0, (const uint8_t[1]){0}, 1); + if (adc == NULL) + { + aerr("Failed to get DFSDM FLT0 interface\n"); + return -ENODEV; + } + + ret = adc_register("/dev/adc_flt0", adc); + if (ret < 0) + { + aerr("adc_register failed: %d\n", ret); + return ret; + } +#endif +#ifdef CONFIG_STM32L4_DFSDM1_FLT1 + adc = stm32l4_dfsdm_initialize(1, (const uint8_t[2]){0,1}, 2); + if (adc == NULL) + { + aerr("Failed to get DFSDM FLT1 interface\n"); + return -ENODEV; + } + + ret = adc_register("/dev/adc_flt1", adc); + if (ret < 0) + { + aerr("adc_register failed: %d\n", ret); + return ret; + } +#endif +#ifdef CONFIG_STM32L4_DFSDM1_FLT2 + adc = stm32l4_dfsdm_initialize(2, (const uint8_t[8]){0,1,2,3,4,5,6,7}, 8); + if (adc == NULL) + { + aerr("Failed to get DFSDM FLT2 interface\n"); + return -ENODEV; + } + + ret = adc_register("/dev/adc_flt2", adc); + if (ret < 0) + { + aerr("adc_register failed: %d\n", ret); + return ret; + } +#endif +#ifdef CONFIG_STM32L4_DFSDM1_FLT3 + adc = stm32l4_dfsdm_initialize(3, (const uint8_t[4]){6,5,4,3}, 4); + if (adc == NULL) + { + aerr("Failed to get DFSDM FLT3 interface\n"); + return -ENODEV; + } + + ret = adc_register("/dev/adc_flt3", adc); + if (ret < 0) + { + aerr("adc_register failed: %d\n", ret); + return ret; + } +#endif + + initialized = true; + } + + return OK; +} +#endif /* CONFIG_ADC && CONFIG_STM32L4_DFSDM */