From 81e17306d153c3f1f0f577b3f1ff9874ff267807 Mon Sep 17 00:00:00 2001 From: David Sidrane Date: Thu, 13 Jun 2019 19:51:12 +0000 Subject: [PATCH] Merged in david_s5/nuttx/master_h7 (pull request #900) stm32 h7 Add ADC and a few fixes for timer and Serial * stm32h7:Fix error when SINGLEWIRE or CONFIG_STM32H7_SERIALBRK_BSDCOMPAT defined * stm32h7:time fixed compile errors with TIM13,TIM14, TIM7 * stm32h7:Added ADC Driver * stmh7x3:Added ADC pins to pin map * stm32h7:Added ADC clocking * nucleo-h743zi:Add ADC Approved-by: Gregory Nutt --- arch/arm/src/stm32h7/Kconfig | 362 +++ arch/arm/src/stm32h7/Make.defs | 4 + arch/arm/src/stm32h7/hardware/stm32_adc.h | 740 ++++++ .../src/stm32h7/hardware/stm32h7x3xx_pinmap.h | 62 + arch/arm/src/stm32h7/stm32_adc.c | 2013 +++++++++++++++++ arch/arm/src/stm32h7/stm32_adc.h | 829 +++++++ arch/arm/src/stm32h7/stm32_serial.c | 18 +- arch/arm/src/stm32h7/stm32_tim.c | 8 +- arch/arm/src/stm32h7/stm32h7x3xx_rcc.c | 35 +- configs/nucleo-h743zi/include/board.h | 24 +- configs/nucleo-h743zi/src/Makefile | 4 + configs/nucleo-h743zi/src/nucleo-h743zi.h | 2 - configs/nucleo-h743zi/src/stm32_adc.c | 218 ++ 13 files changed, 4290 insertions(+), 29 deletions(-) create mode 100644 arch/arm/src/stm32h7/hardware/stm32_adc.h create mode 100644 arch/arm/src/stm32h7/stm32_adc.c create mode 100644 arch/arm/src/stm32h7/stm32_adc.h create mode 100644 configs/nucleo-h743zi/src/stm32_adc.c diff --git a/arch/arm/src/stm32h7/Kconfig b/arch/arm/src/stm32h7/Kconfig index 9f19ece93f..b200160418 100644 --- a/arch/arm/src/stm32h7/Kconfig +++ b/arch/arm/src/stm32h7/Kconfig @@ -143,6 +143,20 @@ config STM32H7_USART default n # These are the peripheral selections proper +config STM32H7_ADC1 + bool "ADC1" + default n + select STM32H7_ADC + +config STM32H7_ADC2 + bool "ADC2" + default n + select STM32H7_ADC + +config STM32H7_ADC3 + bool "ADC3" + default n + select STM32H7_ADC config STM32H7_DMA1 bool "DMA1" @@ -2841,6 +2855,354 @@ config STM32H7_PWM_MULTICHAN Specifies that the PWM driver supports multiple output channels per timer. +config STM32H7_TIM1_ADC + bool "TIM1 ADC" + default n + depends on STM32H7_TIM1 && STM32H7_ADC + ---help--- + Reserve timer 1 for use by an ADC + + Timer devices may be used for different purposes. If STM32H7_TIM1 is + defined then the following may also be defined to indicate that the + timer is intended to be used for ADC conversion. Note that ADC usage + requires two definition: Not only do you have to assign the timer + for used by the ADC, but then you also have to configure which ADC + channel it is assigned to. + +choice + prompt "Select ADC for use with TIM1" + default STM32H7_TIM1_ADC1 + depends on STM32H7_TIM1_ADC + +config STM32H7_TIM1_ADC1 + bool "Use TIM1 for ADC1" + depends on STM32H7_ADC1 + select STM32H7_HAVE_ADC1_TIMER + ---help--- + Reserve TIM1 to trigger ADC1 + +config STM32H7_TIM1_ADC2 + bool "Use TIM1 for ADC2" + depends on STM32H7_ADC2 + select STM32H7_HAVE_ADC2_TIMER + ---help--- + Reserve TIM1 to trigger ADC2 + +config STM32H7_TIM1_ADC3 + bool "Use TIM1 for ADC3" + depends on STM32H7_ADC3 + select STM32H7_HAVE_ADC3_TIMER + ---help--- + Reserve TIM1 to trigger ADC3 + +endchoice + +config STM32H7_TIM2_ADC + bool "TIM2 ADC" + default n + depends on STM32H7_TIM2 && STM32H7_ADC + ---help--- + Reserve timer 2 for use by an ADC + + Timer devices may be used for different purposes. If STM32H7_TIM2 is + defined then the following may also be defined to indicate that the + timer is intended to be used for ADC conversion. Note that ADC usage + requires two definition: Not only do you have to assign the timer + for used by the ADC, but then you also have to configure which ADC + channel it is assigned to. + +choice + prompt "Select ADC for use with TIM2" + default STM32H7_TIM2_ADC1 + depends on STM32H7_TIM2_ADC + +config STM32H7_TIM2_ADC1 + bool "Use TIM2 for ADC1" + depends on STM32H7_ADC1 + select STM32H7_HAVE_ADC1_TIMER + ---help--- + Reserve TIM2 to trigger ADC1 + +config STM32H7_TIM2_ADC2 + bool "Use TIM2 for ADC2" + depends on STM32H7_ADC2 + select STM32H7_HAVE_ADC2_TIMER + ---help--- + Reserve TIM2 to trigger ADC2 + +config STM32H7_TIM2_ADC3 + bool "Use TIM2 for ADC3" + depends on STM32H7_ADC3 + select STM32H7_HAVE_ADC3_TIMER + ---help--- + Reserve TIM2 to trigger ADC3 + +endchoice + +config STM32H7_TIM3_ADC + bool "TIM3 ADC" + default n + depends on STM32H7_TIM3 && STM32H7_ADC + ---help--- + Reserve timer 3 for use by an ADC + + Timer devices may be used for different purposes. If STM32H7_TIM3 is + defined then the following may also be defined to indicate that the + timer is intended to be used for ADC conversion. Note that ADC usage + requires two definition: Not only do you have to assign the timer + for used by the ADC, but then you also have to configure which ADC + channel it is assigned to. + +choice + prompt "Select ADC for use with TIM3" + default STM32H7_TIM3_ADC1 + depends on STM32H7_TIM3_ADC + +config STM32H7_TIM3_ADC1 + bool "Use TIM3 for ADC1" + depends on STM32H7_ADC1 + select STM32H7_HAVE_ADC1_TIMER + ---help--- + Reserve TIM3 to trigger ADC1 + +config STM32H7_TIM3_ADC2 + bool "Use TIM3 for ADC2" + depends on STM32H7_ADC2 + select STM32H7_HAVE_ADC2_TIMER + ---help--- + Reserve TIM3 to trigger ADC2 + +config STM32H7_TIM3_ADC3 + bool "Use TIM3 for ADC3" + depends on STM32H7_ADC3 + select STM32H7_HAVE_ADC3_TIMER + ---help--- + Reserve TIM3 to trigger ADC3 + +endchoice + +config STM32H7_TIM4_ADC + bool "TIM4 ADC" + default n + depends on STM32H7_TIM4 && STM32H7_ADC + ---help--- + Reserve timer 4 for use by ADC + + Timer devices may be used for different purposes. If STM32H7_TIM4 is + defined then the following may also be defined to indicate that the + timer is intended to be used for ADC conversion. Note that ADC usage + requires two definition: Not only do you have to assign the timer + for used by the ADC, but then you also have to configure which ADC + channel it is assigned to. + +choice + prompt "Select ADC for use with TIM4" + default STM32H7_TIM4_ADC1 + depends on STM32H7_TIM4_ADC + +config STM32H7_TIM4_ADC1 + bool "Use TIM4 for ADC1" + depends on STM32H7_ADC1 + select STM32H7_HAVE_ADC1_TIMER + ---help--- + Reserve TIM4 to trigger ADC1 + +config STM32H7_TIM4_ADC2 + bool "Use TIM4 for ADC2" + depends on STM32H7_ADC2 + select STM32H7_HAVE_ADC2_TIMER + ---help--- + Reserve TIM4 to trigger ADC2 + +config STM32H7_TIM4_ADC3 + bool "Use TIM4 for ADC3" + depends on STM32H7_ADC3 + select STM32H7_HAVE_ADC3_TIMER + ---help--- + Reserve TIM4 to trigger ADC3 + +endchoice + +config STM32H7_TIM6_ADC + bool "TIM6 ADC" + default n + depends on STM32H7_TIM6 && STM32H7_ADC + ---help--- + Reserve timer 6 for use by ADC + + Timer devices may be used for different purposes. If STM32H7_TIM6 is + defined then the following may also be defined to indicate that the + timer is intended to be used for ADC conversion. Note that ADC usage + requires two definition: Not only do you have to assign the timer + for used by the ADC, but then you also have to configure which ADC + channel it is assigned to. + +choice + prompt "Select ADC for use with TIM6" + default STM32H7_TIM6_ADC1 + depends on STM32H7_TIM6_ADC + +config STM32H7_TIM6_ADC1 + bool "Use TIM6 for ADC1" + depends on STM32H7_ADC1 + select STM32H7_HAVE_ADC1_TIMER + ---help--- + Reserve TIM6 to trigger ADC1 + +config STM32H7_TIM6_ADC2 + bool "Use TIM6 for ADC2" + depends on STM32H7_ADC2 + select STM32H7_HAVE_ADC2_TIMER + ---help--- + Reserve TIM6 to trigger ADC2 + +config STM32H7_TIM6_ADC3 + bool "Use TIM6 for ADC3" + depends on STM32H7_ADC3 + select STM32H7_HAVE_ADC3_TIMER + ---help--- + Reserve TIM6 to trigger ADC3 + +endchoice + +config STM32H7_TIM8_ADC + bool "TIM8 ADC" + default n + depends on STM32H7_TIM8 && STM32H7_ADC + ---help--- + Reserve timer 8 for use by ADC + + Timer devices may be used for different purposes. If STM32H7_TIM8 is + defined then the following may also be defined to indicate that the + timer is intended to be used for ADC conversion. Note that ADC usage + requires two definition: Not only do you have to assign the timer + for used by the ADC, but then you also have to configure which ADC + channel it is assigned to. + +choice + prompt "Select ADC for use with TIM8" + default STM32H7_TIM8_ADC1 + depends on STM32H7_TIM8_ADC + +config STM32H7_TIM8_ADC1 + bool "Use TIM8 for ADC1" + depends on STM32H7_ADC1 + select STM32H7_HAVE_ADC1_TIMER + ---help--- + Reserve TIM8 to trigger ADC1 + +config STM32H7_TIM8_ADC2 + bool "Use TIM8 for ADC2" + depends on STM32H7_ADC2 + select STM32H7_HAVE_ADC2_TIMER + ---help--- + Reserve TIM8 to trigger ADC2 + +config STM32H7_TIM8_ADC3 + bool "Use TIM8 for ADC3" + depends on STM32H7_ADC3 + select STM32H7_HAVE_ADC3_TIMER + ---help--- + Reserve TIM8 to trigger ADC3 + +endchoice + +config STM32H7_TIM15_ADC + bool "TIM15 ADC" + default n + depends on STM32H7_TIM15 && STM32H7_ADC + ---help--- + Reserve timer 15 for use by ADC + + Timer devices may be used for different purposes. If STM32H7_TIM15 is + defined then the following may also be defined to indicate that the + timer is intended to be used for ADC conversion. Note that ADC usage + requires two definition: Not only do you have to assign the timer + for used by the ADC, but then you also have to configure which ADC + channel it is assigned to. + +choice + prompt "Select ADC for use with TIM15" + default STM32H7_TIM15_ADC1 + depends on STM32H7_TIM15_ADC + +config STM32H7_TIM15_ADC1 + bool "Use TIM15 for ADC1" + depends on STM32H7_ADC1 + select STM32H7_HAVE_ADC1_TIMER + ---help--- + Reserve TIM15 to trigger ADC1 + +config STM32H7_TIM15_ADC2 + bool "Use TIM15 for ADC2" + depends on STM32H7_ADC2 + select STM32H7_HAVE_ADC2_TIMER + ---help--- + Reserve TIM15 to trigger ADC2 + +config STM32H7_TIM15_ADC3 + bool "Use TIM15 for ADC3" + depends on STM32H7_ADC3 + select STM32H7_HAVE_ADC3_TIMER + ---help--- + Reserve TIM15 to trigger ADC3 + +endchoice + +config STM32H7_HAVE_ADC1_TIMER + bool + +config STM32H7_HAVE_ADC2_TIMER + bool + +config STM32H7_HAVE_ADC3_TIMER + bool + +config STM32H7_ADC1_SAMPLE_FREQUENCY + int "ADC1 Sampling Frequency" + default 100 + depends on STM32H7_HAVE_ADC1_TIMER + ---help--- + ADC1 sampling frequency. Default: 100Hz + +config STM32H7_ADC1_TIMTRIG + int "ADC1 Timer Trigger" + default 0 + range 0 4 + depends on STM32H7_HAVE_ADC1_TIMER + ---help--- + Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO + +config STM32H7_ADC2_SAMPLE_FREQUENCY + int "ADC2 Sampling Frequency" + default 100 + depends on STM32H7_HAVE_ADC2_TIMER + ---help--- + ADC2 sampling frequency. Default: 100Hz + +config STM32H7_ADC2_TIMTRIG + int "ADC2 Timer Trigger" + default 0 + range 0 4 + depends on STM32H7_HAVE_ADC2_TIMER + ---help--- + Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO + +config STM32H7_ADC3_SAMPLE_FREQUENCY + int "ADC3 Sampling Frequency" + default 100 + depends on STM32H7_HAVE_ADC3_TIMER + ---help--- + ADC3 sampling frequency. Default: 100Hz + +config STM32H7_ADC3_TIMTRIG + int "ADC3 Timer Trigger" + default 0 + range 0 4 + depends on STM32H7_HAVE_ADC3_TIMER + ---help--- + Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO + config STM32H7_TIM1_CAP bool "TIM1 Capture" default n diff --git a/arch/arm/src/stm32h7/Make.defs b/arch/arm/src/stm32h7/Make.defs index 6047e2a8e8..dd12df7245 100644 --- a/arch/arm/src/stm32h7/Make.defs +++ b/arch/arm/src/stm32h7/Make.defs @@ -102,6 +102,10 @@ ifeq ($(CONFIG_BUILD_PROTECTED),y) CHIP_CSRCS += stm32_userspace.c stm32_mpuinit.c endif +ifeq ($(CONFIG_STM32H7_ADC),y) +CHIP_CSRCS += stm32_adc.c +endif + ifeq ($(CONFIG_STM32H7_DMA),y) CHIP_CSRCS += stm32_dma.c endif diff --git a/arch/arm/src/stm32h7/hardware/stm32_adc.h b/arch/arm/src/stm32h7/hardware/stm32_adc.h new file mode 100644 index 0000000000..71a000a923 --- /dev/null +++ b/arch/arm/src/stm32h7/hardware/stm32_adc.h @@ -0,0 +1,740 @@ +/************************************************************************************ + * arch/arm/src/stm32h7/hardware/stm32_adc.h + * + * Copyright (C) 2017,2019 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * Juha Niskanen + * David Sidrane + * + * 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_STM32H7_HARDWARE_STM32_ADC_H +#define __ARCH_ARM_SRC_STM32H7_HARDWARE_STM32_ADC_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include "chip.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +#define STM32_ADC1_OFFSET 0x0000 +#define STM32_ADC2_OFFSET 0x0100 +#define STM32_ADCCMN_OFFSET 0x0300 + +#define STM32_ADC1_BASE (STM32_ADC1_OFFSET+STM32_ADC12_BASE) /* ADC1 Master ADC */ +#define STM32_ADC2_BASE (STM32_ADC2_OFFSET+STM32_ADC12_BASE) /* ADC2 Slave ADC */ + +/* Register Offsets *****************************************************************/ +/* Register Offsets for each ADC (ADC1-3). At offset 0x0000 for master and offset 0x0100 + * for slave. + */ + +#define STM32_ADC_ISR_OFFSET 0x0000 /* ADC interrupt and status register */ +#define STM32_ADC_IER_OFFSET 0x0004 /* ADC interrupt enable register */ +#define STM32_ADC_CR_OFFSET 0x0008 /* ADC control register */ +#define STM32_ADC_CFGR_OFFSET 0x000c /* ADC configuration register */ +#define STM32_ADC_CFGR2_OFFSET 0x0010 /* ADC configuration register 2 */ +#define STM32_ADC_SMPR1_OFFSET 0x0014 /* ADC sample time register 1 */ +#define STM32_ADC_SMPR2_OFFSET 0x0018 /* ADC sample time register 2 */ +#define STM32_ADC_PCSEL_OFFSET 0x001c /* ADC Channel preselection register */ +#define STM32_ADC_LTR1_OFFSET 0x0020 /* ADC watchdog lower threshold register 1 */ +#define STM32_ADC_HTR1_OFFSET 0x0024 /* ADC watchdog higher threshold register 1 */ +#define STM32_ADC_SQR1_OFFSET 0x0030 /* ADC regular sequence register 1 */ +#define STM32_ADC_SQR2_OFFSET 0x0034 /* ADC regular sequence register 2 */ +#define STM32_ADC_SQR3_OFFSET 0x0038 /* ADC regular sequence register 3 */ +#define STM32_ADC_SQR4_OFFSET 0x003c /* ADC regular sequence register 4 */ +#define STM32_ADC_DR_OFFSET 0x0040 /* ADC regular data register */ +#define STM32_ADC_JSQR_OFFSET 0x004c /* ADC injected sequence register */ +#define STM32_ADC_OFR1_OFFSET 0x0060 /* ADC offset register 1 */ +#define STM32_ADC_OFR2_OFFSET 0x0064 /* ADC offset register 2 */ +#define STM32_ADC_OFR3_OFFSET 0x0068 /* ADC offset register 3 */ +#define STM32_ADC_OFR4_OFFSET 0x006c /* ADC offset register 4 */ +#define STM32_ADC_JDR1_OFFSET 0x0080 /* ADC injected data register 1 */ +#define STM32_ADC_JDR2_OFFSET 0x0084 /* ADC injected data register 2 */ +#define STM32_ADC_JDR3_OFFSET 0x0088 /* ADC injected data register 3 */ +#define STM32_ADC_JDR4_OFFSET 0x008c /* ADC injected data register 4 */ +#define STM32_ADC_AWD2CR_OFFSET 0x00a0 /* ADC analog watchdog 2 configuration register */ +#define STM32_ADC_AWD3CR_OFFSET 0x00a4 /* ADC analog watchdog 3 configuration register */ +#define STM32_ADC_LTR2_OFFSET 0x00b0 /* ADC watchdog lower threshold register 2 */ +#define STM32_ADC_HTR2_OFFSET 0x00b4 /* ADC watchdog higher threshold register 2 */ +#define STM32_ADC_LTR3_OFFSET 0x00b8 /* ADC watchdog lower threshold register 3 */ +#define STM32_ADC_HTR3_OFFSET 0x00bc /* ADC watchdog higher threshold register 3 */ +#define STM32_ADC_DIFSEL_OFFSET 0x00c0 /* ADC differential mode selection register 2 */ +#define STM32_ADC_CALFACT_OFFSET 0x00c4 /* ADC calibration factors register */ +#define STM32_ADC_CALFACT2_OFFSET 0x00c8 /* ADC calibration factors register 2 */ + +/* Master and Slave ADC Common Registers */ + +#define STM32_ADCX_CSR_OFFSET 0x0000 /* Common status register */ +#define STM32_ADCX_CCR_OFFSET 0x0008 /* Common control register */ +#define STM32_ADCX_CDR_OFFSET 0x000c /* Common regular data register for dual mode */ +#define STM32_ADCX_CDR2_OFFSET 0x0010 /* Common regular data register for 32-bit dual mode */ + +#define STM32_ADC_CSR_OFFSET (STM32_ADCCMN_OFFSET+STM32_ADCX_CSR_OFFSET) +#define STM32_ADC_CCR_OFFSET (STM32_ADCCMN_OFFSET+STM32_ADCX_CCR_OFFSET) +#define STM32_ADC_CDR_OFFSET (STM32_ADCCMN_OFFSET+STM32_ADCX_CDR_OFFSET) +#define STM32_ADC_CDR2_OFFSET (STM32_ADCCMN_OFFSET+STM32_ADCX_CDR2_OFFSET) + +/* Register Addresses ***************************************************************/ + +#define STM32_ADC1_ISR (STM32_ADC1_BASE+STM32_ADC_ISR_OFFSET) +#define STM32_ADC1_IER (STM32_ADC1_BASE+STM32_ADC_IER_OFFSET) +#define STM32_ADC1_CR (STM32_ADC1_BASE+STM32_ADC_CR_OFFSET) +#define STM32_ADC1_CFGR (STM32_ADC1_BASE+STM32_ADC_CFGR_OFFSET) +#define STM32_ADC1_CFGR2 (STM32_ADC1_BASE+STM32_ADC_CFGR2_OFFSET) +#define STM32_ADC1_SMPR1 (STM32_ADC1_BASE+STM32_ADC_SMPR1_OFFSET) +#define STM32_ADC1_SMPR2 (STM32_ADC1_BASE+STM32_ADC_SMPR2_OFFSET) +#define STM32_ADC1_PCSEL (STM32_ADC1_BASE+STM32_ADC_PCSEL_OFFSET) +#define STM32_ADC1_LTR1 (STM32_ADC1_BASE+STM32_ADC_LTR1_OFFSET) +#define STM32_ADC1_HTR1 (STM32_ADC1_BASE+STM32_ADC_HTR1_OFFSET) +#define STM32_ADC1_SQR1 (STM32_ADC1_BASE+STM32_ADC_SQR1_OFFSET) +#define STM32_ADC1_SQR2 (STM32_ADC1_BASE+STM32_ADC_SQR2_OFFSET) +#define STM32_ADC1_SQR3 (STM32_ADC1_BASE+STM32_ADC_SQR3_OFFSET) +#define STM32_ADC1_SQR4 (STM32_ADC1_BASE+STM32_ADC_SQR4_OFFSET) +#define STM32_ADC1_DR (STM32_ADC1_BASE+STM32_ADC_DR_OFFSET) +#define STM32_ADC1_JSQR (STM32_ADC1_BASE+STM32_ADC_JSQR_OFFSET) +#define STM32_ADC1_OFR1 (STM32_ADC1_BASE+STM32_ADC_OFR1_OFFSET) +#define STM32_ADC1_OFR2 (STM32_ADC1_BASE+STM32_ADC_OFR2_OFFSET) +#define STM32_ADC1_OFR3 (STM32_ADC1_BASE+STM32_ADC_OFR3_OFFSET) +#define STM32_ADC1_OFR4 (STM32_ADC1_BASE+STM32_ADC_OFR4_OFFSET) +#define STM32_ADC1_JDR1 (STM32_ADC1_BASE+STM32_ADC_JDR1_OFFSET) +#define STM32_ADC1_JDR2 (STM32_ADC1_BASE+STM32_ADC_JDR2_OFFSET) +#define STM32_ADC1_JDR3 (STM32_ADC1_BASE+STM32_ADC_JDR3_OFFSET) +#define STM32_ADC1_JDR4 (STM32_ADC1_BASE+STM32_ADC_JDR4_OFFSET) +#define STM32_ADC1_AWD2CR (STM32_ADC1_BASE+STM32_ADC_AWD2CR_OFFSET) +#define STM32_ADC1_AWD3CR (STM32_ADC1_BASE+STM32_ADC_AWD3CR_OFFSET) +#define STM32_ADC1_LTR2 (STM32_ADC1_BASE+STM32_ADC_LTR2_OFFSET) +#define STM32_ADC1_HTR2 (STM32_ADC1_BASE+STM32_ADC_HTR2_OFFSET) +#define STM32_ADC1_LTR3 (STM32_ADC1_BASE+STM32_ADC_LTR3_OFFSET) +#define STM32_ADC1_HTR3 (STM32_ADC1_BASE+STM32_ADC_HTR3_OFFSET) +#define STM32_ADC1_DIFSEL (STM32_ADC1_BASE+STM32_ADC_DIFSEL_OFFSET) +#define STM32_ADC1_CALFACT (STM32_ADC1_BASE+STM32_ADC_CALFACT_OFFSET) +#define STM32_ADC1_CALFACT2 (STM32_ADC1_BASE+STM32_ADC_CALFACT2_OFFSET) + +#define STM32_ADC1_CSR (STM32_ADC1_BASE+STM32_ADC_CSR_OFFSET) +#define STM32_ADC1_CCR (STM32_ADC1_BASE+STM32_ADC_CCR_OFFSET) +#define STM32_ADC1_CDR (STM32_ADC1_BASE+STM32_ADC_CDR_OFFSET) +#define STM32_ADC1_CDR2 (STM32_ADC1_BASE+STM32_ADC_CDR2_OFFSET) + +#define STM32_ADC2_ISR (STM32_ADC2_BASE+STM32_ADC_ISR_OFFSET) +#define STM32_ADC2_IER (STM32_ADC2_BASE+STM32_ADC_IER_OFFSET) +#define STM32_ADC2_CR (STM32_ADC2_BASE+STM32_ADC_CR_OFFSET) +#define STM32_ADC2_CFGR (STM32_ADC2_BASE+STM32_ADC_CFGR_OFFSET) +#define STM32_ADC2_CFGR2 (STM32_ADC2_BASE+STM32_ADC_CFGR2_OFFSET) +#define STM32_ADC2_SMPR1 (STM32_ADC2_BASE+STM32_ADC_SMPR1_OFFSET) +#define STM32_ADC2_SMPR2 (STM32_ADC2_BASE+STM32_ADC_SMPR2_OFFSET) +#define STM32_ADC2_PCSEL (STM32_ADC2_BASE+STM32_ADC_PCSEL_OFFSET) +#define STM32_ADC2_LTR1 (STM32_ADC2_BASE+STM32_ADC_LTR1_OFFSET) +#define STM32_ADC2_HTR1 (STM32_ADC2_BASE+STM32_ADC_HTR1_OFFSET) +#define STM32_ADC2_SQR1 (STM32_ADC2_BASE+STM32_ADC_SQR1_OFFSET) +#define STM32_ADC2_SQR2 (STM32_ADC2_BASE+STM32_ADC_SQR2_OFFSET) +#define STM32_ADC2_SQR3 (STM32_ADC2_BASE+STM32_ADC_SQR3_OFFSET) +#define STM32_ADC2_SQR4 (STM32_ADC2_BASE+STM32_ADC_SQR4_OFFSET) +#define STM32_ADC2_DR (STM32_ADC2_BASE+STM32_ADC_DR_OFFSET) +#define STM32_ADC2_JSQR (STM32_ADC2_BASE+STM32_ADC_JSQR_OFFSET) +#define STM32_ADC2_OFR1 (STM32_ADC2_BASE+STM32_ADC_OFR1_OFFSET) +#define STM32_ADC2_OFR2 (STM32_ADC2_BASE+STM32_ADC_OFR2_OFFSET) +#define STM32_ADC2_OFR3 (STM32_ADC2_BASE+STM32_ADC_OFR3_OFFSET) +#define STM32_ADC2_OFR4 (STM32_ADC2_BASE+STM32_ADC_OFR4_OFFSET) +#define STM32_ADC2_JDR1 (STM32_ADC2_BASE+STM32_ADC_JDR1_OFFSET) +#define STM32_ADC2_JDR2 (STM32_ADC2_BASE+STM32_ADC_JDR2_OFFSET) +#define STM32_ADC2_JDR3 (STM32_ADC2_BASE+STM32_ADC_JDR3_OFFSET) +#define STM32_ADC2_JDR4 (STM32_ADC2_BASE+STM32_ADC_JDR4_OFFSET) +#define STM32_ADC2_AWD2CR (STM32_ADC2_BASE+STM32_ADC_AWD2CR_OFFSET) +#define STM32_ADC2_AWD3CR (STM32_ADC2_BASE+STM32_ADC_AWD3CR_OFFSET) +#define STM32_ADC2_LTR2 (STM32_ADC2_BASE+STM32_ADC_LTR2_OFFSET) +#define STM32_ADC2_HTR2 (STM32_ADC2_BASE+STM32_ADC_HTR2_OFFSET) +#define STM32_ADC2_LTR3 (STM32_ADC2_BASE+STM32_ADC_LTR3_OFFSET) +#define STM32_ADC2_HTR3 (STM32_ADC2_BASE+STM32_ADC_HTR3_OFFSET) +#define STM32_ADC2_DIFSEL (STM32_ADC2_BASE+STM32_ADC_DIFSEL_OFFSET) +#define STM32_ADC2_CALFACT (STM32_ADC2_BASE+STM32_ADC_CALFACT_OFFSET) +#define STM32_ADC2_CALFACT2 (STM32_ADC2_BASE+STM32_ADC_CALFACT2_OFFSET) + +/* Common for ADC 1 and 2 */ + +#define STM32_ADC2_CSR (STM32_ADC1_BASE+STM32_ADC_CSR_OFFSET) +#define STM32_ADC2_CCR (STM32_ADC1_BASE+STM32_ADC_CCR_OFFSET) +#define STM32_ADC2_CDR (STM32_ADC1_BASE+STM32_ADC_CDR_OFFSET) +#define STM32_ADC2_CDR2 (STM32_ADC1_BASE+STM32_ADC_CDR2_OFFSET) + +#define STM32_ADC3_ISR (STM32_ADC3_BASE+STM32_ADC_ISR_OFFSET) +#define STM32_ADC3_IER (STM32_ADC3_BASE+STM32_ADC_IER_OFFSET) +#define STM32_ADC3_CR (STM32_ADC3_BASE+STM32_ADC_CR_OFFSET) +#define STM32_ADC3_CFGR (STM32_ADC3_BASE+STM32_ADC_CFGR_OFFSET) +#define STM32_ADC3_CFGR2 (STM32_ADC3_BASE+STM32_ADC_CFGR2_OFFSET) +#define STM32_ADC3_SMPR1 (STM32_ADC3_BASE+STM32_ADC_SMPR1_OFFSET) +#define STM32_ADC3_SMPR2 (STM32_ADC3_BASE+STM32_ADC_SMPR2_OFFSET) +#define STM32_ADC3_PCSEL (STM32_ADC3_BASE+STM32_ADC_PCSEL_OFFSET) +#define STM32_ADC3_LTR1 (STM32_ADC3_BASE+STM32_ADC_LTR1_OFFSET) +#define STM32_ADC3_HTR1 (STM32_ADC3_BASE+STM32_ADC_HTR1_OFFSET) +#define STM32_ADC3_SQR1 (STM32_ADC3_BASE+STM32_ADC_SQR1_OFFSET) +#define STM32_ADC3_SQR2 (STM32_ADC3_BASE+STM32_ADC_SQR2_OFFSET) +#define STM32_ADC3_SQR3 (STM32_ADC3_BASE+STM32_ADC_SQR3_OFFSET) +#define STM32_ADC3_SQR4 (STM32_ADC3_BASE+STM32_ADC_SQR4_OFFSET) +#define STM32_ADC3_DR (STM32_ADC3_BASE+STM32_ADC_DR_OFFSET) +#define STM32_ADC3_JSQR (STM32_ADC3_BASE+STM32_ADC_JSQR_OFFSET) +#define STM32_ADC3_OFR1 (STM32_ADC3_BASE+STM32_ADC_OFR1_OFFSET) +#define STM32_ADC3_OFR2 (STM32_ADC3_BASE+STM32_ADC_OFR2_OFFSET) +#define STM32_ADC3_OFR3 (STM32_ADC3_BASE+STM32_ADC_OFR3_OFFSET) +#define STM32_ADC3_OFR4 (STM32_ADC3_BASE+STM32_ADC_OFR4_OFFSET) +#define STM32_ADC3_JDR1 (STM32_ADC3_BASE+STM32_ADC_JDR1_OFFSET) +#define STM32_ADC3_JDR2 (STM32_ADC3_BASE+STM32_ADC_JDR2_OFFSET) +#define STM32_ADC3_JDR3 (STM32_ADC3_BASE+STM32_ADC_JDR3_OFFSET) +#define STM32_ADC3_JDR4 (STM32_ADC3_BASE+STM32_ADC_JDR4_OFFSET) +#define STM32_ADC3_AWD2CR (STM32_ADC3_BASE+STM32_ADC_AWD2CR_OFFSET) +#define STM32_ADC3_AWD3CR (STM32_ADC3_BASE+STM32_ADC_AWD3CR_OFFSET) +#define STM32_ADC3_LTR2 (STM32_ADC3_BASE+STM32_ADC_LTR2_OFFSET) +#define STM32_ADC3_HTR2 (STM32_ADC3_BASE+STM32_ADC_HTR2_OFFSET) +#define STM32_ADC3_LTR3 (STM32_ADC3_BASE+STM32_ADC_LTR3_OFFSET) +#define STM32_ADC3_HTR3 (STM32_ADC3_BASE+STM32_ADC_HTR3_OFFSET) +#define STM32_ADC3_DIFSEL (STM32_ADC3_BASE+STM32_ADC_DIFSEL_OFFSET) +#define STM32_ADC3_CALFACT (STM32_ADC3_BASE+STM32_ADC_CALFACT_OFFSET) +#define STM32_ADC3_CALFACT2 (STM32_ADC3_BASE+STM32_ADC_CALFACT2_OFFSET) + +#define STM32_ADC3_CSR (STM32_ADC3_BASE+STM32_ADC_CSR_OFFSET) +#define STM32_ADC3_CCR (STM32_ADC3_BASE+STM32_ADC_CCR_OFFSET) +#define STM32_ADC3_CDR (STM32_ADC3_BASE+STM32_ADC_CDR_OFFSET) +#define STM32_ADC3_CDR2 (STM32_ADC3_BASE+STM32_ADC_CDR2_OFFSET) + +/* Register Bitfield Definitions ****************************************************/ +/* ADC interrupt and status register (ISR) and ADC interrupt enable register (IER) */ + +#define ADC_INT_ADRDY (1 << 0) /* Bit 0: ADC ready */ +#define ADC_INT_EOSMP (1 << 1) /* Bit 1: End of sampling flag */ +#define ADC_INT_EOC (1 << 2) /* Bit 2: End of conversion */ +#define ADC_INT_EOS (1 << 3) /* Bit 3: End of regular sequence flag */ +#define ADC_INT_OVR (1 << 4) /* Bit 4: Overrun */ +#define ADC_INT_JEOC (1 << 5) /* Bit 5: Injected channel end of conversion */ +#define ADC_INT_JEOS (1 << 6) /* Bit 6: Injected channel end of sequence flag */ +#define ADC_INT_AWD1 (1 << 7) /* Bit 7: Analog watchdog 1 flag */ +#define ADC_INT_AWD2 (1 << 8) /* Bit 8: Analog watchdog 2 flag */ +#define ADC_INT_AWD3 (1 << 9) /* Bit 9: Analog watchdog 3 flag */ +#define ADC_INT_JQOVF (1 << 10) /* Bit 10: Injected context queue overflow */ + /* Bits 11-31: Reserved */ + +#define ADC_INT_MASK (0x7ff) + +/* ADC control register */ + +#define ADC_CR_ADEN (1 << 0) /* Bit 0: ADC enable control */ +#define ADC_CR_ADDIS (1 << 1) /* Bit 1: ADC disable command */ +#define ADC_CR_ADSTART (1 << 2) /* Bit 2: ADC start of regular conversion */ +#define ADC_CR_JADSTART (1 << 3) /* Bit 3: ADC start of injected conversion */ +#define ADC_CR_ADSTP (1 << 4) /* Bit 4: ADC stop of regular conversion command */ +#define ADC_CR_JADSTP (1 << 5) /* Bit 5: ADC stop of injected conversion command */ + /* Bits 6-7: Reserved */ +#if defined(ADC_DEVICE_VERSION_V) +# define ADC_CR_BOOST_SHIFT (8) /* Bits 8-9: ADC Boost mode control */ +# define ADC_CR_BOOST_MASK (3 << ADC_CR_BOOST_SHIFT) +# define ADC_CR_BOOST_6p25_MHZ (0 << ADC_CR_BOOST_SHIFT) +# define ADC_CR_BOOST_12p5_MHZ (1 << ADC_CR_BOOST_SHIFT) +# define ADC_CR_BOOST_25_MHZ (2 << ADC_CR_BOOST_SHIFT) +# define ADC_CR_BOOST_50_MHZ (3 << ADC_CR_BOOST_SHIFT) + /* Bits 10-15: Reserved */ +#else +# define ADC_CR_BOOST (1 << 8) /* Bit 8: ADC Boost mode control */ + /* Bits 9-15: Reserved */ +#endif +#define ADC_CR_ADCALLIN (1 << 16) /* Bit 16: ADC Linearity calibration */ + /* Bits 17-21: Reserved */ +#define ADC_CR_LINCALRDYW1 (1 << 22) /* Bit 22: ADC Linearity calibration ready Word 1*/ +#define ADC_CR_LINCALRDYW2 (1 << 23) /* Bit 23: ADC Linearity calibration ready Word 1*/ +#define ADC_CR_LINCALRDYW3 (1 << 24) /* Bit 24: ADC Linearity calibration ready Word 1*/ +#define ADC_CR_LINCALRDYW4 (1 << 25) /* Bit 25: ADC Linearity calibration ready Word 1*/ +#define ADC_CR_LINCALRDYW5 (1 << 26) /* Bit 26: ADC Linearity calibration ready Word 1*/ +#define ADC_CR_LINCALRDYW6 (1 << 27) /* Bit 27: ADC Linearity calibration ready Word 1*/ +#define ADC_CR_ADVREGEN (1 << 28) /* Bit 28: ADC voltage regulator enable */ +#define ADC_CR_DEEPPWD (1 << 29) /* Bit 29: Deep-power-down enable */ +#define ADC_CR_ADCALDIF (1 << 30) /* Bit 30: Differential mode for calibration */ +#define ADC_CR_ADCAL (1 << 31) /* Bit 31: ADC calibration */ + +/* ADC configuration register */ + +#define ADC_CFGR_DMNGT_SHIFT (0) /* Bits 0-1: Data Management configuration */ +#define ADC_CFGR_DMNGT_MASK (3 << ADC_CFGR_DMNGT_SHIFT) +# define ADC_CFGR_DMNGT_DR (0 << ADC_CFGR_DMNGT_SHIFT) /* Regular conversion data stored in DR only */ +# define ADC_CFGR_DMNGT_DMA_ONESHOT (1 << ADC_CFGR_DMNGT_SHIFT) /* RDMA One Shot Mode selected */ +# define ADC_CFGR_DMNGT_DFSDM (2 << ADC_CFGR_DMNGT_SHIFT) /* DFSDM mode selected */ +# define ADC_CFGR_DMNGT_DMA_CIR (3 << ADC_CFGR_DMNGT_SHIFT) /* DMA Circular Mode selected */ +#define ADC_CFGR_RES_SHIFT (0) /* Bits 2-4: Data resolution */ +#define ADC_CFGR_RES_MASK (7 << ADC_CFGR_RES_SHIFT) +# define ADC_CFGR_RES_16BIT (0 << ADC_CFGR_RES_SHIFT) /* 16 Bit */ +# define ADC_CFGR_RES_14BIT (1 << ADC_CFGR_RES_SHIFT) /* 14 Bit */ +# define ADC_CFGR_RES_12BIT (2 << ADC_CFGR_RES_SHIFT) /* 12 Bit */ +# define ADC_CFGR_RES_10BIT (3 << ADC_CFGR_RES_SHIFT) /* 10 Bit */ +# if defined(ADC_DEVICE_VERSION_V) +# define ADC_CFGR_RES_8BIT (7 << ADC_CFGR_RES_SHIFT) /* 8 rev V Bit */ +# else +# define ADC_CFGR_RES_8BIT (4 << ADC_CFGR_RES_SHIFT) /* 8 rev Y Bit */ +# endif +#define ADC_CFGR_EXTSEL_SHIFT (5) /* Bits 5-9: External Event Select for regular group */ +#define ADC_CFGR_EXTSEL_MASK (31 << ADC_CFGR_EXTSEL_SHIFT) +# define ADC_CFGR_EXTSEL(event) ((event) << ADC_CFGR_EXTSEL_SHIFT) /* Event = 0..31 */ +# define ADC_CFGR_EXTSEL_T1CC1 (0x00 << ADC_CFGR_EXTSEL_SHIFT) /* 00000: Timer 1 CC1 event */ +# define ADC_CFGR_EXTSEL_T1CC2 (0x01 << ADC_CFGR_EXTSEL_SHIFT) /* 00001: Timer 1 CC2 event */ +# define ADC_CFGR_EXTSEL_T1CC3 (0x02 << ADC_CFGR_EXTSEL_SHIFT) /* 00010: Timer 1 CC3 event */ +# define ADC_CFGR_EXTSEL_T2CC2 (0x03 << ADC_CFGR_EXTSEL_SHIFT) /* 00011: Timer 2 CC2 event */ +# define ADC_CFGR_EXTSEL_T3TRGO (0x04 << ADC_CFGR_EXTSEL_SHIFT) /* 00100: Timer 3 TRGO event */ +# define ADC_CFGR_EXTSEL_T4CC4 (0x05 << ADC_CFGR_EXTSEL_SHIFT) /* 00101: Timer 4 CC4 event */ +# define ADC_CFGR_EXTSEL_EXTI11 (0x06 << ADC_CFGR_EXTSEL_SHIFT) /* 00110: EXTI line 11 */ +# define ADC_CFGR_EXTSEL_T8TRGO (0x07 << ADC_CFGR_EXTSEL_SHIFT) /* 00111: Timer 8 TRGO event */ +# define ADC_CFGR_EXTSEL_T8TRGO2 (0x08 << ADC_CFGR_EXTSEL_SHIFT) /* 01000: Timer 8 TRGO2 event */ +# define ADC_CFGR_EXTSEL_T1TRGO (0x09 << ADC_CFGR_EXTSEL_SHIFT) /* 01001: Timer 1 TRGO event */ +# define ADC_CFGR_EXTSEL_T1TRGO2 (0x0a << ADC_CFGR_EXTSEL_SHIFT) /* 01010: Timer 1 TRGO2 event */ +# define ADC_CFGR_EXTSEL_T2TRGO (0x0b << ADC_CFGR_EXTSEL_SHIFT) /* 01011: Timer 2 TRGO event */ +# define ADC_CFGR_EXTSEL_T4TRGO (0x0c << ADC_CFGR_EXTSEL_SHIFT) /* 01100: Timer 4 TRGO event */ +# define ADC_CFGR_EXTSEL_T6TRGO (0x0d << ADC_CFGR_EXTSEL_SHIFT) /* 01101: Timer 6 TRGO event */ +# define ADC_CFGR_EXTSEL_T15TRGO (0x0e << ADC_CFGR_EXTSEL_SHIFT) /* 01110: Timer 15 TRGO event */ +# define ADC_CFGR_EXTSEL_T3CC4 (0x0f << ADC_CFGR_EXTSEL_SHIFT) /* 01111: Timer 3 CC4 event */ +# define ADC_CFGR_EXTSEL_HRTIM1TRG1 (0x10 << ADC_CFGR_EXTSEL_SHIFT) /* 10000: HRTIM1 ADC TRG1 event */ +# define ADC_CFGR_EXTSEL_HRTIM1TRG3 (0x11 << ADC_CFGR_EXTSEL_SHIFT) /* 10001: HRTIM1 ADC TRG3 event */ +# define ADC_CFGR_EXTSEL_LPTIM1_OUT (0x12 << ADC_CFGR_EXTSEL_SHIFT) /* 10010: LP TIM1 OUT CC4 event */ +# define ADC_CFGR_EXTSEL_LPTIM2_OUT (0x13 << ADC_CFGR_EXTSEL_SHIFT) /* 10011: LP TIM2 OUT CC4 event */ +# define ADC_CFGR_EXTSEL_LPTIM3_OUT (0x14 << ADC_CFGR_EXTSEL_SHIFT) /* 10100: LP TIM3 OUT CC4 event */ +#define ADC_CFGR_EXTEN_SHIFT (10) /* Bits 10-11: External trigger/polarity selection regular channels */ +#define ADC_CFGR_EXTEN_MASK (3 << ADC_CFGR_EXTEN_SHIFT) +# define ADC_CFGR_EXTEN_NONE (0 << ADC_CFGR_EXTEN_SHIFT) /* Trigger detection disabled */ +# define ADC_CFGR_EXTEN_RISING (1 << ADC_CFGR_EXTEN_SHIFT) /* Trigger detection on the rising edge */ +# define ADC_CFGR_EXTEN_FALLING (2 << ADC_CFGR_EXTEN_SHIFT) /* Trigger detection on the falling edge */ +# define ADC_CFGR_EXTEN_BOTH (3 << ADC_CFGR_EXTEN_SHIFT) /* Trigger detection on both edges */ +#define ADC_CFGR_OVRMOD (1 << 12) /* Bit 12: Overrun Mode */ +#define ADC_CFGR_CONT (1 << 13) /* Bit 13: Continuous mode for regular conversions */ +#define ADC_CFGR_AUTDLY (1 << 14) /* Bit 14: Delayed conversion mode */ +#define ADC_CFGR_DISCEN (1 << 16) /* Bit 16: Discontinuous mode on regular channels */ +#define ADC_CFGR_DISCNUM_SHIFT (17) /* Bits 17-19: Discontinuous mode channel count */ +#define ADC_CFGR_DISCNUM_MASK (7 << ADC_CFGR_DISCNUM_SHIFT) +# define ADC_CFGR_DISCNUM(n) (((n) - 1) << ADC_CFGR_DISCNUM_SHIFT) /* n = 1..8 channels */ +#define ADC_CFGR_JDISCEN (1 << 20) /* Bit 20: Discontinuous mode on injected channels */ +#define ADC_CFGR_JQM (1 << 21) /* Bit 21: JSQR queue mode */ +#define ADC_CFGR_AWD1SGL (1 << 22) /* Bit 22: Enable watchdog on single/all channels */ +#define ADC_CFGR_AWD1EN (1 << 23) /* Bit 23: Analog watchdog enable 1 regular channels */ +#define ADC_CFGR_JAWD1EN (1 << 22) /* Bit 22: Analog watchdog enable 1 injected channels */ +#define ADC_CFGR_JAUTO (1 << 25) /* Bit 25: Automatic Injected Group conversion */ +#define ADC_CFGR_AWD1CH_SHIFT (26) /* Bits 26-30: Analog watchdog 1 channel select bits */ +#define ADC_CFGR_AWD1CH_MASK (31 << ADC_CFGR_AWD1CH_SHIFT) +# define ADC_CFGR_AWD1CH_DISABLED (0 << ADC_CFGR_AWD1CH_SHIFT) +#define ADC_CFGR_JQDIS (1 << 31) /* Bit 31: Injected Queue disable */ + +/* ADC configuration register 2 */ + +#define ADC_CFGR2_ROVSE (1 << 0) /* Bit 0: Regular Oversampling Enable */ +#define ADC_CFGR2_JOVSE (1 << 1) /* Bit 1: Injected Oversampling Enable */ + /* Bits 2-4: Reserved */ +#define ADC_CFGR2_OVSS_SHIFT (5) /* Bits 5-8: Oversampling shift */ +#define ADC_CFGR2_OVSS_MASK (0xf << ADC_CFGR2_OVSS_SHIFT) +# define ADC_CFGR2_OVSS(value) ((value) << ADC_CFGR2_OVSS_SHIFT) /* Value = 0..11 */ +#define ADC_CFGR2_TROVS (1 << 9) /* Bit 9: Triggered Regular Oversampling */ +#define ADC_CFGR2_ROVSM (1 << 10) /* Bit 10: Regular Oversampling mode */ +#define ADC_CFGR2_RSHIFT1 (1 << 11) /* Bit 11: Right-shift data after Offset 1 correction*/ +#define ADC_CFGR2_RSHIFT2 (1 << 12) /* Bit 12: Right-shift data after Offset 2 correction*/ +#define ADC_CFGR2_RSHIFT3 (1 << 13) /* Bit 13: Right-shift data after Offset 3 correction*/ +#define ADC_CFGR2_RSHIFT4 (1 << 14) /* Bit 14: Right-shift data after Offset 4 correction*/ + /* Bit 15: Reserved */ +#define ADC_CFGR2_OVSR_SHIFT (16) /* Bits 16-25: Oversampling ratio */ +#define ADC_CFGR2_OVSR_MASK (0x3ff << ADC_CFGR2_OVSR_SHIFT) +# define ADC_CFGR2_OVSR(value) ((value) << ADC_CFGR2_OVSR_SHIFT) /* Value = 0..1024 */ + /* Bits 26-27: Reserved */ +#define ADC_CFGR2_LSHIFT_SHIFT (28) /* Bits 28-31: Left shift factor */ +#define ADC_CFGR2_LSHIFT_MASK (0xf << ADC_CFGR2_LSHIFT_SHIFT) +# define ADC_CFGR2_LSHIFT(value) ((value) << ADC_CFGR2_LSHIFT_SHIFT) /* Value = 0..15 */ + +/* ADC sample time register 1 */ + +#define ADC_SMPR_1p5 0 /* 000: 1.5 cycles */ +#define ADC_SMPR_2p5 1 /* 001: 2.5 cycles */ +#define ADC_SMPR_8p5 2 /* 010: 8.5 cycles */ +#define ADC_SMPR_16p5 3 /* 011: 16.5 cycles */ +#define ADC_SMPR_32p5 4 /* 100: 32.5 cycles */ +#define ADC_SMPR_64p5 5 /* 101: 64.5 cycles */ +#define ADC_SMPR_387p5 6 /* 110: 387.5 cycles */ +#define ADC_SMPR_810p5 7 /* 111: 810.5 cycles */ + +#define ADC_SMPR1_SMP0_SHIFT (0) /* Bits 2-0: Channel 0 Sample time selection */ +#define ADC_SMPR1_SMP0_MASK (7 << ADC_SMPR1_SMP0_SHIFT) + +#define ADC_SMPR1_SMP1_SHIFT (3) /* Bits 5-3: Channel 1 Sample time selection */ +#define ADC_SMPR1_SMP1_MASK (7 << ADC_SMPR1_SMP1_SHIFT) +#define ADC_SMPR1_SMP2_SHIFT (6) /* Bits 8-6: Channel 2 Sample time selection */ +#define ADC_SMPR1_SMP2_MASK (7 << ADC_SMPR1_SMP2_SHIFT) +#define ADC_SMPR1_SMP3_SHIFT (9) /* Bits 11-9: Channel 3 Sample time selection */ +#define ADC_SMPR1_SMP3_MASK (7 << ADC_SMPR1_SMP3_SHIFT) +#define ADC_SMPR1_SMP4_SHIFT (12) /* Bits 14-12: Channel 4 Sample time selection */ +#define ADC_SMPR1_SMP4_MASK (7 << ADC_SMPR1_SMP4_SHIFT) +#define ADC_SMPR1_SMP5_SHIFT (15) /* Bits 17-15: Channel 5 Sample time selection */ +#define ADC_SMPR1_SMP5_MASK (7 << ADC_SMPR1_SMP5_SHIFT) +#define ADC_SMPR1_SMP6_SHIFT (18) /* Bits 20-18: Channel 6 Sample time selection */ +#define ADC_SMPR1_SMP6_MASK (7 << ADC_SMPR1_SMP6_SHIFT) +#define ADC_SMPR1_SMP7_SHIFT (21) /* Bits 23-21: Channel 7 Sample time selection */ +#define ADC_SMPR1_SMP7_MASK (7 << ADC_SMPR1_SMP7_SHIFT) +#define ADC_SMPR1_SMP8_SHIFT (24) /* Bits 26-24: Channel 8 Sample time selection */ +#define ADC_SMPR1_SMP8_MASK (7 << ADC_SMPR1_SMP8_SHIFT) +#define ADC_SMPR1_SMP9_SHIFT (27) /* Bits 29-27: Channel 9 Sample time selection */ +#define ADC_SMPR1_SMP9_MASK (7 << ADC_SMPR1_SMP9_SHIFT) + +/* ADC sample time register 2 */ + +#define ADC_SMPR2_SMP10_SHIFT (0) /* Bits 0-2: Channel 10 Sample time selection */ +#define ADC_SMPR2_SMP10_MASK (7 << ADC_SMPR2_SMP10_SHIFT) +#define ADC_SMPR2_SMP11_SHIFT (3) /* Bits 3-5: Channel 11 Sample time selection */ +#define ADC_SMPR2_SMP11_MASK (7 << ADC_SMPR2_SMP11_SHIFT) +#define ADC_SMPR2_SMP12_SHIFT (6) /* Bits 6-8: Channel 12 Sample time selection */ +#define ADC_SMPR2_SMP12_MASK (7 << ADC_SMPR2_SMP12_SHIFT) +#define ADC_SMPR2_SMP13_SHIFT (9) /* Bits 9-11: Channel 13 Sample time selection */ +#define ADC_SMPR2_SMP13_MASK (7 << ADC_SMPR2_SMP13_SHIFT) +#define ADC_SMPR2_SMP14_SHIFT (12) /* Bits 12-14: Channel 14 Sample time selection */ +#define ADC_SMPR2_SMP14_MASK (7 << ADC_SMPR2_SMP14_SHIFT) +#define ADC_SMPR2_SMP15_SHIFT (15) /* Bits 15-17: Channel 15 Sample time selection */ +#define ADC_SMPR2_SMP15_MASK (7 << ADC_SMPR2_SMP15_SHIFT) +#define ADC_SMPR2_SMP16_SHIFT (18) /* Bits 18-20: Channel 16 Sample time selection */ +#define ADC_SMPR2_SMP16_MASK (7 << ADC_SMPR2_SMP16_SHIFT) +#define ADC_SMPR2_SMP17_SHIFT (21) /* Bits 21-23: Channel 17 Sample time selection */ +#define ADC_SMPR2_SMP17_MASK (7 << ADC_SMPR2_SMP17_SHIFT) +#define ADC_SMPR2_SMP18_SHIFT (24) /* Bits 24-26: Channel 18 Sample time selection */ +#define ADC_SMPR2_SMP18_MASK (7 << ADC_SMPR2_SMP18_SHIFT) +#define ADC_SMPR2_SMP19_SHIFT (27) /* Bits 27-29: Channel 19 Sample time selection */ +#define ADC_SMPR2_SMP19_MASK (7 << ADC_SMPR2_SMP19_SHIFT) + +/* ADC channel preselection register */ + +#define ADC_PCSEL_PCSEL_ALL 0xfffff /* Bits 0-19: All Channels pre selection */ +#define ADC_PCSEL_PCSEL0 (1 << 0) /* Bit 0: :Channel 0 (VINP[i]) pre selection */ +#define ADC_PCSEL_PCSEL1 (1 << 1) /* Bit 1: :Channel 1 (VINP[i]) pre selection */ +#define ADC_PCSEL_PCSEL2 (1 << 2) /* Bit 2: :Channel 2 (VINP[i]) pre selection */ +#define ADC_PCSEL_PCSEL3 (1 << 3) /* Bit 3: :Channel 3 (VINP[i]) pre selection */ +#define ADC_PCSEL_PCSEL4 (1 << 4) /* Bit 4: :Channel 4 (VINP[i]) pre selection */ +#define ADC_PCSEL_PCSEL5 (1 << 5) /* Bit 5: :Channel 5 (VINP[i]) pre selection */ +#define ADC_PCSEL_PCSEL6 (1 << 6) /* Bit 6: :Channel 6 (VINP[i]) pre selection */ +#define ADC_PCSEL_PCSEL7 (1 << 7) /* Bit 7: :Channel 7 (VINP[i]) pre selection */ +#define ADC_PCSEL_PCSEL8 (1 << 8) /* Bit 8: :Channel 8 (VINP[i]) pre selection */ +#define ADC_PCSEL_PCSEL9 (1 << 9) /* Bit 9: :Channel 9 (VINP[i]) pre selection */ +#define ADC_PCSEL_PCSEL10 (1 << 10) /* Bit 10: :Channel 10 (VINP[i]) pre selection */ +#define ADC_PCSEL_PCSEL11 (1 << 11) /* Bit 11: :Channel 11 (VINP[i]) pre selection */ +#define ADC_PCSEL_PCSEL12 (1 << 12) /* Bit 12: :Channel 12 (VINP[i]) pre selection */ +#define ADC_PCSEL_PCSEL13 (1 << 13) /* Bit 13: :Channel 13 (VINP[i]) pre selection */ +#define ADC_PCSEL_PCSEL14 (1 << 14) /* Bit 14: :Channel 14 (VINP[i]) pre selection */ +#define ADC_PCSEL_PCSEL15 (1 << 15) /* Bit 15: :Channel 15 (VINP[i]) pre selection */ +#define ADC_PCSEL_PCSEL16 (1 << 16) /* Bit 16: :Channel 16 (VINP[i]) pre selection */ +#define ADC_PCSEL_PCSEL17 (1 << 17) /* Bit 17: :Channel 17 (VINP[i]) pre selection */ +#define ADC_PCSEL_PCSEL18 (1 << 18) /* Bit 18: :Channel 18 (VINP[i]) pre selection */ +#define ADC_PCSEL_PCSEL19 (1 << 19) /* Bit 19: :Channel 19 (VINP[i]) pre selection */ + +/* ADC watchdog threshold register 1 Lower */ + +#define ADC_LTR1_LT_SHIFT (0) /* Bits 0-25: Analog watchdog 1 lower threshold */ +#define ADC_LTR1_LT_MASK (0x03ffffff << ADC_LTR1_LT_SHIFT) + +/* ADC watchdog threshold register 1 Higher */ + +#define ADC_HTR1_HT_SHIFT (0) /* Bits 0-25: Analog watchdog 1 higher threshold */ +#define ADC_HTR1_HT_MASK (0x03ffffff << ADC_HTR1_HT_SHIFT) + +/* Offset between SQ bits */ + +#define ADC_SQ_OFFSET (6) + +/* ADC regular sequence register 1 */ + +#define ADC_SQR1_L_SHIFT (0) /* Bits 0-3: Regular channel sequence length */ +#define ADC_SQR1_L_MASK (0x0f << ADC_SQR1_L_SHIFT) + /* Bits 4-5: Reserved */ +#define ADC_SQR1_SQ1_SHIFT (6) /* Bits 6-10: 13th conversion in regular sequence */ +#define ADC_SQR1_SQ1_MASK (0x1f << ADC_SQR1_SQ1_SHIFT) + /* Bit 11: Reserved */ +#define ADC_SQR1_SQ2_SHIFT (12) /* Bits 12-16: 2nd conversion in regular sequence */ +#define ADC_SQR1_SQ2_MASK (0x1f << ADC_SQR1_SQ2_SHIFT) + /* Bit 17: Reserved */ +#define ADC_SQR1_SQ3_SHIFT (18) /* Bits 18-22: 3rd conversion in regular sequence */ +#define ADC_SQR1_SQ3_MASK (0x1f << ADC_SQR1_SQ3_SHIFT) + /* Bit 23: Reserved */ +#define ADC_SQR1_SQ4_SHIFT (24) /* Bits 24-28: 4th conversion in regular sequence */ +#define ADC_SQR1_SQ4_MASK (0x1f << ADC_SQR1_SQ4_SHIFT) + /* Bits 29-31: Reserved */ +#define ADC_SQR1_RESERVED (0xe0820830) +#define ADC_SQR1_FIRST (1) +#define ADC_SQR1_LAST (4) +#define ADC_SQR1_SQ_OFFSET (1*ADC_SQ_OFFSET) + +/* ADC regular sequence register 2 */ + +#define ADC_SQR2_SQ5_SHIFT (0) /* Bits 4-0: 5th conversion in regular sequence */ +#define ADC_SQR2_SQ5_MASK (0x1f << ADC_SQR2_SQ5_SHIFT) + /* Bits 4-5: Reserved */ +#define ADC_SQR2_SQ6_SHIFT (6) /* Bits 6-10: 6th conversion in regular sequence */ +#define ADC_SQR2_SQ6_MASK (0x1f << ADC_SQR2_SQ6_SHIFT) + /* Bit 11: Reserved */ +#define ADC_SQR2_SQ7_SHIFT (12) /* Bits 12-16: 7th conversion in regular sequence */ +#define ADC_SQR2_SQ7_MASK (0x1f << ADC_SQR2_SQ7_SHIFT) + /* Bit 17: Reserved */ +#define ADC_SQR2_SQ8_SHIFT (18) /* Bits 18-22: 8th conversion in regular sequence */ +#define ADC_SQR2_SQ8_MASK (0x1f << ADC_SQR2_SQ8_SHIFT) + /* Bit 23: Reserved */ +#define ADC_SQR2_SQ9_SHIFT (24) /* Bits 24-28: 9th conversion in regular sequence */ +#define ADC_SQR2_SQ9_MASK (0x1f << ADC_SQR2_SQ9_SHIFT ) + /* Bits 29-31: Reserved */ +#define ADC_SQR2_RESERVED (0xe0820820) +#define ADC_SQR2_FIRST (5) +#define ADC_SQR2_LAST (9) +#define ADC_SQR2_SQ_OFFSET (0) + +/* ADC regular sequence register 3 */ + +#define ADC_SQR3_SQ10_SHIFT (0) /* Bits 4-0: 10th conversion in regular sequence */ +#define ADC_SQR3_SQ10_MASK (0x1f << ADC_SQR3_SQ10_SHIFT) + /* Bits 4-5: Reserved */ +#define ADC_SQR3_SQ11_SHIFT (6) /* Bits 6-10: 11th conversion in regular sequence */ +#define ADC_SQR3_SQ11_MASK (0x1f << ADC_SQR3_SQ11_SHIFT) + /* Bit 11: Reserved */ +#define ADC_SQR3_SQ12_SHIFT (12) /* Bits 12-16: 12th conversion in regular sequence */ +#define ADC_SQR3_SQ12_MASK (0x1f << ADC_SQR3_SQ12_SHIFT) + /* Bit 17: Reserved */ +#define ADC_SQR3_SQ13_SHIFT (18) /* Bits 18-22: 13th conversion in regular sequence */ +#define ADC_SQR3_SQ13_MASK (0x1f << ADC_SQR3_SQ13_SHIFT) + /* Bit 23: Reserved */ +#define ADC_SQR3_SQ14_SHIFT (24) /* Bits 24-28: 14th conversion in regular sequence */ +#define ADC_SQR3_SQ14_MASK (0x1f << ADC_SQR3_SQ14_SHIFT) +#define ADC_SQR3_RESERVED (0xe0820820) +#define ADC_SQR3_FIRST (10) +#define ADC_SQR3_LAST (14) +#define ADC_SQR3_SQ_OFFSET (0) + +/* ADC regular sequence register 4 */ + +#define ADC_SQR4_SQ15_SHIFT (0) /* Bits 4-0: 15th conversion in regular sequence */ +#define ADC_SQR4_SQ15_MASK (0x1f << ADC_SQR4_SQ15_SHIFT) + /* Bit 5: Reserved */ +#define ADC_SQR4_SQ16_SHIFT (6) /* Bits 6-10: 16th conversion in regular sequence */ +#define ADC_SQR4_SQ16_MASK (0x1f << ADC_SQR4_SQ16_SHIFT) + /* Bits 11-31: Reserved */ +#define ADC_SQR4_RESERVED (0xfffff820) +#define ADC_SQR4_FIRST (15) +#define ADC_SQR4_LAST (16) +#define ADC_SQR4_SQ_OFFSET (0) + +/* ADC regular data register */ + +#define ADC_DR_MASK (0xffffffff) + +/* ADC injected sequence register */ + +#define ADC_JSQR_JL_SHIFT (0) /* Bits 0-1: Injected Sequence length */ +#define ADC_JSQR_JL_MASK (3 << ADC_JSQR_JL_SHIFT) +# define ADC_JSQR_JL(n) (((n)-1) << ADC_JSQR_JL_SHIFT) /* n=1..4 */ +#define ADC_JSQR_JEXTSEL_SHIFT (2) /* Bits 2-6: External Trigger Selection for injected group */ +#define ADC_JSQR_JEXTSEL_MASK (31 << ADC_JSQR_JEXTSEL_SHIFT) +# define ADC_JSQR_JEXTSEL(event) ((event) << ADC_JSQR_JEXTSEL_SHIFT) /* Event = 0..31 */ +#define ADC_JSQR_JEXTEN_SHIFT (7) /* Bits 7-8: External trigger selection for injected greoup */ +#define ADC_JSQR_JEXTEN_MASK (3 << ADC_JSQR_JEXTEN_SHIFT) +# define ADC_JSQR_JEXTEN_NONE (0 << ADC_JSQR_JEXTEN_SHIFT) /* 00: Trigger detection disabled */ +# define ADC_JSQR_JEXTEN_RISING (1 << ADC_JSQR_JEXTEN_SHIFT) /* 01: Trigger detection on the rising edge */ +# define ADC_JSQR_JEXTEN_FALLING (2 << ADC_JSQR_JEXTEN_SHIFT) /* 10: Trigger detection on the falling edge */ +# define ADC_JSQR_JEXTEN_BOTH (3 << ADC_JSQR_JEXTEN_SHIFT) /* 11: Trigger detection on both the rising and falling edges */ +#define ADC_JSQR_JSQ1_SHIFT (9) /* Bits 9-13: 1st conversion in injected sequence */ +#define ADC_JSQR_JSQ1_MASK (0x1f << ADC_JSQR_JSQ1_SHIFT) +# define ADC_JSQR_JSQ1(ch) ((ch) << ADC_JSQR_JSQ1_SHIFT) /* Channel number 0..19 */ + /* Bit 14: Reserved */ +#define ADC_JSQR_JSQ2_SHIFT (15) /* Bits 15-19: 2nd conversion in injected sequence */ +#define ADC_JSQR_JSQ2_MASK (0x1f << ADC_JSQR_JSQ2_MASK) +# define ADC_JSQR_JSQ2(ch) ((ch) << ADC_JSQR_JSQ2_MASK) /* Channel number 0..19 */ + /* Bit 20: Reserved */ +#define ADC_JSQR_JSQ3_SHIFT (21) /* Bits 21-25: 3rd conversion in injected sequence */ +#define ADC_JSQR_JSQ3_MASK (0x1f << ADC_JSQR_JSQ3_SHIFT) +# define ADC_JSQR_JSQ3(ch) ((ch) << ADC_JSQR_JSQ3_SHIFT) /* Channel number 0..19 */ + /* Bit 26: Reserved */ +#define ADC_JSQR_JSQ4_SHIFT (27) /* Bits 27-31: 4th conversion in injected sequence */ +#define ADC_JSQR_JSQ4_MASK (0x1f << ADC_JSQR_JSQ4_SHIFT) +# define ADC_JSQR_JSQ4(ch) ((ch) << ADC_JSQR_JSQ4_SHIFT) /* Channel number 0..19 */ + +/* ADC offset register 1, 2, 3, and 4 */ + +#define ADC_OFR_OFFSETY_SHIFT (0) /* Bits 0-25: Data offset y for channel OFFSETY_CH */ +#define ADC_OFR_OFFSETY_MASK (0x03ffffff << ADC_OFR_OFFSETY_SHIFT) +# define ADC_OFR_OFFSETY(offset) ((offset) << ADC_OFR_OFFSETY_SHIFT) +#define ADC_OFR_OFFSETY_CH_SHIFT (26) /* Bits 26-30: Channel selection for data offset y */ +#define ADC_OFR_OFFSETY_CH_MASK (31 << ADC_OFR_OFFSETY_CH_SHIFT) +# define ADC_OFR_OFFSETY_CH(ch) ((ch) << ADC_OFR_OFFSETY_CH_SHIFT) +#define ADC_OFR_SSATE_EN (1 << 31) /* Bit 31: Signed saturation Enable */ + +/* ADC injected data register 1, 2, 3, and 4 */ + +#define ADC_JDR_MASK (0xffffffff) + +/* ADC analog watchdog 2 configuration register */ + +#define ADC_AWD2CR_CH_SHIFT (0) /* Bits 0-19: Analog watchdog 2 channel selection */ +#define ADC_AWD2CR_CH_MASK (0xfffff << ADC_AWD2CR_CH_SHIFT) +# define ADC_AWD2CR_CH(n) (1 << (n)) /* Channel n=0..19 */ + /* Bits 20-31: Reserved */ + +/* ADC analog watchdog 3 configuration register */ + +#define ADC_AWD3CR_CH_SHIFT (0) /* Bits 0-19: Analog watchdog 2 channel selection */ +#define ADC_AWD3CR_CH_MASK (0xfffff << ADC_AWD3CR_CH_SHIFT) +# define ADC_AWD3CR_CH(n) (1 << (n)) /* Channel n=0..19 */ + /* Bits 20-31: Reserved */ + +/* ADC watchdog threshold register 2 Lower */ + +#define ADC_LTR2_LT_SHIFT (0) /* Bits 0-25: Analog watchdog 2 lower threshold */ +#define ADC_LTR2_LT_MASK (0x03ffffff << ADC_LTR2_LT_SHIFT) + /* Bits 26-31: Reserved */ + +/* ADC watchdog threshold register 2 Higher */ + +#define ADC_HTR2_HT_SHIFT (0) /* Bits 0-25: Analog watchdog 2 higher threshold */ +#define ADC_HTR2_HT_MASK (0x03ffffff << ADC_HTR2_LT_SHIFT) + /* Bits 26-31: Reserved */ + +/* ADC watchdog threshold register 3 Lower */ + +#define ADC_LTR3_LT_SHIFT (0) /* Bits 0-25: Analog watchdog 3 lower threshold */ +#define ADC_LTR3_LT_MASK (0x03ffffff << ADC_LTR3_LT_SHIFT) + /* Bits 26-31: Reserved */ + +/* ADC watchdog threshold register 2 Higher */ + +#define ADC_HTR3_HT_SHIFT (0) /* Bits 0-25: Analog watchdog 3 higher threshold */ +#define ADC_HTR3_HT_MASK (0x03ffffff << ADC_HTR3_LT_SHIFT) + /* Bits 26-31: Reserved */ + + +/* ADC differential mode selection register */ + +#define ADC_DIFSEL_CH_SHIFT (0) /* Bits 0-19: Analog watchdog 2 channel selection */ +#define ADC_DIFSEL_CH_MASK (0xfffff << ADC_DIFSEL_CH_SHIFT) +# define ADC_DIFSEL_CH(n) (1 << (n)) /* Channel n=0..19 */ + /* Bits 20-31: Reserved */ + +/* ADC calibration factors */ + +#define ADC_CALFACT_S_SHIFT (0) /* Bits 0-10: Calibration factors in single-ended mode */ +#define ADC_CALFACT_S_MASK (0x7ff << ADC_CALFACT_S_SHIFT) +#define ADC_CALFACT_D_SHIFT (16) /* Bits 16-26: Calibration Factors indifferential mode */ +#define ADC_CALFACT_D_MASK (0x7ff << ADC_CALFACT_D_SHIFT) + /* Bits 27-31: Reserved */ + +/* ADC calibration factor register 2 */ + +#define ADC_CALFACT2_LINCALFACT_SHIFT (0) /* Bits 0-29: Calibration factors in single-ended mode */ +#define ADC_CALFACT2_LINCALFACT_MASK (0x3fffffff << ADC_CALFACT2_LINCALFACT_SHIFT) + /* Bits 30-31: Reserved */ + +/* Common status register */ + +#define ADC_CSR_ADRDY_MST (1 << 0) /* Bit 0: Master ADC ready */ +#define ADC_CSR_EOSMP_MST (1 << 1) /* Bit 1: End of Sampling phase flag (master ADC) */ +#define ADC_CSR_EOC_MST (1 << 2) /* Bit 2: End of regular conversion (master ADC) */ +#define ADC_CSR_EOS_MST (1 << 3) /* Bit 3: End of regular sequence flag (master ADC) */ +#define ADC_CSR_OVR_MST (1 << 4) /* Bit 4: Overrun flag (master ADC) */ +#define ADC_CSR_JEOC_MST (1 << 5) /* Bit 5: End of injected conversion flag (master ADC) */ +#define ADC_CSR_JEOS_MST (1 << 6) /* Bit 6: End of injected sequence flag (master ADC) */ +#define ADC_CSR_AWD1_MST (1 << 7) /* Bit 7: Analog watchdog 1 flag (master ADC) */ +#define ADC_CSR_AWD2_MST (1 << 8) /* Bit 8: Analog watchdog 2 flag (master ADC) */ +#define ADC_CSR_AWD3_MST (1 << 9) /* Bit 9: Analog watchdog 3 flag (master ADC) */ +#define ADC_CSR_JQOVF_MST (1 << 10) /* Bit 10: Injected Context Queue Overflow flag (master ADC) */ + /* Bits 11-15: Reserved */ +#define ADC_CSR_ADRDY_SLV (1 << 16) /* Bit 16: Slave ADC ready */ +#define ADC_CSR_EOSMP_SLV (1 << 17) /* Bit 17: End of Sampling phase flag (slave ADC) */ +#define ADC_CSR_EOC_SLV (1 << 18) /* Bit 18: End of regular conversion (slave ADC) */ +#define ADC_CSR_EOS_SLV (1 << 19) /* Bit 19: End of regular sequence flag (slave ADC) */ +#define ADC_CSR_OVR_SLV (1 << 20) /* Bit 20: Overrun flag (slave ADC) */ +#define ADC_CSR_JEOC_SLV (1 << 21) /* Bit 21: End of injected conversion flag (slave ADC) */ +#define ADC_CSR_JEOS_SLV (1 << 22) /* Bit 22: End of injected sequence flag (slave ADC) */ +#define ADC_CSR_AWD1_SLV (1 << 23) /* Bit 23: Analog watchdog 1 flag (slave ADC) */ +#define ADC_CSR_AWD2_SLV (1 << 24) /* Bit 24: Analog watchdog 2 flag (slave ADC) */ +#define ADC_CSR_AWD3_SLV (1 << 25) /* Bit 25: Analog watchdog 3 flag (slave ADC) */ +#define ADC_CSR_JQOVF_SLV (1 << 26) /* Bit 26: Injected Context Queue Overflow flag (slave ADC) */ + /* Bits 27-31: Reserved */ + +/* Common control register */ + +#define ADC_CCR_DUAL_SHIFT (0) /* Bits 0-4: Dual ADC mode selection */ +#define ADC_CCR_DUAL_MASK (31 << ADC_CCR_DUAL_SHIFT) +# define ADC_CCR_DUAL_IND (0 << ADC_CCR_DUAL_SHIFT) /* Independent mode */ +# define ADC_CCR_DUAL_DUAL (1 << ADC_CCR_DUAL_SHIFT) /* Dual mode, master/slave ADCs together */ +# define ADC_CCR_DUAL_SIMINJ (1 << ADC_CCR_DUAL_SHIFT) /* Combined regular sim. + injected sim. */ +# define ADC_CCR_DUAL_SIMALT (2 << ADC_CCR_DUAL_SHIFT) /* Combined regular sim. + alternate trigger */ +# define ADC_CCR_DUAL_INJECTED (5 << ADC_CCR_DUAL_SHIFT) /* Injected simultaneous mode only */ +# define ADC_CCR_DUAL_SIM (6 << ADC_CCR_DUAL_SHIFT) /* Regular simultaneous mode only */ +# define ADC_CCR_DUAL_INTERLEAVE (7 << ADC_CCR_DUAL_SHIFT) /* Interleaved mode only */ +# define ADC_CCR_DUAL_ALT (9 << ADC_CCR_DUAL_SHIFT) /* Alternate trigger mode only */ + /* Bits 5-7: Reserved */ +#define ADC_CCR_DELAY_SHIFT (8) /* Bits 8-11: Delay between 2 sampling phases */ +#define ADC_CCR_DELAY_MASK (15 << ADC_CCR_DELAY_SHIFT) +# define ADC_CCR_DELAY(n) (((n)-1) << ADC_CCR_DELAY_SHIFT) /* n * TADCCLK, 1-13 */ + /* Bits 12-13: Reserved */ +#define ADC_CCR_DAMDF_SHIFT (14) /* Bits 14-15: Dual ADC Mode Data Format */ +#define ADC_CCR_DAMDF_MASK (3 << ADC_CCR_DAMDF_MASK) +# define ADC_CCR_DAMDF_NOPACK (0 << ADC_CCR_DAMDF_MASK) /* Dual ADC mode without data packing */ +# define ADC_CCR_DAMDF_RESERVD (1 << ADC_CCR_DAMDF_MASK) /* Reserved. */ +# define ADC_CCR_DAMDF_32_10 (2 << ADC_CCR_DAMDF_MASK) /* Data formatting mode for 32 down to 10-bit resolution */ +# define ADC_CCR_DAMDF_8 (3 << ADC_CCR_DAMDF_MASK) /* Data formatting mode for 8-bit resolution */ +#define ADC_CCR_CKMODE_SHIFT (16) /* Bits 16-17: ADC clock mode */ +#define ADC_CCR_CKMODE_MASK (3 << ADC_CCR_CKMODE_SHIFT) +# define ADC_CCR_CKMODE_ASYCH (0 << ADC_CCR_CKMODE_SHIFT) /* Asynchronous clock mode */ +# define ADC_CCR_CKMODE_SYNCH_DIV1 (1 << ADC_CCR_CKMODE_SHIFT) /* Synchronous clock mode divided by 1 */ +# define ADC_CCR_CKMODE_SYNCH_DIV2 (2 << ADC_CCR_CKMODE_SHIFT) /* Synchronous clock mode divided by 2 */ +# define ADC_CCR_CKMODE_SYNCH_DIV4 (3 << ADC_CCR_CKMODE_SHIFT) /* Synchronous clock mode divided by 4 */ +#define ADC_CCR_PRESC_SHIFT (18) /* Bits 18-21: ADC prescaler */ +#define ADC_CCR_PRESC_MASK (15 << ADC_CCR_PRESC_SHIFT) +# define ADC_CCR_PRESC_NOT_DIV (0 << ADC_CCR_PRESC_SHIFT) /* Input ADC clock not divided */ +# define ADC_CCR_PRESC_DIV2 (1 << ADC_CCR_PRESC_SHIFT) /* Input ADC clock divided by 2 */ +# define ADC_CCR_PRESC_DIV4 (2 << ADC_CCR_PRESC_SHIFT) /* Input ADC clock divided by 4 */ +# define ADC_CCR_PRESC_DIV6 (3 << ADC_CCR_PRESC_SHIFT) /* Input ADC clock divided by 6 */ +# define ADC_CCR_PRESC_DIV8 (4 << ADC_CCR_PRESC_SHIFT) /* Input ADC clock divided by 8 */ +# define ADC_CCR_PRESC_DIV10 (5 << ADC_CCR_PRESC_SHIFT) /* Input ADC clock divided by 10 */ +# define ADC_CCR_PRESC_DIV12 (6 << ADC_CCR_PRESC_SHIFT) /* Input ADC clock divided by 12 */ +# define ADC_CCR_PRESC_DIV16 (7 << ADC_CCR_PRESC_SHIFT) /* Input ADC clock divided by 16 */ +# define ADC_CCR_PRESC_DIV32 (8 << ADC_CCR_PRESC_SHIFT) /* Input ADC clock divided by 32 */ +# define ADC_CCR_PRESC_DIV64 (9 << ADC_CCR_PRESC_SHIFT) /* Input ADC clock divided by 64 */ +# define ADC_CCR_PRESC_DIV128 (10 << ADC_CCR_PRESC_SHIFT) /* Input ADC clock divided by 128 */ +# define ADC_CCR_PRESC_DIV256 (11 << ADC_CCR_PRESC_SHIFT) /* Input ADC clock divided by 256 */ +#define ADC_CCR_VREFEN (1 << 22) /* Bit 22: VREFINT enable */ +#define ADC_CCR_VSENSEEN (1 << 23) /* Bit 23: Temperature sensor voltage enable */ +#define ADC_CCR_VBATEN (1 << 24) /* Bit 22: VBAT enable */ + +/* Common regular data register for dual mode */ + +#define ADC_CDR_RDATA_MST_SHIFT (0) /* Bits 0-15: Regular data of the master ADC */ +#define ADC_CDR_RDATA_MST_MASK (0xffff << ADC_CDR_RDATA_MST_SHIFT) +#define ADC_CDR_RDATA_SLV_SHIFT (16) /* Bits 16-31: Regular data of the slave ADC */ +#define ADC_CDR_RDATA_SLV_MASK (0xffff << ADC_CDR_RDATA_SLV_SHIFT) + +/* Common regular data register for 32 bit dual mode */ + +#define ADC_CDR2_RDATA_ALT_SHIFT (0) /* Bits 0-31: Regular data of the master/slave alternated ADCs */ +#define ADC_CDR2_RDATA_ALT_MASK (0xffffffff << ADC_CDR_RDATA_ALT_SHIFT) + +#endif /* __ARCH_ARM_SRC_STM32H7_HARDWARE_STM32_ADC_H */ diff --git a/arch/arm/src/stm32h7/hardware/stm32h7x3xx_pinmap.h b/arch/arm/src/stm32h7/hardware/stm32h7x3xx_pinmap.h index 1367baba5e..da4003c554 100644 --- a/arch/arm/src/stm32h7/hardware/stm32h7x3xx_pinmap.h +++ b/arch/arm/src/stm32h7/hardware/stm32h7x3xx_pinmap.h @@ -70,6 +70,68 @@ * pins in this file. */ +/* ADC */ + +#define GPIO_ADC1_INP2 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN11) +#define GPIO_ADC1_INN2 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN12) +#define GPIO_ADC1_INP6 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN12) +#define GPIO_ADC1_INP16 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN0) +#define GPIO_ADC1_INN16 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN1) +#define GPIO_ADC1_INP17 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN1) + +#define GPIO_ADC12_INP0 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN0_C) +#define GPIO_ADC12_INP1 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN1_C) +#define GPIO_ADC12_INN1 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN0_C) +#define GPIO_ADC12_INP3 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN6) +#define GPIO_ADC12_INN3 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN7) +#define GPIO_ADC12_INP4 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN4) +#define GPIO_ADC12_INN4 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN5) +#define GPIO_ADC12_INP5 (GPIO_ANALOG|GPIO_PORTB|GPIO_PIN1) +#define GPIO_ADC12_INN5 (GPIO_ANALOG|GPIO_PORTB|GPIO_PIN0) +#define GPIO_ADC12_INP7 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN7) +#define GPIO_ADC12_INP8 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN5) +#define GPIO_ADC12_INP9 (GPIO_ANALOG|GPIO_PORTB|GPIO_PIN0) +#define GPIO_ADC12_INN12 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN3) +#define GPIO_ADC12_INP13 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN3) +#define GPIO_ADC12_INP14 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN2) +#define GPIO_ADC12_INP15 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN3) +#define GPIO_ADC12_INP18 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN4) +#define GPIO_ADC12_INN18 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN5) +#define GPIO_ADC12_INP19 (GPIO_ANALOG|GPIO_PORTA|GPIO_PIN5) + +#define GPIO_ADC123_INP10 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN0) +#define GPIO_ADC123_INN10 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN1) +#define GPIO_ADC123_INP11 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN1) +#define GPIO_ADC123_INN11 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN2) +#define GPIO_ADC123_INP12 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN2) + +#define GPIO_ADC2_INN2 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN14) +#define GPIO_ADC2_INP2 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN13) +#define GPIO_ADC2_INP6 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN14) + +#define GPIO_ADC3_INP0 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN2_C) +#define GPIO_ADC3_INP1 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN3_C) +#define GPIO_ADC3_INN1 (GPIO_ANALOG|GPIO_PORTC|GPIO_PIN2_C) +#define GPIO_ADC3_INP2 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN9) +#define GPIO_ADC3_INN2 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN10) +#define GPIO_ADC3_INP3 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN7) +#define GPIO_ADC3_INN3 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN8) +#define GPIO_ADC3_INP4 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN5) +#define GPIO_ADC3_INN4 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN6) +#define GPIO_ADC3_INP5 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN3) +#define GPIO_ADC3_INN5 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN4) +#define GPIO_ADC3_INP6 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN10) +#define GPIO_ADC3_INP7 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN8) +#define GPIO_ADC3_INP8 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN6) +#define GPIO_ADC3_INP9 (GPIO_ANALOG|GPIO_PORTF|GPIO_PIN4) +#define GPIO_ADC3_INP13 (GPIO_ANALOG|GPIO_PORTH|GPIO_PIN2) +#define GPIO_ADC3_INN13 (GPIO_ANALOG|GPIO_PORTH|GPIO_PIN3) +#define GPIO_ADC3_INP14 (GPIO_ANALOG|GPIO_PORTH|GPIO_PIN3) +#define GPIO_ADC3_INN14 (GPIO_ANALOG|GPIO_PORTH|GPIO_PIN4) +#define GPIO_ADC3_INP15 (GPIO_ANALOG|GPIO_PORTH|GPIO_PIN4) +#define GPIO_ADC3_INN15 (GPIO_ANALOG|GPIO_PORTH|GPIO_PIN5) +#define GPIO_ADC3_INP16 (GPIO_ANALOG|GPIO_PORTH|GPIO_PIN5) + /* CAN */ #define GPIO_CAN1_RX_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN11) diff --git a/arch/arm/src/stm32h7/stm32_adc.c b/arch/arm/src/stm32h7/stm32_adc.c new file mode 100644 index 0000000000..c79742ad18 --- /dev/null +++ b/arch/arm/src/stm32h7/stm32_adc.c @@ -0,0 +1,2013 @@ +/**************************************************************************** + * arch/arm/src/stm32h7/stm32_adc.c + * + * Copyright (C) 2017, 2019 Gregory Nutt. All rights reserved. + * Copyright (C) 2015 Motorola Mobility, LLC. All rights reserved. + * Copyright (C) 2015 Omni Hoverboards Inc. All rights reserved. + * Authors: Gregory Nutt + * Diego Sanchez + * Paul Alexander Patience + * Mateusz Szafoni + * Juha Niskanen + * David Sidrane + * + * 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 + +#include "chip.h" +#include "stm32_rcc.h" +#include "stm32_tim.h" +#include "stm32_dma.h" +#include "stm32_adc.h" + +/* ADC "upper half" support must be enabled */ + +#ifdef CONFIG_ADC + +/* Some ADC peripheral must be enabled */ + +#if defined(CONFIG_STM32H7_ADC1) || defined(CONFIG_STM32H7_ADC2) || \ + defined(CONFIG_STM32H7_ADC3) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef container_of +# define container_of(ptr, type, member) \ + ((type *)((intptr_t)(ptr) - offsetof(type, member))) +#endif + +/* ADC Channels/DMA ********************************************************/ +/* The maximum number of channels that can be sampled. While DMA support is + * very nice for reliable multi-channel sampling, the STM32H7 can function + * without, although there is a risk of overrun. + */ + +#define ADC_MAX_CHANNELS_DMA 20 +#define ADC_MAX_CHANNELS_NODMA 20 + +#ifdef ADC_HAVE_DMA +# if !defined(CONFIG_STM32H7_DMA1) && !defined(CONFIG_STM32H7_DMA2) +# /* REVISIT: check accordingly to which one is configured in board.h */ +# error "STM32H7 ADC DMA support requires CONFIG_STM32H7_DMA1 or CONFIG_STM32H7_DMA2" +# endif +#endif + +#ifdef ADC_HAVE_DMA +# define ADC_MAX_SAMPLES ADC_MAX_CHANNELS_DMA +#else +# define ADC_MAX_SAMPLES ADC_MAX_CHANNELS_NODMA +#endif + +#define ADC_DMA_CONTROL_WORD (DMA_CCR_MSIZE_16BITS | \ + DMA_CCR_PSIZE_16BITS | \ + DMA_CCR_MINC | \ + DMA_CCR_CIRC) + +/* DMA channels and interface values */ + +#define ADC_SMPR_DEFAULT ADC_SMPR_810p5 +#define ADC_SMPR1_DEFAULT ((ADC_SMPR_DEFAULT << ADC_SMPR1_SMP0_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR1_SMP1_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR1_SMP2_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR1_SMP3_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR1_SMP4_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR1_SMP5_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR1_SMP6_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR1_SMP7_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR1_SMP8_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR1_SMP9_SHIFT)) +#define ADC_SMPR2_DEFAULT ((ADC_SMPR_DEFAULT << ADC_SMPR2_SMP10_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR2_SMP11_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR2_SMP12_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR2_SMP13_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR2_SMP14_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR2_SMP15_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR2_SMP16_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR2_SMP17_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR2_SMP18_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR2_SMP19_SHIFT)) + +/* The channels not in this range are internal channels for reading + * Vbat ADC3:17, VSence (temperature) ADC3:18 and Vrefint ADC3:19 + * + * N.B. DAC channels on ADC2 are not supported + */ + +#define ADC_EXTERNAL_CHAN_MAX 16 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure describes the state of one ADC block */ + +struct stm32_dev_s +{ + FAR const struct adc_callback_s *cb; + uint8_t irq; /* Interrupt generated by this ADC block */ + uint8_t nchannels; /* Number of channels */ + uint8_t cchannels; /* Number of configured channels */ + uint8_t intf; /* ADC interface number */ + uint8_t current; /* Current ADC channel being converted */ +#ifdef ADC_HAVE_DMA + uint8_t dmachan; /* DMA channel needed by this ADC */ + bool hasdma; /* True: This ADC supports DMA */ +#endif +#ifdef ADC_HAVE_DFSDM + bool hasdfsdm; /* True: This ADC routes its output to DFSDM */ +#endif +#ifdef ADC_HAVE_TIMER + uint8_t trigger; /* Timer trigger channel: 0=CC1, 1=CC2, 2=CC3, + * 3=CC4, 4=TRGO, 5=TRGO2 */ +#endif + xcpt_t isr; /* Interrupt handler for this ADC block */ + uint32_t base; /* Base address of registers unique to this ADC + * block */ +#ifdef ADC_HAVE_TIMER + uint32_t tbase; /* Base address of timer used by this ADC block */ + uint32_t trcc_enr; /* RCC ENR Register */ + uint32_t trcc_en; /* RCC EN Bit in ENR Register */ + uint32_t extsel; /* EXTSEL value used by this ADC block */ + uint32_t pclck; /* The PCLK frequency that drives this timer */ + uint32_t freq; /* The desired frequency of conversions */ +#endif + +#ifdef CONFIG_PM + struct pm_callback_s pm_callback; +#endif + +#ifdef ADC_HAVE_DMA + DMA_HANDLE dma; /* Allocated DMA channel */ + + /* DMA transfer buffer */ + + uint16_t dmabuffer[ADC_MAX_SAMPLES]; +#endif + + /* List of selected ADC channels to sample */ + + uint8_t chanlist[ADC_MAX_SAMPLES]; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* ADC Register access */ + +static uint32_t adc_getreg(FAR struct stm32_dev_s *priv, int offset); +static void adc_putreg(FAR struct stm32_dev_s *priv, int offset, + uint32_t value); +static void adc_modifyreg(FAR struct stm32_dev_s *priv, int offset, + uint32_t clrbits, uint32_t setbits); + +#ifdef ADC_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 + +/* ADC Miscellaneous Helpers */ + +static void adc_rccreset(FAR struct stm32_dev_s *priv, bool reset); +static void adc_enable(FAR struct stm32_dev_s *priv); +static uint32_t adc_sqrbits(FAR struct stm32_dev_s *priv, int first, int last, + int offset); +static int adc_set_ch(FAR struct adc_dev_s *dev, uint8_t ch); +static bool adc_internal(FAR struct stm32_dev_s * priv, uint32_t *adc_ccr); + +#ifdef ADC_HAVE_TIMER +static void adc_timstart(FAR struct stm32_dev_s *priv, bool enable); +static int adc_timinit(FAR struct stm32_dev_s *priv); +#endif + +#ifdef ADC_HAVE_DMA +static void adc_dmaconvcallback(DMA_HANDLE handle, uint8_t isr, + FAR void *arg); +#endif + +#ifdef ADC_HAVE_DFSDM +static int adc_setoffset(FAR struct stm32_dev_s *priv, uint8_t ch, uint8_t i, + uint16_t offset); +#endif + +static void adc_startconv(FAR struct stm32_dev_s *priv, bool enable); + +#ifdef CONFIG_PM +static int adc_pm_prepare(struct pm_callback_s *cb, int domain, + enum pm_state_e state); +#endif + +/* ADC Interrupt Handler */ + +static int adc_interrupt(FAR struct adc_dev_s *dev, uint32_t regval); +#if defined(CONFIG_STM32H7_ADC1) || defined(CONFIG_STM32H7_ADC2) +static int adc12_interrupt(int irq, FAR void *context, FAR void *arg); +#endif +#if defined(CONFIG_STM32H7_ADC3) +static int adc3_interrupt(int irq, FAR void *context, FAR void *arg); +#endif + +/* ADC Driver Methods */ + +static int adc_bind(FAR struct adc_dev_s *dev, + FAR const struct adc_callback_s *callback); +static void adc_reset(FAR struct adc_dev_s *dev); +static int adc_setup(FAR struct adc_dev_s *dev); +static void adc_shutdown(FAR struct adc_dev_s *dev); +static void adc_rxint(FAR struct adc_dev_s *dev, bool enable); +static int adc_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 = adc_bind, + .ao_reset = adc_reset, + .ao_setup = adc_setup, + .ao_shutdown = adc_shutdown, + .ao_rxint = adc_rxint, + .ao_ioctl = adc_ioctl, +}; + +/* ADC1 state */ + +#ifdef CONFIG_STM32H7_ADC1 +static struct stm32_dev_s g_adcpriv1 = +{ + .irq = STM32_IRQ_ADC12, + .isr = adc12_interrupt, + .intf = 1, + .base = STM32_ADC1_BASE, +#ifdef ADC1_HAVE_TIMER + .trigger = CONFIG_STM32H7_ADC1_TIMTRIG, + .tbase = ADC1_TIMER_BASE, + .trcc_enr = ADC1_TIMER_RCC_ENR, + .trcc_en = ADC1_TIMER_RCC_EN, + .extsel = ADC1_EXTSEL_VALUE, + .pclck = ADC1_TIMER_PCLK_FREQUENCY, + .freq = CONFIG_STM32H7_ADC1_SAMPLE_FREQUENCY, +#endif +#ifdef ADC1_HAVE_DMA + .dmachan = ADC1_DMA_CHAN, + .hasdma = true, +#endif +#ifdef ADC1_HAVE_DFSDM + .hasdfsdm = true, +#endif +#ifdef CONFIG_PM + .pm_callback = + { + .prepare = adc_pm_prepare, + } +#endif +}; + +static struct adc_dev_s g_adcdev1 = +{ + .ad_ops = &g_adcops, + .ad_priv = &g_adcpriv1, +}; +#endif + +/* ADC2 state */ + +#ifdef CONFIG_STM32H7_ADC2 +static struct stm32_dev_s g_adcpriv2 = +{ + .irq = STM32_IRQ_ADC12, + .isr = adc12_interrupt, + .intf = 2, + .base = STM32_ADC2_BASE, +#ifdef ADC2_HAVE_TIMER + .trigger = CONFIG_STM32H7_ADC2_TIMTRIG, + .tbase = ADC2_TIMER_BASE, + .trcc_enr = ADC2_TIMER_RCC_ENR, + .trcc_en = ADC2_TIMER_RCC_EN, + .extsel = ADC2_EXTSEL_VALUE, + .pclck = ADC2_TIMER_PCLK_FREQUENCY, + .freq = CONFIG_STM32H7_ADC2_SAMPLE_FREQUENCY, +#endif +#ifdef ADC2_HAVE_DMA + .dmachan = ADC2_DMA_CHAN, + .hasdma = true, +#endif +#ifdef ADC2_HAVE_DFSDM + .hasdfsdm = true, +#endif +#ifdef CONFIG_PM + .pm_callback = + { + .prepare = adc_pm_prepare, + } +#endif +}; + +static struct adc_dev_s g_adcdev2 = +{ + .ad_ops = &g_adcops, + .ad_priv = &g_adcpriv2, +}; +#endif + +/* ADC3 state */ + +#ifdef CONFIG_STM32H7_ADC3 +static struct stm32_dev_s g_adcpriv3 = +{ + .irq = STM32_IRQ_ADC3, + .isr = adc3_interrupt, + .intf = 3, + .base = STM32_ADC3_BASE, +#ifdef ADC3_HAVE_TIMER + .trigger = CONFIG_STM32H7_ADC3_TIMTRIG, + .tbase = ADC3_TIMER_BASE, + .trcc_enr = ADC3_TIMER_RCC_ENR, + .trcc_en = ADC3_TIMER_RCC_EN, + .extsel = ADC3_EXTSEL_VALUE, + .pclck = ADC3_TIMER_PCLK_FREQUENCY, + .freq = CONFIG_STM32H7_ADC3_SAMPLE_FREQUENCY, +#endif +#ifdef ADC3_HAVE_DMA + .dmachan = ADC3_DMA_CHAN, + .hasdma = true, +#endif +#ifdef ADC3_HAVE_DFSDM + .hasdfsdm = true, +#endif +#ifdef CONFIG_PM + .pm_callback = + { + .prepare = adc_pm_prepare, + } +#endif +}; + +static struct adc_dev_s g_adcdev3 = +{ + .ad_ops = &g_adcops, + .ad_priv = &g_adcpriv3, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: adc_getreg + * + * Description: + * Read the value of an ADC register. + * + * Input Parameters: + * priv - A reference to the ADC block status + * offset - The offset to the register to read + * + * Returned Value: + * The current contents of the specified register + * + ****************************************************************************/ + +static uint32_t adc_getreg(FAR struct stm32_dev_s *priv, int offset) +{ + return getreg32(priv->base + offset); +} + +/**************************************************************************** + * Name: adc_putreg + * + * Description: + * Write a value to an ADC register. + * + * Input Parameters: + * priv - A reference to the ADC block status + * offset - The offset to the register to write to + * value - The value to write to the register + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void adc_putreg(FAR struct stm32_dev_s *priv, int offset, + uint32_t value) +{ + putreg32(value, priv->base + offset); +} + +/**************************************************************************** + * Name: adc_modifyreg + * + * Description: + * Modify the value of an ADC 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 adc_modifyreg(FAR struct stm32_dev_s *priv, int offset, + uint32_t clrbits, uint32_t setbits) +{ + adc_putreg(priv, offset, (adc_getreg(priv, offset) & ~clrbits) | setbits); +} + +/**************************************************************************** + * Name: tim_getreg + * + * Description: + * Read the value of an ADC timer register. + * + * Input Parameters: + * priv - A reference to the ADC block status + * offset - The offset to the register to read + * + * Returned Value: + * The current contents of the specified register + * + ****************************************************************************/ + +#ifdef ADC_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 ADC timer register. + * + * Input Parameters: + * priv - A reference to the ADC block status + * offset - The offset to the register to write to + * value - The value to write to the register + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef ADC_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 ADC timer 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 + * + ****************************************************************************/ + +#ifdef ADC_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 ADC block status + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef ADC_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, STM32_GTIM_CR1_OFFSET), + tim_getreg(priv, STM32_GTIM_CR2_OFFSET), + tim_getreg(priv, STM32_GTIM_SMCR_OFFSET), + tim_getreg(priv, STM32_GTIM_DIER_OFFSET)); + ainfo(" SR: %04x EGR: 0000 CCMR1: %04x CCMR2: %04x\n", + tim_getreg(priv, STM32_GTIM_SR_OFFSET), + tim_getreg(priv, STM32_GTIM_CCMR1_OFFSET), + tim_getreg(priv, STM32_GTIM_CCMR2_OFFSET)); + ainfo(" CCER: %04x CNT: %04x PSC: %04x ARR: %04x\n", + tim_getreg(priv, STM32_GTIM_CCER_OFFSET), + tim_getreg(priv, STM32_GTIM_CNT_OFFSET), + tim_getreg(priv, STM32_GTIM_PSC_OFFSET), + tim_getreg(priv, STM32_GTIM_ARR_OFFSET)); + ainfo(" CCR1: %04x CCR2: %04x CCR3: %04x CCR4: %04x\n", + tim_getreg(priv, STM32_GTIM_CCR1_OFFSET), + tim_getreg(priv, STM32_GTIM_CCR2_OFFSET), + tim_getreg(priv, STM32_GTIM_CCR3_OFFSET), + tim_getreg(priv, STM32_GTIM_CCR4_OFFSET)); + + if (priv->tbase == STM32_TIM1_BASE || priv->tbase == STM32_TIM8_BASE) + { + ainfo(" RCR: %04x BDTR: %04x DCR: %04x DMAR: %04x\n", + tim_getreg(priv, STM32_ATIM_RCR_OFFSET), + tim_getreg(priv, STM32_ATIM_BDTR_OFFSET), + tim_getreg(priv, STM32_ATIM_DCR_OFFSET), + tim_getreg(priv, STM32_ATIM_DMAR_OFFSET)); + } + else + { + ainfo(" DCR: %04x DMAR: %04x\n", + tim_getreg(priv, STM32_GTIM_DCR_OFFSET), + tim_getreg(priv, STM32_GTIM_DMAR_OFFSET)); + } +} +#endif + +/**************************************************************************** + * Name: adc_timstart + * + * Description: + * Start (or stop) the timer counter + * + * Input Parameters: + * priv - A reference to the ADC block status + * enable - True: Start conversion + * + * Returned Value: + * + ****************************************************************************/ + +#ifdef ADC_HAVE_TIMER +static void adc_timstart(FAR struct stm32_dev_s *priv, bool enable) +{ + ainfo("enable: %d\n", enable ? 1 : 0); + + if (enable) + { + /* Start the counter */ + + tim_modifyreg(priv, STM32_GTIM_CR1_OFFSET, 0, GTIM_CR1_CEN); + } + else + { + /* Disable the counter */ + + tim_modifyreg(priv, STM32_GTIM_CR1_OFFSET, GTIM_CR1_CEN, 0); + } +} +#endif + +/**************************************************************************** + * Name: adc_timinit + * + * Description: + * Initialize the timer that drivers the ADC sampling for this channel + * using the pre-calculated timer divider definitions. + * + * Input Parameters: + * priv - A reference to the ADC block status + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +#ifdef ADC_HAVE_TIMER +static int adc_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); + + adc_modifyreg(priv, STM32_ADC_CFGR_OFFSET, + ADC_CFGR_EXTEN_MASK | ADC_CFGR_EXTSEL_MASK, + ADC_CFGR_EXTEN_RISING | priv->extsel); + + /* Configure the timer channel to drive the ADC */ + + /* Enable Timer clocking */ + + modifyreg32(priv->trcc_enr, 0, priv->trcc_en); + + /* 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 */ + + adc_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, STM32_GTIM_CR1_OFFSET, clrbits, setbits); + + /* Set the reload and prescaler values */ + + tim_putreg(priv, STM32_GTIM_PSC_OFFSET, prescaler-1); + tim_putreg(priv, STM32_GTIM_ARR_OFFSET, reload); + + /* Clear the advanced timers repetition counter in TIM1 */ + + if (priv->tbase == STM32_TIM1_BASE || priv->tbase == STM32_TIM8_BASE) + { + tim_putreg(priv, STM32_ATIM_RCR_OFFSET, 0); + tim_putreg(priv, STM32_ATIM_BDTR_OFFSET, ATIM_BDTR_MOE); /* Check me */ + } + + /* TIMx event generation: Bit 0 UG: Update generation */ + + tim_putreg(priv, STM32_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, STM32_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, STM32_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, STM32_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, STM32_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, STM32_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, STM32_GTIM_CCER_OFFSET); + ccer &= ~ccenable; + tim_putreg(priv, STM32_GTIM_CCER_OFFSET, ccer); + + /* Fetch the CR2, CCMR1, and CCMR2 register (already have ccer) */ + + cr2 = tim_getreg(priv, STM32_GTIM_CR2_OFFSET); + ccmr1 = tim_getreg(priv, STM32_GTIM_CCMR1_OFFSET); + ccmr2 = tim_getreg(priv, STM32_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 == STM32_TIM1_BASE || priv->tbase == STM32_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, STM32_GTIM_CR2_OFFSET, cr2); + tim_putreg(priv, STM32_GTIM_CCMR1_OFFSET, ccmr1); + tim_putreg(priv, STM32_GTIM_CCMR2_OFFSET, ccmr2); + tim_putreg(priv, STM32_GTIM_CCER_OFFSET, ccer); + tim_putreg(priv, STM32_GTIM_EGR_OFFSET, egr); + + /* Set the ARR Preload Bit */ + + tim_modifyreg(priv, STM32_GTIM_CR1_OFFSET, 0, GTIM_CR1_ARPE); + + /* Enable the timer counter */ + + adc_timstart(priv, true); + + tim_dumpregs(priv, "After starting timers"); + + return OK; +} +#endif + +/**************************************************************************** + * Name: adc_pm_prepare + * + * Description: + * Called by power management framework when it wants to enter low power + * states. Check if ADC is in progress and if so prevent from entering STOP. + * + ****************************************************************************/ +#ifdef CONFIG_PM +static int adc_pm_prepare(struct pm_callback_s *cb, int domain, + enum pm_state_e state) +{ + FAR struct stm32_dev_s *priv = + container_of(cb, struct stm32_dev_s, pm_callback); + uint32_t regval; + + regval = adc_getreg(priv, STM32_ADC_CR_OFFSET); + if ((state >= PM_IDLE) && (regval & ADC_CR_ADSTART)) + { + return -EBUSY; + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: adc_wdog_enable + * + * Description: + * Enable the analog watchdog. + * + ****************************************************************************/ + +static void adc_wdog_enable(struct stm32_dev_s *priv) +{ + uint32_t regval; + + /* Initialize the Analog watchdog enable */ + + regval = adc_getreg(priv, STM32_ADC_CFGR_OFFSET); + regval |= ADC_CFGR_AWD1EN | ADC_CFGR_CONT | ADC_CFGR_OVRMOD; + adc_putreg(priv, STM32_ADC_CFGR_OFFSET, regval); + + /* Switch to analog watchdog interrupt */ + + regval = adc_getreg(priv, STM32_ADC_IER_OFFSET); + regval |= ADC_INT_AWD1; + regval &= ~ADC_INT_EOC; + adc_putreg(priv, STM32_ADC_IER_OFFSET, regval); +} + +/**************************************************************************** + * Name: adc_startconv + * + * Description: + * Start (or stop) the ADC conversion process + * + * Input Parameters: + * priv - A reference to the ADC block status + * enable - True: Start conversion + * + * Returned Value: + * + ****************************************************************************/ + +static void adc_startconv(FAR struct stm32_dev_s *priv, bool enable) +{ + uint32_t regval; + + ainfo("enable: %d\n", enable ? 1 : 0); + + regval = adc_getreg(priv, STM32_ADC_CR_OFFSET); + if (enable) + { + /* Start conversion of regular channels */ + + regval |= ADC_CR_ADSTART; + } + else + { + /* Disable the conversion of regular channels */ + + regval |= ADC_CR_ADSTP; + } + + adc_putreg(priv, STM32_ADC_CR_OFFSET, regval); +} + +/**************************************************************************** + * Name: adc_rccreset + * + * Description: + * Deinitializes the ADCx peripheral registers to their default + * reset values. It could set all the ADCs configured. + * + * Input Parameters: + * priv - A reference to the ADC block status + * reset - Condition, set or reset + * + * Returned Value: + * + ****************************************************************************/ + +static void adc_rccreset(FAR struct stm32_dev_s *priv, bool reset) +{ + irqstate_t flags; + uint32_t regval; + uint32_t reg = STM32_RCC_AHB4RSTR; + uint32_t bit = RCC_AHB4RSTR_ADC3RST; + + /* Pick the appropriate bit in the AHBx reset register. */ + + if (priv->intf != 3) + { + reg = STM32_RCC_AHB1RSTR; + bit = RCC_AHB1RSTR_ADC12RST; + } + + /* First must disable interrupts because the AHB2RSTR register is used by + * several different drivers. + */ + + flags = enter_critical_section(); + + /* Set or clear the selected bit in the AHB2 reset register */ + + regval = getreg32(reg); + if (reset) + { + regval |= bit; + } + else + { + regval &= ~bit; + } + + putreg32(regval, reg); + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: adc_enable + * + * Description: + * Enables the specified ADC peripheral. + * + * Input Parameters: + * priv - A reference to the ADC block status + * + * Returned Value: + * + ****************************************************************************/ + +static void adc_enable(FAR struct stm32_dev_s *priv) +{ + uint32_t regval; + + regval = adc_getreg(priv, STM32_ADC_CR_OFFSET); + + /* Exit deep power down mode and enable voltage regulator */ + + regval &= ~ADC_CR_DEEPPWD; + regval |= ADC_CR_ADVREGEN; + adc_putreg(priv, STM32_ADC_CR_OFFSET, regval); + + /* Wait for voltage regulator to power up */ + + up_udelay(20); + + /* Enable ADC calibration. ADCALDIF == 0 so this is only for + * single-ended conversions, not for differential ones. + */ + + regval |= ADC_CR_ADCAL; + adc_putreg(priv, STM32_ADC_CR_OFFSET, regval); + + /* Wait for calibration to complete */ + + while (adc_getreg(priv, STM32_ADC_CR_OFFSET) & ADC_CR_ADCAL); + + /* Enable ADC + * Note: ADEN bit cannot be set during ADCAL=1 and 4 ADC clock cycle + * after the ADCAL bit is cleared by hardware. If we are using SYSCLK + * as ADC clock source, this is the same as time taken to execute 4 + * ARM instructions. + */ + + regval = adc_getreg(priv, STM32_ADC_CR_OFFSET); + regval |= ADC_CR_ADEN; + adc_putreg(priv, STM32_ADC_CR_OFFSET, regval); + + /* Wait for hardware to be ready for conversions */ + + while (!(adc_getreg(priv, STM32_ADC_ISR_OFFSET) & ADC_INT_ADRDY)); +} + +/**************************************************************************** + * Name: adc_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 adc_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: adc_reset + * + * Description: + * Reset the ADC device. Called early to initialize the hardware. This + * is called, before adc_setup() and on error conditions. + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + +static void adc_reset(FAR struct adc_dev_s *dev) +{ + FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv; + + ainfo("intf: ADC%d\n", priv->intf); + + /* Enable ADC reset state */ + + adc_rccreset(priv, true); + + /* Release ADC from reset state */ + + adc_rccreset(priv, false); +} + +/**************************************************************************** + * Name: adc_setup + * + * Description: + * Configure the ADC. 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. + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + +static int adc_setup(FAR struct adc_dev_s *dev) +{ + FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv; + int ret; + int i; + irqstate_t flags; + uint32_t clrbits; + uint32_t setbits; + + /* Attach the ADC 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 ADC device is in the powered up, reset state. */ + + adc_reset(dev); + + /* Initialize the same sample time for each ADC. + * During sample cycles channel selection bits must remain unchanged. + */ + + adc_putreg(priv, STM32_ADC_SMPR1_OFFSET, ADC_SMPR1_DEFAULT); + adc_putreg(priv, STM32_ADC_SMPR2_OFFSET, ADC_SMPR2_DEFAULT); + + /* Set the resolution of the conversion. */ + + clrbits = ADC_CFGR_RES_MASK | ADC_CFGR_DMNGT_MASK; + setbits = ADC_CFGR_RES_16BIT; + +#ifdef ADC_HAVE_DMA + if (priv->hasdma) + { + /* Enable One shot DMA */ + + setbits |= ADC_CFGR_DMNGT_DMA_ONESHOT; + } +#endif + +#ifdef ADC_HAVE_DFSDM + if (priv->hasdfsdm) + { + /* Enable routing to DFSDM */ + + setbits |= ADC_CFGR_DMNGT_DFSDM; + } +#endif + + /* Disable continuous mode */ + + clrbits |= ADC_CFGR_CONT; + + /* Disable external trigger for regular channels */ + + clrbits |= ADC_CFGR_EXTEN_MASK; + setbits |= ADC_CFGR_EXTEN_NONE; + + /* Set CFGR configuration */ + + adc_modifyreg(priv, STM32_ADC_CFGR_OFFSET, clrbits, setbits); + + /* Set CFGR2 configuration to align right no oversample */ + + clrbits = ADC_CFGR2_ROVSE | ADC_CFGR2_JOVSE | ADC_CFGR2_OVSS_MASK \ + | ADC_CFGR2_OVSR_MASK | ADC_CFGR2_LSHIFT_MASK; + setbits = 0; + + adc_modifyreg(priv, STM32_ADC_CFGR2_OFFSET, clrbits, setbits); + + /* Configuration of the channel conversions */ + + adc_set_ch(dev, 0); + + /* ADC CCR configuration */ + + clrbits = ADC_CCR_PRESC_MASK | ADC_CCR_VREFEN | + ADC_CCR_VSENSEEN | ADC_CCR_VBATEN; + setbits = ADC_CCR_PRESC_NOT_DIV | ADC_CCR_CKMODE_ASYCH; + + adc_internal(priv, &setbits); + + adc_modifyreg(priv, STM32_ADC_CCR_OFFSET, clrbits, setbits); + +#ifdef ADC_HAVE_DMA + + /* Enable DMA */ + + if (priv->hasdma) + { + /* Stop and free DMA if it was started before */ + + if (priv->dma != NULL) + { + stm32_dmastop(priv->dma); + stm32_dmafree(priv->dma); + } + + priv->dma = stm32_dmachannel(priv->dmachan); + + stm32_dmasetup(priv->dma, + priv->base + STM32_ADC_DR_OFFSET, + (uint32_t)priv->dmabuffer, + priv->nchannels, + ADC_DMA_CONTROL_WORD); + + stm32_dmastart(priv->dma, adc_dmaconvcallback, dev, false); + } + +#endif + + /* Set up the PCSEL bits. */ + + setbits = 0; + clrbits = ADC_PCSEL_PCSEL_ALL; + for (i = 0; i < priv->cchannels && priv->chanlist[i]; i++) + { + setbits |= 1 << priv->chanlist[i]; + } + + adc_modifyreg(priv, STM32_ADC_PCSEL_OFFSET, clrbits, setbits); + + + /* Set ADEN to wake up the ADC from Power Down. */ + + adc_enable(priv); + +#ifdef ADC_HAVE_TIMER + if (priv->tbase != 0) + { + ret = adc_timinit(priv); + if (ret < 0) + { + aerr("ERROR: adc_timinit failed: %d\n", ret); + } + + adc_startconv(priv, ret < 0 ? false : true); + } +#endif + + leave_critical_section(flags); + + ainfo("ISR: 0x%08x CR: 0x%08x CFGR: 0x%08x CFGR2: 0x%08x\n", + adc_getreg(priv, STM32_ADC_ISR_OFFSET), + adc_getreg(priv, STM32_ADC_CR_OFFSET), + adc_getreg(priv, STM32_ADC_CFGR_OFFSET), + adc_getreg(priv, STM32_ADC_CFGR2_OFFSET)); + ainfo("SQR1: 0x%08x SQR2: 0x%08x SQR3: 0x%08x SQR4: 0x%08x\n", + adc_getreg(priv, STM32_ADC_SQR1_OFFSET), + adc_getreg(priv, STM32_ADC_SQR2_OFFSET), + adc_getreg(priv, STM32_ADC_SQR3_OFFSET), + adc_getreg(priv, STM32_ADC_SQR4_OFFSET)); + ainfo("CCR: 0x%08x\n", getreg32(STM32_ADC_CCR)); + + /* Enable the ADC interrupt */ + + ainfo("Enable the ADC interrupt: irq=%d\n", priv->irq); + up_enable_irq(priv->irq); + + return ret; +} + +/**************************************************************************** + * Name: adc_shutdown + * + * Description: + * Disable the ADC. This method is called when the ADC device is closed. + * This method reverses the operation the setup method. + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + +static void adc_shutdown(FAR struct adc_dev_s *dev) +{ + FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv; + + /* Stop the ADC */ + + adc_startconv(priv, false); + + /* Disable ADC interrupts and detach the ADC interrupt handler */ + + up_disable_irq(priv->irq); + irq_detach(priv->irq); + + /* Disable and reset the ADC module */ + + adc_reset(dev); +} + +/**************************************************************************** + * Name: adc_rxint + * + * Description: + * Call to enable or disable RX interrupts. + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + +static void adc_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 = adc_getreg(priv, STM32_ADC_IER_OFFSET); + if (enable) + { + /* Enable end of conversion interrupt */ + + regval |= ADC_INT_EOC; + } + else + { + /* Disable all interrupts */ + + regval &= ~ADC_INT_MASK; + } + adc_putreg(priv, STM32_ADC_IER_OFFSET, regval); +} + +/**************************************************************************** + * Name: adc_sqrbits + ****************************************************************************/ + +static uint32_t adc_sqrbits(FAR struct stm32_dev_s *priv, int first, int last, + int offset) +{ + uint32_t bits = 0; + int i; + + for (i = first - 1; + i < priv->nchannels && i < last; + i++, offset += ADC_SQ_OFFSET) + { + bits |= (uint32_t)priv->chanlist[i] << offset; + } + + return bits; +} + +/**************************************************************************** + * Name: adc_internal + ****************************************************************************/ + +static bool adc_internal(FAR struct stm32_dev_s * priv, uint32_t *adc_ccr) +{ + int i; + bool internal = false; + + if (priv->intf == 3) + { + for (i = 0; i < priv->nchannels; i++) + { + if (priv->chanlist[i] > ADC_EXTERNAL_CHAN_MAX) + { + internal = true; + switch (priv->chanlist[i]) + { + case 17: + *adc_ccr |= ADC_CCR_VSENSEEN; + break; + + case 18: + *adc_ccr |= ADC_CCR_VBATEN; + break; + + case 19: + *adc_ccr |= ADC_CCR_VREFEN; + break; + } + } + + } + } + return internal; +} + +/**************************************************************************** + * Name: adc_set_offset + ****************************************************************************/ + +#ifdef ADC_HAVE_DFSDM +static int adc_setoffset(FAR struct stm32_dev_s *priv, uint8_t ch, uint8_t i, + uint16_t offset) +{ + uint32_t reg; + uint32_t regval; + + if (i >= 4) + { + /* There are only four offset registers. */ + + return -E2BIG; + } + + reg = STM32_ADC_OFR1_OFFSET + i * 4; + + regval = ADC_OFR_OFFSETY_EN; + adc_putreg(priv, reg, regval); + + regval |= ADC_OFR_OFFSETY_CH(ch) | ADC_OFR_OFFSETY(offset); + adc_putreg(priv, reg, regval); + return OK; +} +#endif + +/**************************************************************************** + * Name: adc_set_ch + * + * Description: + * Sets the ADC 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 adc_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 bits; + 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 <= ADC_MAX_SAMPLES); + + bits = adc_sqrbits(priv, ADC_SQR4_FIRST, ADC_SQR4_LAST, ADC_SQR4_SQ_OFFSET); + adc_modifyreg(priv, STM32_ADC_SQR4_OFFSET, ~ADC_SQR4_RESERVED, bits); + + bits = adc_sqrbits(priv, ADC_SQR3_FIRST, ADC_SQR3_LAST, ADC_SQR3_SQ_OFFSET); + adc_modifyreg(priv, STM32_ADC_SQR3_OFFSET, ~ADC_SQR3_RESERVED, bits); + + bits = adc_sqrbits(priv, ADC_SQR2_FIRST, ADC_SQR2_LAST, ADC_SQR2_SQ_OFFSET); + adc_modifyreg(priv, STM32_ADC_SQR2_OFFSET, ~ADC_SQR2_RESERVED, bits); + + bits = ((uint32_t)priv->nchannels - 1) << ADC_SQR1_L_SHIFT | + adc_sqrbits(priv, ADC_SQR1_FIRST, ADC_SQR1_LAST, ADC_SQR1_SQ_OFFSET); + adc_modifyreg(priv, STM32_ADC_SQR1_OFFSET, ~ADC_SQR1_RESERVED, bits); + +#ifdef ADC_HAVE_DFSDM + if (priv->hasdfsdm) + { + /* Convert 12-bit ADC result to signed 16-bit. */ + + if (ch == 0) + { + for (i = 0; i < priv->cchannels; i++) + { + adc_setoffset(priv, priv->chanlist[i], i, 0x800); + } + } + else + { + adc_setoffset(priv, priv->current, 0, 0x800); + } + } +#endif + + return OK; +} + +/**************************************************************************** + * Name: adc_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 adc_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: + adc_startconv(priv, true); + break; + + case ANIOC_WDOG_UPPER: /* Set watchdog upper threshold */ + { + regval = adc_getreg(priv, STM32_ADC_LTR1_OFFSET); + + /* Verify new upper threshold greater than lower threshold */ + + tmp = (regval & ADC_LTR1_LT_MASK) >> ADC_LTR1_LT_SHIFT; + if (arg < tmp) + { + ret = -EINVAL; + break; + } + + /* Set the watchdog threshold register */ + + regval = ((arg << ADC_HTR1_HT_SHIFT) & ADC_HTR1_HT_MASK); + adc_putreg(priv, STM32_ADC_HTR1_OFFSET, regval); + + /* Ensure analog watchdog is enabled */ + + adc_wdog_enable(priv); + } + break; + + case ANIOC_WDOG_LOWER: /* Set watchdog lower threshold */ + { + regval = adc_getreg(priv, STM32_ADC_HTR1_OFFSET); + + /* Verify new lower threshold less than upper threshold */ + + tmp = (regval & ADC_HTR1_HT_MASK) >> ADC_HTR1_HT_SHIFT; + if (arg > tmp) + { + ret = -EINVAL; + break; + } + + /* Set the watchdog threshold register */ + + regval= ((arg << ADC_LTR1_LT_SHIFT) & ADC_LTR1_LT_MASK); + adc_putreg(priv, STM32_ADC_LTR1_OFFSET, regval); + + /* Ensure analog watchdog is enabled */ + + adc_wdog_enable(priv); + } + break; + + default: + aerr("ERROR: Unknown cmd: %d\n", cmd); + ret = -ENOTTY; + break; + } + + return ret; +} + +/**************************************************************************** + * Name: adc_interrupt + * + * Description: + * Common ADC interrupt handler. + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + +static int adc_interrupt(FAR struct adc_dev_s *dev, uint32_t adcisr) +{ + FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv; + int32_t value; + + /* Identifies the interruption AWD or OVR */ + + if ((adcisr & ADC_INT_AWD1) != 0) + { + value = adc_getreg(priv, STM32_ADC_DR_OFFSET); + value &= ADC_DR_MASK; + + awarn("WARNING: Analog Watchdog, Value (0x%03x) out of range!\n", value); + + /* Stop ADC conversions to avoid continuous interrupts */ + + adc_startconv(priv, false); + } + + if ((adcisr & ADC_INT_OVR) != 0) + { + awarn("WARNING: Overrun has occurred!\n"); + } + + /* EOC: End of conversion */ + + if ((adcisr & ADC_INT_EOC) != 0) + { + /* Read the converted value and clear EOC bit + * (It is cleared by reading the ADC_DR) + */ + + value = adc_getreg(priv, STM32_ADC_DR_OFFSET); + value &= ADC_DR_MASK; + + /* 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: adc12_interrupt + * + * Description: + * ADC1/2 interrupt handler + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + +#if defined(CONFIG_STM32H7_ADC1) || defined(CONFIG_STM32H7_ADC2) +static int adc12_interrupt(int irq, FAR void *context, FAR void *arg) +{ + uint32_t regval; + uint32_t pending; + +#ifdef CONFIG_STM32H7_ADC1 + regval = getreg32(STM32_ADC1_ISR); + pending = regval & ADC_INT_MASK; + if (pending != 0) + { + adc_interrupt(&g_adcdev1, regval); + + /* Clear interrupts */ + + putreg32(regval, STM32_ADC1_ISR); + } +#endif + +#ifdef CONFIG_STM32H7_ADC2 + regval = getreg32(STM32_ADC2_ISR); + pending = regval & ADC_INT_MASK; + if (pending != 0) + { + adc_interrupt(&g_adcdev2, regval); + + /* Clear interrupts */ + + putreg32(regval, STM32_ADC2_ISR); + } +#endif + + return OK; +} +#endif + +/**************************************************************************** + * Name: adc3_interrupt + * + * Description: + * ADC3 interrupt handler + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ +#ifdef CONFIG_STM32H7_ADC3 +static int adc3_interrupt(int irq, FAR void *context, FAR void *arg) +{ + uint32_t regval; + uint32_t pending; + + regval = getreg32(STM32_ADC3_ISR); + pending = regval & ADC_INT_MASK; + if (pending != 0) + { + adc_interrupt(&g_adcdev3, regval); + + /* Clear interrupts */ + + putreg32(regval, STM32_ADC3_ISR); + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: adc_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 - adc device + * + * Returned Value: + * + ****************************************************************************/ + +#ifdef ADC_HAVE_DMA +static void adc_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 */ + + adc_modifyreg(priv, STM32_ADC_CFGR_OFFSET, ADC_CFGR_DMAEN, 0); + adc_modifyreg(priv, STM32_ADC_CFGR_OFFSET, 0, ADC_CFGR_DMAEN); +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32h7_adc_initialize + * + * Description: + * Initialize the ADC. + * + * The logic is, save nchannels : # of channels (conversions) in ADC_SQR1_L + * Then, take the chanlist array and store it in the SQR Regs, + * chanlist[0] -> ADC_SQR3_SQ1 + * chanlist[1] -> ADC_SQR3_SQ2 + * ... + * chanlist[15]-> ADC_SQR1_SQ16 + * + * up to + * chanlist[nchannels] + * + * Input Parameters: + * intf - Could be {1,2,3} for ADC1, ADC2, or ADC3 + * 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 *stm32h7_adc_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) + { +#ifdef CONFIG_STM32H7_ADC1 + case 1: + ainfo("ADC1 selected\n"); + dev = &g_adcdev1; + break; +#endif +#ifdef CONFIG_STM32H7_ADC2 + case 2: + ainfo("ADC2 selected\n"); + dev = &g_adcdev2; + break; +#endif +#ifdef CONFIG_STM32H7_ADC3 + case 3: + ainfo("ADC3 selected\n"); + dev = &g_adcdev3; + break; +#endif + default: + aerr("ERROR: No ADC interface defined\n"); + return NULL; + } + + /* Configure the selected ADC */ + + priv = (FAR struct stm32_dev_s *)dev->ad_priv; + priv->cb = NULL; + + DEBUGASSERT(cchannels <= ADC_MAX_SAMPLES); + if (cchannels > ADC_MAX_SAMPLES) + { + cchannels = ADC_MAX_SAMPLES; + } + + priv->cchannels = cchannels; + memcpy(priv->chanlist, chanlist, cchannels); + +#ifdef CONFIG_PM + if (pm_register(&priv->pm_callback) != OK) + { + aerr("Power management registration failed\n"); + return NULL; + } +#endif + + return dev; +} + +#endif /* CONFIG_STM32H7_ADC1 || CONFIG_STM32H7_ADC2 || CONFIG_STM32H7_ADC3 */ +#endif /* CONFIG_ADC */ diff --git a/arch/arm/src/stm32h7/stm32_adc.h b/arch/arm/src/stm32h7/stm32_adc.h new file mode 100644 index 0000000000..1c967c1dd2 --- /dev/null +++ b/arch/arm/src/stm32h7/stm32_adc.h @@ -0,0 +1,829 @@ +/************************************************************************************ + * arch/arm/src/stm32h7/stm32_adc.h + * + * Copyright (C) 2009, 2011, 2015-2017,2019 Gregory Nutt. All rights reserved. + * Copyright (C) 2015 Omni Hoverboards Inc. All rights reserved. + * Authors: Gregory Nutt + * Paul Alexander Patience + * David Sidrane + * + * 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_STM32H7_STM32_ADC_H +#define __ARCH_ARM_SRC_STM32H7_STM32_ADC_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include +#include "chip.h" +#include "hardware/stm32_adc.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ +/* Configuration ********************************************************************/ + +/* Timer devices may be used for different purposes. One special purpose is to + * control periodic ADC sampling. If CONFIG_STM32H7_TIMn is defined then + * CONFIG_STM32H7_TIMn_ADC must also be defined to indicate that timer "n" is + * intended to be used for that purpose. Timers 1,2,3,6 and 15 may be used on + * STM32H7X3, while STM32H7X6 adds support for timers 4 and 8 as well. + */ + +#ifndef CONFIG_STM32H7_TIM1 +# undef CONFIG_STM32H7_TIM1_ADC +# undef CONFIG_STM32H7_TIM1_ADC1 +# undef CONFIG_STM32H7_TIM1_ADC2 +# undef CONFIG_STM32H7_TIM1_ADC3 +#endif +#ifndef CONFIG_STM32H7_TIM2 +# undef CONFIG_STM32H7_TIM2_ADC +# undef CONFIG_STM32H7_TIM2_ADC1 +# undef CONFIG_STM32H7_TIM2_ADC2 +# undef CONFIG_STM32H7_TIM2_ADC3 +#endif +#ifndef CONFIG_STM32H7_TIM3 +# undef CONFIG_STM32H7_TIM3_ADC +# undef CONFIG_STM32H7_TIM3_ADC1 +# undef CONFIG_STM32H7_TIM3_ADC2 +# undef CONFIG_STM32H7_TIM3_ADC3 +#endif +#ifndef CONFIG_STM32H7_TIM4 +# undef CONFIG_STM32H7_TIM4_ADC +# undef CONFIG_STM32H7_TIM4_ADC1 +# undef CONFIG_STM32H7_TIM4_ADC2 +# undef CONFIG_STM32H7_TIM4_ADC3 +#endif +#ifndef CONFIG_STM32H7_TIM6 +# undef CONFIG_STM32H7_TIM6_ADC +# undef CONFIG_STM32H7_TIM6_ADC1 +# undef CONFIG_STM32H7_TIM6_ADC2 +# undef CONFIG_STM32H7_TIM6_ADC3 +#endif +#ifndef CONFIG_STM32H7_TIM8 +# undef CONFIG_STM32H7_TIM8_ADC +# undef CONFIG_STM32H7_TIM8_ADC1 +# undef CONFIG_STM32H7_TIM8_ADC2 +# undef CONFIG_STM32H7_TIM8_ADC3 +#endif +#ifndef CONFIG_STM32H7_TIM15 +# undef CONFIG_STM32H7_TIM15_ADC +# undef CONFIG_STM32H7_TIM15_ADC1 +# undef CONFIG_STM32H7_TIM15_ADC2 +# undef CONFIG_STM32H7_TIM15_ADC3 +#endif + +#if defined(CONFIG_STM32H7_ADC1) || defined(CONFIG_STM32H7_ADC2) || \ + defined(CONFIG_STM32H7_ADC3) + +/* ADC output to DFSDM support. Note that DFSDM and DMA are + * mutually exclusive. + */ + +#undef ADC_HAVE_DFSDM +#if defined(CONFIG_STM32H7_ADC1_OUTPUT_DFSDM) || \ + defined(CONFIG_STM32H7_ADC2_OUTPUT_DFSDM) || \ + defined(CONFIG_STM32H7_ADC3_OUTPUT_DFSDM) +# define ADC_HAVE_DFSDM +#endif + +#if defined(CONFIG_STM32H7_ADC1_OUTPUT_DFSDM) +# define ADC1_HAVE_DFSDM 1 +# undef CONFIG_STM32H7_ADC1_DMA +#else +# undef ADC1_HAVE_DFSDM +#endif + +#if defined(CONFIG_STM32H7_ADC2_OUTPUT_DFSDM) +# define ADC2_HAVE_DFSDM 1 +# undef CONFIG_STM32H7_ADC2_DMA +#else +# undef ADC2_HAVE_DFSDM +#endif + +#if defined(CONFIG_STM32H7_ADC3_OUTPUT_DFSDM) +# define ADC3_HAVE_DFSDM 1 +# undef CONFIG_STM32H7_ADC3_DMA +#else +# undef ADC3_HAVE_DFSDM +#endif + +/* DMA support */ + +#undef ADC_HAVE_DMA +#if defined(CONFIG_STM32H7_ADC1_DMA) || defined(CONFIG_STM32H7_ADC2_DMA) || \ + defined(CONFIG_STM32H7_ADC3_DMA) +# define ADC_HAVE_DMA 1 +#endif + +#ifdef CONFIG_STM32H7_ADC1_DMA +# define ADC1_HAVE_DMA 1 +#else +# undef ADC1_HAVE_DMA +#endif + +#ifdef CONFIG_STM32H7_ADC2_DMA +# define ADC2_HAVE_DMA 1 +#else +# undef ADC2_HAVE_DMA +#endif + +#ifdef CONFIG_STM32H7_ADC3_DMA +# define ADC3_HAVE_DMA 1 +#else +# undef ADC3_HAVE_DMA +#endif + +/* Timer configuration: If a timer trigger is specified, then get + * information about the timer. + */ + +#if defined(CONFIG_STM32H7_TIM1_ADC1) +# define ADC1_HAVE_TIMER 1 +# define ADC1_TIMER_BASE STM32_TIM1_BASE +# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB2_TIM1_CLKIN +# define ADC1_TIMER_RCC_ENR STM32_RCC_APB2ENR +# define ADC1_TIMER_RCC_EN RCC_APB2ENR_TIM1EN +#elif defined(CONFIG_STM32H7_TIM2_ADC1) +# define ADC1_HAVE_TIMER 1 +# define ADC1_TIMER_BASE STM32_TIM2_BASE +# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB1_TIM2_CLKIN +# define ADC1_TIMER_RCC_ENR STM32_RCC_APB1LENR +# define ADC1_TIMER_RCC_EN RCC_APB1LENR_TIM2EN +#elif defined(CONFIG_STM32H7_TIM3_ADC1) +# define ADC1_HAVE_TIMER 1 +# define ADC1_TIMER_BASE STM32_TIM3_BASE +# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB1_TIM3_CLKIN +# define ADC1_TIMER_RCC_ENR STM32_RCC_APB1LENR +# define ADC1_TIMER_RCC_EN RCC_APB1LENR_TIM3EN +#elif defined(CONFIG_STM32H7_TIM4_ADC1) +# define ADC1_HAVE_TIMER 1 +# define ADC1_TIMER_BASE STM32_TIM4_BASE +# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB1_TIM4_CLKIN +# define ADC1_TIMER_RCC_ENR STM32_RCC_APB1LENR +# define ADC1_TIMER_RCC_EN RCC_APB1LENR_TIM4EN +#elif defined(CONFIG_STM32H7_TIM6_ADC1) +# define ADC1_HAVE_TIMER 1 +# define ADC1_TIMER_BASE STM32_TIM6_BASE +# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB1_TIM6_CLKIN +# define ADC1_TIMER_RCC_ENR STM32_RCC_APB1LENR +# define ADC1_TIMER_RCC_EN RCC_APB1LENR_TIM6EN +#elif defined(CONFIG_STM32H7_TIM8_ADC1) +# define ADC1_HAVE_TIMER 1 +# define ADC1_TIMER_BASE STM32_TIM8_BASE +# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB2_TIM8_CLKIN +# define ADC1_TIMER_RCC_ENR STM32_RCC_APB2ENR +# define ADC1_TIMER_RCC_EN RCC_APB2ENR_TIM8EN +#elif defined(CONFIG_STM32H7_TIM15_ADC1) +# define ADC1_HAVE_TIMER 1 +# define ADC1_TIMER_BASE STM32_TIM15_BASE +# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB2_TIM15_CLKIN +# define ADC1_TIMER_RCC_ENR STM32_RCC_APB2ENR +# define ADC1_TIMER_RCC_EN RCC_APB2ENR_TIM15EN +#else +# undef ADC1_HAVE_TIMER +#endif + +#ifdef ADC1_HAVE_TIMER +# ifndef CONFIG_STM32H7_ADC1_SAMPLE_FREQUENCY +# error "CONFIG_STM32H7_ADC1_SAMPLE_FREQUENCY not defined" +# endif +# ifndef CONFIG_STM32H7_ADC1_TIMTRIG +# error "CONFIG_STM32H7_ADC1_TIMTRIG not defined" +# warning "Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO" +# endif +#endif + +#if defined(CONFIG_STM32H7_TIM1_ADC2) +# define ADC2_HAVE_TIMER 1 +# define ADC2_TIMER_BASE STM32_TIM1_BASE +# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB2_TIM1_CLKIN +# define ADC2_TIMER_RCC_ENR STM32_RCC_APB2ENR +# define ADC2_TIMER_RCC_EN RCC_APB2ENR_TIM1EN +#elif defined(CONFIG_STM32H7_TIM2_ADC2) +# define ADC2_HAVE_TIMER 1 +# define ADC2_TIMER_BASE STM32_TIM2_BASE +# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB1_TIM2_CLKIN +# define ADC2_TIMER_RCC_ENR STM32_RCC_APB1LENR +# define ADC2_TIMER_RCC_EN RCC_APB1LENR_TIM2EN +#elif defined(CONFIG_STM32H7_TIM3_ADC2) +# define ADC2_HAVE_TIMER 1 +# define ADC2_TIMER_BASE STM32_TIM3_BASE +# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB1_TIM3_CLKIN +# define ADC2_TIMER_RCC_ENR STM32_RCC_APB1LENR +# define ADC2_TIMER_RCC_EN RCC_APB1LENR_TIM3EN +#elif defined(CONFIG_STM32H7_TIM4_ADC2) +# define ADC2_HAVE_TIMER 1 +# define ADC2_TIMER_BASE STM32_TIM4_BASE +# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB1_TIM4_CLKIN +# define ADC2_TIMER_RCC_ENR STM32_RCC_APB1LENR +# define ADC2_TIMER_RCC_EN RCC_APB1LENR_TIM4EN +#elif defined(CONFIG_STM32H7_TIM6_ADC2) +# define ADC2_HAVE_TIMER 1 +# define ADC2_TIMER_BASE STM32_TIM6_BASE +# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB1_TIM6_CLKIN +# define ADC2_TIMER_RCC_ENR STM32_RCC_APB1LENR +# define ADC2_TIMER_RCC_EN RCC_APB1LENR_TIM6EN +#elif defined(CONFIG_STM32H7_TIM8_ADC2) +# define ADC2_HAVE_TIMER 1 +# define ADC2_TIMER_BASE STM32_TIM8_BASE +# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB2_TIM8_CLKIN +# define ADC2_TIMER_RCC_ENR STM32_RCC_APB2ENR +# define ADC2_TIMER_RCC_EN RCC_APB2ENR_TIM8EN +#elif defined(CONFIG_STM32H7_TIM15_ADC2) +# define ADC2_HAVE_TIMER 1 +# define ADC2_TIMER_BASE STM32_TIM15_BASE +# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB2_TIM15_CLKIN +# define ADC2_TIMER_RCC_ENR STM32_RCC_APB2ENR +# define ADC2_TIMER_RCC_EN RCC_APB2ENR_TIM15EN +#else +# undef ADC2_HAVE_TIMER +#endif + +#ifdef ADC2_HAVE_TIMER +# ifndef CONFIG_STM32H7_ADC2_SAMPLE_FREQUENCY +# error "CONFIG_STM32H7_ADC2_SAMPLE_FREQUENCY not defined" +# endif +# ifndef CONFIG_STM32H7_ADC2_TIMTRIG +# error "CONFIG_STM32H7_ADC2_TIMTRIG not defined" +# warning "Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO" +# endif +#endif + +#if defined(CONFIG_STM32H7_TIM1_ADC3) +# define ADC3_HAVE_TIMER 1 +# define ADC3_TIMER_BASE STM32_TIM1_BASE +# define ADC3_TIMER_PCLK_FREQUENCY STM32_APB2_TIM1_CLKIN +# define ADC3_TIMER_RCC_ENR STM32_RCC_APB2ENR +# define ADC3_TIMER_RCC_EN RCC_APB2ENR_TIM1EN +#elif defined(CONFIG_STM32H7_TIM2_ADC3) +# define ADC3_HAVE_TIMER 1 +# define ADC3_TIMER_BASE STM32_TIM2_BASE +# define ADC3_TIMER_PCLK_FREQUENCY STM32_APB1_TIM2_CLKIN +# define ADC3_TIMER_RCC_ENR STM32_RCC_APB1LENR +# define ADC3_TIMER_RCC_EN RCC_APB1LENR_TIM2EN +#elif defined(CONFIG_STM32H7_TIM3_ADC3) +# define ADC3_HAVE_TIMER 1 +# define ADC3_TIMER_BASE STM32_TIM3_BASE +# define ADC3_TIMER_PCLK_FREQUENCY STM32_APB1_TIM3_CLKIN +# define ADC3_TIMER_RCC_ENR STM32_RCC_APB1LENR +# define ADC3_TIMER_RCC_EN RCC_APB1LENR_TIM3EN +#elif defined(CONFIG_STM32H7_TIM4_ADC3) +# define ADC3_HAVE_TIMER 1 +# define ADC3_TIMER_BASE STM32_TIM4_BASE +# define ADC3_TIMER_PCLK_FREQUENCY STM32_APB1_TIM4_CLKIN +# define ADC3_TIMER_RCC_ENR STM32_RCC_APB1LENR +# define ADC3_TIMER_RCC_EN RCC_APB1LENR_TIM4EN +#elif defined(CONFIG_STM32H7_TIM6_ADC3) +# define ADC3_HAVE_TIMER 1 +# define ADC3_TIMER_BASE STM32_TIM6_BASE +# define ADC3_TIMER_PCLK_FREQUENCY STM32_APB1_TIM6_CLKIN +# define ADC3_TIMER_RCC_ENR STM32_RCC_APB1LENR +# define ADC3_TIMER_RCC_EN RCC_APB1LENR_TIM6EN +#elif defined(CONFIG_STM32H7_TIM8_ADC3) +# define ADC3_HAVE_TIMER 1 +# define ADC3_TIMER_BASE STM32_TIM8_BASE +# define ADC3_TIMER_PCLK_FREQUENCY STM32_APB2_TIM8_CLKIN +# define ADC3_TIMER_RCC_ENR STM32_RCC_APB2ENR +# define ADC3_TIMER_RCC_EN RCC_APB2ENR_TIM8EN +#elif defined(CONFIG_STM32H7_TIM15_ADC3) +# define ADC3_HAVE_TIMER 1 +# define ADC3_TIMER_BASE STM32_TIM15_BASE +# define ADC3_TIMER_PCLK_FREQUENCY STM32_APB2_TIM15_CLKIN +# define ADC3_TIMER_RCC_ENR STM32_RCC_APB2ENR +# define ADC3_TIMER_RCC_EN RCC_APB2ENR_TIM15EN +#else +# undef ADC3_HAVE_TIMER +#endif + +#ifdef ADC3_HAVE_TIMER +# ifndef CONFIG_STM32H7_ADC3_SAMPLE_FREQUENCY +# error "CONFIG_STM32H7_ADC3_SAMPLE_FREQUENCY not defined" +# endif +# ifndef CONFIG_STM32H7_ADC3_TIMTRIG +# error "CONFIG_STM32H7_ADC3_TIMTRIG not defined" +# warning "Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO" +# endif +#endif + +#if defined(ADC1_HAVE_TIMER) || defined(ADC2_HAVE_TIMER) || \ + defined(ADC3_HAVE_TIMER) +# define ADC_HAVE_TIMER 1 +#else +# undef ADC_HAVE_TIMER +#endif + +/* NOTE: The following assumes that all possible combinations of timers and + * values are support EXTSEL. 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 ADC1_EXTSEL_T1CC1 ADC_CFGR_EXTSEL_T1CC1 +#define ADC1_EXTSEL_T1CC2 ADC_CFGR_EXTSEL_T1CC2 +#define ADC1_EXTSEL_T1CC3 ADC_CFGR_EXTSEL_T1CC3 +#define ADC1_EXTSEL_T1CC4 ADC_CFGR_EXTSEL_T1CC4 +#define ADC1_EXTSEL_T1TRGO ADC_CFGR_EXTSEL_T1TRGO +#define ADC1_EXTSEL_T1TRGO2 ADC_CFGR_EXTSEL_T1TRGO2 +#define ADC2_EXTSEL_T1CC1 ADC_CFGR_EXTSEL_T1CC1 +#define ADC2_EXTSEL_T1CC2 ADC_CFGR_EXTSEL_T1CC2 +#define ADC2_EXTSEL_T1CC3 ADC_CFGR_EXTSEL_T1CC3 +#define ADC2_EXTSEL_T1CC4 ADC_CFGR_EXTSEL_T1CC4 +#define ADC2_EXTSEL_T1TRGO ADC_CFGR_EXTSEL_T1TRGO +#define ADC2_EXTSEL_T1TRGO2 ADC_CFGR_EXTSEL_T1TRGO2 +#define ADC3_EXTSEL_T1CC1 ADC_CFGR_EXTSEL_T1CC1 +#define ADC3_EXTSEL_T1CC2 ADC_CFGR_EXTSEL_T1CC2 +#define ADC3_EXTSEL_T1CC3 ADC_CFGR_EXTSEL_T1CC3 +#define ADC3_EXTSEL_T1CC4 ADC_CFGR_EXTSEL_T1CC4 +#define ADC3_EXTSEL_T1TRGO ADC_CFGR_EXTSEL_T1TRGO +#define ADC3_EXTSEL_T1TRGO2 ADC_CFGR_EXTSEL_T1TRGO2 + +#define ADC1_EXTSEL_T2CC1 ADC_CFGR_EXTSEL_T2CC1 +#define ADC1_EXTSEL_T2CC2 ADC_CFGR_EXTSEL_T2CC2 +#define ADC1_EXTSEL_T2CC3 ADC_CFGR_EXTSEL_T2CC3 +#define ADC1_EXTSEL_T2CC4 ADC_CFGR_EXTSEL_T2CC4 +#define ADC1_EXTSEL_T2TRGO ADC_CFGR_EXTSEL_T2TRGO +#define ADC2_EXTSEL_T2CC1 ADC_CFGR_EXTSEL_T2CC1 +#define ADC2_EXTSEL_T2CC2 ADC_CFGR_EXTSEL_T2CC2 +#define ADC2_EXTSEL_T2CC3 ADC_CFGR_EXTSEL_T2CC3 +#define ADC2_EXTSEL_T2CC4 ADC_CFGR_EXTSEL_T2CC4 +#define ADC2_EXTSEL_T2TRGO ADC_CFGR_EXTSEL_T2TRGO +#define ADC3_EXTSEL_T2CC1 ADC_CFGR_EXTSEL_T2CC1 +#define ADC3_EXTSEL_T2CC2 ADC_CFGR_EXTSEL_T2CC2 +#define ADC3_EXTSEL_T2CC3 ADC_CFGR_EXTSEL_T2CC3 +#define ADC3_EXTSEL_T2CC4 ADC_CFGR_EXTSEL_T2CC4 +#define ADC3_EXTSEL_T2TRGO ADC_CFGR_EXTSEL_T2TRGO + +#define ADC1_EXTSEL_T3CC1 ADC_CFGR_EXTSEL_T3CC1 +#define ADC1_EXTSEL_T3CC2 ADC_CFGR_EXTSEL_T3CC2 +#define ADC1_EXTSEL_T3CC3 ADC_CFGR_EXTSEL_T3CC3 +#define ADC1_EXTSEL_T3CC4 ADC_CFGR_EXTSEL_T3CC4 +#define ADC1_EXTSEL_T3TRGO ADC_CFGR_EXTSEL_T3TRGO +#define ADC2_EXTSEL_T3CC1 ADC_CFGR_EXTSEL_T3CC1 +#define ADC2_EXTSEL_T3CC2 ADC_CFGR_EXTSEL_T3CC2 +#define ADC2_EXTSEL_T3CC3 ADC_CFGR_EXTSEL_T3CC3 +#define ADC2_EXTSEL_T3CC4 ADC_CFGR_EXTSEL_T3CC4 +#define ADC2_EXTSEL_T3TRGO ADC_CFGR_EXTSEL_T3TRGO +#define ADC3_EXTSEL_T3CC1 ADC_CFGR_EXTSEL_T3CC1 +#define ADC3_EXTSEL_T3CC2 ADC_CFGR_EXTSEL_T3CC2 +#define ADC3_EXTSEL_T3CC3 ADC_CFGR_EXTSEL_T3CC3 +#define ADC3_EXTSEL_T3CC4 ADC_CFGR_EXTSEL_T3CC4 +#define ADC3_EXTSEL_T3TRGO ADC_CFGR_EXTSEL_T3TRGO + +#define ADC1_EXTSEL_T4CC1 ADC_CFGR_EXTSEL_T4CC1 +#define ADC1_EXTSEL_T4CC2 ADC_CFGR_EXTSEL_T4CC2 +#define ADC1_EXTSEL_T4CC3 ADC_CFGR_EXTSEL_T4CC3 +#define ADC1_EXTSEL_T4CC4 ADC_CFGR_EXTSEL_T4CC4 +#define ADC1_EXTSEL_T4TRGO ADC_CFGR_EXTSEL_T4TRGO +#define ADC2_EXTSEL_T4CC1 ADC_CFGR_EXTSEL_T4CC1 +#define ADC2_EXTSEL_T4CC2 ADC_CFGR_EXTSEL_T4CC2 +#define ADC2_EXTSEL_T4CC3 ADC_CFGR_EXTSEL_T4CC3 +#define ADC2_EXTSEL_T4CC4 ADC_CFGR_EXTSEL_T4CC4 +#define ADC2_EXTSEL_T4TRGO ADC_CFGR_EXTSEL_T4TRGO +#define ADC3_EXTSEL_T4CC1 ADC_CFGR_EXTSEL_T4CC1 +#define ADC3_EXTSEL_T4CC2 ADC_CFGR_EXTSEL_T4CC2 +#define ADC3_EXTSEL_T4CC3 ADC_CFGR_EXTSEL_T4CC3 +#define ADC3_EXTSEL_T4CC4 ADC_CFGR_EXTSEL_T4CC4 +#define ADC3_EXTSEL_T4TRGO ADC_CFGR_EXTSEL_T4TRGO + +#define ADC1_EXTSEL_T6CC1 ADC_CFGR_EXTSEL_T6CC1 +#define ADC1_EXTSEL_T6CC2 ADC_CFGR_EXTSEL_T6CC2 +#define ADC1_EXTSEL_T6CC3 ADC_CFGR_EXTSEL_T6CC3 +#define ADC1_EXTSEL_T6CC4 ADC_CFGR_EXTSEL_T6CC4 +#define ADC1_EXTSEL_T6TRGO ADC_CFGR_EXTSEL_T6TRGO +#define ADC2_EXTSEL_T6CC1 ADC_CFGR_EXTSEL_T6CC1 +#define ADC2_EXTSEL_T6CC2 ADC_CFGR_EXTSEL_T6CC2 +#define ADC2_EXTSEL_T6CC3 ADC_CFGR_EXTSEL_T6CC3 +#define ADC2_EXTSEL_T6CC4 ADC_CFGR_EXTSEL_T6CC4 +#define ADC2_EXTSEL_T6TRGO ADC_CFGR_EXTSEL_T6TRGO +#define ADC3_EXTSEL_T6CC1 ADC_CFGR_EXTSEL_T6CC1 +#define ADC3_EXTSEL_T6CC2 ADC_CFGR_EXTSEL_T6CC2 +#define ADC3_EXTSEL_T6CC3 ADC_CFGR_EXTSEL_T6CC3 +#define ADC3_EXTSEL_T6CC4 ADC_CFGR_EXTSEL_T6CC4 +#define ADC3_EXTSEL_T6TRGO ADC_CFGR_EXTSEL_T6TRGO + +#define ADC1_EXTSEL_T8CC1 ADC_CFGR_EXTSEL_T8CC1 +#define ADC1_EXTSEL_T8CC2 ADC_CFGR_EXTSEL_T8CC2 +#define ADC1_EXTSEL_T8CC3 ADC_CFGR_EXTSEL_T8CC3 +#define ADC1_EXTSEL_T8CC4 ADC_CFGR_EXTSEL_T8CC4 +#define ADC1_EXTSEL_T8TRGO ADC_CFGR_EXTSEL_T8TRGO +#define ADC1_EXTSEL_T8TRGO2 ADC_CFGR_EXTSEL_T8TRGO2 +#define ADC2_EXTSEL_T8CC1 ADC_CFGR_EXTSEL_T8CC1 +#define ADC2_EXTSEL_T8CC2 ADC_CFGR_EXTSEL_T8CC2 +#define ADC2_EXTSEL_T8CC3 ADC_CFGR_EXTSEL_T8CC3 +#define ADC2_EXTSEL_T8CC4 ADC_CFGR_EXTSEL_T8CC4 +#define ADC2_EXTSEL_T8TRGO ADC_CFGR_EXTSEL_T8TRGO +#define ADC2_EXTSEL_T8TRGO2 ADC_CFGR_EXTSEL_T8TRGO2 +#define ADC3_EXTSEL_T8CC1 ADC_CFGR_EXTSEL_T8CC1 +#define ADC3_EXTSEL_T8CC2 ADC_CFGR_EXTSEL_T8CC2 +#define ADC3_EXTSEL_T8CC3 ADC_CFGR_EXTSEL_T8CC3 +#define ADC3_EXTSEL_T8CC4 ADC_CFGR_EXTSEL_T8CC4 +#define ADC3_EXTSEL_T8TRGO ADC_CFGR_EXTSEL_T8TRGO +#define ADC3_EXTSEL_T8TRGO2 ADC_CFGR_EXTSEL_T8TRGO2 + +#define ADC1_EXTSEL_T15CC1 ADC_CFGR_EXTSEL_T15CC1 +#define ADC1_EXTSEL_T15CC2 ADC_CFGR_EXTSEL_T15CC2 +#define ADC1_EXTSEL_T15CC3 ADC_CFGR_EXTSEL_T15CC3 +#define ADC1_EXTSEL_T15CC4 ADC_CFGR_EXTSEL_T15CC4 +#define ADC1_EXTSEL_T15TRGO ADC_CFGR_EXTSEL_T15TRGO +#define ADC2_EXTSEL_T15CC1 ADC_CFGR_EXTSEL_T15CC1 +#define ADC2_EXTSEL_T15CC2 ADC_CFGR_EXTSEL_T15CC2 +#define ADC2_EXTSEL_T15CC3 ADC_CFGR_EXTSEL_T15CC3 +#define ADC2_EXTSEL_T15CC4 ADC_CFGR_EXTSEL_T15CC4 +#define ADC2_EXTSEL_T15TRGO ADC_CFGR_EXTSEL_T15TRGO +#define ADC3_EXTSEL_T15CC1 ADC_CFGR_EXTSEL_T15CC1 +#define ADC3_EXTSEL_T15CC2 ADC_CFGR_EXTSEL_T15CC2 +#define ADC3_EXTSEL_T15CC3 ADC_CFGR_EXTSEL_T15CC3 +#define ADC3_EXTSEL_T15CC4 ADC_CFGR_EXTSEL_T15CC4 +#define ADC3_EXTSEL_T15TRGO ADC_CFGR_EXTSEL_T15TRGO + + +#if defined(CONFIG_STM32H7_TIM1_ADC1) +# if CONFIG_STM32H7_ADC1_TIMTRIG == 0 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T1CC1 +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 1 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T1CC2 +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 2 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T1CC3 +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 3 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T1CC4 +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 4 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T1TRGO +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 5 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T1TRGO2 +# else +# error "CONFIG_STM32H7_ADC1_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32H7_TIM2_ADC1) +# if CONFIG_STM32H7_ADC1_TIMTRIG == 0 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T2CC1 +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 1 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T2CC2 +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 2 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T2CC3 +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 3 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T2CC4 +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 4 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T2TRGO +# else +# error "CONFIG_STM32H7_ADC1_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32H7_TIM3_ADC1) +# if CONFIG_STM32H7_ADC1_TIMTRIG == 0 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T3CC1 +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 1 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T3CC2 +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 2 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T3CC3 +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 3 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T3CC4 +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 4 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T3TRGO +# else +# error "CONFIG_STM32H7_ADC1_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32H7_TIM4_ADC1) +# if CONFIG_STM32H7_ADC1_TIMTRIG == 0 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T4CC1 +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 1 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T4CC2 +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 2 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T4CC3 +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 3 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T4CC4 +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 4 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T4TRGO +# else +# error "CONFIG_STM32H7_ADC1_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32H7_TIM6_ADC1) +# if CONFIG_STM32H7_ADC1_TIMTRIG == 0 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T6CC1 +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 1 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T6CC2 +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 2 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T6CC3 +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 3 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T6CC4 +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 4 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T6TRGO +# else +# error "CONFIG_STM32H7_ADC1_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32H7_TIM8_ADC1) +# if CONFIG_STM32H7_ADC1_TIMTRIG == 0 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T8CC1 +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 1 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T8CC2 +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 2 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T8CC3 +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 3 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T8CC4 +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 4 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T8TRGO +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 5 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T8TRGO2 +# else +# error "CONFIG_STM32H7_ADC1_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32H7_TIM15_ADC1) +# if CONFIG_STM32H7_ADC1_TIMTRIG == 0 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T15CC1 +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 1 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T15CC2 +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 2 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T15CC3 +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 3 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T15CC4 +# elif CONFIG_STM32H7_ADC1_TIMTRIG == 4 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T15TRGO +# else +# error "CONFIG_STM32H7_ADC1_TIMTRIG is out of range" +# endif +#endif + +#if defined(CONFIG_STM32H7_TIM1_ADC2) +# if CONFIG_STM32H7_ADC2_TIMTRIG == 0 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T1CC1 +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 1 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T1CC2 +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 2 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T1CC3 +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 3 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T1CC4 +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 4 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T1TRGO +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 5 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T1TRGO2 +# else +# error "CONFIG_STM32H7_ADC2_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32H7_TIM2_ADC2) +# if CONFIG_STM32H7_ADC2_TIMTRIG == 0 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T2CC1 +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 1 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T2CC2 +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 2 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T2CC3 +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 3 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T2CC4 +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 4 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T2TRGO +# else +# error "CONFIG_STM32H7_ADC2_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32H7_TIM3_ADC2) +# if CONFIG_STM32H7_ADC2_TIMTRIG == 0 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T3CC1 +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 1 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T3CC2 +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 2 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T3CC3 +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 3 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T3CC4 +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 4 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T3TRGO +# else +# error "CONFIG_STM32H7_ADC2_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32H7_TIM4_ADC2) +# if CONFIG_STM32H7_ADC2_TIMTRIG == 0 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T4CC1 +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 1 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T4CC2 +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 2 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T4CC3 +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 3 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T4CC4 +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 4 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T4TRGO +# else +# error "CONFIG_STM32H7_ADC2_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32H7_TIM6_ADC2) +# if CONFIG_STM32H7_ADC2_TIMTRIG == 0 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T6CC1 +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 1 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T6CC2 +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 2 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T6CC3 +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 3 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T6CC4 +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 4 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T6TRGO +# else +# error "CONFIG_STM32H7_ADC2_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32H7_TIM8_ADC2) +# if CONFIG_STM32H7_ADC2_TIMTRIG == 0 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T8CC1 +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 1 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T8CC2 +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 2 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T8CC3 +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 3 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T8CC4 +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 4 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T8TRGO +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 5 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T8TRGO2 +# else +# error "CONFIG_STM32H7_ADC2_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32H7_TIM15_ADC2) +# if CONFIG_STM32H7_ADC2_TIMTRIG == 0 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T15CC1 +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 1 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T15CC2 +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 2 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T15CC3 +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 3 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T15CC4 +# elif CONFIG_STM32H7_ADC2_TIMTRIG == 4 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T15TRGO +# else +# error "CONFIG_STM32H7_ADC2_TIMTRIG is out of range" +# endif +#endif + +#if defined(CONFIG_STM32H7_TIM1_ADC3) +# if CONFIG_STM32H7_ADC3_TIMTRIG == 0 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T1CC1 +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 1 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T1CC2 +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 2 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T1CC3 +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 3 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T1CC4 +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 4 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T1TRGO +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 5 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T1TRGO2 +# else +# error "CONFIG_STM32H7_ADC3_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32H7_TIM2_ADC3) +# if CONFIG_STM32H7_ADC3_TIMTRIG == 0 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T2CC1 +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 1 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T2CC2 +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 2 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T2CC3 +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 3 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T2CC4 +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 4 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T2TRGO +# else +# error "CONFIG_STM32H7_ADC3_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32H7_TIM3_ADC3) +# if CONFIG_STM32H7_ADC3_TIMTRIG == 0 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T3CC1 +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 1 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T3CC2 +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 2 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T3CC3 +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 3 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T3CC4 +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 4 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T3TRGO +# else +# error "CONFIG_STM32H7_ADC3_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32H7_TIM4_ADC3) +# if CONFIG_STM32H7_ADC3_TIMTRIG == 0 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T4CC1 +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 1 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T4CC2 +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 2 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T4CC3 +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 3 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T4CC4 +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 4 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T4TRGO +# else +# error "CONFIG_STM32H7_ADC3_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32H7_TIM6_ADC3) +# if CONFIG_STM32H7_ADC3_TIMTRIG == 0 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T6CC1 +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 1 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T6CC2 +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 2 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T6CC3 +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 3 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T6CC4 +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 4 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T6TRGO +# else +# error "CONFIG_STM32H7_ADC3_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32H7_TIM8_ADC3) +# if CONFIG_STM32H7_ADC3_TIMTRIG == 0 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T8CC1 +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 1 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T8CC2 +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 2 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T8CC3 +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 3 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T8CC4 +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 4 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T8TRGO +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 5 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T8TRGO2 +# else +# error "CONFIG_STM32H7_ADC3_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32H7_TIM15_ADC3) +# if CONFIG_STM32H7_ADC3_TIMTRIG == 0 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T15CC1 +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 1 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T15CC2 +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 2 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T15CC3 +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 3 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T15CC4 +# elif CONFIG_STM32H7_ADC3_TIMTRIG == 4 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T15TRGO +# else +# error "CONFIG_STM32H7_ADC3_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: stm32h7_adc_initialize + * + * Description: + * Initialize the ADC. + * + * Input Parameters: + * intf - Could be {1,2,3} for ADC1, ADC2, or ADC3 + * 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 *stm32h7_adc_initialize(int intf, + FAR const uint8_t *chanlist, + int nchannels); +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif /* __ASSEMBLY__ */ + +#endif /* CONFIG_STM32H7_ADC1 || CONFIG_STM32H7_ADC2 || CONFIG_STM32H7_ADC3 */ +#endif /* __ARCH_ARM_SRC_STM32H7_STM32_ADC_H */ diff --git a/arch/arm/src/stm32h7/stm32_serial.c b/arch/arm/src/stm32h7/stm32_serial.c index 09d2c84bc4..21ee19de12 100644 --- a/arch/arm/src/stm32h7/stm32_serial.c +++ b/arch/arm/src/stm32h7/stm32_serial.c @@ -1482,11 +1482,14 @@ static int up_interrupt(int irq, void *context, FAR void *arg) static int up_ioctl(struct file *filep, int cmd, unsigned long arg) { #if defined(CONFIG_SERIAL_TERMIOS) || defined(CONFIG_SERIAL_TIOCSERGSTRUCT) \ + || defined(CONFIG_STM32H7_USART_SINGLEWIRE) \ || defined(CONFIG_STM32H7_SERIALBRK_BSDCOMPAT) struct inode *inode = filep->f_inode; struct uart_dev_s *dev = inode->i_private; #endif -#if defined(CONFIG_SERIAL_TERMIOS) || defined(CONFIG_STM32H7_SERIALBRK_BSDCOMPAT) +#if defined(CONFIG_SERIAL_TERMIOS) \ + || defined(CONFIG_STM32H7_USART_SINGLEWIRE) \ + || defined(CONFIG_STM32H7_SERIALBRK_BSDCOMPAT) struct up_dev_s *priv = (struct up_dev_s *)dev->priv; #endif int ret = OK; @@ -1701,21 +1704,12 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg) flags = enter_critical_section(); cr1 = up_serialin(priv, STM32_USART_CR1_OFFSET); - up_serialout(priv, STM32_USART_CR1_OFFSET, cr1 | USART_CR1_SBK); + up_serialout(priv, STM32_USART_RQR_OFFSET, cr1 | USART_RQR_SBKRQ); leave_critical_section(flags); } break; - case TIOCCBRK: /* No BSD compatibility: May turn off break too soon */ - { - uint32_t cr1; - irqstate_t flags; - - flags = enter_critical_section(); - cr1 = up_serialin(priv, STM32_USART_CR1_OFFSET); - up_serialout(priv, STM32_USART_CR1_OFFSET, cr1 & ~USART_CR1_SBK); - leave_critical_section(flags); - } + case TIOCCBRK: /* No BSD compatibility: HW does not support stopping a break */ break; # endif #endif diff --git a/arch/arm/src/stm32h7/stm32_tim.c b/arch/arm/src/stm32h7/stm32_tim.c index a3e96c2953..362584501c 100644 --- a/arch/arm/src/stm32h7/stm32_tim.c +++ b/arch/arm/src/stm32h7/stm32_tim.c @@ -389,7 +389,7 @@ struct stm32_tim_priv_s stm32_tim12_priv = #endif #ifdef CONFIG_STM32H7_TIM13 -struct stm32_tim_priv_s stm32_tim12_priv = +struct stm32_tim_priv_s stm32_tim13_priv = { .ops = &stm32_tim_ops, .mode = STM32_TIM_MODE_UNUSED, @@ -398,7 +398,7 @@ struct stm32_tim_priv_s stm32_tim12_priv = #endif #ifdef CONFIG_STM32H7_TIM14 -struct stm32_tim_priv_s stm32_tim12_priv = +struct stm32_tim_priv_s stm32_tim14_priv = { .ops = &stm32_tim_ops, .mode = STM32_TIM_MODE_UNUSED, @@ -1430,7 +1430,7 @@ int stm32_tim_deinit(FAR struct stm32_tim_dev_s * dev) #endif #ifdef CONFIG_STM32H7_TIM7 case STM32_TIM7_BASE: - modifyreg32(STM32_RCC_APB1LENR, RCC_APB1ENR_TIM7EN, 0); + modifyreg32(STM32_RCC_APB1LENR, RCC_APB1LENR_TIM7EN, 0); break; #endif #ifdef CONFIG_STM32H7_TIM8 @@ -1444,7 +1444,7 @@ int stm32_tim_deinit(FAR struct stm32_tim_dev_s * dev) break; #endif #ifdef CONFIG_STM32H7_TIM13 - case STM32_TIM12_BASE: + case STM32_TIM13_BASE: modifyreg32(STM32_RCC_APB1LENR, RCC_APB1LENR_TIM13EN, 0); break; #endif diff --git a/arch/arm/src/stm32h7/stm32h7x3xx_rcc.c b/arch/arm/src/stm32h7/stm32h7x3xx_rcc.c index 63bbcf3fe6..492cbd8bf3 100644 --- a/arch/arm/src/stm32h7/stm32h7x3xx_rcc.c +++ b/arch/arm/src/stm32h7/stm32h7x3xx_rcc.c @@ -145,6 +145,11 @@ static inline void rcc_enableahb1(void) */ regval = getreg32(STM32_RCC_AHB1ENR); +#if defined(CONFIG_STM32H7_ADC1) || defined(CONFIG_STM32H7_ADC2) + /* ADC1 & 2 clock enable */ + + regval |= RCC_AHB1ENR_ADC12EN; +#endif #ifdef CONFIG_STM32H7_DMA1 /* DMA 1 clock enable */ @@ -262,6 +267,12 @@ static inline void rcc_enableahb4(void) regval = getreg32(STM32_RCC_AHB4ENR); +#ifdef CONFIG_STM32H7_ADC3 + /* ADC3 clock enable */ + + regval |= RCC_AHB4ENR_ADC3EN; +#endif + /* Enable GPIO, GPIOB, ... GPIOK */ #if STM32H7_NGPIO > 0 @@ -673,16 +684,26 @@ static void stm32_stdclockconfig(void) regval |= RCC_CR_PLL1ON; putreg32(regval, STM32_RCC_CR); - /* TODO: Enable the PLL2 */ + /* Enable the PLL2 */ + + regval = getreg32(STM32_RCC_CR); + regval |= RCC_CR_PLL2ON; + putreg32(regval, STM32_RCC_CR); /* TODO: Enable the PLL3 */ - /* Wait until the PLL is ready */ + /* Wait until the PLL1 is ready */ while ((getreg32(STM32_RCC_CR) & RCC_CR_PLL1RDY) == 0) { } + /* Wait until the PLL2 is ready */ + + while ((getreg32(STM32_RCC_CR) & RCC_CR_PLL2RDY) == 0) + { + } + /* Configure FLASH wait states */ regval = FLASH_ACR_LATENCY(BOARD_FLASH_WAITSTATES); @@ -760,6 +781,16 @@ static void stm32_stdclockconfig(void) putreg32(regval, STM32_RCC_D2CCIP2R); #endif + /* Configure ADC source clock */ + +#if defined(STM32_RCC_D3CCIPR_ADCSEL) + regval = getreg32(STM32_RCC_D3CCIPR); + regval &= ~RCC_D3CCIPR_ADCSEL_MASK; + regval |= STM32_RCC_D3CCIPR_ADCSEL; + putreg32(regval, STM32_RCC_D3CCIPR); +#endif + + #if defined(CONFIG_STM32H7_IWDG) || defined(CONFIG_STM32H7_RTC_LSICLOCK) /* Low speed internal clock source LSI */ diff --git a/configs/nucleo-h743zi/include/board.h b/configs/nucleo-h743zi/include/board.h index e0faca428d..a126aa6394 100644 --- a/configs/nucleo-h743zi/include/board.h +++ b/configs/nucleo-h743zi/include/board.h @@ -134,15 +134,17 @@ /* PLL2 */ -#define STM32_PLLCFG_PLL2CFG 0 -#define STM32_PLLCFG_PLL2M 0 -#define STM32_PLLCFG_PLL2N 0 -#define STM32_PLLCFG_PLL2P 0 -#define STM32_PLLCFG_PLL2Q 0 -#define STM32_PLLCFG_PLL2R 0 +#define STM32_PLLCFG_PLL2CFG (RCC_PLLCFGR_PLL2VCOSEL_WIDE | \ + RCC_PLLCFGR_PLL2RGE_4_8_MHZ | \ + RCC_PLLCFGR_DIVP2EN) +#define STM32_PLLCFG_PLL2M RCC_PLLCKSELR_DIVM2(2) +#define STM32_PLLCFG_PLL2N RCC_PLL2DIVR_N2(200) +#define STM32_PLLCFG_PLL2P RCC_PLL2DIVR_P2(40) +#define STM32_PLLCFG_PLL2Q 0 +#define STM32_PLLCFG_PLL2R 0 -#define STM32_VCO2_FREQUENCY -#define STM32_PLL2P_FREQUENCY +#define STM32_VCO2_FREQUENCY ((STM32_HSE_FREQUENCY / 2) * 200) +#define STM32_PLL2P_FREQUENCY (STM32_VCO2_FREQUENCY / 2) #define STM32_PLL2Q_FREQUENCY #define STM32_PLL2R_FREQUENCY @@ -248,7 +250,11 @@ /* USB 1 and 2 clock source - HSI48 */ -#define STM32_RCC_D2CCIP2R_USBSRC RCC_D2CCIP2R_USBSEL_HSI48 +#define STM32_RCC_D2CCIP2R_USBSRC RCC_D2CCIP2R_USBSEL_HSI48 + +/* ADC 1 2 3 clock source - pll2_pclk */ + +#define STM32_RCC_D3CCIPR_ADCSEL RCC_D3CCIPR_ADCSEL_PLL2 /* FLASH wait states * diff --git a/configs/nucleo-h743zi/src/Makefile b/configs/nucleo-h743zi/src/Makefile index dc896ccd7a..eb1eee7148 100644 --- a/configs/nucleo-h743zi/src/Makefile +++ b/configs/nucleo-h743zi/src/Makefile @@ -38,6 +38,10 @@ ASRCS = CSRCS = stm32_boot.c stm32_bringup.c +ifeq ($(CONFIG_ADC),y) +CSRCS += stm32_adc.c +endif + ifeq ($(CONFIG_ARCH_LEDS),y) CSRCS += stm32_autoleds.c else diff --git a/configs/nucleo-h743zi/src/nucleo-h743zi.h b/configs/nucleo-h743zi/src/nucleo-h743zi.h index afe775daf5..f183f335fd 100644 --- a/configs/nucleo-h743zi/src/nucleo-h743zi.h +++ b/configs/nucleo-h743zi/src/nucleo-h743zi.h @@ -186,8 +186,6 @@ void stm32_spidev_initialize(void); * ************************************************************************************/ -// TODO: implement ADC or delete this - #ifdef CONFIG_ADC int stm32_adc_setup(void); #endif diff --git a/configs/nucleo-h743zi/src/stm32_adc.c b/configs/nucleo-h743zi/src/stm32_adc.c new file mode 100644 index 0000000000..1d1399b504 --- /dev/null +++ b/configs/nucleo-h743zi/src/stm32_adc.c @@ -0,0 +1,218 @@ +/************************************************************************************ + * configs/nucleo-h743zi/src/stm32_adc.c + * + * Copyright (C) 2016, 2019 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * David Sidrane + * + * 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 "chip.h" +#include "stm32_gpio.h" +#include "stm32_adc.h" +#include "nucleo-h743zi.h" + +#ifdef CONFIG_ADC + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Configuration ********************************************************************/ +/* Up to 3 ADC interfaces are supported */ + +#if defined(CONFIG_STM32H7_ADC1) || defined(CONFIG_STM32H7_ADC2) || defined(CONFIG_STM32H7_ADC3) +#ifndef CONFIG_STM32H7_ADC1 +# warning "Channel information only available for ADC1" +#endif + +/* The number of ADC channels in the conversion list */ + +#define ADC1_NCHANNELS 5 +#define ADC3_NCHANNELS 1 + +/************************************************************************************ + * Private Data + ************************************************************************************/ + +#ifdef CONFIG_STM32H7_ADC1 +/* Identifying number of each ADC channel: Variable Resistor. + * + * ADC1: {5, 10, 12, 13, 15}; + */ + +static const uint8_t g_adc1_chanlist[ADC1_NCHANNELS] = {5, 10, 12, 13, 15}; + +/* Configurations of pins used by each ADC channels + * + * ADC1: {GPIO_ADC12_INP5, GPIO_ADC123_INP10, GPIO_ADC123_INP12, GPIO_ADC12_INP13, + * GPIO_ADC12_INP15}; + */ + +static const uint32_t g_adc1_pinlist[ADC1_NCHANNELS] = {GPIO_ADC12_INP5, \ + GPIO_ADC123_INP10, \ + GPIO_ADC123_INP12, \ + GPIO_ADC12_INP13, \ + GPIO_ADC12_INP15}; +#endif + +#ifdef CONFIG_STM32H7_ADC3 +/* Identifying number of each ADC channel: Variable Resistor. + * + * ADC3: {6,}; + */ + +static const uint8_t g_adc3_chanlist[ADC1_NCHANNELS] = {6}; + +/* Configurations of pins used by each ADC channels + * + * + * ADC3: {GPIO_ADC3_INP6} + */ + +static const uint32_t g_adc3_pinlist[ADC3_NCHANNELS] = {GPIO_ADC3_INP6}; +#endif + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32_adc_setup + * + * Description: + * Initialize ADC and register the ADC driver. + * + ************************************************************************************/ + +int stm32_adc_setup(void) +{ +#if defined(CONFIG_STM32H7_ADC1) || defined(CONFIG_STM32H7_ADC3) + static bool initialized = false; + struct adc_dev_s *adc; + int ret; + int i; + char devname[] = "/dev/adc0"; + + /* Check if we have already initialized */ + + if (!initialized) + { +#endif +#if defined(CONFIG_STM32H7_ADC1) + /* Configure the pins as analog inputs for the selected channels */ + + for (i = 0; i < ADC1_NCHANNELS; i++) + { + if (g_adc1_pinlist[i] != 0) + { + stm32_configgpio(g_adc1_pinlist[i]); + } + } + + /* Call stm32_adcinitialize() to get an instance of the ADC interface */ + + adc = stm32h7_adc_initialize(1, g_adc1_chanlist, ADC1_NCHANNELS); + if (adc == NULL) + { + aerr("ERROR: Failed to get ADC1 interface\n"); + return -ENODEV; + } + + /* Register the ADC driver at "/dev/adc0" */ + + ret = adc_register(devname, adc); + if (ret < 0) + { + aerr("ERROR: adc_register(%s) failed: %d\n", devname, ret); + return ret; + } + devname[8]++; +#endif +#if defined(CONFIG_STM32H7_ADC3) + /* Configure the pins as analog inputs for the selected channels */ + + for (i = 0; i < ADC3_NCHANNELS; i++) + { + if (g_adc3_pinlist[i] != 0) + { + stm32_configgpio(g_adc3_pinlist[i]); + } + } + + /* Call stm32_adcinitialize() to get an instance of the ADC interface */ + + adc = stm32h7_adc_initialize(3, g_adc3_chanlist, ADC3_NCHANNELS); + if (adc == NULL) + { + aerr("ERROR: Failed to get ADC3 interface\n"); + return -ENODEV; + } + + /* Register the ADC driver at "/dev/adc0 or 1" */ + + ret = adc_register(devname, adc); + if (ret < 0) + { + aerr("ERROR: adc_register(%s) failed: %d\n", devname, ret); + return ret; + } +#endif +#if defined(CONFIG_STM32H7_ADC1) || defined(CONFIG_STM32H7_ADC3) + /* Now we are initialized */ + + initialized = true; + } + + return OK; +#else + return -ENOSYS; +#endif +} + +#endif /* CONFIG_STM32H7_ADC1 || CONFIG_STM32H7_ADC2 || CONFIG_STM32H7_ADC3 */ +#endif /* CONFIG_ADC */