diff --git a/arch/arm/src/stm32l4/Kconfig b/arch/arm/src/stm32l4/Kconfig index aa8fb3a2bf4..00aa03f2634 100644 --- a/arch/arm/src/stm32l4/Kconfig +++ b/arch/arm/src/stm32l4/Kconfig @@ -837,6 +837,10 @@ config STM32L4_DAC bool default n +config STM32L4_DFSDM + bool + default n + config STM32L4_DMA bool default n @@ -3382,6 +3386,42 @@ config STM32L4_DAC2_OUTPUT_ADC endmenu +menu "DFSDM Configuration" + depends on STM32L4_DFSDM1 + +config STM32L4_DFSDM1_FLT0 + bool "DFSDM1 Filter 0" + default n + select STM32L4_DFSDM + +config STM32L4_DFSDM1_FLT1 + bool "DFSDM1 Filter 1" + default n + select STM32L4_DFSDM + +config STM32L4_DFSDM1_FLT2 + bool "DFSDM1 Filter 2" + default n + depends on !STM32L4_STM32L4X3 + select STM32L4_DFSDM + +config STM32L4_DFSDM1_FLT3 + bool "DFSDM1 Filter 3" + default n + depends on !STM32L4_STM32L4X3 + select STM32L4_DFSDM + +config STM32L4_DFSDM1_DMA + bool "DFSDM1 DMA" + depends on STM32L4_DFSDM + default n + ---help--- + If DMA is selected, then the DFSDM may be configured to support + DMA transfer, which is necessary if multiple channels are read + or if very high trigger frequencies are used. + +endmenu + config STM32L4_HAVE_USART1 bool default n diff --git a/arch/arm/src/stm32l4/Make.defs b/arch/arm/src/stm32l4/Make.defs index 271a2ff6293..8fca3712613 100644 --- a/arch/arm/src/stm32l4/Make.defs +++ b/arch/arm/src/stm32l4/Make.defs @@ -135,6 +135,10 @@ ifeq ($(CONFIG_STM32L4_DAC),y) CHIP_CSRCS += stm32l4_dac.c endif +ifeq ($(CONFIG_STM32L4_DFSDM),y) +CHIP_CSRCS += stm32l4_dfsdm.c +endif + ifeq ($(CONFIG_STM32L4_DMA),y) CHIP_CSRCS += stm32l4_dma.c endif diff --git a/arch/arm/src/stm32l4/README.txt b/arch/arm/src/stm32l4/README.txt index a892b74eb56..a5ca0b9bf8e 100644 --- a/arch/arm/src/stm32l4/README.txt +++ b/arch/arm/src/stm32l4/README.txt @@ -59,7 +59,7 @@ LPUART : TODO (Low power UART working with LSE at low baud rates) LPTIM : Code written, to be tested (Low power TIMER) OPAMP : TODO (Analog operational amplifier) COMP : There is some code (Analog comparators) -DFSDM : TODO (Digital Filter and Sigma-Delta Modulator) +DFSDM : There is some code (Digital Filter for Sigma-Delta Modulators) LCD : TODO (Segment LCD controller) SAIPLL : works (PLL For Digital Audio interfaces, and other things) SAI : There is some code (Digital Audio interfaces, I2S, SPDIF, etc) diff --git a/arch/arm/src/stm32l4/chip/stm32l4_dfsdm.h b/arch/arm/src/stm32l4/chip/stm32l4_dfsdm.h new file mode 100644 index 00000000000..d0858e12e89 --- /dev/null +++ b/arch/arm/src/stm32l4/chip/stm32l4_dfsdm.h @@ -0,0 +1,427 @@ +/************************************************************************************ + * arch/arm/src/stm32l4/chip/stm32l4_dfsdm.h + * + * Copyright (C) 2017 Haltian Ltd. All rights reserved. + * Author: 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. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32L4_CHIP_STM32L4_DFSDM_H +#define __ARCH_ARM_SRC_STM32L4_CHIP_STM32L4_DFSDM_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include "chip.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Register Offsets *****************************************************************/ +/* Register Offsets for the DFSDM. */ + +/* DFSDM channel y registers (y=0..7 or y=0..3 on STM32L4X3) */ + +#define STM32L4_DFSDM_CHCFGR1_OFFSET(y) (0x00 + 0x20 * (y)) + +#define STM32L4_DFSDM_CH0CFGR1_OFFSET 0x0000 /* DFSDM channel configuration 0 register */ +#define STM32L4_DFSDM_CH1CFGR1_OFFSET 0x0020 /* DFSDM channel configuration 1 register */ +#define STM32L4_DFSDM_CH2CFGR1_OFFSET 0x0040 /* DFSDM channel configuration 2 register */ +#define STM32L4_DFSDM_CH3CFGR1_OFFSET 0x0060 /* DFSDM channel configuration 3 register */ +#ifndef CONFIG_STM32L4_STM32L4X3 +# define STM32L4_DFSDM_CH4CFGR1_OFFSET 0x0080 /* DFSDM channel configuration 4 register */ +# define STM32L4_DFSDM_CH5CFGR1_OFFSET 0x00a0 /* DFSDM channel configuration 5 register */ +# define STM32L4_DFSDM_CH6CFGR1_OFFSET 0x00c0 /* DFSDM channel configuration 6 register */ +# define STM32L4_DFSDM_CH7CFGR1_OFFSET 0x00e0 /* DFSDM channel configuration 7 register */ +#endif + +#define STM32L4_DFSDM_CHCFGR2_OFFSET(y) (0x04 + 0x20 * (y)) + +#define STM32L4_DFSDM_CH0CFGR2_OFFSET 0x0004 /* DFSDM channel configuration 0 register 2 */ +#define STM32L4_DFSDM_CH1CFGR2_OFFSET 0x0024 /* DFSDM channel configuration 1 register 2 */ +#define STM32L4_DFSDM_CH2CFGR2_OFFSET 0x0044 /* DFSDM channel configuration 2 register 2 */ +#define STM32L4_DFSDM_CH3CFGR2_OFFSET 0x0064 /* DFSDM channel configuration 3 register 2 */ +#ifndef CONFIG_STM32L4_STM32L4X3 +# define STM32L4_DFSDM_CH4CFGR2_OFFSET 0x0084 /* DFSDM channel configuration 4 register 2 */ +# define STM32L4_DFSDM_CH5CFGR2_OFFSET 0x00a4 /* DFSDM channel configuration 5 register 2 */ +# define STM32L4_DFSDM_CH6CFGR2_OFFSET 0x00c4 /* DFSDM channel configuration 6 register 2 */ +# define STM32L4_DFSDM_CH7CFGR2_OFFSET 0x00e4 /* DFSDM channel configuration 7 register 2 */ +#endif + +#define STM32L4_DFSDM_CHAWSCDR_OFFSET(y) (0x08 + 0x20 * (y)) + +#define STM32L4_DFSDM_CH0AWSCDR_OFFSET 0x0008 /* DFSDM channel 0 analog watchdog and short-circuit detector register */ +#define STM32L4_DFSDM_CH1AWSCDR_OFFSET 0x0028 /* DFSDM channel 1 analog watchdog and short-circuit detector register */ +#define STM32L4_DFSDM_CH2AWSCDR_OFFSET 0x0048 /* DFSDM channel 2 analog watchdog and short-circuit detector register */ +#define STM32L4_DFSDM_CH3AWSCDR_OFFSET 0x0068 /* DFSDM channel 3 analog watchdog and short-circuit detector register */ +#ifndef CONFIG_STM32L4_STM32L4X3 +# define STM32L4_DFSDM_CH4AWSCDR_OFFSET 0x0088 /* DFSDM channel 4 analog watchdog and short-circuit detector register */ +# define STM32L4_DFSDM_CH5AWSCDR_OFFSET 0x00a8 /* DFSDM channel 5 analog watchdog and short-circuit detector register */ +# define STM32L4_DFSDM_CH6AWSCDR_OFFSET 0x00c8 /* DFSDM channel 6 analog watchdog and short-circuit detector register */ +# define STM32L4_DFSDM_CH7AWSCDR_OFFSET 0x00e8 /* DFSDM channel 7 analog watchdog and short-circuit detector register */ +#endif + +#define STM32L4_DFSDM_CHWDATR_OFFSET(y) (0x0c + 0x20 * (y)) + +#define STM32L4_DFSDM_CH0WDATR_OFFSET 0x000c /* DFSDM channel 0 watchdog filter data register */ +#define STM32L4_DFSDM_CH1WDATR_OFFSET 0x002c /* DFSDM channel 1 watchdog filter data register */ +#define STM32L4_DFSDM_CH2WDATR_OFFSET 0x004c /* DFSDM channel 2 watchdog filter data register */ +#define STM32L4_DFSDM_CH3WDATR_OFFSET 0x006c /* DFSDM channel 3 watchdog filter data register */ +#ifndef CONFIG_STM32L4_STM32L4X3 + #define STM32L4_DFSDM_CH4WDATR_OFFSET 0x008c /* DFSDM channel 4 watchdog filter data register */ + #define STM32L4_DFSDM_CH5WDATR_OFFSET 0x00ac /* DFSDM channel 5 watchdog filter data register */ + #define STM32L4_DFSDM_CH6WDATR_OFFSET 0x00cc /* DFSDM channel 6 watchdog filter data register */ + #define STM32L4_DFSDM_CH7WDATR_OFFSET 0x00ec /* DFSDM channel 7 watchdog filter data register */ +#endif + +#define STM32L4_DFSDM_CHDATINR_OFFSET(ch) (0x10 + 0x20 * (ch)) /* DFSDM channel data input register */ + +#define STM32L4_DFSDM_CH0DATINR_OFFSET 0x0010 /* DFSDM channel 0 channel data input register */ +#define STM32L4_DFSDM_CH1DATINR_OFFSET 0x0030 /* DFSDM channel 1 channel data input register */ +#define STM32L4_DFSDM_CH2DATINR_OFFSET 0x0050 /* DFSDM channel 2 channel data input register */ +#define STM32L4_DFSDM_CH3DATINR_OFFSET 0x0070 /* DFSDM channel 3 channel data input register */ +#ifndef CONFIG_STM32L4_STM32L4X3 +# define STM32L4_DFSDM_CH4DATINR_OFFSET 0x0090 /* DFSDM channel 4 channel data input register */ +# define STM32L4_DFSDM_CH5DATINR_OFFSET 0x00b0 /* DFSDM channel 5 channel data input register */ +# define STM32L4_DFSDM_CH6DATINR_OFFSET 0x00d0 /* DFSDM channel 6 channel data input register */ +# define STM32L4_DFSDM_CH7DATINR_OFFSET 0x00f0 /* DFSDM channel 7 channel data input register */ +#endif + +/* DFSDM filter x module registers (x=0..3 or x=0..1 on STM32L4X3) */ + +#define STM32L4_DFSDM_FLTCR1_OFFSET(x) (0x100 + 0x80 * (x)) /* DFSDM control register 1 */ +#define STM32L4_DFSDM_FLTCR2_OFFSET(x) (0x104 + 0x80 * (x)) /* DFSDM control register 2 */ +#define STM32L4_DFSDM_FLTISR_OFFSET(x) (0x108 + 0x80 * (x)) /* DFSDM interrupt and status register */ +#define STM32L4_DFSDM_FLTICR_OFFSET(x) (0x10c + 0x80 * (x)) /* DFSDM interrupt flag clear register */ +#define STM32L4_DFSDM_FLTJCHGR_OFFSET(x) (0x110 + 0x80 * (x)) /* DFSDM injected channel group selection register */ +#define STM32L4_DFSDM_FLTFCR_OFFSET(x) (0x114 + 0x80 * (x)) /* DFSDM filter control register */ +#define STM32L4_DFSDM_FLTJDATAR_OFFSET(x) (0x118 + 0x80 * (x)) /* DFSDM data register for injected group */ +#define STM32L4_DFSDM_FLTRDATAR_OFFSET(x) (0x11c + 0x80 * (x)) /* DFSDM data register for the regular channel */ +#define STM32L4_DFSDM_FLTAWHTR_OFFSET(x) (0x120 + 0x80 * (x)) /* DFSDM analog watchdog high threshold register */ +#define STM32L4_DFSDM_FLTAWLTR_OFFSET(x) (0x124 + 0x80 * (x)) /* DFSDM analog watchdog low threshold register */ +#define STM32L4_DFSDM_FLTAWSR_OFFSET(x) (0x128 + 0x80 * (x)) /* DFSDM analog watchdog status register */ +#define STM32L4_DFSDM_FLTAWCFR_OFFSET(x) (0x12c + 0x80 * (x)) /* DFSDM analog watchdog clear flag register */ +#define STM32L4_DFSDM_FLTEXMAX_OFFSET(x) (0x130 + 0x80 * (x)) /* DFSDM Extremes detector maximum register */ +#define STM32L4_DFSDM_FLTEXMIN_OFFSET(x) (0x134 + 0x80 * (x)) /* DFSDM Extremes detector minimum register */ +#define STM32L4_DFSDM_FLTCNVTIMR_OFFSET(x) (0x138 + 0x80 * (x)) /* DFSDM conversion timer register */ + +/* Register Addresses ***************************************************************/ + +/* DFSDM channel y registers (y=0..7 or y=0..3 on STM32L4X3) */ + +#define STM32L4_DFSDM_CHCFGR1(y) (STM32L4_DFSDM_BASE+STM32L4_DFSDM_CHCFGR1_OFFSET(y)) +#define STM32L4_DFSDM_CH0CFGR1 (STM32L4_DFSDM_BASE+STM32L4_DFSDM_CH0CFGR1_OFFSET) + +#define STM32L4_DFSDM_CHCFGR2(y) (STM32L4_DFSDM_BASE+STM32L4_DFSDM_CHCFGR2_OFFSET(y)) +#define STM32L4_DFSDM_CHAWSCDR(y) (STM32L4_DFSDM_BASE+STM32L4_DFSDM_CHAWSCDR_OFFSET(y)) +#define STM32L4_DFSDM_CHWDATR(y) (STM32L4_DFSDM_BASE+STM32L4_DFSDM_CHWDATR_OFFSET(y) +#define STM32L4_DFSDM_CHDATINR(y) (STM32L4_DFSDM_BASE+STM32L4_DFSDM_CHDATINR_OFFSET(y)) + +/* DFSDM filter x module registers (x=0..3 or x=0..1 on STM32L4X3) */ + +#define STM32L4_DFSDM_FLTCR1(x) (STM32L4_DFSDM_BASE+STM32L4_DFSDM_FLTCR1_OFFSET(x)) +#define STM32L4_DFSDM_FLTCR2(x) (STM32L4_DFSDM_BASE+STM32L4_DFSDM_FLTCR2_OFFSET(x)) +#define STM32L4_DFSDM_FLTISR(x) (STM32L4_DFSDM_BASE+STM32L4_DFSDM_FLTISR_OFFSET(x)) +#define STM32L4_DFSDM_FLTICR(x) (STM32L4_DFSDM_BASE+STM32L4_DFSDM_FLTICR_OFFSET(x)) +#define STM32L4_DFSDM_FLTJCHGR(x) (STM32L4_DFSDM_BASE+STM32L4_DFSDM_FLTJCHGR_OFFSET(x)) +#define STM32L4_DFSDM_FLTFCR(x) (STM32L4_DFSDM_BASE+STM32L4_DFSDM_FLTFCR_OFFSET(x)) +#define STM32L4_DFSDM_FLTJDATAR(x) (STM32L4_DFSDM_BASE+STM32L4_DFSDM_FLTJDATAR_OFFSET(x)) +#define STM32L4_DFSDM_FLTRDATAR(x) (STM32L4_DFSDM_BASE+STM32L4_DFSDM_FLTRDATAR_OFFSET(x)) +#define STM32L4_DFSDM_FLTAWHTR(x) (STM32L4_DFSDM_BASE+STM32L4_DFSDM_FLTAWHTR_OFFSET(x)) +#define STM32L4_DFSDM_FLTAWLTR(x) (STM32L4_DFSDM_BASE+STM32L4_DFSDM_FLTAWLTR_OFFSET(x)) +#define STM32L4_DFSDM_FLTAWSR(x) (STM32L4_DFSDM_BASE+STM32L4_DFSDM_FLTAWSR_OFFSET(x)) +#define STM32L4_DFSDM_FLTAWCFR(x) (STM32L4_DFSDM_BASE+STM32L4_DFSDM_FLTAWCFR_OFFSET(x)) +#define STM32L4_DFSDM_FLTEXMAX(x) (STM32L4_DFSDM_BASE+STM32L4_DFSDM_FLTEXMAX_OFFSET(x)) +#define STM32L4_DFSDM_FLTEXMIN(x) (STM32L4_DFSDM_BASE+STM32L4_DFSDM_FLTEXMIN_OFFSET(x)) +#define STM32L4_DFSDM_FLTCNVTIMR(x) (STM32L4_DFSDM_BASE+STM32L4_DFSDM_FLTCNVTIMR_OFFSET(x)) + +/* Register Bitfield Definitions ****************************************************/ +/* DFSDM channel configuration y register (DFSDM_CHyCFGR1) */ + +/* Bits that are present only in DFSDM_CH0CFGR1 register (channel y=0) */ + +#define DFSDM_CH0CFGR1_CKOUTDIV_SHIFT (16) /* Bits 16-23: Output serial clock divider */ +#define DFSDM_CH0CFGR1_CKOUTDIV_MASK (0xff << DFSDM_CH0CFGR1_CKOUTDIV_SHIFT) +# define DFSDM_CH0CFGR1_CKOUTDIV_NONE (0 << DFSDM_CH0CFGR1_CKOUTDIV_SHIFT) /* Output clock generation disabled */ +# define DFSDM_CH0CFGR1_CKOUTDIV(n) ((n) << DFSDM_CH0CFGR1_CKOUTDIV_SHIFT) /* Divider = CKOUTDIV+1, n=1..255 */ +#define DFSDM_CH0CFGR1_CKOUTSRC (1 << 30) /* Bit 30: Output serial clock source selection */ +#define DFSDM_CH0CFGR1_DFSDMEN (1 << 31) /* Bit 31: Global enable for DFSDM */ + +/* Bits that are present in all DFSDM_CHyCFGR1 registers */ + +#define DFSDM_CHCFGR1_SPICKSEL_SHIFT (2) /* Bits 2-3: SPI clock select for channel y */ +#define DFSDM_CHCFGR1_SPICKSEL_MASK (3 << DFSDM_CHCFGR1_SPICKSEL_SHIFT) +# define DFSDM_CHCFGR1_SPICKSEL_EXT (0 << DFSDM_CHCFGR1_SPICKSEL_SHIFT) /* clock coming from external CKINy input */ +# define DFSDM_CHCFGR1_SPICKSEL_CKOUT (1 << DFSDM_CHCFGR1_SPICKSEL_SHIFT) /* clock coming from internal CKOUT output, sampling from SITP[1:0] */ +# define DFSDM_CHCFGR1_SPICKSEL_CKOUTFALL (2 << DFSDM_CHCFGR1_SPICKSEL_SHIFT) /* clock coming from internal CKOUT input, sampling on falling edge */ +# define DFSDM_CHCFGR1_SPICKSEL_CKOUTRISE (3 << DFSDM_CHCFGR1_SPICKSEL_SHIFT) /* clock coming from internal CKOOUT input, sampling on rising edge */ +#define DFSDM_CHCFGR1_SITP_SHIFT (0) /* Bits 0-1: Serial interface type for channel y */ +#define DFSDM_CHCFGR1_SITP_MASK (3 << DFSDM_CHCFGR1_SITP_SHIFT) +# define DFSDM_CHCFGR1_SITP_SPIRISE (0 << DFSDM_CHCFGR1_SITP_SHIFT) /* SPI with rising edge to strobe data */ +# define DFSDM_CHCFGR1_SITP_SPIFALL (1 << DFSDM_CHCFGR1_SITP_SHIFT) /* SPI with falling edge to strobe data */ +# define DFSDM_CHCFGR1_SITP_MANSEFALL (2 << DFSDM_CHCFGR1_SITP_SHIFT) /* Manchester coded input on DATINy pin with falling edge as logic 1 */ +# define DFSDM_CHCFGR1_SITP_MANSERISE (3 << DFSDM_CHCFGR1_SITP_SHIFT) /* Manchester coded input on DATINy pin with rising edge as logic 1 */ + +#define DFSDM_CHCFGR1_SCDEN (1 << 5) /* Bit 5: Short-circuit detector enable on channel y */ +#define DFSDM_CHCFGR1_CKABEN (1 << 6) /* Bit 6: Clock absence detector enable on channel y */ +#define DFSDM_CHCFGR1_CHEN (1 << 7) /* Bit 7: Channel y enable */ +#define DFSDM_CHCFGR1_CHINSEL (1 << 8) /* Bit 8: Channel inputs selection */ +#define DFSDM_CHCFGR1_DATMPX_SHIFT (12) /* Bits 12-13: Input data multiplexer for channel y */ +#define DFSDM_CHCFGR1_DATMPX_MASK (3 << DFSDM_CHCFGR1_DATMPX_SHIFT) +# define DFSDM_CHCFGR1_DATMPX_EXT (0 << DFSDM_CHCFGR1_DATMPX_SHIFT) /* External: Data to channel y are taken from external serial inputs as 1-bit values */ +# define DFSDM_CHCFGR1_DATMPX_ADC (1 << DFSDM_CHCFGR1_DATMPX_SHIFT) /* ADC: Data to channel y are taken from internal analog to digital converter ADC */ +# define DFSDM_CHCFGR1_DATMPX_DATINR (2 << DFSDM_CHCFGR1_DATMPX_SHIFT) /* DATINR: Data to channel y are taken from internal DFSDM_CHyDATINR register by direct CPU/DMA write */ + /* 3: Reserved */ +#define DFSDM_CHCFGR1_DATPACK_SHIFT (14) /* Bits 14-15: Data packing mode in DFSDM_CHyDATINR register. */ +#define DFSDM_CHCFGR1_DATPACK_MASK (3 << DFSDM_CHCFGR1_DATPACK_SHIFT) +# define DFSDM_CHCFGR1_DATPACK_STD (0 << DFSDM_CHCFGR1_DATPACK_SHIFT) /* Standard: input data in DFSDM_CHyDATINR register are stored only in INDAT0[15:0] */ +# define DFSDM_CHCFGR1_DATPACK_INTER (1 << DFSDM_CHCFGR1_DATPACK_SHIFT) /* Interleaved: input data in DFSDM_CHyDATINR register are stored as two samples INDAT0[15:0] and INDAT1[15:0] for channel y */ +# define DFSDM_CHCFGR1_DATPACK_DUAL (2 << DFSDM_CHCFGR1_DATPACK_SHIFT) /* Dual: input data in DFSDM_CHyDATINR register are stored as two samples INDAT0[15:0] and INDAT1[15:0] for channels y and y+1 */ + /* 3: Reserved */ + +/* DFSDM channel configuration y register (DFSDM_CHyCFGR2) */ + +#define DFSDM_CHCFGR2_DTRBS_SHIFT (3) /* Bits 3-7: Data right bit-shift for channel y */ +#define DFSDM_CHCFGR2_DTRBS_MASK (0x1f << DFSDM_CHCFGR2_DTRBS_SHIFT) +# define DFSDM_CHCFGR2_DTRBS(n) ((n) << DFSDM_CHCFGR2_DTRBS_SHIFT) /* n = 0..31 */ + +#define DFSDM_CHCFGR2_OFFSET_SHIFT (8) /* Bits 8-31: 24-bit calibration offset for channel y */ +#define DFSDM_CHCFGR2_OFFSET_MASK (0xffffff << DFSDM_CHCFGR2_OFFSET_SHIFT) +# define DFSDM_CHCFGR2_OFFSET(n) ((n) << DFSDM_CHCFGR2_OFFSET_SHIFT) + +/* DFSDM channel analog watchdog and short-circuit detector register (DFSDM_CHyAWSCDR) */ + +#define DFSDM_CHAWSCDR_SCDT_SHIFT (0) /* Bits 0-7: short-circuit detector threshold */ +#define DFSDM_CHAWSCDR_SCDT_MASK (0xff << DFSDM_CHAWSCDR_SCDT_SHIFT) +# define DFSDM_CHAWSCDR_SCDT(n) ((n) << DFSDM_CHAWSCDR_SCDT_SHIFT) +#define DFSDM_CHAWSCDR_BKSCD_SHIFT (12) /* Bits 12-15: Break signal assignment for short-circuit detector */ +#define DFSDM_CHAWSCDR_BKSCD_MASK (0xf << DFSDM_CHAWSCDR_BKSCD_SHIFT) +#define DFSDM_CHAWSCDR_AWFOSR_SHIFT (16) /* Bits 16-20: Analog watchdog filter oversampling ratio */ +#define DFSDM_CHAWSCDR_AWFOSR_MASK (0x1f << DFSDM_CHAWSCDR_AWFOSR_SHIFT) +# define DFSDM_CHAWSCDR_AWFOSR(n) ((n) << DFSDM_CHAWSCDR_AWFOSR_SHIFT) /* n=0..31 */ +#define DFSDM_CHAWSCDR_AWFORD_SHIFT (22) /* Bits 22-24: Analog watchdog Sinc filter order */ +#define DFSDM_CHAWSCDR_AWFORD_MASK (3 << DFSDM_CHAWSCDR_AWFORD_SHIFT) +# define DFSDM_CHAWSCDR_AWFORD_FASTSINC (0 << DFSDM_CHAWSCDR_AWFORD_SHIFT) +# define DFSDM_CHAWSCDR_AWFORD_SINC1 (1 << DFSDM_CHAWSCDR_AWFORD_SHIFT) +# define DFSDM_CHAWSCDR_AWFORD_SINC2 (2 << DFSDM_CHAWSCDR_AWFORD_SHIFT) +# define DFSDM_CHAWSCDR_AWFORD_SINC3 (3 << DFSDM_CHAWSCDR_AWFORD_SHIFT) + +/* DFSDM channel watchdog filter data register (DFSDM_CHyWDATR) */ + +#define DFSDM_CHWDATR_WDATA_SHIFT (0) /* Bits 0-15: channel watchdog data */ +#define DFSDM_CHWDATR_WDATA_MASK (0xffff << DFSDM_CHWDATR_WDATA_SHIFT) + +/* DFSDM channel data input register (DFSDM_CHyDATINR) */ + +#define DFSDM_CHDATINR_INDAT0_SHIFT (0) /* Bits 0-15: input data 0 */ +#define DFSDM_CHDATINR_INDAT0_MASK (0xffff << DFSDM_CHDATINR_INDAT0_SHIFT) +# define DFSDM_CHDATINR_INDAT0(n) ((n) << DFSDM_CHDATINR_INDAT0_SHIFT) +#define DFSDM_CHDATINR_INDAT1_SHIFT (0) /* Bits 15-31: input data 1 */ +#define DFSDM_CHDATINR_INDAT1_MASK (0xffff << DFSDM_CHDATINR_INDAT1_SHIFT) +# define DFSDM_CHDATINR_INDAT1(n) ((n) << DFSDM_CHDATINR_INDAT1_SHIFT) + +/* DFSDM filter x module registers */ +/* DFSDM control register 1 (DFSDM_FLTxCR1) */ + +#define DFSDM_FLTCR1_DFEN (1 << 0) /* Bit 0: DFSDM_FLTx enable */ +#define DFSDM_FLTCR1_JSWSTART (1 << 1) /* Bit 1: Start a conversion of the injected group of channels */ +#define DFSDM_FLTCR1_JSYNC (1 << 3) /* Bit 3: Launch an injected conversion synchronously with the DFSDM_FLT0 JSWSTART trigger */ +#define DFSDM_FLTCR1_JSCAN (1 << 4) /* Bit 4: Scanning conversion mode for injected conversions */ +#define DFSDM_FLTCR1_JDMAEN (1 << 5) /* Bit 5: DMA channel enabled to read data for the injected channel group */ + /* Bits 6-7: Reserved */ +#define DFSDM_FLTCR1_JEXTSEL_SHIFT (8) /* Bits 8-10: External trigger selection for injected group */ +#define DFSDM_FLTCR1_JEXTSEL_MASK (0x7 << DFSDM_FLTCR1_JEXTSEL_SHIFT) +# define DFSDM_FLTCR1_JEXTSEL(event) ((event) << DFSDM_FLTCR1_JEXTSEL_SHIFT) /* Event = 0..7 */ + /* Bits 11-12: Reserved */ +#define DFSDM_FLTCR1_JEXTEN_SHIFT (13) /* Bits 13-14: Trigger enable and edge election for injected group */ +#define DFSDM_FLTCR1_JEXTEN_MASK (3 << DFSDM_FLTCR1_JEXTEN_SHIFT) +# define DFSDM_FLTCR1_JEXTEN_NONE (0 << DFSDM_FLTCR1_JEXTEN_SHIFT) /* 00: Trigger detection disabled */ +# define DFSDM_FLTCR1_JEXTEN_RISING (1 << DFSDM_FLTCR1_JEXTEN_SHIFT) /* 01: Trigger detection on the rising edge */ +# define DFSDM_FLTCR1_JEXTEN_FALLING (2 << DFSDM_FLTCR1_JEXTEN_SHIFT) /* 10: Trigger detection on the falling edge */ +# define DFSDM_FLTCR1_JEXTEN_BOTH (3 << DFSDM_FLTCR1_JEXTEN_SHIFT) /* 11: Trigger detection on both the rising and falling edges */ +#define DFSDM_FLTCR1_RSWSTART (1 << 17) /* Bit 17: Software start of a conversion on the regular channel */ +#define DFSDM_FLTCR1_RCONT (1 << 18) /* Bit 18: Continuous mode selection for regular conversions */ +#define DFSDM_FLTCR1_RSYNC (1 << 19) /* Bit 19: Launch regular conversion synchronously with DFSDM_FLT0 */ +#define DFSDM_FLTCR1_RDMAEN (1 << 21) /* Bit 21: DMA channel enabled to read data for the regular conversion */ +#define DFSDM_FLTCR1_RCH_SHIFT (24) /* Bits 24-26: Regular channel selection */ +#define DFSDM_FLTCR1_RCH_MASK (0x7 << DFSDM_FLTCR1_RCH_SHIFT) +#define DFSDM_FLTCR1_RCH(ch) ((ch) << DFSDM_FLTCR1_RCH_SHIFT) /* Channel ch is selected as the regular channel */ +#define DFSDM_FLTCR1_FAST (1 << 29) /* Bit 29: Fast conversion mode selection for regular conversions */ +#define DFSDM_FLTCR1_AWFSEL (1 << 30) /* Bit 30: Analog watchdog fast mode select */ + +/* DFSDM control register 2 (DFSDM_FLTxCR2) */ + +/* Bits that are present only in DFSDM_FLT0CR2 register (filter x=0) */ + +#define DFSDM_FLT0CR2_SCDIE (1 << 5) /* Bit 5: Short-circuit detector interrupt enable */ +#define DFSDM_FLT0CR2_CKABIE (1 << 6) /* Bit 6: Clock absence interrupt enable */ + +/* Bits that are present in all DFSDM_FLTxCR2 registers */ + +#define DFSDM_FLTCR2_JEOCIE (1 << 0) /* Bit 0: Injected end of conversion interrupt enable */ +#define DFSDM_FLTCR2_REOCIE (1 << 1) /* Bit 1: Regular end of conversion interrupt enable */ +#define DFSDM_FLTCR2_JOWRIE (1 << 2) /* Bit 2: Injected data overrun interrupt enable */ +#define DFSDM_FLTCR2_ROWRIE (1 << 3) /* Bit 3: Regular data overrun interrupt enable + */ +#define DFSDM_FLTCR2_AWDIE (1 << 4) /* Bit 4: Analog watchdog interrupt enable */ +#define DFSDM_FLTCR2_EXCH_SHIFT (8) /* Bits 8-15: Extremes detector channel selection */ +#define DFSDM_FLTCR2_EXCH_MASK (0xff << DFSDM_FLTCR2_EXCH_SHIFT) +#define DFSDM_FLTCR2_EXCH(ch) ((1 << (ch)) << DFSDM_FLTCR2_EXCH_SHIFT) +#define DFSDM_FLTCR2_AWDCH_SHIFT (16) /* Bits 16-23: Analog watchdog channel selection */ +#define DFSDM_FLTCR2_AWDCH_MASK (0xff << DFSDM_FLTCR2_AWDCH_SHIFT) +#define DFSDM_FLTCR2_AWDCH(ch) ((1 << (ch)) << DFSDM_FLTCR2_AWDCH_SHIFT) + +/* DFSDM interrupt and status register (DFSDM_FLTxISR) */ + +/* Bits that are present only in DFSDM_FLT0ISR register (filter x=0) */ + +#define DFSDM_FLT0ISR_CKABF_SHIFT (16) /* Bits 16-23: short-circuit detector flag */ +#define DFSDM_FLT0ISR_CKABF_MASK (0xff << DFSDM_FLT0ISR_CKABF_SHIFT) +#define DFSDM_FLT0ISR_SCDF_SHIFT (24) /* Bits 24-31: clock absence flag */ +#define DFSDM_FLT0ISR_SCDF_MASK (0xff << DFSDM_FLT0ISR_SCDF_SHIFT) + +/* Bits that are present in all DFSDM_FLTxISR registers */ + +#define DFSDM_FLTISR_JEOCF (1 << 0) /* Bit 0: End of injected conversion flag */ +#define DFSDM_FLTISR_REOCF (1 << 1) /* Bit 1: End of regular conversion flag */ +#define DFSDM_FLTISR_JOVRF (1 << 2) /* Bit 2: Injected conversion overrun flag */ +#define DFSDM_FLTISR_ROVRF (1 << 3) /* Bit 3: Regular conversion overrun flag */ +#define DFSDM_FLTISR_AWDF (1 << 4) /* Bit 4: Analog watchdog */ + +#define DFSDM_FLTISR_JCIP (1 << 13) /* Bit 13: Injected conversion in progress status */ +#define DFSDM_FLTISR_RCIP (1 << 14) /* Bit 14: Regular conversion in progress status */ + +/* DFSDM interrupt flag clear register (DFSDM_FLTxICR) */ + +/* Bits that are present only in DFSDM_FLT0ICR register (filter x=0) */ + +#define DFSDM_FLT0ISR_CLRCKABF_SHIFT (16) /* Bits 16-23: Clear the short-circuit detector flag */ +#define DFSDM_FLT0ISR_CLRCKABF_MASK (0xff << DFSDM_FLT0ISR_CLRCKABF_SHIFT) +#define DFSDM_FLT0ISR_CLRSCDF_SHIFT (24) /* Bits 24-31: clear the clock absence flag */ +#define DFSDM_FLT0ISR_CLRSCDF_MASK (0xff << DFSDM_FLT0ISR_CLRSCDF_SHIFT) + +/* Bits that are present in all DFSDM_FLTxICR registers */ + +#define DFSDM_FLTICR_CLRJOVRF (1 << 2) /* Bit 2: Clear the injected conversion overrun flag */ +#define DFSDM_FLTICR_CLRROVRF (1 << 3) /* Bit 3: Clear the regular conversion overrun flag */ + +/* DFSDM injected channel group selection register (DFSDM_FLTxJCHGR) */ + +#define DFSDM_FLTJCHGR_JCHG_SHIFT (0) /* Bits 0-7: Injected channel group selection */ +#define DFSDM_FLTJCHGR_JCHG_MASK (0xff << DFSDM_FLTJCHGR_JCHG_SHIFT) + +/* DFSDM filter control register (DFSDM_FLTxFCR) */ + +#define DFSDM_FLTFCR_FOSR_SHIFT (16) /* Bits 16-25: Sinc filter oversampling ratio) */ +#define DFSDM_FLTFCR_FOSR_MASK (0x3ff << DFSDM_FLTFCR_FOSR_SHIFT) +# define DFSDM_FLTFCR_FOSR(n) ((n) << DFSDM_FLTFCR_FOSR_SHIFT) /* n=0..1023 */ +#define DFSDM_FLTFCR_FORD_SHIFT (29) /* Bits 29-31: Sinc filter order */ +#define DFSDM_FLTFCR_FORD_MASK (7 << DFSDM_FLTFCR_FORD_SHIFT) +# define DFSDM_FLTFCR_FORD_FASTSINC (0 << DFSDM_FLTFCR_FORD_SHIFT) +# define DFSDM_FLTFCR_FORD_SINC1 (1 << DFSDM_FLTFCR_FORD_SHIFT) +# define DFSDM_FLTFCR_FORD_SINC2 (2 << DFSDM_FLTFCR_FORD_SHIFT) +# define DFSDM_FLTFCR_FORD_SINC3 (3 << DFSDM_FLTFCR_FORD_SHIFT) +# define DFSDM_FLTFCR_FORD_SINC4 (4 << DFSDM_FLTFCR_FORD_SHIFT) +# define DFSDM_FLTFCR_FORD_SINC5 (5 << DFSDM_FLTFCR_FORD_SHIFT) +#define DFSDM_FLTFCR_IOSR_SHIFT (0) /* Bits 0-7: Integrator oversampling ratio) */ +#define DFSDM_FLTFCR_IOSR_MASK (0xff << DFSDM_FLTFCR_IOSR_SHIFT) +# define DFSDM_FLTFCR_IOSR(n) ((n) << DFSDM_FLTFCR_IOSR_SHIFT) /* n=0..255 */ + +/* DFSDM data register for injected group (DFSDM_FLTxJDATAR) */ + +#define DFSDM_FLTJDATAR_JDATACH_SHIFT (0) /* Bits 0-3: Injected channel most recently converted */ +#define DFSDM_FLTJDATAR_JDATACH_MASK (7 << DFSDM_FLTJDATAR_JDATACH_SHIFT) +#define DFSDM_FLTJDATAR_JDATA_SHIFT (8) /* Bits 8-23: Injected group conversion data */ +#define DFSDM_FLTJDATAR_JDATA_MASK (0xffffff << DFSDM_FLTJDATAR_JDATA_SHIFT) + +/* DFSDM data register for the regular channel (DFSDM_FLTxRDATAR) */ + +#if defined(CONFIG_STM32L4_STM32L4X3) || defined(CONFIG_STM32L4_STM32L496XX) +# define DFSDM_FLTRDATAR_RDATACH_SHIFT (0) /* Bits 0-3: channel most recently converted */ +# define DFSDM_FLTRDATAR_RDATACH_MASK (7 << DFSDM_FLTRDATAR_RDATACH_SHIFT) +#endif +#define DFSDM_FLTRDATAR_RPEND (1 << 4 /* Bit 4: Regular channel has pending data */ +#define DFSDM_FLTRDATAR_RDATA_SHIFT (8) /* Bits 8-23: channel conversion data */ +#define DFSDM_FLTRDATAR_RDATA_MASK (0xffffff << DFSDM_FLTRDATAR_RDATA_SHIFT) + +/* DFSDM analog watchdog high threshold register (DFSDM_FLTxAWHTR) */ + +#define DFSDM_AWHTR_BKAWH_SHIFT (0) /* Bits 0-3: Break signal assignment to analog watchdog high threshold event */ +#define DFSDM_AWHTR_BKAWH_MASK (0xf << DFSDM_AWHTR_BKAWH_SHIFT) + /* Bits 4-7: Reserved */ +#define DFSDM_AWHTR_AWHT_SHIFT (8) /* Bits 8-31: Analog watchdog higher threshold */ +#define DFSDM_AWHTR_AWHT_MASK (0xffffff << DFSDM_AWHTR_AWHT_SHIFT) + +/* DFSDM analog watchdog low threshold register (DFSDM_FLTxAWLTR) */ + +#define DFSDM_AWLTR_BKAWL_SHIFT (0) /* Bits 0-3: Break signal assignment to analog watchdog low threshold event */ +#define DFSDM_AWLTR_BKAWL_MASK (0xf << DFSDM_AWLTR_BKAWL_SHIFT) + /* Bits 4-7: Reserved */ +#define DFSDM_AWLTR_AWLT_SHIFT (8) /* Bits 8-31: Analog watchdog lower threshold */ +#define DFSDM_AWLTR_AWLT_MASK (0xffffff << DFSDM_AWLTR_AWLT_SHIFT) + +/* DFSDM analog watchdog status register (DFSDM_FLTxAWSR) */ + +#define DFSDM_AWSR_AWLTF_SHIFT (0) /* Bits 0-7: Analog watchdog low threshold flag */ +#define DFSDM_AWSR_AWLTF_MASK (0xff << DFSDM_AWSR_AWLTF_SHIFT) +#define DFSDM_AWSR_AWHTF_SHIFT (8) /* Bits 8-15: Analog watchdog high threshold flag */ +#define DFSDM_AWSR_AWHTF_MASK (0xff << DFSDM_AWSR_AWHTF_SHIFT) + +/* DFSDM analog watchdog clear flag register (DFSDM_FLTxAWCFR) */ + +#define DFSDM_AWCSR_CLRAWLTF_SHIFT (0) /* Bits 0-7: Clear analog watchdog low threshold flag */ +#define DFSDM_AWCSR_CLRAWLTF_MASK (0xff << DFSDM_AWCSR_CLRAWLTF_SHIFT) +#define DFSDM_AWCSR_CLRAWHTF_SHIFT (8) /* Bits 8-15: Clear analog watchdog high threshold flag */ +#define DFSDM_AWCSR_CLRAWHTF_MASK (0xff << DFSDM_AWCSR_CLRAWHTF_SHIFT) + +/* DFSDM Extremes detector maximum register (DFSDM_FLTxEXMAX) */ + +#define DFSDM_EXMAX_EXMAXCH_SHIFT (0) /* Bits 0-1: Extremes detector maximum data channel */ +#define DFSDM_EXMAX_EXMAXCH_MASK (7 << DFSDM_EXMAX_EXMAXCH_SHIFT) +#define DFSDM_EXMAX_EXMAX_SHIFT (8) /* Bits 8-31: Extremes detector maximum value */ +#define DFSDM_EXMAX_EXMAX_MASK (0xffffff << DFSDM_EXMAX_EXMAX_SHIFT) + +/* DFSDM Extremes detector minimum register (DFSDM_FLTxEXMIN) */ + +#define DFSDM_EXMIN_EXMINCH_SHIFT (0) /* Bits 0-1: Extremes detector minimum data channel */ +#define DFSDM_EXMIN_EXMINCH_MASK (7 << DFSDM_EXMIN_EXMINCH_SHIFT) +#define DFSDM_EXMIN_EXMIN_SHIFT (8) /* Bits 8-31: Extremes detector minimum value */ +#define DFSDM_EXMIN_EXMIN_MASK (0xffffff << DFSDM_EXMIN_EXMIN_SHIFT) + +/* DFSDM conversion timer register (DFSDM_FLTxCNVTIMR) */ + +#define DFSDM_CNVTIMR_CNVCNT_SHIFT (4) /* Bits 4-31: 28-bit timer counting conversion time t = CNVCNT[27:0] / fDFSDMCLK */ +#define DFSDM_CNVTIMR_CNVCNT_MASK (~0xfu) + +#endif /* __ARCH_ARM_SRC_STM32L4_CHIP_STM32L4_DFSDM_H */ diff --git a/arch/arm/src/stm32l4/chip/stm32l4_tim.h b/arch/arm/src/stm32l4/chip/stm32l4_tim.h index 99c4f48e92a..78d5004f557 100644 --- a/arch/arm/src/stm32l4/chip/stm32l4_tim.h +++ b/arch/arm/src/stm32l4/chip/stm32l4_tim.h @@ -54,29 +54,30 @@ #define STM32L4_BTIM_PSC_OFFSET 0x0028 /* Prescaler (16-bit) */ #define STM32L4_BTIM_ARR_OFFSET 0x002c /* Auto-reload register (16-bit) */ -/* 16-/32-bit General Timers with DMA: TIM2, TM3, TIM4, and TIM5 - * TIM3 and 4 are 16-bit - * TIM2 and 5 are 32-bit +/* 16-/32-bit General Timers - TIM2, TIM3, TIM4, TIM5, and TIM15-17. + * TIM3 and 4 are 16-bit. + * TIM2 and 5 are 32-bit. + * TIM15, 16 and 17 are 16-bit. */ #define STM32L4_GTIM_CR1_OFFSET 0x0000 /* Control register 1 (16-bit) */ -#define STM32L4_GTIM_CR2_OFFSET 0x0004 /* Control register 2 (16-bit, TIM2-5 only) */ -#define STM32L4_GTIM_SMCR_OFFSET 0x0008 /* Slave mode control register (16-bit, TIM2-5 only) */ +#define STM32L4_GTIM_CR2_OFFSET 0x0004 /* Control register 2 (16-bit) */ +#define STM32L4_GTIM_SMCR_OFFSET 0x0008 /* Slave mode control register (16-bit, TIM2-5,15 only) */ #define STM32L4_GTIM_DIER_OFFSET 0x000c /* DMA/Interrupt enable register (16-bit) */ #define STM32L4_GTIM_SR_OFFSET 0x0010 /* Status register (16-bit) */ #define STM32L4_GTIM_EGR_OFFSET 0x0014 /* Event generation register (16-bit) */ -#define STM32L4_GTIM_CCMR1_OFFSET 0x0018 /* Capture/compare mode register 1 (16-bit) */ -#define STM32L4_GTIM_CCMR2_OFFSET 0x001c /* Capture/compare mode register 2 (16-bit, TIM2-5 only) */ +#define STM32L4_GTIM_CCMR1_OFFSET 0x0018 /* Capture/compare mode register 1 (32-bit) */ +#define STM32L4_GTIM_CCMR2_OFFSET 0x001c /* Capture/compare mode register 2 (32-bit, TIM2-5 only) */ #define STM32L4_GTIM_CCER_OFFSET 0x0020 /* Capture/compare enable register (16-bit) */ -#define STM32L4_GTIM_CNT_OFFSET 0x0024 /* Counter (16-bit* or 32-bit STM3240 TIM2 and 5 only) */ +#define STM32L4_GTIM_CNT_OFFSET 0x0024 /* Counter (16-bit or 32-bit TIM2/5) */ #define STM32L4_GTIM_PSC_OFFSET 0x0028 /* Prescaler (16-bit) */ -#define STM32L4_GTIM_ARR_OFFSET 0x002c /* Auto-reload register (16-bit) */ -#define STM32L4_GTIM_CCR1_OFFSET 0x0034 /* Capture/compare register 1 (16-bit or 32-bit STM3240 TIM2/5 only) */ -#define STM32L4_GTIM_CCR2_OFFSET 0x0038 /* Capture/compare register 2 (16-bit TIM2-5 only or 32-bit STM32 F4 TIM2/5 or STM2 F3 TIM15 only) */ -#define STM32L4_GTIM_CCR3_OFFSET 0x003c /* Capture/compare register 3 (16-bit TIM2-5 only or 32-bit STM32 F4 TIM2/5 only) */ -#define STM32L4_GTIM_CCR4_OFFSET 0x0040 /* Capture/compare register 4 (16-bit TIM2-5 only or 32-bit STM32 F4 TIM2/5 only) */ -#define STM32L4_GTIM_DCR_OFFSET 0x0048 /* DMA control register (16-bit, TIM2-5 only) */ -#define STM32L4_GTIM_DMAR_OFFSET 0x004c /* DMA address for burst mode (16-bit, TIM2-5 only) */ +#define STM32L4_GTIM_ARR_OFFSET 0x002c /* Auto-reload register (16-bit or 32-bit TIM2/5) */ +#define STM32L4_GTIM_CCR1_OFFSET 0x0034 /* Capture/compare register 1 (16-bit or 32-bit TIM2/5) */ +#define STM32L4_GTIM_CCR2_OFFSET 0x0038 /* Capture/compare register 2 (16-bit TIM2-5,15 only or 32-bit TIM2/5) */ +#define STM32L4_GTIM_CCR3_OFFSET 0x003c /* Capture/compare register 3 (16-bit TIM2-5 only or 32-bit TIM2/5) */ +#define STM32L4_GTIM_CCR4_OFFSET 0x0040 /* Capture/compare register 4 (16-bit TIM2-5 only or 32-bit TIM2/5) */ +#define STM32L4_GTIM_DCR_OFFSET 0x0048 /* DMA control register (16-bit) */ +#define STM32L4_GTIM_DMAR_OFFSET 0x004c /* DMA address for burst mode (16-bit) */ #define STM32L4_GTIM_OR1_OFFSET 0x0050 /* Option register 1 */ #define STM32L4_GTIM_OR2_OFFSET 0x0060 /* Option register 2 */ @@ -185,9 +186,10 @@ #define STM32L4_TIM8_OR2 (STM32L4_TIM8_BASE+STM32L4_ATIM_OR2_OFFSET) #define STM32L4_TIM8_OR3 (STM32L4_TIM8_BASE+STM32L4_ATIM_OR3_OFFSET) -/* 16-/32-bit General Timers - TIM2, TIM3, TIM4, and TIM5 with DMA. +/* 16-/32-bit General Timers - TIM2, TIM3, TIM4, TIM5, and TIM15-17. * TIM3 and 4 are 16-bit. - * TIM2 and 5 are 32-bit + * TIM2 and 5 are 32-bit. + * TIM15, 16 and 17 are 16-bit. */ #define STM32L4_TIM2_CR1 (STM32L4_TIM2_BASE+STM32L4_GTIM_CR1_OFFSET) @@ -292,7 +294,6 @@ #define STM32L4_TIM16_SR (STM32L4_TIM16_BASE+STM32L4_GTIM_SR_OFFSET) #define STM32L4_TIM16_EGR (STM32L4_TIM16_BASE+STM32L4_GTIM_EGR_OFFSET) #define STM32L4_TIM16_CCMR1 (STM32L4_TIM16_BASE+STM32L4_GTIM_CCMR1_OFFSET) -#define STM32L4_TIM16_CCMR2 (STM32L4_TIM16_BASE+STM32L4_GTIM_CCMR2_OFFSET) #define STM32L4_TIM16_CCER (STM32L4_TIM16_BASE+STM32L4_GTIM_CCER_OFFSET) #define STM32L4_TIM16_CNT (STM32L4_TIM16_BASE+STM32L4_GTIM_CNT_OFFSET) #define STM32L4_TIM16_PSC (STM32L4_TIM16_BASE+STM32L4_GTIM_PSC_OFFSET) @@ -310,7 +311,6 @@ #define STM32L4_TIM17_SR (STM32L4_TIM17_BASE+STM32L4_GTIM_SR_OFFSET) #define STM32L4_TIM17_EGR (STM32L4_TIM17_BASE+STM32L4_GTIM_EGR_OFFSET) #define STM32L4_TIM17_CCMR1 (STM32L4_TIM17_BASE+STM32L4_GTIM_CCMR1_OFFSET) -#define STM32L4_TIM17_CCMR2 (STM32L4_TIM17_BASE+STM32L4_GTIM_CCMR2_OFFSET) #define STM32L4_TIM17_CCER (STM32L4_TIM17_BASE+STM32L4_GTIM_CCER_OFFSET) #define STM32L4_TIM17_CNT (STM32L4_TIM17_BASE+STM32L4_GTIM_CNT_OFFSET) #define STM32L4_TIM17_PSC (STM32L4_TIM17_BASE+STM32L4_GTIM_PSC_OFFSET) @@ -706,7 +706,7 @@ # define ATIM_BDTR_LOCKOFF (0 << ATIM_BDTR_LOCK_SHIFT) /* 00: LOCK OFF - No bit is write protected */ # define ATIM_BDTR_LOCK1 (1 << ATIM_BDTR_LOCK_SHIFT) /* 01: LOCK Level 1 protection */ # define ATIM_BDTR_LOCK2 (2 << ATIM_BDTR_LOCK_SHIFT) /* 10: LOCK Level 2 protection */ -# define ATIM_BDTR_LOCK3 (3 << ATIM_BDTR_LOCK_SHIFT) /* 11: LOCK Level 3 protection */ */ +# define ATIM_BDTR_LOCK3 (3 << ATIM_BDTR_LOCK_SHIFT) /* 11: LOCK Level 3 protection */ #define ATIM_BDTR_OSSI (1 << 10) /* Bit 10: Off-State Selection for Idle mode */ #define ATIM_BDTR_OSSR (1 << 11) /* Bit 11: Off-State Selection for Run mode */ #define ATIM_BDTR_BKE (1 << 12) /* Bit 12: Break enable */ @@ -885,15 +885,15 @@ #define GTIM_SR_CC3OF (1 << 11) /* Bit 11: Capture/Compare 3 Overcapture flag (TIM2-5 only) */ #define GTIM_SR_CC4OF (1 << 12) /* Bit 12: Capture/Compare 4 Overcapture flag (TIM2-5 only) */ -/* Event generation register (TIM2-5 and TIM9-14) */ +/* Event generation register (TIM2-5, TIM15-17) */ #define GTIM_EGR_UG (1 << 0) /* Bit 0: Update generation */ #define GTIM_EGR_CC1G (1 << 1) /* Bit 1: Capture/compare 1 generation */ -#define GTIM_EGR_CC2G (1 << 2) /* Bit 2: Capture/compare 2 generation (TIM2-5,9,12,&15 only) */ +#define GTIM_EGR_CC2G (1 << 2) /* Bit 2: Capture/compare 2 generation (TIM2-5,15 only) */ #define GTIM_EGR_CC3G (1 << 3) /* Bit 3: Capture/compare 3 generation (TIM2-5 only) */ #define GTIM_EGR_CC4G (1 << 4) /* Bit 4: Capture/compare 4 generation (TIM2-5 only) */ #define GTIM_EGR_COMIG (1 << 5) /* Bit 5: Capture/Compare control update generation (TIM15-17 only) */ -#define GTIM_EGR_TG (1 << 6) /* Bit 6: Trigger generation (TIM2-5,9,12&16-17 only) */ +#define GTIM_EGR_TG (1 << 6) /* Bit 6: Trigger generation (TIM2-5,16-17 only) */ #define GTIM_EGR_BG (1 << 7) /* Bit 7: Break generation (TIM15-17 only) */ /* Capture/compare mode register 1 - Output compare mode (TIM2-5) */ @@ -1057,7 +1057,7 @@ # define GTIM_BDTR_LOCKOFF (0 << GTIM_BDTR_LOCK_SHIFT) /* 00: LOCK OFF - No bit is write protected */ # define GTIM_BDTR_LOCK1 (1 << GTIM_BDTR_LOCK_SHIFT) /* 01: LOCK Level 1 protection */ # define GTIM_BDTR_LOCK2 (2 << GTIM_BDTR_LOCK_SHIFT) /* 10: LOCK Level 2 protection */ -# define GTIM_BDTR_LOCK3 (3 << GTIM_BDTR_LOCK_SHIFT) /* 11: LOCK Level 3 protection */ */ +# define GTIM_BDTR_LOCK3 (3 << GTIM_BDTR_LOCK_SHIFT) /* 11: LOCK Level 3 protection */ #define GTIM_BDTR_OSSI (1 << 10) /* Bit 10: Off-State Selection for Idle mode */ #define GTIM_BDTR_OSSR (1 << 11) /* Bit 11: Off-State Selection for Run mode */ #define GTIM_BDTR_BKE (1 << 12) /* Bit 12: Break enable */ diff --git a/arch/arm/src/stm32l4/chip/stm32l4x3xx_dma.h b/arch/arm/src/stm32l4/chip/stm32l4x3xx_dma.h index 8723fc1c0aa..a00945deb96 100644 --- a/arch/arm/src/stm32l4/chip/stm32l4x3xx_dma.h +++ b/arch/arm/src/stm32l4/chip/stm32l4x3xx_dma.h @@ -344,8 +344,8 @@ /* DFSDM */ -#define DMACHAN_DFSDM1_FLT0 DMACHAN_SETTING(STM32L4_DMA1_CHAN5, 0) -#define DMACHAN_DFSDM1_FLT1 DMACHAN_SETTING(STM32L4_DMA1_CHAN6, 0) +#define DMACHAN_DFSDM0 DMACHAN_SETTING(STM32L4_DMA1_CHAN5, 0) +#define DMACHAN_DFSDM1 DMACHAN_SETTING(STM32L4_DMA1_CHAN6, 0) /* I2C */ diff --git a/arch/arm/src/stm32l4/stm32l4_dac.c b/arch/arm/src/stm32l4/stm32l4_dac.c index 36cf044a6b0..de4ab69ffba 100644 --- a/arch/arm/src/stm32l4/stm32l4_dac.c +++ b/arch/arm/src/stm32l4/stm32l4_dac.c @@ -386,7 +386,11 @@ uint16_t stm32l4_dac1_dmabuffer[CONFIG_STM32L4_DAC1_DMA_BUFFER_SIZE]; static struct stm32_chan_s g_dac1priv = { .intf = 0, +#ifdef CONFIG_STM32L4_DAC1_OUTPUT_ADC + .pin = 0xffffffffU, +#else .pin = GPIO_DAC1_OUT, +#endif .dro = STM32L4_DAC_DHR12R1, .cr = STM32L4_DAC_CR, #ifdef CONFIG_STM32L4_DAC1_DMA @@ -419,7 +423,11 @@ uint16_t stm32l4_dac2_dmabuffer[CONFIG_STM32L4_DAC2_DMA_BUFFER_SIZE]; static struct stm32_chan_s g_dac2priv = { .intf = 1, +#ifdef CONFIG_STM32L4_DAC2_OUTPUT_ADC + .pin = 0xffffffffU, +#else .pin = GPIO_DAC2_OUT, +#endif .dro = STM32L4_DAC_DHR12R2, .cr = STM32L4_DAC_CR, #ifdef CONFIG_STM32L4_DAC2_DMA @@ -1011,7 +1019,10 @@ static int dac_chaninit(FAR struct stm32_chan_s *chan) * should first be configured to analog (AIN)". */ - stm32l4_configgpio(chan->pin); + if (chan->pin != 0xffffffffU) + { + stm32l4_configgpio(chan->pin); + } /* DAC channel configuration: * @@ -1036,24 +1047,14 @@ static int dac_chaninit(FAR struct stm32_chan_s *chan) /* Enable output buffer or route DAC output to on-chip peripherals (ADC) */ clearbits = DAC_MCR_MODE1_MASK; -#if defined(CONFIG_STM32L4_DAC1_OUTPUT_ADC) - if (chan->intf == 0) - { - setbits = DAC_MCR_MODE_IN; - } - else -#endif -#if defined(CONFIG_STM32L4_DAC2_OUTPUT_ADC) - if (chan->intf == 1) - { - setbits = DAC_MCR_MODE_IN; - } - else -#endif + if (chan->pin != 0xffffffffU) { setbits = DAC_MCR_MODE_EXTBUF; } - + else + { + setbits = DAC_MCR_MODE_IN; + } stm32l4_dac_modify_mcr(chan, clearbits, setbits); #ifdef HAVE_DMA diff --git a/arch/arm/src/stm32l4/stm32l4_dfsdm.c b/arch/arm/src/stm32l4/stm32l4_dfsdm.c new file mode 100644 index 00000000000..e0efee19a77 --- /dev/null +++ b/arch/arm/src/stm32l4/stm32l4_dfsdm.c @@ -0,0 +1,1789 @@ +/**************************************************************************** + * arch/arm/src/stm32l4/stm32l4_dfsdm.c + * + * Copyright (C) 2017 Haltian Ltd. All rights reserved. + * Author: 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 + +#include +#include +#include +#include +#include +#include + +#include "chip.h" +#include "stm32l4_rcc.h" +#include "stm32l4_tim.h" +#include "stm32l4_dma.h" +#include "stm32l4_dfsdm.h" + +/* ADC "upper half" support must be enabled. DFSDM are ADC devices. */ + +#ifdef CONFIG_ADC + +/* The peripheral must be enabled */ + +#ifdef CONFIG_STM32L4_DFSDM + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Sanity checking **********************************************************/ + +#if !defined(CONFIG_STM32L4_DFSDM1_FLT0) && \ + !defined(CONFIG_STM32L4_DFSDM1_FLT1) && \ + !defined(CONFIG_STM32L4_DFSDM1_FLT2) && !defined(CONFIG_STM32L4_DFSDM1_FLT3) +# error "At least one DFSDM filter must be defined" +#endif + +#if defined(CONFIG_STM32L4_STM32L4X3) +# if defined(CONFIG_STM32L4_DFSDM1_FLT2) || defined(CONFIG_STM32L4_DFSDM1_FLT3) +# error "Non-existent DFSDM filter defined" +# endif +#endif + +/* Abbreviated register access **********************************************/ + +#define CHCFGR1_OFFSET(priv) STM32L4_DFSDM_CHCFGR1_OFFSET((priv)->current) +#define CHCFGR2_OFFSET(priv) STM32L4_DFSDM_CHCFGR2_OFFSET((priv)->current) + +#define FLTCR1_OFFSET(priv) STM32L4_DFSDM_FLTCR1_OFFSET((priv)->intf) +#define FLTCR2_OFFSET(priv) STM32L4_DFSDM_FLTCR2_OFFSET((priv)->intf) +#define FLTISR_OFFSET(priv) STM32L4_DFSDM_FLTISR_OFFSET((priv)->intf) +#define FLTICR_OFFSET(priv) STM32L4_DFSDM_FLTICR_OFFSET((priv)->intf) +#define FLTFCR_OFFSET(priv) STM32L4_DFSDM_FLTFCR_OFFSET((priv)->intf) +#define FLTRDATAR_OFFSET(priv) STM32L4_DFSDM_FLTRDATAR_OFFSET((priv)->intf) +#define FLTAWHTR_OFFSET(priv) STM32L4_DFSDM_FLTAWHTR_OFFSET((priv)->intf) +#define FLTAWLTR_OFFSET(priv) STM32L4_DFSDM_FLTAWLTR_OFFSET((priv)->intf) +#define FLTAWSR_OFFSET(priv) STM32L4_DFSDM_FLTAWSR_OFFSET((priv)->intf) +#define FLTAWCFR_OFFSET(priv) STM32L4_DFSDM_FLTAWCFR_OFFSET((priv)->intf) +#define FLTEXMAX_OFFSET(priv) STM32L4_DFSDM_FLTEXMAX_OFFSET((priv)->intf) +#define FLTEXMIN_OFFSET(priv) STM32L4_DFSDM_FLTEXMIN_OFFSET((priv)->intf) + +/* DFSDM Filter interrupts **************************************************/ + +/* These bits are same in FLRCR2 and FLTISR (FLTICR only has JOVR and ROVR) */ +#define DFSDM_INT_JEOC DFSDM_FLTCR2_JEOCIE +#define DFSDM_INT_REOC DFSDM_FLTCR2_REOCIE +#define DFSDM_INT_JOVR DFSDM_FLTCR2_JOWRIE +#define DFSDM_INT_ROVR DFSDM_FLTCR2_ROWRIE +#define DFSDM_INT_AWD DFSDM_FLTCR2_AWDIE + +/* SCDIE and CKABIE are not in this, as the bits exist only in FLT0 filter CR2. */ +#define DFSDM_INT_MASK (DFSDM_FLTCR2_JEOCIE | DFSDM_FLTCR2_REOCIE | \ + DFSDM_FLTCR2_JOWRIE | DFSDM_FLTCR2_ROWRIE | \ + DFSDM_FLTCR2_AWDIE) + +/* Similarly, this is missing SCDF and CKABF as special support is needed. */ +#define DFSDM_ISR_MASK (DFSDM_FLTISR_JEOCF | DFSDM_FLTISR_REOCF | \ + DFSDM_FLTISR_JOVRF | DFSDM_FLTISR_ROVRF | \ + DFSDM_FLTISR_AWDF) + +/* DFSDM Channels/DMA ********************************************************/ +/* The maximum number of channels that can be sampled. While DMA support is + * very nice for reliable multi-channel sampling, the STM32L4 can function + * without, although there is a risk of overrun. + */ + +#if defined(CONFIG_STM32L4_STM32L4X3) +# define DFSDM_MAX_CHANNELS 4 +# define DFSDM_MAX_FILTERS 2 +#else +# define DFSDM_MAX_CHANNELS 8 +# define DFSDM_MAX_FILTERS 4 +#endif + +#ifdef DFSDM_HAVE_DMA +# if !defined(CONFIG_STM32L4_DMA1) +# error "STM32L4 DFSDM DMA support requires CONFIG_STM32L4_DMA1" +# endif +#endif + +/* We currently only use DMA to read DFSDM conversion results, not for + * parallel inputs to DFSDM_CHyDATINR register. + */ + +#define DFSDM_DMA_CONTROL_WORD (DMA_CCR_MSIZE_16BITS | \ + DMA_CCR_PSIZE_16BITS | \ + DMA_CCR_MINC | \ + DMA_CCR_CIRC) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure describes the state of one DFSDM block */ + +struct stm32_dev_s +{ + FAR const struct adc_callback_s *cb; + uint8_t irq; /* Interrupt generated by this block */ + uint8_t nchannels; /* Number of channels */ + uint8_t cchannels; /* Number of configured channels */ + uint8_t intf; /* DFSDM filter number */ + uint8_t current; /* Current channel being converted */ +#ifdef DFSDM_HAVE_DMA + uint8_t dmachan; /* DMA channel needed by this filter */ + bool hasdma; /* True: This filter supports DMA */ +#endif +#ifdef DFSDM_HAVE_TIMER + uint8_t trigger; /* Timer trigger channel: 0=CC1, 1=CC2, 2=CC3, + * 3=CC4, 4=TRGO, 5=TRGO2 */ +#endif + xcpt_t isr; /* Interrupt handler for this filter block */ + uint32_t base; /* Base address of registers */ +#ifdef DFSDM_HAVE_TIMER + uint32_t tbase; /* Base address of timer */ + uint32_t extsel; /* EXTSEL value used */ + uint32_t pclck; /* The PCLK frequency that drives this timer */ + uint32_t freq; /* The desired frequency of conversions */ +#endif + +#ifdef DFSDM_HAVE_DMA + DMA_HANDLE dma; /* Allocated DMA channel */ + + /* DMA transfer buffer */ + + uint32_t dmabuffer[DFSDM_MAX_CHANNELS]; +#endif + + /* List of selected channels to sample */ + + uint8_t chanlist[DFSDM_MAX_CHANNELS]; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Register access */ + +static uint32_t dfsdm_getreg(FAR struct stm32_dev_s *priv, int offset); +static void dfsdm_putreg(FAR struct stm32_dev_s *priv, int offset, + uint32_t value); +static void dfsdm_modifyreg(FAR struct stm32_dev_s *priv, int offset, + uint32_t clrbits, uint32_t setbits); + +#ifdef DFSDM_HAVE_TIMER +static uint16_t tim_getreg(FAR struct stm32_dev_s *priv, int offset); +static void tim_putreg(FAR struct stm32_dev_s *priv, int offset, + uint16_t value); +static void tim_modifyreg(FAR struct stm32_dev_s *priv, int offset, + uint16_t clrbits, uint16_t setbits); +static void tim_dumpregs(FAR struct stm32_dev_s *priv, + FAR const char *msg); +#endif + +/* Miscellaneous Helpers */ + +static void dfsdm_rccreset(FAR struct stm32_dev_s *priv, bool reset); +static void dfsdm_enable(FAR struct stm32_dev_s *priv); +static int dfsdm_set_ch(FAR struct adc_dev_s *dev, uint8_t ch); + +#ifdef DFSDM_HAVE_TIMER +static void dfsdm_timstart(FAR struct stm32_dev_s *priv, bool enable); +static int dfsdm_timinit(FAR struct stm32_dev_s *priv); +#endif + +#ifdef DFSDM_HAVE_DMA +static void dfsdm_dmaconvcallback(DMA_HANDLE handle, uint8_t isr, + FAR void *arg); +#endif + +static void dfsdm_startconv(FAR struct stm32_dev_s *priv, bool enable); + +/* Interrupt Handler */ + +static int dfsdm_interrupt(FAR struct adc_dev_s *dev, uint32_t regval); +#if defined(CONFIG_STM32L4_DFSDM1_FLT0) +static int dfsdm_flt0_interrupt(int irq, FAR void *context, FAR void *arg); +#endif +#if defined(CONFIG_STM32L4_DFSDM1_FLT1) +static int dfsdm_flt1_interrupt(int irq, FAR void *context, FAR void *arg); +#endif +#if defined(CONFIG_STM32L4_DFSDM1_FLT2) +static int dfsdm_flt2_interrupt(int irq, FAR void *context, FAR void *arg); +#endif +#if defined(CONFIG_STM32L4_DFSDM1_FLT3) +static int dfsdm_flt3_interrupt(int irq, FAR void *context, FAR void *arg); +#endif + +/* ADC Driver Methods */ + +static int dfsdm_bind(FAR struct adc_dev_s *dev, + FAR const struct adc_callback_s *callback); +static void dfsdm_reset(FAR struct adc_dev_s *dev); +static int dfsdm_setup(FAR struct adc_dev_s *dev); +static void dfsdm_shutdown(FAR struct adc_dev_s *dev); +static void dfsdm_rxint(FAR struct adc_dev_s *dev, bool enable); +static int dfsdm_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* ADC interface operations */ + +static const struct adc_ops_s g_adcops = +{ + .ao_bind = dfsdm_bind, + .ao_reset = dfsdm_reset, + .ao_setup = dfsdm_setup, + .ao_shutdown = dfsdm_shutdown, + .ao_rxint = dfsdm_rxint, + .ao_ioctl = dfsdm_ioctl, +}; + +/* DFSDM FLT0 */ + +#if defined(CONFIG_STM32L4_DFSDM1_FLT0) +static struct stm32_dev_s g_dfsdmpriv0 = +{ + .irq = STM32L4_IRQ_DFSDM0, + .isr = dfsdm_flt0_interrupt, + .intf = 0, + .base = STM32L4_DFSDM_BASE, +#ifdef DFSDM_HAVE_TIMER + .trigger = CONFIG_STM32L4_DFSDM_TIMTRIG, + .tbase = DFSDM_TIMER_BASE, + .extsel = DFSDM_JEXTSEL_VALUE, + .pclck = DFSDM_TIMER_PCLK_FREQUENCY, + .freq = CONFIG_STM32L4_DFSDM_SAMPLE_FREQUENCY, +#endif +#ifdef DFSDM_HAVE_DMA + .dmachan = DMACHAN_DFSDM0, + .hasdma = true, +#endif +}; + +static struct adc_dev_s g_dfsdmdev0 = +{ + .ad_ops = &g_adcops, + .ad_priv = &g_dfsdmpriv0, +}; +#endif + +/* DFSDM FLT1 */ + +#if defined(CONFIG_STM32L4_DFSDM1_FLT1) +static struct stm32_dev_s g_dfsdmpriv1 = +{ + .irq = STM32L4_IRQ_DFSDM1, + .isr = dfsdm_flt1_interrupt, + .intf = 1, + .base = STM32L4_DFSDM_BASE, +#ifdef DFSDM_HAVE_TIMER + .trigger = CONFIG_STM32L4_DFSDM_TIMTRIG, + .tbase = DFSDM_TIMER_BASE, + .extsel = DFSDM_JEXTSEL_VALUE, + .pclck = DFSDM_TIMER_PCLK_FREQUENCY, + .freq = CONFIG_STM32L4_DFSDM_SAMPLE_FREQUENCY, +#endif +#ifdef DFSDM_HAVE_DMA + .dmachan = DMACHAN_DFSDM1, + .hasdma = true, +#endif +}; + +static struct adc_dev_s g_dfsdmdev1 = +{ + .ad_ops = &g_adcops, + .ad_priv = &g_dfsdmpriv1, +}; +#endif + +/* DFSDM FLT2 */ + +#if defined(CONFIG_STM32L4_DFSDM1_FLT2) +static struct stm32_dev_s g_dfsdmpriv2 = +{ + .irq = STM32L4_IRQ_DFSDM2, + .isr = dfsdm_flt2_interrupt, + .intf = 0, + .base = STM32L4_DFSDM_BASE, +#ifdef DFSDM_HAVE_TIMER + .trigger = CONFIG_STM32L4_DFSDM_TIMTRIG, + .tbase = DFSDM_TIMER_BASE, + .extsel = DFSDM_JEXTSEL_VALUE, + .pclck = DFSDM_TIMER_PCLK_FREQUENCY, + .freq = CONFIG_STM32L4_DFSDM_SAMPLE_FREQUENCY, +#endif +#ifdef DFSDM_HAVE_DMA + .dmachan = DMACHAN_DFSDM2, + .hasdma = true, +#endif +}; + +static struct adc_dev_s g_dfsdmdev2 = +{ + .ad_ops = &g_adcops, + .ad_priv = &g_dfsdmpriv2, +}; +#endif + +/* DFSDM FLT3 */ + +#if defined(CONFIG_STM32L4_DFSDM1_FLT3) +static struct stm32_dev_s g_dfsdmpriv3 = +{ + .irq = STM32L4_IRQ_DFSDM3, + .isr = dfsdm_flt3_interrupt, + .intf = 0, + .base = STM32L4_DFSDM_BASE, +#ifdef DFSDM_HAVE_TIMER + .trigger = CONFIG_STM32L4_DFSDM_TIMTRIG, + .tbase = DFSDM_TIMER_BASE, + .extsel = DFSDM_JEXTSEL_VALUE, + .pclck = DFSDM_TIMER_PCLK_FREQUENCY, + .freq = CONFIG_STM32L4_DFSDM_SAMPLE_FREQUENCY, +#endif +#ifdef DFSDM_HAVE_DMA + .dmachan = DMACHAN_DFSDM3, + .hasdma = true, +#endif +}; + +static struct adc_dev_s g_dfsdmdev3 = +{ + .ad_ops = &g_adcops, + .ad_priv = &g_dfsdmpriv3, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: dfsdm_getreg + * + * Description: + * Read the value of a DFSDM register. + * + * Input Parameters: + * priv - A reference to the DFSDM block status + * offset - The offset to the register to read + * + * Returned Value: + * The current contents of the specified register + * + ****************************************************************************/ + +static uint32_t dfsdm_getreg(FAR struct stm32_dev_s *priv, int offset) +{ + return getreg32(priv->base + offset); +} + +/**************************************************************************** + * Name: dfsdm_putreg + * + * Description: + * Write a value to an DFSDM register. + * + * Input Parameters: + * priv - A reference to the DFSDM block status + * offset - The offset to the register to write to + * value - The value to write to the register + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void dfsdm_putreg(FAR struct stm32_dev_s *priv, int offset, + uint32_t value) +{ + putreg32(value, priv->base + offset); +} + +/**************************************************************************** + * Name: dfsdm_modifyreg + * + * Description: + * Modify the value of an DFSDM register (not atomic). + * + * Input Parameters: + * priv - A reference to the ADC block status + * offset - The offset to the register to modify + * clrbits - The bits to clear + * setbits - The bits to set + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void dfsdm_modifyreg(FAR struct stm32_dev_s *priv, int offset, + uint32_t clrbits, uint32_t setbits) +{ + dfsdm_putreg(priv, offset, (dfsdm_getreg(priv, offset) & ~clrbits) | setbits); +} + +/**************************************************************************** + * Name: tim_getreg + * + * Description: + * Read the value of an DFSDM timer register. + * + * Input Parameters: + * priv - A reference to the DFSDM block status + * offset - The offset to the register to read + * + * Returned Value: + * The current contents of the specified register + * + ****************************************************************************/ + +#ifdef DFSDM_HAVE_TIMER +static uint16_t tim_getreg(FAR struct stm32_dev_s *priv, int offset) +{ + return getreg16(priv->tbase + offset); +} +#endif + +/**************************************************************************** + * Name: tim_putreg + * + * Description: + * Write a value to an DFSDM timer register. + * + * Input Parameters: + * priv - A reference to the DFSDM block status + * offset - The offset to the register to write to + * value - The value to write to the register + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef DFSDM_HAVE_TIMER +static void tim_putreg(FAR struct stm32_dev_s *priv, int offset, + uint16_t value) +{ + putreg16(value, priv->tbase + offset); +} +#endif + +/**************************************************************************** + * Name: tim_modifyreg + * + * Description: + * Modify the value of an DFSDM timer register (not atomic). + * + * Input Parameters: + * priv - A reference to the DFSDM block status + * offset - The offset to the register to modify + * clrbits - The bits to clear + * setbits - The bits to set + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef DFSDM_HAVE_TIMER +static void tim_modifyreg(FAR struct stm32_dev_s *priv, int offset, + uint16_t clrbits, uint16_t setbits) +{ + tim_putreg(priv, offset, (tim_getreg(priv, offset) & ~clrbits) | setbits); +} +#endif + +/**************************************************************************** + * Name: tim_dumpregs + * + * Description: + * Dump all timer registers. + * + * Input parameters: + * priv - A reference to the DFSDM block status + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef DFSDM_HAVE_TIMER +static void tim_dumpregs(FAR struct stm32_dev_s *priv, FAR const char *msg) +{ + ainfo("%s:\n", msg); + ainfo(" CR1: %04x CR2: %04x SMCR: %04x DIER: %04x\n", + tim_getreg(priv, STM32L4_GTIM_CR1_OFFSET), + tim_getreg(priv, STM32L4_GTIM_CR2_OFFSET), + tim_getreg(priv, STM32L4_GTIM_SMCR_OFFSET), + tim_getreg(priv, STM32L4_GTIM_DIER_OFFSET)); + ainfo(" SR: %04x EGR: 0000 CCMR1: %04x CCMR2: %04x\n", + tim_getreg(priv, STM32L4_GTIM_SR_OFFSET), + tim_getreg(priv, STM32L4_GTIM_CCMR1_OFFSET), + tim_getreg(priv, STM32L4_GTIM_CCMR2_OFFSET)); + ainfo(" CCER: %04x CNT: %04x PSC: %04x ARR: %04x\n", + tim_getreg(priv, STM32L4_GTIM_CCER_OFFSET), + tim_getreg(priv, STM32L4_GTIM_CNT_OFFSET), + tim_getreg(priv, STM32L4_GTIM_PSC_OFFSET), + tim_getreg(priv, STM32L4_GTIM_ARR_OFFSET)); + ainfo(" CCR1: %04x CCR2: %04x CCR3: %04x CCR4: %04x\n", + tim_getreg(priv, STM32L4_GTIM_CCR1_OFFSET), + tim_getreg(priv, STM32L4_GTIM_CCR2_OFFSET), + tim_getreg(priv, STM32L4_GTIM_CCR3_OFFSET), + tim_getreg(priv, STM32L4_GTIM_CCR4_OFFSET)); + if (priv->tbase == STM32L4_TIM1_BASE || priv->tbase == STM32L4_TIM8_BASE) + { + ainfo(" RCR: %04x BDTR: %04x DCR: %04x DMAR: %04x\n", + tim_getreg(priv, STM32L4_ATIM_RCR_OFFSET), + tim_getreg(priv, STM32L4_ATIM_BDTR_OFFSET), + tim_getreg(priv, STM32L4_ATIM_DCR_OFFSET), + tim_getreg(priv, STM32L4_ATIM_DMAR_OFFSET)); + } + else + { + ainfo(" DCR: %04x DMAR: %04x\n", + tim_getreg(priv, STM32L4_GTIM_DCR_OFFSET), + tim_getreg(priv, STM32L4_GTIM_DMAR_OFFSET)); + } +} +#endif + +/**************************************************************************** + * Name: dfsdm_timstart + * + * Description: + * Start (or stop) the timer counter + * + * Input Parameters: + * priv - A reference to the DFSDM block status + * enable - True: Start conversion + * + * Returned Value: + * + ****************************************************************************/ + +#ifdef DFSDM_HAVE_TIMER +static void dfsdm_timstart(FAR struct stm32_dev_s *priv, bool enable) +{ + ainfo("enable: %d\n", enable ? 1 : 0); + + if (enable) + { + /* Start the counter */ + + tim_modifyreg(priv, STM32L4_GTIM_CR1_OFFSET, 0, GTIM_CR1_CEN); + } + else + { + /* Disable the counter */ + + tim_modifyreg(priv, STM32L4_GTIM_CR1_OFFSET, GTIM_CR1_CEN, 0); + } +} +#endif + +/**************************************************************************** + * Name: dfsdm_timinit + * + * Description: + * Initialize the timer that drivers the DFSDM sampling for this channel + * using the pre-calculated timer divider definitions. + * + * Input Parameters: + * priv - A reference to the DFSDM block status + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +#ifdef DFSDM_HAVE_TIMER +static int dfsdm_timinit(FAR struct stm32_dev_s *priv) +{ + uint32_t prescaler; + uint32_t reload; + uint32_t timclk; + + uint16_t clrbits = 0; + uint16_t setbits = 0; + uint16_t cr2; + uint16_t ccmr1; + uint16_t ccmr2; + uint16_t ocmode1; + uint16_t ocmode2; + uint16_t ccenable; + uint16_t ccer; + uint16_t egr; + + /* If the timer base address is zero, then this ADC was not configured to + * use a timer. + */ + + if (priv->tbase == 0) + { + return ERROR; + } + /* EXTSEL selection: These bits select the external event used to trigger + * the start of conversion of a regular group. NOTE: + * + * - The position with of the EXTSEL field varies from one STM32 MCU + * to another. + * - The width of the EXTSEL field varies from one STM32 MCU to another. + * - The value in priv->extsel is already shifted into the correct bit + * position. + */ + + ainfo("Initializing timers extsel = 0x%08x\n", priv->extsel); + + dfsdm_modifyreg(priv, FLTCR2_OFFSET(priv), + DFSDM_FLTCR1_JEXTEN_MASK | DFSDM_FLTCR1_JEXTSEL_MASK, + DFSDM_FLTCR1_JEXTEN_RISING | priv->extsel); + + /* Configure the timer channel to drive the ADC */ + + /* Caculate optimal values for the timer prescaler and for the timer + * reload register. If freq is the desired frequency, then + * + * reload = timclk / freq + * reload = (pclck / prescaler) / freq + * + * There are many solutions to do this, but the best solution will be the + * one that has the largest reload value and the smallest prescaler value. + * That is the solution that should give us the most accuracy in the timer + * control. Subject to: + * + * 0 <= prescaler <= 65536 + * 1 <= reload <= 65535 + * + * So ( prescaler = pclck / 65535 / freq ) would be optimal. + */ + + prescaler = (priv->pclck / priv->freq + 65534) / 65535; + + /* We need to decrement the prescaler value by one, but only, the value + * does not underflow. + */ + + if (prescaler < 1) + { + awarn("WARNING: Prescaler underflowed.\n"); + prescaler = 1; + } + + /* Check for overflow */ + + else if (prescaler > 65536) + { + awarn("WARNING: Prescaler overflowed.\n"); + prescaler = 65536; + } + + timclk = priv->pclck / prescaler; + + reload = timclk / priv->freq; + if (reload < 1) + { + awarn("WARNING: Reload value underflowed.\n"); + reload = 1; + } + + else if (reload > 65535) + { + awarn("WARNING: Reload value overflowed.\n"); + reload = 65535; + } + + /* Disable the timer until we get it configured */ + + dfsdm_timstart(priv, false); + + /* Set up the timer CR1 register. + * + * Select the Counter Mode == count up: + * + * ATIM_CR1_EDGE: The counter counts up or down depending on the + * direction bit(DIR). + * ATIM_CR1_DIR: 0: count up, 1: count down + * + * Set the clock division to zero for all + */ + clrbits = GTIM_CR1_DIR | GTIM_CR1_CMS_MASK | GTIM_CR1_CKD_MASK; + setbits = GTIM_CR1_EDGE; + tim_modifyreg(priv, STM32L4_GTIM_CR1_OFFSET, clrbits, setbits); + + /* Set the reload and prescaler values */ + + tim_putreg(priv, STM32L4_GTIM_PSC_OFFSET, prescaler-1); + tim_putreg(priv, STM32L4_GTIM_ARR_OFFSET, reload); + + /* Clear the advanced timers repetition counter in TIM1 */ + + if (priv->tbase == STM32L4_TIM1_BASE || priv->tbase == STM32L4_TIM8_BASE) + { + tim_putreg(priv, STM32L4_ATIM_RCR_OFFSET, 0); + tim_putreg(priv, STM32L4_ATIM_BDTR_OFFSET, ATIM_BDTR_MOE); /* Check me */ + } + + /* TIMx event generation: Bit 0 UG: Update generation */ + + tim_putreg(priv, STM32L4_GTIM_EGR_OFFSET, GTIM_EGR_UG); + + /* Handle channel specific setup */ + + ocmode1 = 0; + ocmode2 = 0; + + switch (priv->trigger) + { + case 0: /* TimerX CC1 event */ + { + ccenable = ATIM_CCER_CC1E; + ocmode1 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC1S_SHIFT) | + (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR1_OC1M_SHIFT) | + ATIM_CCMR1_OC1PE; + + /* Set the event CC1 */ + + egr = ATIM_EGR_CC1G; + + /* Set the duty cycle by writing to the CCR register for this + * channel + */ + + tim_putreg(priv, STM32L4_GTIM_CCR1_OFFSET, (uint16_t)(reload >> 1)); + } + break; + + case 1: /* TimerX CC2 event */ + { + ccenable = ATIM_CCER_CC2E; + ocmode1 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC2S_SHIFT) | + (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR1_OC2M_SHIFT) | + ATIM_CCMR1_OC2PE; + + /* Set the event CC2 */ + + egr = ATIM_EGR_CC2G; + + /* Set the duty cycle by writing to the CCR register for this + * channel + */ + + tim_putreg(priv, STM32L4_GTIM_CCR2_OFFSET, (uint16_t)(reload >> 1)); + } + break; + + case 2: /* TimerX CC3 event */ + { + ccenable = ATIM_CCER_CC3E; + ocmode2 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR2_CC3S_SHIFT) | + (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR2_OC3M_SHIFT) | + ATIM_CCMR2_OC3PE; + + /* Set the event CC3 */ + + egr = ATIM_EGR_CC3G; + + /* Set the duty cycle by writing to the CCR register for this + * channel + */ + + tim_putreg(priv, STM32L4_GTIM_CCR3_OFFSET, (uint16_t)(reload >> 1)); + } + break; + + case 3: /* TimerX CC4 event */ + { + ccenable = ATIM_CCER_CC4E; + ocmode2 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR2_CC4S_SHIFT) | + (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR2_OC4M_SHIFT) | + ATIM_CCMR2_OC4PE; + + /* Set the event CC4 */ + + egr = ATIM_EGR_CC4G; + + /* Set the duty cycle by writing to the CCR register for this + * channel + */ + + tim_putreg(priv, STM32L4_GTIM_CCR4_OFFSET, (uint16_t)(reload >> 1)); + } + break; + + case 4: /* TimerX TRGO event */ + { + /* TODO: TRGO support not yet implemented */ + /* Set the event TRGO */ + + ccenable = 0; + egr = GTIM_EGR_TG; + + /* Set the duty cycle by writing to the CCR register for this + * channel + */ + + tim_putreg(priv, STM32L4_GTIM_CCR4_OFFSET, (uint16_t)(reload >> 1)); + } + break; + + default: + aerr("ERROR: No such trigger: %d\n", priv->trigger); + return -EINVAL; + } + + /* Disable the Channel by resetting the CCxE Bit in the CCER register */ + ccer = tim_getreg(priv, STM32L4_GTIM_CCER_OFFSET); + ccer &= ~ccenable; + tim_putreg(priv, STM32L4_GTIM_CCER_OFFSET, ccer); + + /* Fetch the CR2, CCMR1, and CCMR2 register (already have ccer) */ + + cr2 = tim_getreg(priv, STM32L4_GTIM_CR2_OFFSET); + ccmr1 = tim_getreg(priv, STM32L4_GTIM_CCMR1_OFFSET); + ccmr2 = tim_getreg(priv, STM32L4_GTIM_CCMR2_OFFSET); + + /* Reset the Output Compare Mode Bits and set the select output compare + * mode + */ + + ccmr1 &= ~(ATIM_CCMR1_CC1S_MASK | ATIM_CCMR1_OC1M_MASK | ATIM_CCMR1_OC1PE | + ATIM_CCMR1_CC2S_MASK | ATIM_CCMR1_OC2M_MASK | ATIM_CCMR1_OC2PE); + ccmr2 &= ~(ATIM_CCMR2_CC3S_MASK | ATIM_CCMR2_OC3M_MASK | ATIM_CCMR2_OC3PE | + ATIM_CCMR2_CC4S_MASK | ATIM_CCMR2_OC4M_MASK | ATIM_CCMR2_OC4PE); + ccmr1 |= ocmode1; + ccmr2 |= ocmode2; + + /* Reset the output polarity level of all channels (selects high + * polarity) + */ + ccer &= ~(ATIM_CCER_CC1P | ATIM_CCER_CC2P | + ATIM_CCER_CC3P | ATIM_CCER_CC4P); + + /* Enable the output state of the selected channel (only) */ + + ccer &= ~(ATIM_CCER_CC1E | ATIM_CCER_CC2E | + ATIM_CCER_CC3E | ATIM_CCER_CC4E); + ccer |= ccenable; + + if (priv->tbase == STM32L4_TIM1_BASE || priv->tbase == STM32L4_TIM8_BASE) + { + /* Reset output N polarity level, output N state, output compare state, + * output compare N idle state. + */ + + ccer &= ~(ATIM_CCER_CC1NE | ATIM_CCER_CC1NP | + ATIM_CCER_CC2NE | ATIM_CCER_CC2NP | + ATIM_CCER_CC3NE | ATIM_CCER_CC3NP | + ATIM_CCER_CC4NP); + + /* Reset the output compare and output compare N IDLE State */ + cr2 &= ~(ATIM_CR2_OIS1 | ATIM_CR2_OIS1N | + ATIM_CR2_OIS2 | ATIM_CR2_OIS2N | + ATIM_CR2_OIS3 | ATIM_CR2_OIS3N | + ATIM_CR2_OIS4); + } + else + { + ccer &= ~(GTIM_CCER_CC1NP | GTIM_CCER_CC2NP | GTIM_CCER_CC3NP); + } + + /* Save the modified register values */ + + tim_putreg(priv, STM32L4_GTIM_CR2_OFFSET, cr2); + tim_putreg(priv, STM32L4_GTIM_CCMR1_OFFSET, ccmr1); + tim_putreg(priv, STM32L4_GTIM_CCMR2_OFFSET, ccmr2); + tim_putreg(priv, STM32L4_GTIM_CCER_OFFSET, ccer); + tim_putreg(priv, STM32L4_GTIM_EGR_OFFSET, egr); + + /* Set the ARR Preload Bit */ + + tim_modifyreg(priv, STM32L4_GTIM_CR1_OFFSET, 0, GTIM_CR1_ARPE); + + /* Enable the timer counter */ + + dfsdm_timstart(priv, true); + + tim_dumpregs(priv, "After starting timers"); + + return OK; +} +#endif + +/**************************************************************************** + * Name: dfsdm_wdog_enable + * + * Description: + * Enable the analog watchdog. This is for filter watchdog only, channel + * watchdogs are not supported by current implementation. + * + ****************************************************************************/ + +static void dfsdm_wdog_enable(struct stm32_dev_s *priv) +{ + uint32_t regval; + + /* Initialize the Analog watchdog for current channel + * and switch to analog watchdog interrupt + */ + + regval = dfsdm_getreg(priv, FLTCR2_OFFSET(priv)); + regval |= DFSDM_FLTCR2_AWDCH(priv->current); + regval |= DFSDM_INT_AWD; + regval &= ~(DFSDM_INT_REOC | DFSDM_INT_JEOC); + dfsdm_putreg(priv, FLTCR2_OFFSET(priv), regval); +} + +/**************************************************************************** + * Name: dfsdm_startconv + * + * Description: + * Start (or stop) the ADC conversion process + * + * Input Parameters: + * priv - A reference to the DFSDM block status + * enable - True: Start conversion + * + ****************************************************************************/ + +static void dfsdm_startconv(FAR struct stm32_dev_s *priv, bool enable) +{ + uint32_t regval; + + ainfo("enable: %d\n", enable ? 1 : 0); + + regval = dfsdm_getreg(priv, FLTCR1_OFFSET(priv)); + if (enable) + { + /* Enable the filter */ + + regval |= DFSDM_FLTCR1_DFEN; + } + else + { + /* Disable the filter */ + + regval &= ~DFSDM_FLTCR1_DFEN; + } + dfsdm_putreg(priv, FLTCR1_OFFSET(priv), regval); + + if (enable) + { + /* Start conversion of regular channels */ + + regval |= DFSDM_FLTCR1_RSWSTART; + dfsdm_putreg(priv, FLTCR1_OFFSET(priv), regval); + } +} + +/**************************************************************************** + * Name: dfsdm_rccreset + * + * Description: + * Deinitializes the DFSDM peripheral registers to their default + * reset values. + * + * Input Parameters: + * priv - A reference to the DFSDM block status + * reset - Condition, set or reset + * + ****************************************************************************/ + +static void dfsdm_rccreset(FAR struct stm32_dev_s *priv, bool reset) +{ + irqstate_t flags; + uint32_t regval; + + /* First must disable interrupts because the APB2RSTR register is used by + * several different drivers. + */ + + flags = enter_critical_section(); + + /* Set or clear the selected bit in the APB2 reset register */ + + regval = getreg32(STM32L4_RCC_APB2RSTR); + if (reset) + { + regval |= RCC_APB2RSTR_DFSDMRST; + } + else + { + regval &= ~RCC_APB2RSTR_DFSDMRST; + } + putreg32(regval, STM32L4_RCC_APB2RSTR); + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: dfsdm_enable + * + * Description : Enables the DFSDM peripheral. + * + * Input Parameters: + * priv - A reference to the DFSDM block status + * + ****************************************************************************/ + +static void dfsdm_enable(FAR struct stm32_dev_s *priv) +{ + uint32_t regval; + + regval = dfsdm_getreg(priv, STM32L4_DFSDM_CH0CFGR1_OFFSET); + + /* Enable DFSMDM */ + + regval |= DFSDM_CH0CFGR1_DFSDMEN; + dfsdm_putreg(priv, STM32L4_DFSDM_CH0CFGR1_OFFSET, regval); +} + +/**************************************************************************** + * Name: dfsdm_bind + * + * Description: + * Bind the upper-half driver callbacks to the lower-half implementation. This + * must be called early in order to receive ADC event notifications. + * + ****************************************************************************/ + +static int dfsdm_bind(FAR struct adc_dev_s *dev, + FAR const struct adc_callback_s *callback) +{ + FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv; + + DEBUGASSERT(priv != NULL); + priv->cb = callback; + return OK; +} + +/**************************************************************************** + * Name: dfsdm_reset + * + * Description: + * Reset the DFSDM device. Called early to initialize the hardware. This + * is called, before dfsdm_setup() and on error conditions. + * + * Input Parameters: + * + ****************************************************************************/ + +static void dfsdm_reset(FAR struct adc_dev_s *dev) +{ + FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv; + + /* Enable DFSDM reset state */ + + dfsdm_rccreset(priv, true); + + /* Release DFSDM from reset state */ + + dfsdm_rccreset(priv, false); +} + +/**************************************************************************** + * Name: dfsdm_setup + * + * Description: + * Configure the DFSDM. This method is called the first time that the ADC + * device is opened. This will occur when the port is first opened. + * This setup includes configuring and attaching ADC interrupts. + * Interrupts are all disabled upon return. + * + ****************************************************************************/ + +static int dfsdm_setup(FAR struct adc_dev_s *dev) +{ + FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv; + int ret; + irqstate_t flags; + uint32_t clrbits; + uint32_t setbits; + + /* Attach the interrupt */ + + ret = irq_attach(priv->irq, priv->isr, NULL); + if (ret < 0) + { + ainfo("irq_attach failed: %d\n", ret); + return ret; + } + + flags = enter_critical_section(); + + /* Make sure that the device is in the powered up, reset state. */ + + dfsdm_reset(dev); + + /* Initialize the filter settings. */ + + clrbits = 0; + setbits = DFSDM_FLTFCR_FORD_SINC1 | \ + DFSDM_FLTFCR_FOSR(0) | \ + DFSDM_FLTFCR_IOSR(0); + + dfsdm_modifyreg(priv, FLTFCR_OFFSET(priv), clrbits, setbits); + + setbits = 0; + +#ifdef DFSDM_HAVE_DMA + if (priv->hasdma) + { + /* Enable DMA */ + + setbits |= DFSDM_FLTCR1_RDMAEN; + } +#endif + + /* Disable continuous mode and synchronized mode */ + + clrbits = DFSDM_FLTCR1_RCONT | DFSDM_FLTCR1_RSYNC; + + /* Set CR1 configuration */ + + dfsdm_modifyreg(priv, FLTCR1_OFFSET(priv), clrbits, setbits); + + /* Configuration of the channel conversions */ + + dfsdm_set_ch(dev, 0); + +#ifdef DFSDM_HAVE_DMA + + /* Enable DMA */ + + if (priv->hasdma) + { + /* Stop and free DMA if it was started before */ + + if (priv->dma != NULL) + { + stm32l4_dmastop(priv->dma); + stm32l4_dmafree(priv->dma); + } + + priv->dma = stm32l4_dmachannel(priv->dmachan); + + stm32l4_dmasetup(priv->dma, + priv->base + FLTRDATAR_OFFSET(priv), + (uint32_t)priv->dmabuffer, + priv->nchannels, + DFSDM_DMA_CONTROL_WORD); + + stm32l4_dmastart(priv->dma, dfsdm_dmaconvcallback, dev, false); + } +#endif + + dfsdm_enable(priv); + +#ifdef DFSDM_HAVE_TIMER + + /* TODO: timers would require injected conversions, which are + * not implemented at the moment. + */ +# warning "DFSDM Timer not fully implemented!" + + if (priv->tbase != 0) + { + ret = dfsdm_timinit(priv); + if (ret < 0) + { + aerr("ERROR: dfsdm_timinit failed: %d\n", ret); + } + } +#endif + + leave_critical_section(flags); + + ainfo("ISR: 0x%08x FCR: 0x%08x CR1: 0x%08x CR2: 0x%08x\n", + dfsdm_getreg(priv, FLTISR_OFFSET(priv)), + dfsdm_getreg(priv, FLTFCR_OFFSET(priv)), + dfsdm_getreg(priv, FLTCR1_OFFSET(priv)), + dfsdm_getreg(priv, FLTCR2_OFFSET(priv))); + + /* Enable the DFSDM FLT interrupt */ + + ainfo("Enable the FLT interrupt: irq=%d\n", priv->irq); + up_enable_irq(priv->irq); + + return ret; +} + +/**************************************************************************** + * Name: dfsdm_shutdown + * + * Description: + * Disable the DFSDM. This method is called when the ADC device is closed. + * This method reverses the operation the setup method. + * + ****************************************************************************/ + +static void dfsdm_shutdown(FAR struct adc_dev_s *dev) +{ + FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv; + + /* Disable interrupts and detach the FLT interrupt handler */ + + up_disable_irq(priv->irq); + irq_detach(priv->irq); + + /* Disable and reset the DFSDM module */ + + dfsdm_reset(dev); +} + +/**************************************************************************** + * Name: dfsdm_rxint + * + * Description: + * Call to enable or disable RX interrupts. + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + +static void dfsdm_rxint(FAR struct adc_dev_s *dev, bool enable) +{ + FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv; + uint32_t regval; + + ainfo("intf: %d enable: %d\n", priv->intf, enable ? 1 : 0); + + regval = dfsdm_getreg(priv, FLTCR2_OFFSET(priv)); + if (enable) + { + /* Enable end of conversion interrupt */ + + regval |= DFSDM_INT_REOC; + } + else + { + /* Disable all interrupts */ + + regval &= ~DFSDM_INT_MASK; + } + dfsdm_putreg(priv, FLTCR2_OFFSET(priv), regval); +} + +/**************************************************************************** + * Name: dfsdm_set_ch + * + * Description: + * Sets the DFSDM channel. + * + * Input Parameters: + * dev - pointer to device structure used by the driver + * ch - ADC channel number + 1. 0 reserved for all configured channels + * + * Returned Value: + * int - errno + * + ****************************************************************************/ + +static int dfsdm_set_ch(FAR struct adc_dev_s *dev, uint8_t ch) +{ + FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv; + uint32_t regval; + int i; + + if (ch == 0) + { + priv->current = 0; + priv->nchannels = priv->cchannels; + } + else + { + for (i = 0; i < priv->cchannels && priv->chanlist[i] != ch - 1; i++); + + if (i >= priv->cchannels) + { + return -ENODEV; + } + + priv->current = i; + priv->nchannels = 1; + } + + DEBUGASSERT(priv->nchannels <= DFSDM_MAX_CHANNELS); + + /* Select channel for filter. + * TODO: regular conversion supports one channel only. + */ + + /* Set channel in CR1 configuration */ + + regval = dfsdm_getreg(priv, FLTCR1_OFFSET(priv)); + 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); +#endif + + /* Enable the channel */ + + regval |= DFSDM_CHCFGR1_CHEN; + dfsdm_putreg(priv, CHCFGR1_OFFSET(priv), regval); + + return OK; +} + +/**************************************************************************** + * Name: dfsdm_ioctl + * + * Description: + * All ioctl calls will be routed through this method. + * + * Input Parameters: + * dev - pointer to device structure used by the driver + * cmd - command + * arg - arguments passed with command + * + * Returned Value: + * + ****************************************************************************/ + +static int dfsdm_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg) +{ + FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv; + uint32_t regval; + uint32_t tmp; + int ret = OK; + + switch (cmd) + { + case ANIOC_TRIGGER: + dfsdm_startconv(priv, true); + break; + + case ANIOC_WDOG_UPPER: /* Set watchdog upper threshold */ + { + regval = dfsdm_getreg(priv, FLTAWLTR_OFFSET(priv)); + + /* Verify new upper threshold greater than lower threshold */ + + tmp = (regval & DFSDM_AWLTR_AWLT_MASK) >> DFSDM_AWLTR_AWLT_SHIFT; + if (arg < tmp) + { + ret = -EINVAL; + break; + } + + /* Set the watchdog threshold register */ + + regval = ((arg << DFSDM_AWHTR_AWHT_SHIFT) & DFSDM_AWHTR_AWHT_MASK); + + dfsdm_putreg(priv, FLTAWHTR_OFFSET(priv), regval); + + /* Ensure analog watchdog is enabled */ + + dfsdm_wdog_enable(priv); + } + break; + + case ANIOC_WDOG_LOWER: /* Set watchdog lower threshold */ + { + regval = dfsdm_getreg(priv, FLTAWHTR_OFFSET(priv)); + + /* Verify new lower threshold less than upper threshold */ + + tmp = (regval & DFSDM_AWHTR_AWHT_MASK) >> DFSDM_AWHTR_AWHT_SHIFT; + if (arg > tmp) + { + ret = -EINVAL; + break; + } + + /* Set the watchdog threshold register */ + + regval = ((arg << DFSDM_AWLTR_AWLT_SHIFT) & DFSDM_AWLTR_AWLT_MASK); + dfsdm_putreg(priv, FLTAWLTR_OFFSET(priv), regval); + + /* Ensure analog watchdog is enabled */ + + dfsdm_wdog_enable(priv); + } + break; + + default: + aerr("ERROR: Unknown cmd: %d\n", cmd); + ret = -ENOTTY; + break; + } + + return ret; +} + +/**************************************************************************** + * Name: dfsdm_interrupt + * + * Description: + * Common DFSDM interrupt handler. + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + +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; + + /* Identifies the interruption AWD or OVR */ + + if ((isr & DFSDM_INT_AWD) != 0) + { + value = dfsdm_getreg(priv, FLTAWSR_OFFSET(priv)); + + awarn("WARNING: Analog Watchdog, extreme value on channels (0x%x)!\n", value); + + /* Clear AWD flags */ + + dfsdm_putreg(priv, FLTAWCFR_OFFSET(priv), value); + + /* Stop ADC conversions to avoid continuous interrupts */ + + dfsdm_startconv(priv, false); + } + + if ((isr & DFSDM_INT_ROVR) != 0) + { + awarn("WARNING: Regular conversion overrun has occurred!\n"); + + /* Clear overrun flag */ + + dfsdm_putreg(priv, FLTAWCFR_OFFSET(priv), DFSDM_INT_ROVR); + } + + if ((isr & DFSDM_INT_JOVR) != 0) + { + awarn("WARNING: Injected conversion overrun has occurred!\n"); + + /* Clear overrun flag */ + + dfsdm_putreg(priv, FLTAWCFR_OFFSET(priv), DFSDM_INT_JOVR); + } + + /* EOC: End of conversion */ + + if ((isr & DFSDM_INT_REOC) != 0) + { + /* Read the converted value and clear EOC bit + * (It is cleared by reading the FLTRDATAR) + */ + + value = dfsdm_getreg(priv, FLTRDATAR_OFFSET(priv)); + value = (value & DFSDM_FLTRDATAR_RDATA_MASK) >> DFSDM_FLTRDATAR_RDATA_SHIFT; + + /* Verify that the upper-half driver has bound its callback functions */ + + if (priv->cb != NULL) + { + /* Give the ADC data to the ADC driver. The ADC receive() method + * accepts 3 parameters: + * + * 1) The first is the ADC device instance for this ADC block. + * 2) The second is the channel number for the data, and + * 3) The third is the converted data for the channel. + */ + + DEBUGASSERT(priv->cb->au_receive != NULL); + priv->cb->au_receive(dev, priv->chanlist[priv->current], value); + } + + /* Set the channel number of the next channel that will complete conversion */ + + priv->current++; + + if (priv->current >= priv->nchannels) + { + /* Restart the conversion sequence from the beginning */ + + priv->current = 0; + } + } + + return OK; +} + +/**************************************************************************** + * Name: dfsdm_flt0_interrupt + * + * Description: + * DFSDM filter interrupt handler + * + ****************************************************************************/ + +#if defined(CONFIG_STM32L4_DFSDM1_FLT0) +static int dfsdm_flt0_interrupt(int irq, FAR void *context, FAR void *arg) +{ + uint32_t regval; + uint32_t pending; + + regval = getreg32(STM32L4_DFSDM_FLTISR(0)); + pending = regval & DFSDM_ISR_MASK; + if (pending != 0) + { + dfsdm_interrupt(&g_dfsdmdev0, regval); + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: dfsdm_flt1_interrupt + * + * Description: + * DFSDM filter interrupt handler + * + ****************************************************************************/ +#if defined(CONFIG_STM32L4_DFSDM1_FLT1) +static int dfsdm_flt1_interrupt(int irq, FAR void *context, FAR void *arg) +{ + uint32_t regval; + uint32_t pending; + + regval = getreg32(STM32L4_DFSDM_FLTISR(1)); + pending = regval & DFSDM_ISR_MASK; + if (pending != 0) + { + dfsdm_interrupt(&g_dfsdmdev1, regval); + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: dfsdm_flt2_interrupt + * + * Description: + * DFSDM filter interrupt handler + * + ****************************************************************************/ +#if defined(CONFIG_STM32L4_DFSDM1_FLT2) +static int dfsdm_flt2_interrupt(int irq, FAR void *context, FAR void *arg) +{ + uint32_t regval; + uint32_t pending; + + regval = getreg32(STM32L4_DFSDM_FLTISR(2)); + pending = regval & DFSDM_ISR_MASK; + if (pending != 0) + { + dfsdm_interrupt(&g_dfsdmdev2, regval); + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: dfsdm_flt3_interrupt + * + * Description: + * DFSDM filter interrupt handler + * + ****************************************************************************/ +#if defined(CONFIG_STM32L4_DFSDM1_FLT3) +static int dfsdm_flt3_interrupt(int irq, FAR void *context, FAR void *arg) +{ + uint32_t regval; + uint32_t pending; + + regval = getreg32(STM32L4_DFSDM_FLTISR(3)); + pending = regval & DFSDM_ISR_MASK; + if (pending != 0) + { + dfsdm_interrupt(&g_dfsdmdev3, regval); + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: dfsdm_dmaconvcallback + * + * Description: + * Callback for DMA. Called from the DMA transfer complete interrupt after + * all channels have been converted and transferred with DMA. + * + * Input Parameters: + * + * handle - handle to DMA + * isr - + * arg - device + * + * Returned Value: + * + ****************************************************************************/ + +#ifdef DFSDM_HAVE_DMA +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; + int i; + + /* Verify that the upper-half driver has bound its callback functions */ + + if (priv->cb != NULL) + { + DEBUGASSERT(priv->cb->au_receive != NULL); + + for (i = 0; i < priv->nchannels; i++) + { + priv->cb->au_receive(dev, priv->chanlist[priv->current], priv->dmabuffer[priv->current]); + priv->current++; + if (priv->current >= priv->nchannels) + { + /* Restart the conversion sequence from the beginning */ + + priv->current = 0; + } + } + } + + /* Restart DMA for the next conversion series */ + + dfsdm_modifyreg(priv, FLTCR1_OFFSET(priv), DFSDM_FLTCR1_RDMAEN, 0); + dfsdm_modifyreg(priv, FLTCR1_OFFSET(priv), 0, DFSDM_FLTCR1_RDMAEN); +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32l4_dfsdm_initialize + * + * Description: + * Initialize the DFSDM. + * + * Input Parameters: + * intf - Could be {0,1,2,3} for DFSDM1 FLT0, FLT1, FLT2, FLT3 + * chanlist - The list of channels + * cchannels - Number of channels + * + * Returned Value: + * Valid ADC device structure reference on success; a NULL on failure + * + ****************************************************************************/ + +struct adc_dev_s *stm32l4_dfsdm_initialize(int intf, FAR const uint8_t *chanlist, + int cchannels) +{ + FAR struct adc_dev_s *dev; + FAR struct stm32_dev_s *priv; + + ainfo("intf: %d cchannels: %d\n", intf, cchannels); + + switch (intf) + { +#if defined(CONFIG_STM32L4_DFSDM1_FLT0) + case 0: + ainfo("DFSDM FLT0 selected\n"); + dev = &g_dfsdmdev0; + break; +#endif +#if defined(CONFIG_STM32L4_DFSDM1_FLT1) + case 1: + ainfo("DFSDM FLT1 selected\n"); + dev = &g_dfsdmdev1; + break; +#endif +#if defined(CONFIG_STM32L4_DFSDM1_FLT2) + case 2: + ainfo("DFSDM FLT2 selected\n"); + dev = &g_dfsdmdev2; + break; +#endif +#if defined(CONFIG_STM32L4_DFSDM1_FLT3) + case 3: + ainfo("DFSDM FLT3 selected\n"); + dev = &g_dfsdmdev3; + break; +#endif + default: + aerr("ERROR: No DFSDM interface defined\n"); + return NULL; + } + + /* Configure the selected DFSDM */ + + priv = (FAR struct stm32_dev_s *)dev->ad_priv; + priv->cb = NULL; + + DEBUGASSERT(cchannels <= DFSDM_MAX_CHANNELS); + + /* TODO: regular conversion supports one channel only. */ + +#if 0 + if (cchannels > DFSDM_MAX_CHANNELS) + { + cchannels = DFSDM_MAX_CHANNELS; + } +#else + if (cchannels > 1) + { + cchannels = 1; +# warning "Only one channel supported at the moment!" + } +#endif + + priv->cchannels = cchannels; + memcpy(priv->chanlist, chanlist, cchannels); + + return dev; +} + +#endif /* CONFIG_STM32L4_DFSDM */ +#endif /* CONFIG_ADC */ diff --git a/arch/arm/src/stm32l4/stm32l4_dfsdm.h b/arch/arm/src/stm32l4/stm32l4_dfsdm.h new file mode 100644 index 00000000000..fec5393d4a0 --- /dev/null +++ b/arch/arm/src/stm32l4/stm32l4_dfsdm.h @@ -0,0 +1,337 @@ +/************************************************************************************ + * arch/arm/src/stm32L4/stm32l4_dfsdm.h + * + * 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. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32L4_STM32L4_DFSDM_H +#define __ARCH_ARM_SRC_STM32L4_STM32L4_DFSDM_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include +#include "chip.h" +#include "chip/stm32l4_dfsdm.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ +/* Configuration ********************************************************************/ + +/* Timer devices may be used for different purposes. One special purpose is to + * control periodic ADC sampling. If CONFIG_STM32L4_TIMn is defined then + * CONFIG_STM32L4_TIMn_DFSDM must also be defined to indicate that timer "n" is + * intended to be used for that purpose. Timers 1,3,6 and 16 may be used on + * STM32L4X3, while STM32L4X6 adds support for timers 4,7 and 8 as well. + */ + +#ifndef CONFIG_STM32L4_TIM1 +# undef CONFIG_STM32L4_TIM1_DFSDM +#endif +#ifndef CONFIG_STM32L4_TIM3 +# undef CONFIG_STM32L4_TIM3_DFSDM +#endif +#ifndef CONFIG_STM32L4_TIM4 +# undef CONFIG_STM32L4_TIM4_DFSDM +#endif +#ifndef CONFIG_STM32L4_TIM6 +# undef CONFIG_STM32L4_TIM6_DFSDM +#endif +#ifndef CONFIG_STM32L4_TIM7 +# undef CONFIG_STM32L4_TIM7_DFSDM +#endif +#ifndef CONFIG_STM32L4_TIM8 +# undef CONFIG_STM32L4_TIM8_DFSDM +#endif +#ifndef CONFIG_STM32L4_TIM16 +# undef CONFIG_STM32L4_TIM16_DFSDM +#endif + +#if defined(CONFIG_STM32L4_DFSDM) + +/* DMA support */ + +#undef DFSDM_HAVE_DMA +#if defined(CONFIG_STM32L4_DFSDM1_DMA) +# define DFSDM_HAVE_DMA 1 +#endif + +/* Timer configuration: If a timer trigger is specified, then get + * information about the timer. + */ + +#if defined(CONFIG_STM32L4_TIM1_DFSDM) +# define DFSDM_HAVE_TIMER 1 +# define DFSDM_TIMER_BASE STM32L4_TIM1_BASE +# define DFSDM_TIMER_PCLK_FREQUENCY STM32L4_APB2_TIM1_CLKIN +#elif defined(CONFIG_STM32L4_TIM3_DFSDM) +# define DFSDM_HAVE_TIMER 1 +# define DFSDM_TIMER_BASE STM32L4_TIM3_BASE +# define DFSDM_TIMER_PCLK_FREQUENCY STM32L4_APB1_TIM3_CLKIN +#elif defined(CONFIG_STM32L4_TIM4_DFSDM) +# define DFSDM_HAVE_TIMER 1 +# define DFSDM_TIMER_BASE STM32L4_TIM4_BASE +# define DFSDM_TIMER_PCLK_FREQUENCY STM32L4_APB1_TIM4_CLKIN +#elif defined(CONFIG_STM32L4_TIM6_DFSDM) +# define DFSDM_HAVE_TIMER 1 +# define DFSDM_TIMER_BASE STM32L4_TIM6_BASE +# define DFSDM_TIMER_PCLK_FREQUENCY STM32L4_APB1_TIM6_CLKIN +#elif defined(CONFIG_STM32L4_TIM7_DFSDM) +# define DFSDM_HAVE_TIMER 1 +# define DFSDM_TIMER_BASE STM32L4_TIM7_BASE +# define DFSDM_TIMER_PCLK_FREQUENCY STM32L4_APB1_TIM7_CLKIN +#elif defined(CONFIG_STM32L4_TIM8_DFSDM) +# define DFSDM_HAVE_TIMER 1 +# define DFSDM_TIMER_BASE STM32L4_TIM8_BASE +# define DFSDM_TIMER_PCLK_FREQUENCY STM32L4_APB2_TIM8_CLKIN +#elif defined(CONFIG_STM32L4_TIM16_DFSDM) +# define DFSDM_HAVE_TIMER 1 +# define DFSDM_TIMER_BASE STM32L4_TIM16_BASE +# define DFSDM_TIMER_PCLK_FREQUENCY STM32L4_APB2_TIM16_CLKIN +#else +# undef DFSDM_HAVE_TIMER +#endif + +#ifdef DFSDM_HAVE_TIMER +# ifndef CONFIG_STM32L4_DFSDM_SAMPLE_FREQUENCY +# error "CONFIG_STM32L4_DFSDM_SAMPLE_FREQUENCY not defined" +# endif +# ifndef CONFIG_STM32L4_DFSDM_TIMTRIG +# error "CONFIG_STM32L4_DFSDM_TIMTRIG not defined" +# warning "Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO 5:TRGO2" +# endif +#endif + +/* NOTE: The following assumes that all possible combinations of timers and + * values are support JEXTSEL. That is not so and it varies from one STM32 + * to another. But this (wrong) assumptions keeps the logic as simple as + * possible. If unsupported combination is used, an error will show up + * later during compilation although it may be difficult to track it back + * to this simplification. + */ + +#define DFSDM_JEXTSEL_T1CC1 DFSDM_FLTCR1_JEXTSEL_T1CC1 +#define DFSDM_JEXTSEL_T1CC2 DFSDM_FLTCR1_JEXTSEL_T1CC2 +#define DFSDM_JEXTSEL_T1CC3 DFSDM_FLTCR1_JEXTSEL_T1CC3 +#define DFSDM_JEXTSEL_T1CC4 DFSDM_FLTCR1_JEXTSEL_T1CC4 +#define DFSDM_JEXTSEL_T1TRGO DFSDM_FLTCR1_JEXTSEL_T1TRGO +#define DFSDM_JEXTSEL_T1TRGO2 DFSDM_FLTCR1_JEXTSEL_T1TRGO2 + +#define DFSDM_JEXTSEL_T3CC1 DFSDM_FLTCR1_JEXTSEL_T3CC1 +#define DFSDM_JEXTSEL_T3CC2 DFSDM_FLTCR1_JEXTSEL_T3CC2 +#define DFSDM_JEXTSEL_T3CC3 DFSDM_FLTCR1_JEXTSEL_T3CC3 +#define DFSDM_JEXTSEL_T3CC4 DFSDM_FLTCR1_JEXTSEL_T3CC4 +#define DFSDM_JEXTSEL_T3TRGO DFSDM_FLTCR1_JEXTSEL_T3TRGO + +#define DFSDM_JEXTSEL_T4CC1 DFSDM_FLTCR1_JEXTSEL_T4CC1 +#define DFSDM_JEXTSEL_T4CC2 DFSDM_FLTCR1_JEXTSEL_T4CC2 +#define DFSDM_JEXTSEL_T4CC3 DFSDM_FLTCR1_JEXTSEL_T4CC3 +#define DFSDM_JEXTSEL_T4CC4 DFSDM_FLTCR1_JEXTSEL_T4CC4 +#define DFSDM_JEXTSEL_T4TRGO DFSDM_FLTCR1_JEXTSEL_T4TRGO + +#define DFSDM_JEXTSEL_T6CC1 DFSDM_FLTCR1_JEXTSEL_T6CC1 +#define DFSDM_JEXTSEL_T6CC2 DFSDM_FLTCR1_JEXTSEL_T6CC2 +#define DFSDM_JEXTSEL_T6CC3 DFSDM_FLTCR1_JEXTSEL_T6CC3 +#define DFSDM_JEXTSEL_T6CC4 DFSDM_FLTCR1_JEXTSEL_T6CC4 +#define DFSDM_JEXTSEL_T6TRGO DFSDM_FLTCR1_JEXTSEL_T6TRGO + +#define DFSDM_JEXTSEL_T7CC1 DFSDM_FLTCR1_JEXTSEL_T7CC1 +#define DFSDM_JEXTSEL_T7CC2 DFSDM_FLTCR1_JEXTSEL_T7CC2 +#define DFSDM_JEXTSEL_T7CC3 DFSDM_FLTCR1_JEXTSEL_T7CC3 +#define DFSDM_JEXTSEL_T7CC4 DFSDM_FLTCR1_JEXTSEL_T7CC4 +#define DFSDM_JEXTSEL_T7TRGO DFSDM_FLTCR1_JEXTSEL_T7TRGO + +#define DFSDM_JEXTSEL_T8CC1 DFSDM_FLTCR1_JEXTSEL_T8CC1 +#define DFSDM_JEXTSEL_T8CC2 DFSDM_FLTCR1_JEXTSEL_T8CC2 +#define DFSDM_JEXTSEL_T8CC3 DFSDM_FLTCR1_JEXTSEL_T8CC3 +#define DFSDM_JEXTSEL_T8CC4 DFSDM_FLTCR1_JEXTSEL_T8CC4 +#define DFSDM_JEXTSEL_T8TRGO DFSDM_FLTCR1_JEXTSEL_T8TRGO +#define DFSDM_JEXTSEL_T8TRGO2 DFSDM_FLTCR1_JEXTSEL_T8TRGO2 + +#define DFSDM_JEXTSEL_T16CC1 DFSDM_FLTCR1_JEXTSEL_T16CC1 +#define DFSDM_JEXTSEL_T16CC2 DFSDM_FLTCR1_JEXTSEL_T16CC2 +#define DFSDM_JEXTSEL_T16CC3 DFSDM_FLTCR1_JEXTSEL_T16CC3 +#define DFSDM_JEXTSEL_T16CC4 DFSDM_FLTCR1_JEXTSEL_T16CC4 +#define DFSDM_JEXTSEL_T16TRGO DFSDM_FLTCR1_JEXTSEL_T16TRGO + +#if defined(CONFIG_STM32L4_TIM1_DFSDM) +# if CONFIG_STM32L4_DFSDM_TIMTRIG == 0 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T1CC1 +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 1 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T1CC2 +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 2 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T1CC3 +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 3 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T1CC4 +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 4 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T1TRGO +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 5 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T1TRGO2 +# else +# error "CONFIG_STM32L4_DFSDM_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32L4_TIM3_DFSDM) +# if CONFIG_STM32L4_DFSDM_TIMTRIG == 0 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T3CC1 +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 1 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T3CC2 +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 2 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T3CC3 +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 3 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T3CC4 +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 4 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T3TRGO +# else +# error "CONFIG_STM32L4_DFSDM_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32L4_TIM4_DFSDM) +# if CONFIG_STM32L4_DFSDM_TIMTRIG == 0 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T4CC1 +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 1 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T4CC2 +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 2 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T4CC3 +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 3 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T4CC4 +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 4 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T4TRGO +# else +# error "CONFIG_STM32L4_DFSDM_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32L4_TIM6_DFSDM) +# if CONFIG_STM32L4_DFSDM_TIMTRIG == 0 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T6CC1 +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 1 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T6CC2 +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 2 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T6CC3 +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 3 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T6CC4 +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 4 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T6TRGO +# else +# error "CONFIG_STM32L4_DFSDM_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32L4_TIM7_DFSDM) +# if CONFIG_STM32L4_DFSDM_TIMTRIG == 0 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T7CC1 +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 1 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T7CC2 +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 2 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T7CC3 +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 3 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T7CC4 +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 4 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T7TRGO +# else +# error "CONFIG_STM32L4_DFSDM_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32L4_TIM8_DFSDM) +# if CONFIG_STM32L4_DFSDM_TIMTRIG == 0 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T8CC1 +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 1 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T8CC2 +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 2 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T8CC3 +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 3 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T8CC4 +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 4 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T8TRGO +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 5 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T8TRGO2 +# else +# error "CONFIG_STM32L4_DFSDM_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32L4_TIM16_DFSDM) +# if CONFIG_STM32L4_DFSDM_TIMTRIG == 0 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T16CC1 +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 1 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T16CC2 +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 2 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T16CC3 +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 3 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T16CC4 +# elif CONFIG_STM32L4_DFSDM_TIMTRIG == 4 +# define DFSDM_JEXTSEL_VALUE DFSDM_JEXTSEL_T16TRGO +# else +# error "CONFIG_STM32L4_DFSDM_TIMTRIG is out of range" +# endif +#endif + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +/************************************************************************************ + * Public Function Prototypes + ************************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: stm32l4_dfsdm_initialize + * + * Description: + * Initialize the DFSDM. + * + * Input Parameters: + * intf - Could be {0,1,2,3} for DFSDM FLT0, FLT1, FLT2, FLT3 + * chanlist - The list of channels + * nchannels - Number of channels + * + * Returned Value: + * Valid ADC device structure reference on success; a NULL on failure + * + ****************************************************************************/ + +struct adc_dev_s; +struct adc_dev_s *stm32l4_dfsdm_initialize(int intf, + FAR const uint8_t *chanlist, + int nchannels); +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif /* __ASSEMBLY__ */ + +#endif /* CONFIG_STM32L4_DFSDM */ +#endif /* __ARCH_ARM_SRC_STM32L4_STM32L4_DFSDM_H */ diff --git a/arch/arm/src/stm32l4/stm32l4_pwm.c b/arch/arm/src/stm32l4/stm32l4_pwm.c index cff34311973..10531d20a8c 100644 --- a/arch/arm/src/stm32l4/stm32l4_pwm.c +++ b/arch/arm/src/stm32l4/stm32l4_pwm.c @@ -126,9 +126,11 @@ enum stm32l4_chanmode_e struct stm32l4_pwmchan_s { uint8_t channel; /* Timer output channel: {1,..4} */ - uint32_t pincfg; /* Output pin configuration */ enum stm32l4_chanmode_e mode; - uint32_t npincfg; /* Complementary output pin configuration (only TIM1/8 CH1-3)*/ + uint32_t pincfg; /* Output pin configuration */ + uint32_t npincfg; /* Complementary output pin configuration + * (only TIM1,8 CH1-3 and TIM15,16,17 CH1) + */ }; /* This structure represents the state of one PWM timer */ @@ -136,8 +138,8 @@ struct stm32l4_pwmchan_s struct stm32l4_pwmtimer_s { FAR const struct pwm_ops_s *ops; /* PWM operations */ - uint8_t timid; /* Timer ID {1,...,17} */ struct stm32l4_pwmchan_s channels[PWM_NCHANNELS]; + uint8_t timid; /* Timer ID {1,...,17} */ uint8_t timtype; /* See the TIMTYPE_* definitions */ enum stm32l4_timmode_e mode; #ifdef CONFIG_PWM_PULSECOUNT @@ -1106,7 +1108,7 @@ static int stm32l4pwm_timer(FAR struct stm32l4_pwmtimer_s *priv, ccenable |= ATIM_CCER_CC1E; - /* Conditionnaly enable the complementary output */ + /* Conditionally enable the complementary output */ if (compout) { @@ -1136,7 +1138,7 @@ static int stm32l4pwm_timer(FAR struct stm32l4_pwmtimer_s *priv, ccenable |= ATIM_CCER_CC2E; - /* Conditionnaly enable the complementary output */ + /* Conditionally enable the complementary output */ if (compout) { @@ -1166,7 +1168,7 @@ static int stm32l4pwm_timer(FAR struct stm32l4_pwmtimer_s *priv, ccenable |= ATIM_CCER_CC3E; - /* Conditionnaly enable the complementary output */ + /* Conditionally enable the complementary output */ if (compout) { @@ -1284,7 +1286,8 @@ static int stm32l4pwm_timer(FAR struct stm32l4_pwmtimer_s *priv, stm32l4pwm_putreg(priv, STM32L4_ATIM_BDTR_OFFSET, bdtr); } else -#if defined(CONFIG_STM32L4_TIM15_PWM) || defined(CONFIG_STM32L4_TIM15_PWM) || defined(CONFIG_STM32L4_TIM15_PWM) +#if defined(CONFIG_STM32L4_TIM15_PWM) || defined(CONFIG_STM32L4_TIM16_PWM) || \ + defined(CONFIG_STM32L4_TIM17_PWM) if (priv->timtype == TIMTYPE_COUNTUP16) { diff --git a/arch/arm/src/stm32l4/stm32l4_pwm.h b/arch/arm/src/stm32l4/stm32l4_pwm.h index b3148345209..ff98f6e509f 100644 --- a/arch/arm/src/stm32l4/stm32l4_pwm.h +++ b/arch/arm/src/stm32l4/stm32l4_pwm.h @@ -491,14 +491,17 @@ # define CONFIG_STM32L4_TIM1_CHANNEL1 1 # define CONFIG_STM32L4_TIM1_CH1MODE CONFIG_STM32L4_TIM1_CHMODE # define PWM_TIM1_CH1CFG GPIO_TIM1_CH1OUT +# define PWM_TIM1_CH1NCFG 0 # elif CONFIG_STM32L4_TIM1_CHANNEL == 2 # define CONFIG_STM32L4_TIM1_CHANNEL2 1 # define CONFIG_STM32L4_TIM1_CH2MODE CONFIG_STM32L4_TIM1_CHMODE # define PWM_TIM1_CH2CFG GPIO_TIM1_CH2OUT +# define PWM_TIM1_CH2NCFG 0 # elif CONFIG_STM32L4_TIM1_CHANNEL == 3 # define CONFIG_STM32L4_TIM1_CHANNEL3 1 # define CONFIG_STM32L4_TIM1_CH3MODE CONFIG_STM32L4_TIM1_CHMODE # define PWM_TIM1_CH3CFG GPIO_TIM1_CH3OUT +# define PWM_TIM1_CH3NCFG 0 # elif CONFIG_STM32L4_TIM1_CHANNEL == 4 # define CONFIG_STM32L4_TIM1_CHANNEL4 1 # define CONFIG_STM32L4_TIM1_CH4MODE CONFIG_STM32L4_TIM1_CHMODE @@ -611,14 +614,17 @@ # define CONFIG_STM32L4_TIM8_CHANNEL1 1 # define CONFIG_STM32L4_TIM8_CH1MODE CONFIG_STM32L4_TIM8_CHMODE # define PWM_TIM8_CH1CFG GPIO_TIM8_CH1OUT +# define PWM_TIM8_CH1NCFG 0 # elif CONFIG_STM32L4_TIM8_CHANNEL == 2 # define CONFIG_STM32L4_TIM8_CHANNEL2 1 # define CONFIG_STM32L4_TIM8_CH2MODE CONFIG_STM32L4_TIM8_CHMODE # define PWM_TIM8_CH2CFG GPIO_TIM8_CH2OUT +# define PWM_TIM8_CH2NCFG 0 # elif CONFIG_STM32L4_TIM8_CHANNEL == 3 # define CONFIG_STM32L4_TIM8_CHANNEL3 1 # define CONFIG_STM32L4_TIM8_CH3MODE CONFIG_STM32L4_TIM8_CHMODE # define PWM_TIM8_CH3CFG GPIO_TIM8_CH3OUT +# define PWM_TIM8_CH3NCFG 0 # elif CONFIG_STM32L4_TIM8_CHANNEL == 4 # define CONFIG_STM32L4_TIM8_CHANNEL4 1 # define CONFIG_STM32L4_TIM8_CH4MODE CONFIG_STM32L4_TIM8_CHMODE @@ -635,6 +641,7 @@ # define CONFIG_STM32L4_TIM15_CHANNEL1 1 # define CONFIG_STM32L4_TIM15_CH1MODE CONFIG_STM32L4_TIM15_CHMODE # define PWM_TIM15_CH1CFG GPIO_TIM15_CH1OUT +# define PWM_TIM15_CH1NCFG 0 # elif CONFIG_STM32L4_TIM15_CHANNEL == 2 # define CONFIG_STM32L4_TIM15_CHANNEL2 1 # define CONFIG_STM32L4_TIM15_CH2MODE CONFIG_STM32L4_TIM15_CHMODE @@ -651,6 +658,7 @@ # define CONFIG_STM32L4_TIM16_CHANNEL1 1 # define CONFIG_STM32L4_TIM16_CH1MODE CONFIG_STM32L4_TIM16_CHMODE # define PWM_TIM16_CH1CFG GPIO_TIM16_CH1OUT +# define PWM_TIM16_CH1NCFG 0 # else # error "Unsupported value of CONFIG_STM32L4_TIM16_CHANNEL" # endif @@ -663,6 +671,7 @@ # define CONFIG_STM32L4_TIM17_CHANNEL1 1 # define CONFIG_STM32L4_TIM17_CH1MODE CONFIG_STM32L4_TIM17_CHMODE # define PWM_TIM17_CH1CFG GPIO_TIM17_CH1OUT +# define PWM_TIM17_CH1NCFG 0 # else # error "Unsupported value of CONFIG_STM32L4_TIM17_CHANNEL" # endif diff --git a/arch/arm/src/stm32l4/stm32l4_tim.c b/arch/arm/src/stm32l4/stm32l4_tim.c index 2180884d7e4..7e70ecededf 100644 --- a/arch/arm/src/stm32l4/stm32l4_tim.c +++ b/arch/arm/src/stm32l4/stm32l4_tim.c @@ -246,9 +246,11 @@ static void stm32l4_tim_reload_counter(FAR struct stm32l4_tim_dev_s *dev); static void stm32l4_tim_enable(FAR struct stm32l4_tim_dev_s *dev); static void stm32l4_tim_disable(FAR struct stm32l4_tim_dev_s *dev); static void stm32l4_tim_reset(FAR struct stm32l4_tim_dev_s *dev); -#if defined(HAVE_TIM1_GPIOCONFIG)||defined(HAVE_TIM2_GPIOCONFIG)||\ - defined(HAVE_TIM3_GPIOCONFIG)||defined(HAVE_TIM4_GPIOCONFIG)||\ - defined(HAVE_TIM5_GPIOCONFIG)||defined(HAVE_TIM8_GPIOCONFIG) +#if defined(HAVE_TIM1_GPIOCONFIG) || defined(HAVE_TIM2_GPIOCONFIG) || \ + defined(HAVE_TIM3_GPIOCONFIG) || defined(HAVE_TIM4_GPIOCONFIG) || \ + defined(HAVE_TIM5_GPIOCONFIG) || defined(HAVE_TIM8_GPIOCONFIG) || \ + defined(HAVE_TIM15_GPIOCONFIG) || defined(HAVE_TIM16_GPIOCONFIG) || \ + defined(HAVE_TIM17_GPIOCONFIG) static void stm32l4_tim_gpioconfig(uint32_t cfg, stm32l4_tim_channel_t mode); #endif @@ -524,9 +526,11 @@ static void stm32l4_tim_reset(FAR struct stm32l4_tim_dev_s *dev) * Name: stm32l4_tim_gpioconfig ************************************************************************************/ -#if defined(HAVE_TIM1_GPIOCONFIG)||defined(HAVE_TIM2_GPIOCONFIG)||\ - defined(HAVE_TIM3_GPIOCONFIG)||defined(HAVE_TIM4_GPIOCONFIG)||\ - defined(HAVE_TIM5_GPIOCONFIG)||defined(HAVE_TIM8_GPIOCONFIG) +#if defined(HAVE_TIM1_GPIOCONFIG) || defined(HAVE_TIM2_GPIOCONFIG) || \ + defined(HAVE_TIM3_GPIOCONFIG) || defined(HAVE_TIM4_GPIOCONFIG) || \ + defined(HAVE_TIM5_GPIOCONFIG) || defined(HAVE_TIM8_GPIOCONFIG) || \ + defined(HAVE_TIM15_GPIOCONFIG) || defined(HAVE_TIM16_GPIOCONFIG) || \ + defined(HAVE_TIM17_GPIOCONFIG) static void stm32l4_tim_gpioconfig(uint32_t cfg, stm32l4_tim_channel_t mode) { /* TODO: Add support for input capture and bipolar dual outputs for TIM8 */ @@ -760,7 +764,7 @@ static int stm32l4_tim_setchannel(FAR struct stm32l4_tim_dev_s *dev, uint16_t ccmr_orig = 0; uint16_t ccmr_val = 0; uint16_t ccmr_mask = 0xff; - uint16_t ccer_val = stm32l4_getreg16(dev, STM32L4_GTIM_CCER_OFFSET); + uint16_t ccer_val; uint8_t ccmr_offset = STM32L4_GTIM_CCMR1_OFFSET; DEBUGASSERT(dev != NULL); @@ -774,6 +778,7 @@ static int stm32l4_tim_setchannel(FAR struct stm32l4_tim_dev_s *dev, /* Assume that channel is disabled and polarity is active high */ + ccer_val = stm32l4_getreg16(dev, STM32L4_GTIM_CCER_OFFSET); ccer_val &= ~(3 << (channel << 2)); /* This function is not supported on basic timers. To enable or diff --git a/arch/arm/src/stm32l4/stm32l4x3xx_rcc.c b/arch/arm/src/stm32l4/stm32l4x3xx_rcc.c index e23751c262c..f4f95ee4e37 100644 --- a/arch/arm/src/stm32l4/stm32l4x3xx_rcc.c +++ b/arch/arm/src/stm32l4/stm32l4x3xx_rcc.c @@ -534,6 +534,16 @@ static inline void rcc_enableccip(void) regval |= RCC_CCIPR_ADCSEL_SYSCLK; #endif +#ifdef CONFIG_STM32L4_DFSDM1 + /* Select SYSCLK as DFSDM clock source */ + + /* TODO: not sure if this can be done on these MCUs. + * RM0394 Rev 3, p. 525 is confused. + */ + + //regval |= RCC_CCIPR_DFSDMSEL_SYSCLK; +#endif + putreg32(regval, STM32L4_RCC_CCIPR); } diff --git a/arch/arm/src/stm32l4/stm32l4x5xx_rcc.c b/arch/arm/src/stm32l4/stm32l4x5xx_rcc.c index 3ada1c21559..3eaa7b81946 100644 --- a/arch/arm/src/stm32l4/stm32l4x5xx_rcc.c +++ b/arch/arm/src/stm32l4/stm32l4x5xx_rcc.c @@ -563,6 +563,12 @@ static inline void rcc_enableccip(void) regval |= RCC_CCIPR_ADCSEL_SYSCLK; #endif +#ifdef CONFIG_STM32L4_DFSDM1 + /* Select SYSCLK as DFSDM clock source */ + + regval |= RCC_CCIPR_DFSDMSEL_SYSCLK; +#endif + putreg32(regval, STM32L4_RCC_CCIPR); } diff --git a/arch/arm/src/stm32l4/stm32l4x6xx_rcc.c b/arch/arm/src/stm32l4/stm32l4x6xx_rcc.c index 1d26d8dd192..d349255a509 100644 --- a/arch/arm/src/stm32l4/stm32l4x6xx_rcc.c +++ b/arch/arm/src/stm32l4/stm32l4x6xx_rcc.c @@ -608,6 +608,12 @@ static inline void rcc_enableccip(void) regval |= RCC_CCIPR_ADCSEL_SYSCLK; #endif +#ifdef CONFIG_STM32L4_DFSDM1 + /* Select SYSCLK as DFSDM clock source */ + + regval |= RCC_CCIPR_DFSDMSEL_SYSCLK; +#endif + putreg32(regval, STM32L4_RCC_CCIPR); }