diff --git a/arch/arm/src/stm32f7/Make.defs b/arch/arm/src/stm32f7/Make.defs index cf86c88c3e6..39364a5f95b 100644 --- a/arch/arm/src/stm32f7/Make.defs +++ b/arch/arm/src/stm32f7/Make.defs @@ -139,6 +139,10 @@ ifeq ($(CONFIG_STM32_PWR),y) CHIP_CSRCS += stm32_exti_pwr.c endif +ifeq ($(CONFIG_ADC),y) +CHIP_CSRCS += stm32_adc.c +endif + ifeq ($(CONFIG_RTC),y) ifeq ($(CONFIG_RTC_ALARM),y) CHIP_CSRCS += stm32_exti_alarm.c diff --git a/arch/arm/src/stm32f7/chip/stm32_adc.h b/arch/arm/src/stm32f7/chip/stm32_adc.h new file mode 100644 index 00000000000..600d6c23b93 --- /dev/null +++ b/arch/arm/src/stm32f7/chip/stm32_adc.h @@ -0,0 +1,495 @@ +/**************************************************************************************************** + * arch/arm/src/stm32f7/chip/stm32_adc.h + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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_STM32F_CHIP_STM32_ADC_H +#define __ARCH_ARM_SRC_STM32F_CHIP_STM32_ADC_H + +/**************************************************************************************************** + * Included Files + ****************************************************************************************************/ + +#include + +#include "chip.h" + +/**************************************************************************************************** + * Pre-processor Definitions + ****************************************************************************************************/ + +/* Register Offsets *********************************************************************************/ + +#define STM32_ADC_SR_OFFSET 0x0000 /* ADC status register (32-bit) */ +#define STM32_ADC_CR1_OFFSET 0x0004 /* ADC control register 1 (32-bit) */ +#define STM32_ADC_CR2_OFFSET 0x0008 /* ADC control register 2 (32-bit) */ +#define STM32_ADC_SMPR1_OFFSET 0x000c /* ADC sample time register 1 (32-bit) */ +#define STM32_ADC_SMPR2_OFFSET 0x0010 /* ADC sample time register 2 (32-bit) */ +#define STM32_ADC_JOFR1_OFFSET 0x0014 /* ADC injected channel data offset register 1 (32-bit) */ +#define STM32_ADC_JOFR2_OFFSET 0x0018 /* ADC injected channel data offset register 2 (32-bit) */ +#define STM32_ADC_JOFR3_OFFSET 0x001c /* ADC injected channel data offset register 3 (32-bit) */ +#define STM32_ADC_JOFR4_OFFSET 0x0020 /* ADC injected channel data offset register 4 (32-bit) */ +#define STM32_ADC_HTR_OFFSET 0x0024 /* ADC watchdog high threshold register (32-bit) */ +#define STM32_ADC_LTR_OFFSET 0x0028 /* ADC watchdog low threshold register (32-bit) */ +#define STM32_ADC_SQR1_OFFSET 0x002c /* ADC regular sequence register 1 (32-bit) */ +#define STM32_ADC_SQR2_OFFSET 0x0030 /* ADC regular sequence register 2 (32-bit) */ +#define STM32_ADC_SQR3_OFFSET 0x0034 /* ADC regular sequence register 3 (32-bit) */ +#define STM32_ADC_JSQR_OFFSET 0x0038 /* ADC injected sequence register (32-bit) */ +#define STM32_ADC_JDR1_OFFSET 0x003c /* ADC injected data register 1 (32-bit) */ +#define STM32_ADC_JDR2_OFFSET 0x0040 /* ADC injected data register 1 (32-bit) */ +#define STM32_ADC_JDR3_OFFSET 0x0044 /* ADC injected data register 1 (32-bit) */ +#define STM32_ADC_JDR4_OFFSET 0x0048 /* ADC injected data register 1 (32-bit) */ +#define STM32_ADC_DR_OFFSET 0x004c /* ADC regular data register (32-bit) */ + + +#define STM32_ADC_CSR_OFFSET 0x0000 /* Common status register */ +#define STM32_ADC_CCR_OFFSET 0x0004 /* Common control register */ +#define STM32_ADC_CDR_OFFSET 0x0008 /* Data register for dual and triple modes */ + +/* Register Addresses *******************************************************************************/ + +#if STM32F7_NADC > 0 +# define STM32_ADC1_SR (STM32_ADC1_BASE+STM32_ADC_SR_OFFSET) +# define STM32_ADC1_CR1 (STM32_ADC1_BASE+STM32_ADC_CR1_OFFSET) +# define STM32_ADC1_CR2 (STM32_ADC1_BASE+STM32_ADC_CR2_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_JOFR1 (STM32_ADC1_BASE+STM32_ADC_JOFR1_OFFSET) +# define STM32_ADC1_JOFR2 (STM32_ADC1_BASE+STM32_ADC_JOFR2_OFFSET) +# define STM32_ADC1_JOFR3 (STM32_ADC1_BASE+STM32_ADC_JOFR3_OFFSET) +# define STM32_ADC1_JOFR4 (STM32_ADC1_BASE+STM32_ADC_JOFR4_OFFSET) +# define STM32_ADC1_HTR (STM32_ADC1_BASE+STM32_ADC_HTR_OFFSET) +# define STM32_ADC1_LTR (STM32_ADC1_BASE+STM32_ADC_LTR_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_JSQR (STM32_ADC1_BASE+STM32_ADC_JSQR_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_DR (STM32_ADC1_BASE+STM32_ADC_DR_OFFSET) +#endif + +#if STM32F7_NADC > 1 +# define STM32_ADC2_SR (STM32_ADC2_BASE+STM32_ADC_SR_OFFSET) +# define STM32_ADC2_CR1 (STM32_ADC2_BASE+STM32_ADC_CR1_OFFSET) +# define STM32_ADC2_CR2 (STM32_ADC2_BASE+STM32_ADC_CR2_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_JOFR1 (STM32_ADC2_BASE+STM32_ADC_JOFR1_OFFSET) +# define STM32_ADC2_JOFR2 (STM32_ADC2_BASE+STM32_ADC_JOFR2_OFFSET) +# define STM32_ADC2_JOFR3 (STM32_ADC2_BASE+STM32_ADC_JOFR3_OFFSET) +# define STM32_ADC2_JOFR4 (STM32_ADC2_BASE+STM32_ADC_JOFR4_OFFSET) +# define STM32_ADC2_HTR (STM32_ADC2_BASE+STM32_ADC_HTR_OFFSET) +# define STM32_ADC2_LTR (STM32_ADC2_BASE+STM32_ADC_LTR_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_JSQR (STM32_ADC2_BASE+STM32_ADC_JSQR_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_DR (STM32_ADC2_BASE+STM32_ADC_DR_OFFSET) +#endif + +#if STM32F7_NADC > 2 +# define STM32_ADC3_SR (STM32_ADC3_BASE+STM32_ADC_SR_OFFSET) +# define STM32_ADC3_CR1 (STM32_ADC3_BASE+STM32_ADC_CR1_OFFSET) +# define STM32_ADC3_CR2 (STM32_ADC3_BASE+STM32_ADC_CR2_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_JOFR1 (STM32_ADC3_BASE+STM32_ADC_JOFR1_OFFSET) +# define STM32_ADC3_JOFR2 (STM32_ADC3_BASE+STM32_ADC_JOFR2_OFFSET) +# define STM32_ADC3_JOFR3 (STM32_ADC3_BASE+STM32_ADC_JOFR3_OFFSET) +# define STM32_ADC3_JOFR4 (STM32_ADC3_BASE+STM32_ADC_JOFR4_OFFSET) +# define STM32_ADC3_HTR (STM32_ADC3_BASE+STM32_ADC_HTR_OFFSET) +# define STM32_ADC3_LTR (STM32_ADC3_BASE+STM32_ADC_LTR_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_JSQR (STM32_ADC3_BASE+STM32_ADC_JSQR_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_DR (STM32_ADC3_BASE+STM32_ADC_DR_OFFSET) +#endif + +#define STM32_ADC_CSR (STM32_ADCCMN_BASE+STM32_ADC_CSR_OFFSET) +#define STM32_ADC_CCR (STM32_ADCCMN_BASE+STM32_ADC_CCR_OFFSET) +#define STM32_ADC_CDR (STM32_ADCCMN_BASE+STM32_ADC_CDR_OFFSET) + +/* Register Bitfield Definitions ********************************************************************/ + +/* ADC status register */ + +#define ADC_SR_AWD (1 << 0) /* Bit 0 : Analog watchdog flag */ +#define ADC_SR_EOC (1 << 1) /* Bit 1 : End of conversion */ +#define ADC_SR_JEOC (1 << 2) /* Bit 2 : Injected channel end of conversion */ +#define ADC_SR_JSTRT (1 << 3) /* Bit 3 : Injected channel Start flag */ +#define ADC_SR_STRT (1 << 4) /* Bit 4 : Regular channel Start flag */ +#define ADC_SR_OVR (1 << 5) /* Bit 5 : Overrun */ + +/* ADC control register 1 */ + +#define ADC_CR1_AWDCH_SHIFT (0) /* Bits 4-0: Analog watchdog channel select bits */ +#define ADC_CR1_AWDCH_MASK (0x1f << ADC_CR1_AWDCH_SHIFT) + +#define ADC_CR1_EOCIE (1 << 5) /* Bit 5: Interrupt enable for EOC */ +#define ADC_CR1_AWDIE (1 << 6) /* Bit 6: Analog Watchdog interrupt enable */ +#define ADC_CR1_JEOCIE (1 << 7) /* Bit 7: Interrupt enable for injected channels */ +#define ADC_CR1_SCAN (1 << 8) /* Bit 8: Scan mode */ +#define ADC_CR1_AWDSGL (1 << 9) /* Bit 9: Enable the watchdog on a single channel in scan mode */ +#define ADC_CR1_JAUTO (1 << 10) /* Bit 10: Automatic Injected Group conversion */ +#define ADC_CR1_DISCEN (1 << 11) /* Bit 11: Discontinuous mode on regular channels */ +#define ADC_CR1_JDISCEN (1 << 12) /* Bit 12: Discontinuous mode on injected channels */ + +#define ADC_CR1_DISCNUM_SHIFT (13) /* Bits 15-13: Discontinuous mode channel count */ +#define ADC_CR1_DISCNUM_MASK (0x07 << ADC_CR1_DISCNUM_SHIFT) + + +#define ADC_CR1_JAWDEN (1 << 22) /* Bit 22: Analog watchdog enable on injected channels */ +#define ADC_CR1_AWDEN (1 << 23) /* Bit 23: Analog watchdog enable on regular channels */ + +#define ADC_CR1_RES_SHIFT (24) /* Bits 24-25: Resolution */ +#define ADC_CR1_RES_MASK (3 << ADC_CR1_RES_SHIFT) +#define ADC_CR1_RES_12BIT (0 << ADC_CR1_RES_SHIFT) /* 15 ADCCLK cycles. For STM32L15XX: 12 ADCCLK cycles */ +#define ADC_CR1_RES_10BIT (1 << ADC_CR1_RES_SHIFT) /* 13 ADCCLK cycles. For STM32L15XX: 11 ADCCLK cycles */ +#define ADC_CR1_RES_8BIT (2 << ADC_CR1_RES_SHIFT) /* 11 ADCCLK cycles. For STM32L15XX: 9 ADCCLK cycles */ +#define ADC_CR1_RES_6BIT (3 << ADC_CR1_RES_SHIFT) /* 9 ADCCLK cycles. For STM32L15XX: 7 ADCCLK cycles */ +#define ADC_CR1_OVRIE (1 << 26) /* Bit 26: Overrun interrupt enable */ + +/* ADC control register 2 */ + +#define ADC_CR2_ADON (1 << 0) /* Bit 0: A/D Converter ON / OFF */ +#define ADC_CR2_CONT (1 << 1) /* Bit 1: Continuous Conversion */ + +#define ADC_CR2_DMA (1 << 8) /* Bit 8: Direct Memory access mode */ + +#define ADC_CR2_DDS (1 << 9) /* Bit 9: DMA disable selection (for single ADC mode) */ +#define ADC_CR2_EOCS (1 << 10) /* Bit 10: End of conversion selection */ + +#define ADC_CR2_ALIGN (1 << 11) /* Bit 11: Data Alignment */ + + /* Bits 12-15: Reserved */ +#define ADC_CR2_JEXTSEL_SHIFT (16) /* Bits 16-19: External event select for injected group */ +#define ADC_CR2_JEXTSEL_MASK (0x0F << ADC_CR2_JEXTSEL_SHIFT) +#define ADC_CR2_JEXTSEL_T1TRGO (0x00 << ADC_CR2_JEXTSEL_SHIFT) /* 0000: Timer 1 TRGO event */ +#define ADC_CR2_JEXTSEL_T1CC4 (0x01 << ADC_CR2_JEXTSEL_SHIFT) /* 0001: Timer 1 CC4 event */ +#define ADC_CR2_JEXTSEL_T2TRGO (0x02 << ADC_CR2_JEXTSEL_SHIFT) /* 0010: Timer 2 TRGO event */ +#define ADC_CR2_JEXTSEL_T2CC1 (0x03 << ADC_CR2_JEXTSEL_SHIFT) /* 0011: Timer 2 CC1 event */ +#define ADC_CR2_JEXTSEL_T3CC4 (0x04 << ADC_CR2_JEXTSEL_SHIFT) /* 0100: Timer 3 CC4 event */ +#define ADC_CR2_JEXTSEL_T4TRGO (0x05 << ADC_CR2_JEXTSEL_SHIFT) /* 0101: Timer 4 TRGO event */ + /* 0110: NA */ +#define ADC_CR2_JEXTSEL_T8CC4 (0x07 << ADC_CR2_JEXTSEL_SHIFT) /* 0111: Timer 8 CC4 event */ +#define ADC_CR2_JEXTSEL_T1TRGO2 (0x08 << ADC_CR2_JEXTSEL_SHIFT) /* 1000: Timer 1 TRGO2 event */ +#define ADC_CR2_JEXTSEL_T8TRGO (0x09 << ADC_CR2_JEXTSEL_SHIFT) /* 1001: Timer 8 TRGO event */ +#define ADC_CR2_JEXTSEL_T8TRGO2 (0x0A << ADC_CR2_JEXTSEL_SHIFT) /* 1010: Timer 8 TRGO2 event */ +#define ADC_CR2_JEXTSEL_T3CC3 (0x0B << ADC_CR2_JEXTSEL_SHIFT) /* 1011: Timer 3 CC3 event */ +#define ADC_CR2_JEXTSEL_T5TRGO (0x0C << ADC_CR2_JEXTSEL_SHIFT) /* 1100: Timer 5 TRGO event */ +#define ADC_CR2_JEXTSEL_T3CC1 (0x0D << ADC_CR2_JEXTSEL_SHIFT) /* 1101: Timer 3 CC1 event */ +#define ADC_CR2_JEXTSEL_T6TRGO (0x0E << ADC_CR2_JEXTSEL_SHIFT) /* 1110: Timer 6 TRGO event */ + /* 1111: NA */ +#define ADC_CR2_JEXTEN_SHIFT (20) /* Bits 20-21: External trigger enable for injected channels */ +#define ADC_CR2_JEXTEN_MASK (3 << ADC_CR2_JEXTEN_SHIFT) +#define ADC_CR2_JEXTEN_NONE (0 << ADC_CR2_JEXTEN_SHIFT) /* 00: Trigger detection disabled */ +#define ADC_CR2_JEXTEN_RISING (1 << ADC_CR2_JEXTEN_SHIFT) /* 01: Trigger detection on the rising edge */ +#define ADC_CR2_JEXTEN_FALLING (2 << ADC_CR2_JEXTEN_SHIFT) /* 10: Trigger detection on the falling edge */ +#define ADC_CR2_JEXTEN_BOTH (3 << ADC_CR2_JEXTEN_SHIFT) /* 11: Trigger detection on both the rising and falling edges */ + +#define ADC_CR2_JSWSTART (1 << 22) /* Bit 22: Start Conversion of injected channels */ + /* Bit 23: Reserved, must be kept at reset value. */ +#define ADC_CR2_EXTSEL_SHIFT (24) /* Bits 24-27: External Event Select for regular group */ +#define ADC_CR2_EXTSEL_MASK (0x0F << ADC_CR2_EXTSEL_SHIFT) +#define ADC_CR2_EXTSEL_T1CC1 (0x0 << ADC_CR2_EXTSEL_SHIFT) /* 0000: Timer 1 CC1 event */ +#define ADC_CR2_EXTSEL_T1CC2 (0x01 << ADC_CR2_EXTSEL_SHIFT) /* 0001: Timer 1 CC2 event */ +#define ADC_CR2_EXTSEL_T1CC3 (0x02 << ADC_CR2_EXTSEL_SHIFT) /* 0010: Timer 1 CC3 event */ +#define ADC_CR2_EXTSEL_T2CC2 (0x03 << ADC_CR2_EXTSEL_SHIFT) /* 0011: Timer 2 CC2 event */ +#define ADC_CR2_EXTSEL_T5TRGO (0x04 << ADC_CR2_EXTSEL_SHIFT) /* 0100: Timer 5 TRGO event */ +#define ADC_CR2_EXTSEL_T4CC4 (0x05 << ADC_CR2_EXTSEL_SHIFT) /* 0101: Timer 4 CC4 event */ +#define ADC_CR2_EXTSEL_T3CC4 (0x06 << ADC_CR2_EXTSEL_SHIFT) /* 0110: Timer 3 CC4 event */ +#define ADC_CR2_EXTSEL_T8TRGO (0x07 << ADC_CR2_EXTSEL_SHIFT) /* 0111: Timer 8 TRGO event */ +#define ADC_CR2_EXTSEL_T8TRGO2 (0x08 << ADC_CR2_EXTSEL_SHIFT) /* 1000: Timer 8 TRGO2 event */ +#define ADC_CR2_EXTSEL_T1TRGO (0x09 << ADC_CR2_EXTSEL_SHIFT) /* 1001: Timer 1 TRGO event */ +#define ADC_CR2_EXTSEL_T1TRGO2 (0x0A << ADC_CR2_EXTSEL_SHIFT) /* 1010: Timer 1 TRGO2 event */ +#define ADC_CR2_EXTSEL_T2TRGO (0x0B << ADC_CR2_EXTSEL_SHIFT) /* 1011: Timer 2 TRGO event */ +#define ADC_CR2_EXTSEL_T4TRGO (0x0C << ADC_CR2_EXTSEL_SHIFT) /* 1100: Timer 4 TRGO event */ +#define ADC_CR2_EXTSEL_T6TRGO (0x0D << ADC_CR2_EXTSEL_SHIFT) /* 1101: Timer 6 TRGO event */ + /* 1110: NA */ +#define ADC_CR2_EXTSEL_EXTI11 (0x0F << ADC_CR2_EXTSEL_SHIFT) /* 1111: EXTI line 11 */ + +#define ADC_CR2_EXTEN_SHIFT (28) /* Bits 28-29: External trigger enable for regular channels */ +#define ADC_CR2_EXTEN_MASK (3 << ADC_CR2_EXTEN_SHIFT) +#define ADC_CR2_EXTEN_NONE (0 << ADC_CR2_EXTEN_SHIFT) /* 00: Trigger detection disabled */ +#define ADC_CR2_EXTEN_RISING (1 << ADC_CR2_EXTEN_SHIFT) /* 01: Trigger detection on the rising edge */ +#define ADC_CR2_EXTEN_FALLING (2 << ADC_CR2_EXTEN_SHIFT) /* 10: Trigger detection on the falling edge */ +#define ADC_CR2_EXTEN_BOTH (3 << ADC_CR2_EXTEN_SHIFT) /* 11: Trigger detection on both the rising and falling edges */ + +# define ADC_CR2_SWSTART (1 << 30) /* Bit 30: Start Conversion of regular channels */ + +/* ADC sample time register 1 */ + +#define ADC_SMPR_3 0 /* 000: 3 cycles */ +#define ADC_SMPR_15 1 /* 001: 15 cycles */ +#define ADC_SMPR_28 2 /* 010: 28 cycles */ +#define ADC_SMPR_56 3 /* 011: 56 cycles */ +#define ADC_SMPR_84 4 /* 100: 84 cycles */ +#define ADC_SMPR_112 5 /* 101: 112 cycles */ +#define ADC_SMPR_144 6 /* 110: 144 cycles */ +#define ADC_SMPR_480 7 /* 111: 480 cycles */ + +#define ADC_SMPR1_SMP10_SHIFT (0) /* Bits 0-2: Channel 10 Sample time selection */ +#define ADC_SMPR1_SMP10_MASK (7 << ADC_SMPR1_SMP10_SHIFT) +#define ADC_SMPR1_SMP11_SHIFT (3) /* Bits 3-5: Channel 11 Sample time selection */ +#define ADC_SMPR1_SMP11_MASK (7 << ADC_SMPR1_SMP11_SHIFT) +#define ADC_SMPR1_SMP12_SHIFT (6) /* Bits 6-8: Channel 12 Sample time selection */ +#define ADC_SMPR1_SMP12_MASK (7 << ADC_SMPR1_SMP12_SHIFT) +#define ADC_SMPR1_SMP13_SHIFT (9) /* Bits 9-11: Channel 13 Sample time selection */ +#define ADC_SMPR1_SMP13_MASK (7 << ADC_SMPR1_SMP13_SHIFT) +#define ADC_SMPR1_SMP14_SHIFT (12) /* Bits 12-14: Channel 14 Sample time selection */ +#define ADC_SMPR1_SMP14_MASK (7 << ADC_SMPR1_SMP14_SHIFT) +#define ADC_SMPR1_SMP15_SHIFT (15) /* Bits 15-17: Channel 15 Sample time selection */ +#define ADC_SMPR1_SMP15_MASK (7 << ADC_SMPR1_SMP15_SHIFT) +#define ADC_SMPR1_SMP16_SHIFT (18) /* Bits 18-20: Channel 16 Sample time selection */ +#define ADC_SMPR1_SMP16_MASK (7 << ADC_SMPR1_SMP16_SHIFT) +#define ADC_SMPR1_SMP17_SHIFT (21) /* Bits 21-23: Channel 17 Sample time selection */ +#define ADC_SMPR1_SMP17_MASK (7 << ADC_SMPR1_SMP17_SHIFT) +#define ADC_SMPR1_SMP18_SHIFT (21) /* Bits 24-26: Channel 18 Sample time selection */ +#define ADC_SMPR1_SMP18_MASK (7 << ADC_SMPR1_SMP17_SHIFT) + + +/* ADC sample time register 2 */ + +#define ADC_SMPR2_SMP0_SHIFT (0) /* Bits 2-0: Channel 0 Sample time selection */ +#define ADC_SMPR2_SMP0_MASK (7 << ADC_SMPR2_SMP0_SHIFT) +#define ADC_SMPR2_SMP1_SHIFT (3) /* Bits 5-3: Channel 1 Sample time selection */ +#define ADC_SMPR2_SMP1_MASK (7 << ADC_SMPR2_SMP1_SHIFT) +#define ADC_SMPR2_SMP2_SHIFT (6) /* Bits 8-6: Channel 2 Sample time selection */ +#define ADC_SMPR2_SMP2_MASK (7 << ADC_SMPR2_SMP2_SHIFT) +#define ADC_SMPR2_SMP3_SHIFT (9) /* Bits 11-9: Channel 3 Sample time selection */ +#define ADC_SMPR2_SMP3_MASK (7 << ADC_SMPR2_SMP3_SHIFT) +#define ADC_SMPR2_SMP4_SHIFT (12) /* Bits 14-12: Channel 4 Sample time selection */ +#define ADC_SMPR2_SMP4_MASK (7 << ADC_SMPR2_SMP4_SHIFT) +#define ADC_SMPR2_SMP5_SHIFT (15) /* Bits 17-15: Channel 5 Sample time selection */ +#define ADC_SMPR2_SMP5_MASK (7 << ADC_SMPR2_SMP5_SHIFT) +#define ADC_SMPR2_SMP6_SHIFT (18) /* Bits 20-18: Channel 6 Sample time selection */ +#define ADC_SMPR2_SMP6_MASK (7 << ADC_SMPR2_SMP6_SHIFT) +#define ADC_SMPR2_SMP7_SHIFT (21) /* Bits 23-21: Channel 7 Sample time selection */ +#define ADC_SMPR2_SMP7_MASK (7 << ADC_SMPR2_SMP7_SHIFT) +#define ADC_SMPR2_SMP8_SHIFT (24) /* Bits 26-24: Channel 8 Sample time selection */ +#define ADC_SMPR2_SMP8_MASK (7 << ADC_SMPR2_SMP8_SHIFT) +#define ADC_SMPR2_SMP9_SHIFT (27) /* Bits 29-27: Channel 9 Sample time selection */ +#define ADC_SMPR2_SMP9_MASK (7 << ADC_SMPR2_SMP9_SHIFT) + + +/* ADC injected channel data offset register 1-4 */ + +#define ADC_JOFR_SHIFT (0) /* Bits 11-0: Data offset for injected channel x */ +#define ADC_JOFR_MASK (0x0fff << ADC_JOFR_SHIFT) + +/* ADC watchdog high threshold register */ + +#define ADC_HTR_SHIFT (0) /* Bits 11-0: Analog watchdog high threshold */ +#define ADC_HTR_MASK (0x0fff << ADC_HTR_SHIFT) + +/* ADC watchdog low threshold register */ + +#define ADC_LTR_SHIFT (0) /* Bits 11-0: Analog watchdog low threshold */ +#define ADC_LTR_MASK (0x0fff << ADC_LTR_SHIFT) + +/* ADC regular sequence register 1 */ + +#define ADC_SQR1_SQ13_SHIFT (0) /* Bits 4-0: 13th conversion in regular sequence */ +#define ADC_SQR1_SQ13_MASK (0x1f << ADC_SQR1_SQ13_SHIFT) +#define ADC_SQR1_SQ14_SHIFT (5) /* Bits 9-5: 14th conversion in regular sequence */ +#define ADC_SQR1_SQ14_MASK (0x1f << ADC_SQR1_SQ14_SHIFT) +#define ADC_SQR1_SQ15_SHIFT (10) /* Bits 14-10: 15th conversion in regular sequence */ +#define ADC_SQR1_SQ15_MASK (0x1f << ADC_SQR1_SQ15_SHIFT) +#define ADC_SQR1_SQ16_SHIFT (15) /* Bits 19-15: 16th conversion in regular sequence */ +#define ADC_SQR1_SQ16_MASK (0x1f << ADC_SQR1_SQ16_SHIFT) +#define ADC_SQR1_L_SHIFT (20) /* Bits 23-20: Regular channel sequence length */ +#define ADC_SQR1_L_MASK (0x0f << ADC_SQR1_L_SHIFT) +#define ADC_SQR1_RESERVED (0xff000000) +#define ADC_SQR1_FIRST (13) +#define ADC_SQR1_LAST (16) +#define ADC_SQR1_SQ_OFFSET (0) + +/* ADC regular sequence register 2 */ + +#define ADC_SQR2_SQ7_SHIFT (0) /* Bits 4-0: 7th conversion in regular sequence */ +#define ADC_SQR2_SQ7_MASK (0x1f << ADC_SQR2_SQ7_SHIFT) +#define ADC_SQR2_SQ8_SHIFT (5) /* Bits 9-5: 8th conversion in regular sequence */ +#define ADC_SQR2_SQ8_MASK (0x1f << ADC_SQR2_SQ8_SHIFT) +#define ADC_SQR2_SQ9_SHIFT (10) /* Bits 14-10: 9th conversion in regular sequence */ +#define ADC_SQR2_SQ9_MASK (0x1f << ADC_SQR2_SQ9_SHIFT) +#define ADC_SQR2_SQ10_SHIFT (15) /* Bits 19-15: 10th conversion in regular sequence */ +#define ADC_SQR2_SQ10_MASK (0x1f << ADC_SQR2_SQ10_SHIFT) +#define ADC_SQR2_SQ11_SHIFT (20) /* Bits 24-20: 11th conversion in regular sequence */ +#define ADC_SQR2_SQ11_MASK (0x1f << ADC_SQR2_SQ11_SHIFT ) +#define ADC_SQR2_SQ12_SHIFT (25) /* Bits 29-25: 12th conversion in regular sequence */ +#define ADC_SQR2_SQ12_MASK (0x1f << ADC_SQR2_SQ12_SHIFT) +#define ADC_SQR2_RESERVED (0xc0000000) +#define ADC_SQR2_FIRST (7) +#define ADC_SQR2_LAST (12) +#define ADC_SQR2_SQ_OFFSET (0) + +/* ADC regular sequence register 3 */ + +#define ADC_SQR3_SQ1_SHIFT (0) /* Bits 4-0: 1st conversion in regular sequence */ +#define ADC_SQR3_SQ1_MASK (0x1f << ADC_SQR3_SQ1_SHIFT) +#define ADC_SQR3_SQ2_SHIFT (5) /* Bits 9-5: 2nd conversion in regular sequence */ +#define ADC_SQR3_SQ2_MASK (0x1f << ADC_SQR3_SQ2_SHIFT) +#define ADC_SQR3_SQ3_SHIFT (10) /* Bits 14-10: 3rd conversion in regular sequence */ +#define ADC_SQR3_SQ3_MASK (0x1f << ADC_SQR3_SQ3_SHIFT) +#define ADC_SQR3_SQ4_SHIFT (15) /* Bits 19-15: 4th conversion in regular sequence */ +#define ADC_SQR3_SQ4_MASK (0x1f << ADC_SQR3_SQ4_SHIFT) +#define ADC_SQR3_SQ5_SHIFT (20) /* Bits 24-20: 5th conversion in regular sequence */ +#define ADC_SQR3_SQ5_MASK (0x1f << ADC_SQR3_SQ5_SHIFT ) +#define ADC_SQR3_SQ6_SHIFT (25) /* Bits 29-25: 6th conversion in regular sequence */ +#define ADC_SQR3_SQ6_MASK (0x1f << ADC_SQR3_SQ6_SHIFT) +#define ADC_SQR3_RESERVED (0xc0000000) +#define ADC_SQR3_FIRST (1) +#define ADC_SQR3_LAST (6) +#define ADC_SQR3_SQ_OFFSET (0) + +/* Offset between SQ bits */ + +#define ADC_SQ_OFFSET (5) + +/* ADC injected sequence register */ + +#define ADC_JSQR_JSQ1_SHIFT (0) /* Bits 4-0: 1st conversion in injected sequence */ +#define ADC_JSQR_JSQ1_MASK (0x1f << ADC_JSQR_JSQ1_SHIFT) +#define ADC_JSQR_JSQ2_SHIFT (5) /* Bits 9-5: 2nd conversion in injected sequence */ +#define ADC_JSQR_JSQ2_MASK (0x1f << ADC_JSQR_JSQ2_SHIFT) +#define ADC_JSQR_JSQ3_SHIFT (10) /* Bits 14-10: 3rd conversion in injected sequence */ +#define ADC_JSQR_JSQ3_MASK (0x1f << ADC_JSQR_JSQ3_SHIFT) +#define ADC_JSQR_JSQ4_SHIFT (15) /* Bits 19-15: 4th conversion in injected sequence */ +#define ADC_JSQR_JSQ4_MASK (0x1f << ADC_JSQR_JSQ4_SHIFT) +#define ADC_JSQR_JL_SHIFT (20) /* Bits 21-20: Injected Sequence length */ +#define ADC_JSQR_JL_MASK (3 << ADC_JSQR_JL_SHIFT) + +/* ADC injected data register 1-4 */ + +#define ADC_JDR_JDATA_SHIFT (0) /* Bits 15-0: Injected data */ +#define ADC_JDR_JDATA_MASK (0xffff << ADC_JDR_JDATA_SHIFT) + +/* ADC regular data register */ + +#define ADC_DR_RDATA_SHIFT (0) /* Bits 15-0 Regular data */ +#define ADC_DR_RDATA_MASK (0xffff << ADC_DR_RDATA_SHIFT) + +/* Common status register */ + +#define ADC_CSR_AWD1 (1 << 0) /* Bit 0: Analog watchdog flag of ADC1 (copy of AWD in ADC1_SR) */ +#define ADC_CSR_EOC1 (1 << 1) /* Bit 1: End of conversion of ADC1 (copy of EOC in ADC1_SR) */ +#define ADC_CSR_JEOC1 (1 << 2) /* Bit 2: Injected channel end of conversion of ADC1 (copy of JEOC in ADC1_SR) */ +#define ADC_CSR_JSTRT1 (1 << 3) /* Bit 3: Injected channel Start flag of ADC1 (copy of JSTRT in ADC1_SR) */ +#define ADC_CSR_STRT1 (1 << 4) /* Bit 4: Regular channel Start flag of ADC1 (copy of STRT in ADC1_SR) */ +#define ADC_CSR_OVR1 (1 << 5) /* Bit 5: Overrun flag of ADC1 (copy of OVR in ADC1_SR) */ + +#define ADC_CSR_AWD2 (1 << 8) /* Bit 8: Analog watchdog flag of ADC2 (copy of AWD in ADC2_SR) */ +#define ADC_CSR_EOC2 (1 << 9) /* Bit 9: End of conversion of ADC2 (copy of EOC in ADC2_SR) */ +#define ADC_CSR_JEOC2 (1 << 10) /* Bit 10: Injected channel end of conversion of ADC2 (copy of JEOC in ADC2_SR) */ +#define ADC_CSR_JSTRT2 (1 << 11) /* Bit 11: Injected channel Start flag of ADC2 (copy of JSTRT in ADC2_SR) */ +#define ADC_CSR_STRT2 (1 << 12) /* Bit 12: Regular channel Start flag of ADC2 (copy of STRT in ADC2_SR) */ +#define ADC_CSR_OVR2 (1 << 13) /* Bit 13: Overrun flag of ADC2 (copy of OVR in ADC2_SR) */ +# /* Bits 14-15: Reserved, must be kept at reset value. */ +#define ADC_CSR_AWD3 (1 << 16) /* Bit 16: ADC3 Analog watchdog flag (copy of AWD in ADC3_SR) */ +#define ADC_CSR_EOC3 (1 << 17) /* Bit 17: ADC3 End of conversion (copy of EOC in ADC3_SR) */ +#define ADC_CSR_JEOC3 (1 << 18) /* Bit 18: ADC3 Injected channel end of conversion (copy of JEOC in ADC3_SR) */ +#define ADC_CSR_JSTRT3 (1 << 19) /* Bit 19: ADC3 Injected channel Start flag (copy of JSTRT in ADC3_SR) */ +#define ADC_CSR_STRT3 (1 << 20) /* Bit 20: ADC3 Regular channel Start flag (copy of STRT in ADC3_SR). */ +#define ADC_CSR_OVR3 (1 << 21) /* Bit 21: ADC3 overrun flag (copy of OVR in ADC3_SR). */ + +/* Common control register */ + +# define ADC_CCR_MULTI_SHIFT (0) /* Bits 0-4: Multi ADC mode selection */ +# define ADC_CCR_MULTI_MASK (31 << ADC_CCR_MULTI_SHIFT) +# define ADC_CCR_MULTI_NONE (0 << ADC_CCR_MULTI_SHIFT) /* 00000: Independent mode */ + /* 00001 to 01001: Dual mode (ADC1 and ADC2), ADC3 independent */ +# define ADC_CCR_MULTI_RSISM2 (1 << ADC_CCR_MULTI_SHIFT) /* 00001: Combined regular simultaneous + injected simultaneous mode */ +# define ADC_CCR_MULTI_RSATM2 (2 << ADC_CCR_MULTI_SHIFT) /* 00010: Combined regular simultaneous + alternate trigger mode */ +# define ADC_CCR_MULTI_ISM2 (5 << ADC_CCR_MULTI_SHIFT) /* 00101: Injected simultaneous mode only */ +# define ADC_CCR_MULTI_RSM2 (6 << ADC_CCR_MULTI_SHIFT) /* 00110: Regular simultaneous mode only */ +# define ADC_CCR_MULTI_IM2 (7 << ADC_CCR_MULTI_SHIFT) /* 00111: interleaved mode only */ +# define ADC_CCR_MULTI_ATM2 (9 << ADC_CCR_MULTI_SHIFT) /* 01001: Alternate trigger mode only */ + /* 10001 to 11001: Triple mode (ADC1, 2 and 3) */ +# define ADC_CCR_MULTI_RSISM3 (17 << ADC_CCR_MULTI_SHIFT) /* 10001: Combined regular simultaneous + injected simultaneous mode */ +# define ADC_CCR_MULTI_RSATM3 (18 << ADC_CCR_MULTI_SHIFT) /* 10010: Combined regular simultaneous + alternate trigger mode */ +# define ADC_CCR_MULTI_ISM3 (21 << ADC_CCR_MULTI_SHIFT) /* 10101: Injected simultaneous mode only */ +# define ADC_CCR_MULTI_RSM3 (22 << ADC_CCR_MULTI_SHIFT) /* 10110: Regular simultaneous mode only */ +# define ADC_CCR_MULTI_IM3 (23 << ADC_CCR_MULTI_SHIFT) /* 10111: interleaved mode only */ +# define ADC_CCR_MULTI_ATM3 (25 << ADC_CCR_MULTI_SHIFT) /* 11001: Alternate trigger mode only */ + /* Bits 5-7: Reserved, must be kept at reset value. */ +# 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)-5) << ADC_CCR_DELAY_SHIFT) /* n * TADCCLK, n=5-20 */ + /* Bit 12 Reserved, must be kept at reset value. */ +# define ADC_CCR_DDS (1 << 13) /* Bit 13: DMA disable selection (for multi-ADC mode) */ + +# define ADC_CCR_DMA_SHIFT (14) /* Bits 14-15: Direct memory access mode for multi ADC mode */ +# define ADC_CCR_DMA_MASK (3 << ADC_CCR_DMA_SHIFT) +# define ADC_CCR_DMA_DISABLED (0 << ADC_CCR_DMA_SHIFT) /* 00: DMA mode disabled */ +# define ADC_CCR_DMA_MODE1 (1 << ADC_CCR_DMA_SHIFT) /* 01: DMA mode 1 enabled */ +# define ADC_CCR_DMA_MODE2 (2 << ADC_CCR_DMA_SHIFT) /* 10: DMA mode 2 enabled */ +# define ADC_CCR_DMA_MODE3 (3 << ADC_CCR_DMA_SHIFT) /* 11: DMA mode 3 enabled */ + +# define ADC_CCR_ADCPRE_SHIFT (16) /* Bits 16-17: ADC prescaler */ +# define ADC_CCR_ADCPRE_MASK (3 << ADC_CCR_ADCPRE_SHIFT) +# define ADC_CCR_ADCPRE_DIV2 (0 << ADC_CCR_ADCPRE_SHIFT) /* 00: PCLK2 divided by 2 */ +# define ADC_CCR_ADCPRE_DIV4 (1 << ADC_CCR_ADCPRE_SHIFT) /* 01: PCLK2 divided by 4 */ +# define ADC_CCR_ADCPRE_DIV6 (2 << ADC_CCR_ADCPRE_SHIFT) /* 10: PCLK2 divided by 6 */ +# define ADC_CCR_ADCPRE_DIV8 (3 << ADC_CCR_ADCPRE_SHIFT) /* 11: PCLK2 divided by 8 */ + /* Bits 18-21: Reserved, must be kept at reset value. */ +# define ADC_CCR_VBATE (1 << 22) /* Bit 22: VBAT enable */ +# define ADC_CCR_TSVREFE (1 << 23) /* Bit 23: Temperature sensor and VREFINT enable */ + /* Bits 24-31 Reserved, must be kept at reset value. */ + +/* Data register for dual and triple modes (32-bit data with no named fields) */ + +/**************************************************************************************************** + * Public Types + ****************************************************************************************************/ + +/**************************************************************************************************** + * Public Data + ****************************************************************************************************/ + +/**************************************************************************************************** + * Public Function Prototypes + ****************************************************************************************************/ + +#endif /* __ARCH_ARM_SRC_STM32F_CHIP_STM32_ADC_H */ diff --git a/arch/arm/src/stm32f7/stm32_adc.c b/arch/arm/src/stm32f7/stm32_adc.c new file mode 100644 index 00000000000..99d48238c57 --- /dev/null +++ b/arch/arm/src/stm32f7/stm32_adc.c @@ -0,0 +1,1700 @@ +/**************************************************************************** + * arch/arm/src/stm32f7/stm32_adc.c + * + * Copyright (C) 2011, 2013, 2015-2016 Gregory Nutt. All rights reserved. + * Copyright (C) 2015 Omni Hoverboards Inc. All rights reserved. + * Authors: Gregory Nutt + * Diego Sanchez + * Paul Alexander Patience + * + * 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 +#include + +#include "up_internal.h" +#include "up_arch.h" + +#include "chip.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_STM32F7_ADC1) || defined(CONFIG_STM32F7_ADC2) || \ + defined(CONFIG_STM32F7_ADC3) + +/* This implementation is for the STM32 F7 only */ + +#if defined(CONFIG_STM32F7_STM32F74XX) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* RCC reset ****************************************************************/ + +#define STM32_RCC_RSTR STM32_RCC_APB2RSTR +#define RCC_RSTR_ADC1RST RCC_APB2RSTR_ADCRST +#define RCC_RSTR_ADC2RST RCC_APB2RSTR_ADCRST +#define RCC_RSTR_ADC3RST RCC_APB2RSTR_ADCRST + +/* ADC interrupts ***********************************************************/ + +#define STM32_ADC_DMAREG_OFFSET STM32_ADC_CR2_OFFSET +#define ADC_DMAREG_DMA ADC_CR2_DMA +#define STM32_ADC_EXTREG_OFFSET STM32_ADC_CR2_OFFSET +#define ADC_EXTREG_EXTSEL_MASK ADC_CR2_EXTSEL_MASK +#define STM32_ADC_ISR_OFFSET STM32_ADC_SR_OFFSET +#define STM32_ADC_IER_OFFSET STM32_ADC_CR1_OFFSET +#define ADC_ISR_EOC ADC_SR_EOC +#define ADC_IER_EOC ADC_CR1_EOCIE +#define ADC_ISR_AWD ADC_SR_AWD +#define ADC_IER_AWD ADC_CR1_AWDIE +#define ADC_ISR_JEOC ADC_SR_JEOC +#define ADC_IER_JEOC ADC_CR1_JEOCIE +#define ADC_EXTREG_EXTEN_MASK ADC_CR2_EXTEN_MASK +#define ADC_EXTREG_EXTEN_NONE ADC_CR2_EXTEN_NONE +#define ADC_EXTREG_EXTEN_DEFAULT ADC_CR2_EXTEN_RISING +#define ADC_ISR_OVR ADC_SR_OVR +#define ADC_IER_OVR ADC_CR1_OVRIE + +#define ADC_ISR_ALLINTS (ADC_ISR_EOC | ADC_ISR_AWD | ADC_ISR_JEOC | \ + ADC_ISR_OVR) +#define ADC_IER_ALLINTS (ADC_IER_EOC | ADC_IER_AWD | ADC_IER_JEOC | \ + ADC_IER_OVR) + +/* ADC Channels/DMA ********************************************************/ +/* The maximum number of channels that can be sampled. If DMA support is + * not enabled, then only a single channel can be sampled. Otherwise, + * data overruns would occur. + */ + +#define ADC_MAX_CHANNELS_DMA 16 +#define ADC_MAX_CHANNELS_NODMA 1 + +#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_SCR_MSIZE_16BITS | \ + DMA_SCR_PSIZE_16BITS | \ + DMA_SCR_MINC | \ + DMA_SCR_CIRC | \ + DMA_SCR_DIR_P2M) + +/* DMA channels and interface values */ + +#define ADC_SMPR_DEFAULT ADC_SMPR_112 +#define ADC_SMPR1_DEFAULT ((ADC_SMPR_DEFAULT << ADC_SMPR1_SMP10_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR1_SMP11_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR1_SMP12_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR1_SMP13_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR1_SMP14_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR1_SMP15_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR1_SMP16_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR1_SMP17_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR1_SMP18_SHIFT)) +#define ADC_SMPR2_DEFAULT ((ADC_SMPR_DEFAULT << ADC_SMPR2_SMP0_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR2_SMP1_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR2_SMP2_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR2_SMP3_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR2_SMP4_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR2_SMP5_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR2_SMP6_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR2_SMP7_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR2_SMP8_SHIFT) | \ + (ADC_SMPR_DEFAULT << ADC_SMPR2_SMP9_SHIFT)) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure describes the state of one ADC block */ + +struct stm32_dev_s +{ + 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 channel supports DMA */ +#endif +#ifdef ADC_HAVE_TIMER + uint8_t trigger; /* Timer trigger channel: 0=CC1, 1=CC2, 2=CC3, + * 3=CC4, 4=TRGO */ +#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 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 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 void stm32_modifyreg32(unsigned int addr, uint32_t clrbits, + uint32_t setbits); +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 + +static void adc_rccreset(FAR struct stm32_dev_s *priv, bool reset); + +/* ADC Interrupt Handler */ +static int adc_interrupt(FAR struct adc_dev_s *dev); +static int adc123_interrupt(int irq, FAR void *context); + +/* ADC Driver Methods */ + +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); +static void adc_enable(FAR struct stm32_dev_s *priv, bool enable); + +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); + +#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 + +static void adc_startconv(FAR struct stm32_dev_s *priv, bool enable); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* ADC interface operations */ + +static const struct adc_ops_s g_adcops = +{ + .ao_reset = adc_reset, + .ao_setup = adc_setup, + .ao_shutdown = adc_shutdown, + .ao_rxint = adc_rxint, + .ao_ioctl = adc_ioctl, +}; + +/* ADC1 state */ + +#ifdef CONFIG_STM32F7_ADC1 +static struct stm32_dev_s g_adcpriv1 = +{ + .irq = STM32_IRQ_ADC, + .isr = adc123_interrupt, + .intf = 1, + .base = STM32_ADC1_BASE, +#ifdef ADC1_HAVE_TIMER + .trigger = CONFIG_STM32F7_ADC1_TIMTRIG, + .tbase = ADC1_TIMER_BASE, + .extsel = ADC1_EXTSEL_VALUE, + .pclck = ADC1_TIMER_PCLK_FREQUENCY, + .freq = CONFIG_STM32F7_ADC1_SAMPLE_FREQUENCY, +#endif +#ifdef ADC1_HAVE_DMA + .dmachan = ADC1_DMA_CHAN, + .hasdma = true, +#endif +}; + +static struct adc_dev_s g_adcdev1 = +{ + .ad_ops = &g_adcops, + .ad_priv = &g_adcpriv1, +}; +#endif + +/* ADC2 state */ + +#ifdef CONFIG_STM32F7_ADC2 +static struct stm32_dev_s g_adcpriv2 = +{ + .irq = STM32_IRQ_ADC, + .isr = adc123_interrupt, + .intf = 2, + .base = STM32_ADC2_BASE, +#ifdef ADC2_HAVE_TIMER + .trigger = CONFIG_STM32F7_ADC2_TIMTRIG, + .tbase = ADC2_TIMER_BASE, + .extsel = ADC2_EXTSEL_VALUE, + .pclck = ADC2_TIMER_PCLK_FREQUENCY, + .freq = CONFIG_STM32F7_ADC2_SAMPLE_FREQUENCY, +#endif +#ifdef ADC2_HAVE_DMA + .dmachan = ADC2_DMA_CHAN, + .hasdma = true, +#endif +}; + +static struct adc_dev_s g_adcdev2 = +{ + .ad_ops = &g_adcops, + .ad_priv = &g_adcpriv2, +}; +#endif + +/* ADC3 state */ + +#ifdef CONFIG_STM32F7_ADC3 +static struct stm32_dev_s g_adcpriv3 = +{ + .irq = STM32_IRQ_ADC, + .isr = adc123_interrupt, + .intf = 3, + .base = STM32_ADC3_BASE, +#ifdef ADC3_HAVE_TIMER + .trigger = CONFIG_STM32F7_ADC3_TIMTRIG, + .tbase = ADC3_TIMER_BASE, + .extsel = ADC3_EXTSEL_VALUE, + .pclck = ADC3_TIMER_PCLK_FREQUENCY, + .freq = CONFIG_STM32F7_ADC3_SAMPLE_FREQUENCY, +#endif +#ifdef ADC3_HAVE_DMA + .dmachan = ADC3_DMA_CHAN, + .hasdma = true, +#endif +}; + +static struct adc_dev_s g_adcdev3 = +{ + .ad_ops = &g_adcops, + .ad_priv = &g_adcpriv3, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_modifyreg32 + * + * Description: + * Modify the value of a 32-bit register (not atomic). + * + * Input Parameters: + * addr - The address of the register + * clrbits - The bits to clear + * setbits - The bits to set + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void stm32_modifyreg32(unsigned int addr, uint32_t clrbits, + uint32_t setbits) +{ + putreg32((getreg32(addr) & ~clrbits) | setbits, addr); +} + +/**************************************************************************** + * 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) +{ + avdbg("%s:\n", msg); + avdbg(" 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)); + avdbg(" 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)); + avdbg(" 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)); + avdbg(" 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) + { + avdbg(" 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 + { + avdbg(" 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) +{ + avdbg("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. + */ + + avdbg("Initializing timers extsel = 0x%08x\n", priv->extsel); + + adc_modifyreg(priv, STM32_ADC_EXTREG_OFFSET, + ADC_EXTREG_EXTEN_MASK | ADC_EXTREG_EXTSEL_MASK, + ADC_EXTREG_EXTEN_DEFAULT | priv->extsel); + + /* Configure the timer channel to drive the ADC */ + + /* Caculate optimal values for the timer prescaler and for the timer + * reload register. If freq is the desired frequency, then + * + * reload = timclk / freq + * reload = (pclck / prescaler) / freq + * + * There are many solutions to do this, but the best solution will be the + * one that has the largest reload value and the smallest prescaler value. + * That is the solution that should give us the most accuracy in the timer + * control. Subject to: + * + * 0 <= prescaler <= 65536 + * 1 <= reload <= 65535 + * + * So ( prescaler = pclck / 65535 / freq ) would be optimal. + */ + + prescaler = (priv->pclck / priv->freq + 65534) / 65535; + + /* We need to decrement the prescaler value by one, but only, the value + * does not underflow. + */ + + if (prescaler < 1) + { + adbg("WARNING: Prescaler underflowed.\n"); + prescaler = 1; + } + + /* Check for overflow */ + + else if (prescaler > 65536) + { + adbg("WARNING: Prescaler overflowed.\n"); + prescaler = 65536; + } + + timclk = priv->pclck / prescaler; + + reload = timclk / priv->freq; + if (reload < 1) + { + adbg("WARNING: Reload value underflowed.\n"); + reload = 1; + } + else if (reload > 65535) + { + adbg("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: + adbg("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_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) +{ + avdbg("enable: %d\n", enable ? 1 : 0); + + if (enable) + { + /* Start the conversion of regular channels */ + + adc_modifyreg(priv, STM32_ADC_CR2_OFFSET, 0, ADC_CR2_SWSTART); + } + else + { + /* Stop the conversion */ + + adc_modifyreg(priv, STM32_ADC_CR2_OFFSET, ADC_CR2_SWSTART, 0); + } +} + +/**************************************************************************** + * Name: adc_rccreset + * + * Description: + * Deinitializes the ADCx peripheral registers to their default + * reset values. It could set all the ADCs configured. + * + * Input Parameters: + * regaddr - The register to read + * reset - Condition, set or reset + * + * Returned Value: + * + ****************************************************************************/ + +static void adc_rccreset(FAR struct stm32_dev_s *priv, bool reset) +{ + uint32_t adcbit; + + /* Pick the appropriate bit in the APB2 reset register. + * For the STM32 F1, there is an individual bit to reset each ADC, + * but for the STM32 F2/F4, there is one common reset for all ADCs. + * THIS will probably cause some problems! + */ + + switch (priv->intf) + { +#ifdef CONFIG_STM32F7_ADC1 + case 1: + adcbit = RCC_RSTR_ADC1RST; + break; +#endif +#ifdef CONFIG_STM32F7_ADC2 + case 2: + adcbit = RCC_RSTR_ADC2RST; + break; +#endif +#ifdef CONFIG_STM32F7_ADC3 + case 3: + adcbit = RCC_RSTR_ADC3RST; + break; +#endif + default: + return; + } + + /* Set or clear the selected bit in the APB2 reset register. + * modifyreg32() disables interrupts. Disabling interrupts is necessary + * because the APB2RTSR register is used by several different drivers. + */ + + if (reset) + { + /* Enable ADC reset state */ + + modifyreg32(STM32_RCC_RSTR, 0, adcbit); + } + else + { + /* Release ADC from reset state */ + + modifyreg32(STM32_RCC_RSTR, adcbit, 0); + } +} + +/**************************************************************************** + * Name: adc_enable + * + * Description : Enables or disables the specified ADC peripheral. + * Also, starts a conversion when the ADC is not + * triggered by timers + * + * Input Parameters: + * + * enable - true: enable ADC conversion + * false: disable ADC conversion + * + * Returned Value: + * + ****************************************************************************/ + +static void adc_enable(FAR struct stm32_dev_s *priv, bool enable) +{ +#ifdef ADC_SR_ADONS + bool enabled = (adc_getreg(priv, STM32_ADC_SR_OFFSET) & ADC_SR_ADONS) != 0; +#else + bool enabled = false; +#endif + + avdbg("enable: %d\n", enable ? 1 : 0); + + if (!enabled && enable) + { + adc_modifyreg(priv, STM32_ADC_CR2_OFFSET, 0, ADC_CR2_ADON); + } + else if (enabled && !enable) + { + adc_modifyreg(priv, STM32_ADC_CR2_OFFSET, ADC_CR2_ADON, 0); + } +} + +/**************************************************************************** + * Name: adc_dmacovcallback + * + * 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; + + for (i = 0; i < priv->nchannels; i++) + { + adc_receive(dev, 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_DMAREG_OFFSET, ADC_DMAREG_DMA, 0); + adc_modifyreg(priv, STM32_ADC_DMAREG_OFFSET, 0, ADC_DMAREG_DMA); +} +#endif + +/**************************************************************************** + * 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; + irqstate_t flags; + uint32_t clrbits; + uint32_t setbits; +#ifdef ADC_HAVE_TIMER + int ret; +#endif + + allvdbg("intf: %d\n", priv->intf); + flags = enter_critical_section(); + + /* Enable ADC reset state */ + + adc_rccreset(priv, true); + + /* Release ADC from reset state */ + + adc_rccreset(priv, false); + + /* Initialize the watchdog high threshold register */ + + adc_putreg(priv, STM32_ADC_HTR_OFFSET, 0x00000fff); + + /* Initialize the watchdog low threshold register */ + + adc_putreg(priv, STM32_ADC_LTR_OFFSET, 0x00000000); + + /* 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); + + /* Enable the analog watchdog */ + + clrbits = ADC_CR1_AWDCH_MASK; + setbits = ADC_CR1_AWDEN | (priv->chanlist[0] << ADC_CR1_AWDCH_SHIFT); + + /* Set the resolution of the conversion */ + + clrbits |= ADC_CR1_RES_MASK; + setbits |= ADC_CR1_RES_12BIT; + +#ifdef ADC_HAVE_DMA + if (priv->hasdma) + { + setbits |= ADC_CR1_SCAN; + } +#endif + + /* Enable interrupt flags, but disable overrun interrupt */ + + clrbits |= ADC_IER_OVR; + setbits |= ADC_IER_ALLINTS & ~ADC_IER_OVR; + + /* Set CR1 configuration */ + + adc_modifyreg(priv, STM32_ADC_CR1_OFFSET, clrbits, setbits); + + /* Disable continuous mode and set align to right */ + + clrbits = ADC_CR2_CONT | ADC_CR2_ALIGN; + setbits = 0; + + /* Disable external trigger for regular channels */ + + clrbits |= ADC_EXTREG_EXTEN_MASK; + setbits |= ADC_EXTREG_EXTEN_NONE; + +#ifdef ADC_HAVE_DMA + if (priv->hasdma) + { + setbits |= ADC_CR2_DMA; + } +#endif + + /* Set CR2 configuration */ + + adc_modifyreg(priv, STM32_ADC_CR2_OFFSET, clrbits, setbits); + + /* Configuration of the channel conversions */ + + adc_set_ch(dev, 0); + + /* ADC CCR configuration */ + + clrbits = ADC_CCR_ADCPRE_MASK | ADC_CCR_TSVREFE; + setbits = ADC_CCR_ADCPRE_DIV2; + + clrbits |= ADC_CCR_MULTI_MASK | ADC_CCR_DELAY_MASK | ADC_CCR_DDS | + ADC_CCR_DMA_MASK | ADC_CCR_VBATE; + setbits |= ADC_CCR_MULTI_NONE | ADC_CCR_DMA_DISABLED; + + stm32_modifyreg32(STM32_ADC_CCR, 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 ADON to wake up the ADC from the power down state */ + + adc_enable(priv, true); + +#ifdef ADC_HAVE_TIMER + if (priv->tbase != 0) + { + ret = adc_timinit(priv); + if (ret < 0) + { + adbg("adc_timinit failed: %d\n", ret); + } + } +#ifndef CONFIG_ADC_NO_STARTUP_CONV + else +#endif +#endif +#ifndef CONFIG_ADC_NO_STARTUP_CONV + { + adc_startconv(priv, true); + } +#endif + + leave_critical_section(flags); + + avdbg("SR: 0x%08x CR1: 0x%08x CR2: 0x%08x\n", + adc_getreg(priv, STM32_ADC_SR_OFFSET), + adc_getreg(priv, STM32_ADC_CR1_OFFSET), + adc_getreg(priv, STM32_ADC_CR2_OFFSET)); + + avdbg("SQR1: 0x%08x SQR2: 0x%08x SQR3: 0x%08x\n", + adc_getreg(priv, STM32_ADC_SQR1_OFFSET), + adc_getreg(priv, STM32_ADC_SQR2_OFFSET), + adc_getreg(priv, STM32_ADC_SQR3_OFFSET)); + + avdbg("CCR: 0x%08x\n", getreg32(STM32_ADC_CCR)); + +} + +/**************************************************************************** + * 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; + + /* Attach the ADC interrupt */ + + ret = irq_attach(priv->irq, priv->isr); + if (ret < 0) + { + avdbg("irq_attach failed: %d\n", ret); + return ret; + } + + /* Make sure that the ADC device is in the powered up, reset state */ + + adc_reset(dev); + + /* Enable the ADC interrupt */ + + avdbg("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; + + adc_enable(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_rccreset(priv, true); +} + +/**************************************************************************** + * 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; + + avdbg("intf: %d enable: %d\n", priv->intf, enable ? 1 : 0); + + if (enable) + { + /* Enable the end-of-conversion ADC and analog watchdog interrupts */ + + adc_modifyreg(priv, STM32_ADC_IER_OFFSET, 0, ADC_IER_ALLINTS); + } + else + { + /* Disable all ADC interrupts */ + + adc_modifyreg(priv, STM32_ADC_IER_OFFSET, ADC_IER_ALLINTS, 0); + } +} + +/**************************************************************************** + * 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_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; + } + +#ifdef STM32_ADC_SQR5_OFFSET + bits = adc_sqrbits(priv, ADC_SQR5_FIRST, ADC_SQR5_LAST, ADC_SQR5_SQ_OFFSET); + adc_modifyreg(priv, STM32_ADC_SQR5_OFFSET, ~ADC_SQR5_RESERVED, bits); +#endif + +#ifdef STM32_ADC_SQR4_OFFSET + 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); +#endif + + 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); + + 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; + int ret = OK; + + switch (cmd) + { + case ANIOC_TRIGGER: + adc_startconv(priv, true); + break; + + default: + adbg("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) +{ + FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv; + uint32_t regval; + uint32_t pending; + int32_t data; + + regval = adc_getreg(priv, STM32_ADC_ISR_OFFSET); + pending = regval & ADC_ISR_ALLINTS; + if (pending == 0) + { + return OK; + } + + /* Identifies the interruption AWD, OVR or EOC */ + + if ((regval & ADC_ISR_AWD) != 0) + { + alldbg("WARNING: Analog Watchdog, Value converted out of range!\n"); + } + + if ((regval & ADC_ISR_OVR) != 0) + { + alldbg("WARNING: Overrun has occurred!\n"); + } + + /* EOC: End of conversion */ + + if ((regval & ADC_ISR_EOC) != 0) + { + /* Read the converted value and clear EOC bit + * (It is cleared by reading the ADC_DR) + */ + + data = adc_getreg(priv, STM32_ADC_DR_OFFSET) & ADC_DR_RDATA_MASK; + + /* Give the ADC data to the ADC driver. adc_receive() 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. + */ + + adc_receive(dev, priv->chanlist[priv->current], data); + + /* 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; + } + } + + regval &= ~pending; + adc_putreg(priv, STM32_ADC_ISR_OFFSET, regval); + return OK; +} + +/**************************************************************************** + * Name: adc123_interrupt + * + * Description: + * ADC1/2/3 interrupt handler + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + +static int adc123_interrupt(int irq, FAR void *context) +{ +#ifdef CONFIG_STM32F7_ADC1 + adc_interrupt(&g_adcdev1); +#endif + +#ifdef CONFIG_STM32F7_ADC2 + adc_interrupt(&g_adcdev2); +#endif + +#ifdef CONFIG_STM32F7_ADC3 + adc_interrupt(&g_adcdev3); +#endif + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_adcinitialize + * + * 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 succcess; a NULL on failure + * + ****************************************************************************/ + +struct adc_dev_s *stm32_adcinitialize(int intf, FAR const uint8_t *chanlist, + int cchannels) +{ + FAR struct adc_dev_s *dev; + FAR struct stm32_dev_s *priv; + + avdbg("intf: %d cchannels: %d\n", intf, cchannels); + + switch (intf) + { +#ifdef CONFIG_STM32F7_ADC1 + case 1: + avdbg("ADC1 selected\n"); + dev = &g_adcdev1; + break; +#endif +#ifdef CONFIG_STM32F7_ADC2 + case 2: + avdbg("ADC2 selected\n"); + dev = &g_adcdev2; + break; +#endif +#ifdef CONFIG_STM32F7_ADC3 + case 3: + avdbg("ADC3 selected\n"); + dev = &g_adcdev3; + break; +#endif + default: + adbg("No ADC interface defined\n"); + return NULL; + } + + /* Configure the selected ADC */ + + priv = (FAR struct stm32_dev_s *)dev->ad_priv; + + DEBUGASSERT(cchannels <= ADC_MAX_SAMPLES); + + priv->cchannels = cchannels; + + memcpy(priv->chanlist, chanlist, cchannels); + + return dev; +} + +#endif /* CONFIG_STM32F7_STM32F74XX */ +#endif /* CONFIG_STM32F7_ADC1 || CONFIG_STM32F7_ADC2 || + * CONFIG_STM32F7_ADC3 + */ +#endif /* CONFIG_ADC */ diff --git a/arch/arm/src/stm32f7/stm32_adc.h b/arch/arm/src/stm32f7/stm32_adc.h new file mode 100644 index 00000000000..b4383c74fba --- /dev/null +++ b/arch/arm/src/stm32f7/stm32_adc.h @@ -0,0 +1,774 @@ +/************************************************************************************ + * arch/arm/src/stm32f7/stm32_adc.h + * + * Copyright (C) 2009, 2011, 2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2015 Omni Hoverboards Inc. All rights reserved. + * Authors: Gregory Nutt + * Paul Alexander Patience + * + * 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_STM32F7_STM32_ADC_H +#define __ARCH_ARM_SRC_STM32F7_STM32_ADC_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include +#include "chip.h" +#include "chip/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_STM32F7_TIMn is defined then + * CONFIG_STM32F7_TIMn_ADC must also be defined to indicate that timer "n" is intended + * to be used for that purpose. Timers 1-6 and 8 may be used. + */ + +#ifndef CONFIG_STM32F7_TIM1 +# undef CONFIG_STM32F7_TIM1_ADC +# undef CONFIG_STM32F7_TIM1_ADC1 +# undef CONFIG_STM32F7_TIM1_ADC2 +# undef CONFIG_STM32F7_TIM1_ADC3 +#endif +#ifndef CONFIG_STM32F7_TIM2 +# undef CONFIG_STM32F7_TIM2_ADC +# undef CONFIG_STM32F7_TIM2_ADC1 +# undef CONFIG_STM32F7_TIM2_ADC2 +# undef CONFIG_STM32F7_TIM2_ADC3 +#endif +#ifndef CONFIG_STM32F7_TIM3 +# undef CONFIG_STM32F7_TIM3_ADC +# undef CONFIG_STM32F7_TIM3_ADC1 +# undef CONFIG_STM32F7_TIM3_ADC2 +# undef CONFIG_STM32F7_TIM3_ADC3 +#endif +#ifndef CONFIG_STM32F7_TIM4 +# undef CONFIG_STM32F7_TIM4_ADC +# undef CONFIG_STM32F7_TIM4_ADC1 +# undef CONFIG_STM32F7_TIM4_ADC2 +# undef CONFIG_STM32F7_TIM4_ADC3 +#endif +#ifndef CONFIG_STM32F7_TIM5 +# undef CONFIG_STM32F7_TIM5_ADC +# undef CONFIG_STM32F7_TIM5_ADC1 +# undef CONFIG_STM32F7_TIM5_ADC2 +# undef CONFIG_STM32F7_TIM5_ADC3 +#endif +#ifndef CONFIG_STM32F7_TIM6 +# undef CONFIG_STM32F7_TIM6_ADC +# undef CONFIG_STM32F7_TIM6_ADC1 +# undef CONFIG_STM32F7_TIM6_ADC2 +# undef CONFIG_STM32F7_TIM6_ADC3 +#endif +#ifndef CONFIG_STM32F7_TIM8 +# undef CONFIG_STM32F7_TIM8_ADC +# undef CONFIG_STM32F7_TIM8_ADC1 +# undef CONFIG_STM32F7_TIM8_ADC2 +# undef CONFIG_STM32F7_TIM8_ADC3 +#endif + +/* Up to 3 ADC interfaces are supported */ + +#if STM32_NADC < 4 +# undef CONFIG_STM32F7_ADC4 +#endif + +#if STM32_NADC < 3 +# undef CONFIG_STM32F7_ADC3 +#endif + +#if STM32_NADC < 2 +# undef CONFIG_STM32F7_ADC2 +#endif + +#if STM32_NADC < 1 +# undef CONFIG_STM32F7_ADC1 +#endif + +#if defined(CONFIG_STM32F7_ADC1) || defined(CONFIG_STM32F7_ADC2) || \ + defined(CONFIG_STM32F7_ADC3) + +/* DMA support */ + +#undef ADC_HAVE_DMA +#if defined(CONFIG_STM32F7_ADC1_DMA) || defined(CONFIG_STM32F7_ADC2_DMA) || \ + defined(CONFIG_STM32F7_ADC3_DMA) +# define ADC_HAVE_DMA 1 +#endif + +#ifdef CONFIG_STM32F7_ADC1_DMA +# define ADC1_HAVE_DMA 1 +#else +# undef ADC1_HAVE_DMA +#endif + +#ifdef CONFIG_STM32F7_ADC2_DMA +# define ADC2_HAVE_DMA 1 +#else +# undef ADC2_HAVE_DMA +#endif + +#ifdef CONFIG_STM32F7_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_STM32F7_TIM1_ADC1) +# define ADC1_HAVE_TIMER 1 +# define ADC1_TIMER_BASE STM32_TIM1_BASE +# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB2_TIM1_CLKIN +#elif defined(CONFIG_STM32F7_TIM2_ADC1) +# define ADC1_HAVE_TIMER 1 +# define ADC1_TIMER_BASE STM32_TIM2_BASE +# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB1_TIM2_CLKIN +#elif defined(CONFIG_STM32F7_TIM3_ADC1) +# define ADC1_HAVE_TIMER 1 +# define ADC1_TIMER_BASE STM32_TIM3_BASE +# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB1_TIM3_CLKIN +#elif defined(CONFIG_STM32F7_TIM4_ADC1) +# define ADC1_HAVE_TIMER 1 +# define ADC1_TIMER_BASE STM32_TIM4_BASE +# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB1_TIM4_CLKIN +#elif defined(CONFIG_STM32F7_TIM5_ADC1) +# define ADC1_HAVE_TIMER 1 +# define ADC1_TIMER_BASE STM32_TIM5_BASE +# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB1_TIM5_CLKIN +#elif defined(CONFIG_STM32F7_TIM6_ADC1) +# define ADC1_HAVE_TIMER 1 +# define ADC1_TIMER_BASE STM32_TIM6_BASE +# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB1_TIM6_CLKIN +#elif defined(CONFIG_STM32F7_TIM8_ADC1) +# define ADC1_HAVE_TIMER 1 +# define ADC1_TIMER_BASE STM32_TIM8_BASE +# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB2_TIM8_CLKIN +#else +# undef ADC1_HAVE_TIMER +#endif + +#ifdef ADC1_HAVE_TIMER +# ifndef CONFIG_STM32F7_ADC1_SAMPLE_FREQUENCY +# error "CONFIG_STM32F7_ADC1_SAMPLE_FREQUENCY not defined" +# endif +# ifndef CONFIG_STM32F7_ADC1_TIMTRIG +# error "CONFIG_STM32F7_ADC1_TIMTRIG not defined" +# warning "Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO" +# endif +#endif + +#if defined(CONFIG_STM32F7_TIM1_ADC2) +# define ADC2_HAVE_TIMER 1 +# define ADC2_TIMER_BASE STM32_TIM1_BASE +# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB2_TIM1_CLKIN +#elif defined(CONFIG_STM32F7_TIM2_ADC2) +# define ADC2_HAVE_TIMER 1 +# define ADC2_TIMER_BASE STM32_TIM2_BASE +# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB1_TIM2_CLKIN +#elif defined(CONFIG_STM32F7_TIM3_ADC2) +# define ADC2_HAVE_TIMER 1 +# define ADC2_TIMER_BASE STM32_TIM3_BASE +# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB1_TIM3_CLKIN +#elif defined(CONFIG_STM32F7_TIM4_ADC2) +# define ADC2_HAVE_TIMER 1 +# define ADC2_TIMER_BASE STM32_TIM4_BASE +# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB1_TIM4_CLKIN +#elif defined(CONFIG_STM32F7_TIM5_ADC2) +# define ADC2_HAVE_TIMER 1 +# define ADC2_TIMER_BASE STM32_TIM5_BASE +# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB1_TIM5_CLKIN +#elif defined(CONFIG_STM32F7_TIM6_ADC2) +# define ADC2_HAVE_TIMER 1 +# define ADC2_TIMER_BASE STM32_TIM6_BASE +# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB1_TIM6_CLKIN +#elif defined(CONFIG_STM32F7_TIM8_ADC2) +# define ADC2_HAVE_TIMER 1 +# define ADC2_TIMER_BASE STM32_TIM8_BASE +# define ADC2_TIMER_PCLK_FREQUENCY STM32_APB2_TIM8_CLKIN +#else +# undef ADC2_HAVE_TIMER +#endif + +#ifdef ADC2_HAVE_TIMER +# ifndef CONFIG_STM32F7_ADC2_SAMPLE_FREQUENCY +# error "CONFIG_STM32F7_ADC2_SAMPLE_FREQUENCY not defined" +# endif +# ifndef CONFIG_STM32F7_ADC2_TIMTRIG +# error "CONFIG_STM32F7_ADC2_TIMTRIG not defined" +# warning "Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO" +# endif +#endif + +#if defined(CONFIG_STM32F7_TIM1_ADC3) +# define ADC3_HAVE_TIMER 1 +# define ADC3_TIMER_BASE STM32_TIM1_BASE +# define ADC3_TIMER_PCLK_FREQUENCY STM32_APB2_TIM1_CLKIN +#elif defined(CONFIG_STM32F7_TIM2_ADC3) +# define ADC3_HAVE_TIMER 1 +# define ADC3_TIMER_BASE STM32_TIM2_BASE +# define ADC3_TIMER_PCLK_FREQUENCY STM32_APB1_TIM2_CLKIN +#elif defined(CONFIG_STM32F7_TIM3_ADC3) +# define ADC3_HAVE_TIMER 1 +# define ADC3_TIMER_BASE STM32_TIM3_BASE +# define ADC3_TIMER_PCLK_FREQUENCY STM32_APB1_TIM3_CLKIN +#elif defined(CONFIG_STM32F7_TIM4_ADC3) +# define ADC3_HAVE_TIMER 1 +# define ADC3_TIMER_BASE STM32_TIM4_BASE +# define ADC3_TIMER_PCLK_FREQUENCY STM32_APB1_TIM4_CLKIN +#elif defined(CONFIG_STM32F7_TIM5_ADC3) +# define ADC3_HAVE_TIMER 1 +# define ADC3_TIMER_BASE STM32_TIM5_BASE +# define ADC3_TIMER_PCLK_FREQUENCY STM32_APB1_TIM5_CLKIN +#elif defined(CONFIG_STM32F7_TIM6_ADC3) +# define ADC3_HAVE_TIMER 1 +# define ADC3_TIMER_BASE STM32_TIM6_BASE +# define ADC3_TIMER_PCLK_FREQUENCY STM32_APB1_TIM6_CLKIN +#elif defined(CONFIG_STM32F7_TIM8_ADC3) +# define ADC3_HAVE_TIMER 1 +# define ADC3_TIMER_BASE STM32_TIM8_BASE +# define ADC3_TIMER_PCLK_FREQUENCY STM32_APB2_TIM8_CLKIN +#else +# undef ADC3_HAVE_TIMER +#endif + +#ifdef ADC3_HAVE_TIMER +# ifndef CONFIG_STM32F7_ADC3_SAMPLE_FREQUENCY +# error "CONFIG_STM32F7_ADC3_SAMPLE_FREQUENCY not defined" +# endif +# ifndef CONFIG_STM32F7_ADC3_TIMTRIG +# error "CONFIG_STM32F7_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_CR2_EXTSEL_T1CC1 +# define ADC1_EXTSEL_T1CC2 ADC_CR2_EXTSEL_T1CC2 +# define ADC1_EXTSEL_T1CC3 ADC_CR2_EXTSEL_T1CC3 +# define ADC1_EXTSEL_T1CC4 ADC_CR2_EXTSEL_T1CC4 +# define ADC1_EXTSEL_T1TRGO ADC_CR2_EXTSEL_T1TRGO +# define ADC1_EXTSEL_T1TRGO2 ADC_CR2_EXTSEL_T1TRGO2 +# define ADC2_EXTSEL_T1CC1 ADC_CR2_EXTSEL_T1CC1 +# define ADC2_EXTSEL_T1CC2 ADC_CR2_EXTSEL_T1CC2 +# define ADC2_EXTSEL_T1CC3 ADC_CR2_EXTSEL_T1CC3 +# define ADC2_EXTSEL_T1CC4 ADC_CR2_EXTSEL_T1CC4 +# define ADC2_EXTSEL_T1TRGO ADC_CR2_EXTSEL_T1TRGO +# define ADC2_EXTSEL_T1TRGO2 ADC_CR2_EXTSEL_T1TRGO2 +# define ADC3_EXTSEL_T1CC1 ADC_CR2_EXTSEL_T1CC1 +# define ADC3_EXTSEL_T1CC2 ADC_CR2_EXTSEL_T1CC2 +# define ADC3_EXTSEL_T1CC3 ADC_CR2_EXTSEL_T1CC3 +# define ADC3_EXTSEL_T1CC4 ADC_CR2_EXTSEL_T1CC4 +# define ADC3_EXTSEL_T1TRGO ADC_CR2_EXTSEL_T1TRGO +# define ADC3_EXTSEL_T1TRGO2 ADC_CR2_EXTSEL_T1TRGO2 + +# define ADC1_EXTSEL_T2CC1 ADC_CR2_EXTSEL_T2CC1 +# define ADC1_EXTSEL_T2CC2 ADC_CR2_EXTSEL_T2CC2 +# define ADC1_EXTSEL_T2CC3 ADC_CR2_EXTSEL_T2CC3 +# define ADC1_EXTSEL_T2CC4 ADC_CR2_EXTSEL_T2CC4 +# define ADC1_EXTSEL_T2TRGO ADC_CR2_EXTSEL_T2TRGO +# define ADC2_EXTSEL_T2CC1 ADC_CR2_EXTSEL_T2CC1 +# define ADC2_EXTSEL_T2CC2 ADC_CR2_EXTSEL_T2CC2 +# define ADC2_EXTSEL_T2CC3 ADC_CR2_EXTSEL_T2CC3 +# define ADC2_EXTSEL_T2CC4 ADC_CR2_EXTSEL_T2CC4 +# define ADC2_EXTSEL_T2TRGO ADC_CR2_EXTSEL_T2TRGO +# define ADC3_EXTSEL_T2CC1 ADC_CR2_EXTSEL_T2CC1 +# define ADC3_EXTSEL_T2CC2 ADC_CR2_EXTSEL_T2CC2 +# define ADC3_EXTSEL_T2CC3 ADC_CR2_EXTSEL_T2CC3 +# define ADC3_EXTSEL_T2CC4 ADC_CR2_EXTSEL_T2CC4 +# define ADC3_EXTSEL_T2TRGO ADC_CR2_EXTSEL_T2TRGO + +# define ADC1_EXTSEL_T3CC1 ADC_CR2_EXTSEL_T3CC1 +# define ADC1_EXTSEL_T3CC2 ADC_CR2_EXTSEL_T3CC2 +# define ADC1_EXTSEL_T3CC3 ADC_CR2_EXTSEL_T3CC3 +# define ADC1_EXTSEL_T3CC4 ADC_CR2_EXTSEL_T3CC4 +# define ADC1_EXTSEL_T3TRGO ADC_CR2_EXTSEL_T3TRGO +# define ADC2_EXTSEL_T3CC1 ADC_CR2_EXTSEL_T3CC1 +# define ADC2_EXTSEL_T3CC2 ADC_CR2_EXTSEL_T3CC2 +# define ADC2_EXTSEL_T3CC3 ADC_CR2_EXTSEL_T3CC3 +# define ADC2_EXTSEL_T3CC4 ADC_CR2_EXTSEL_T3CC4 +# define ADC2_EXTSEL_T3TRGO ADC_CR2_EXTSEL_T3TRGO +# define ADC3_EXTSEL_T3CC1 ADC_CR2_EXTSEL_T3CC1 +# define ADC3_EXTSEL_T3CC2 ADC_CR2_EXTSEL_T3CC2 +# define ADC3_EXTSEL_T3CC3 ADC_CR2_EXTSEL_T3CC3 +# define ADC3_EXTSEL_T3CC4 ADC_CR2_EXTSEL_T3CC4 +# define ADC3_EXTSEL_T3TRGO ADC_CR2_EXTSEL_T3TRGO + +# define ADC1_EXTSEL_T4CC1 ADC_CR2_EXTSEL_T4CC1 +# define ADC1_EXTSEL_T4CC2 ADC_CR2_EXTSEL_T4CC2 +# define ADC1_EXTSEL_T4CC3 ADC_CR2_EXTSEL_T4CC3 +# define ADC1_EXTSEL_T4CC4 ADC_CR2_EXTSEL_T4CC4 +# define ADC1_EXTSEL_T4TRGO ADC_CR2_EXTSEL_T4TRGO +# define ADC2_EXTSEL_T4CC1 ADC_CR2_EXTSEL_T4CC1 +# define ADC2_EXTSEL_T4CC2 ADC_CR2_EXTSEL_T4CC2 +# define ADC2_EXTSEL_T4CC3 ADC_CR2_EXTSEL_T4CC3 +# define ADC2_EXTSEL_T4CC4 ADC_CR2_EXTSEL_T4CC4 +# define ADC2_EXTSEL_T4TRGO ADC_CR2_EXTSEL_T4TRGO +# define ADC3_EXTSEL_T4CC1 ADC_CR2_EXTSEL_T4CC1 +# define ADC3_EXTSEL_T4CC2 ADC_CR2_EXTSEL_T4CC2 +# define ADC3_EXTSEL_T4CC3 ADC_CR2_EXTSEL_T4CC3 +# define ADC3_EXTSEL_T4CC4 ADC_CR2_EXTSEL_T4CC4 +# define ADC3_EXTSEL_T4TRGO ADC_CR2_EXTSEL_T4TRGO + +# define ADC1_EXTSEL_T5CC1 ADC_CR2_EXTSEL_T5CC1 +# define ADC1_EXTSEL_T5CC2 ADC_CR2_EXTSEL_T5CC2 +# define ADC1_EXTSEL_T5CC3 ADC_CR2_EXTSEL_T5CC3 +# define ADC1_EXTSEL_T5CC4 ADC_CR2_EXTSEL_T5CC4 +# define ADC1_EXTSEL_T5TRGO ADC_CR2_EXTSEL_T5TRGO +# define ADC2_EXTSEL_T5CC1 ADC_CR2_EXTSEL_T5CC1 +# define ADC2_EXTSEL_T5CC2 ADC_CR2_EXTSEL_T5CC2 +# define ADC2_EXTSEL_T5CC3 ADC_CR2_EXTSEL_T5CC3 +# define ADC2_EXTSEL_T5CC4 ADC_CR2_EXTSEL_T5CC4 +# define ADC2_EXTSEL_T5TRGO ADC_CR2_EXTSEL_T5TRGO +# define ADC3_EXTSEL_T5CC1 ADC_CR2_EXTSEL_T5CC1 +# define ADC3_EXTSEL_T5CC2 ADC_CR2_EXTSEL_T5CC2 +# define ADC3_EXTSEL_T5CC3 ADC_CR2_EXTSEL_T5CC3 +# define ADC3_EXTSEL_T5CC4 ADC_CR2_EXTSEL_T5CC4 +# define ADC3_EXTSEL_T5TRGO ADC_CR2_EXTSEL_T5TRGO + +# define ADC1_EXTSEL_T6CC1 ADC_CR2_EXTSEL_T6CC1 +# define ADC1_EXTSEL_T6CC2 ADC_CR2_EXTSEL_T6CC2 +# define ADC1_EXTSEL_T6CC3 ADC_CR2_EXTSEL_T6CC3 +# define ADC1_EXTSEL_T6CC4 ADC_CR2_EXTSEL_T6CC4 +# define ADC1_EXTSEL_T6TRGO ADC_CR2_EXTSEL_T6TRGO +# define ADC2_EXTSEL_T6CC1 ADC_CR2_EXTSEL_T6CC1 +# define ADC2_EXTSEL_T6CC2 ADC_CR2_EXTSEL_T6CC2 +# define ADC2_EXTSEL_T6CC3 ADC_CR2_EXTSEL_T6CC3 +# define ADC2_EXTSEL_T6CC4 ADC_CR2_EXTSEL_T6CC4 +# define ADC2_EXTSEL_T6TRGO ADC_CR2_EXTSEL_T6TRGO +# define ADC3_EXTSEL_T6CC1 ADC_CR2_EXTSEL_T6CC1 +# define ADC3_EXTSEL_T6CC2 ADC_CR2_EXTSEL_T6CC2 +# define ADC3_EXTSEL_T6CC3 ADC_CR2_EXTSEL_T6CC3 +# define ADC3_EXTSEL_T6CC4 ADC_CR2_EXTSEL_T6CC4 +# define ADC3_EXTSEL_T6TRGO ADC_CR2_EXTSEL_T6TRGO + +# define ADC1_EXTSEL_T8CC1 ADC_CR2_EXTSEL_T8CC1 +# define ADC1_EXTSEL_T8CC2 ADC_CR2_EXTSEL_T8CC2 +# define ADC1_EXTSEL_T8CC3 ADC_CR2_EXTSEL_T8CC3 +# define ADC1_EXTSEL_T8CC4 ADC_CR2_EXTSEL_T8CC4 +# define ADC1_EXTSEL_T8TRGO ADC_CR2_EXTSEL_T8TRGO +# define ADC1_EXTSEL_T8TRGO2 ADC_CR2_EXTSEL_T8TRGO2 +# define ADC2_EXTSEL_T8CC1 ADC_CR2_EXTSEL_T8CC1 +# define ADC2_EXTSEL_T8CC2 ADC_CR2_EXTSEL_T8CC2 +# define ADC2_EXTSEL_T8CC3 ADC_CR2_EXTSEL_T8CC3 +# define ADC2_EXTSEL_T8CC4 ADC_CR2_EXTSEL_T8CC4 +# define ADC2_EXTSEL_T8TRGO ADC_CR2_EXTSEL_T8TRGO +# define ADC2_EXTSEL_T8TRGO2 ADC_CR2_EXTSEL_T8TRGO2 +# define ADC3_EXTSEL_T8CC1 ADC_CR2_EXTSEL_T8CC1 +# define ADC3_EXTSEL_T8CC2 ADC_CR2_EXTSEL_T8CC2 +# define ADC3_EXTSEL_T8CC3 ADC_CR2_EXTSEL_T8CC3 +# define ADC3_EXTSEL_T8CC4 ADC_CR2_EXTSEL_T8CC4 +# define ADC3_EXTSEL_T8TRGO ADC_CR2_EXTSEL_T8TRGO +# define ADC3_EXTSEL_T8TRGO2 ADC_CR2_EXTSEL_T8TRGO2 + + +#if defined(CONFIG_STM32F7_TIM1_ADC1) +# if CONFIG_STM32F7_ADC1_TIMTRIG == 0 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T1CC1 +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 1 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T1CC2 +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 2 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T1CC3 +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 3 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T1CC4 +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 4 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T1TRGO +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 5 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T1TRGO2 +# else +# error "CONFIG_STM32F7_ADC1_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32F7_TIM2_ADC1) +# if CONFIG_STM32F7_ADC1_TIMTRIG == 0 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T2CC1 +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 1 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T2CC2 +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 2 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T2CC3 +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 3 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T2CC4 +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 4 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T2TRGO +# else +# error "CONFIG_STM32F7_ADC1_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32F7_TIM3_ADC1) +# if CONFIG_STM32F7_ADC1_TIMTRIG == 0 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T3CC1 +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 1 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T3CC2 +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 2 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T3CC3 +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 3 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T3CC4 +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 4 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T3TRGO +# else +# error "CONFIG_STM32F7_ADC1_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32F7_TIM4_ADC1) +# if CONFIG_STM32F7_ADC1_TIMTRIG == 0 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T4CC1 +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 1 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T4CC2 +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 2 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T4CC3 +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 3 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T4CC4 +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 4 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T4TRGO +# else +# error "CONFIG_STM32F7_ADC1_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32F7_TIM5_ADC1) +# if CONFIG_STM32F7_ADC1_TIMTRIG == 0 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T5CC1 +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 1 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T5CC2 +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 2 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T5CC3 +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 3 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T5CC4 +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 4 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T5TRGO +# else +# error "CONFIG_STM32F7_ADC1_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32F7_TIM6_ADC1) +# if CONFIG_STM32F7_ADC1_TIMTRIG == 0 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T6CC1 +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 1 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T6CC2 +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 2 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T6CC3 +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 3 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T6CC4 +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 4 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T6TRGO +# else +# error "CONFIG_STM32F7_ADC1_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32F7_TIM8_ADC1) +# if CONFIG_STM32F7_ADC1_TIMTRIG == 0 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T8CC1 +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 1 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T8CC2 +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 2 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T8CC3 +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 3 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T8CC4 +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 4 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T8TRGO +# elif CONFIG_STM32F7_ADC1_TIMTRIG == 5 +# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T8TRGO2 +# else +# error "CONFIG_STM32F7_ADC1_TIMTRIG is out of range" +# endif +#endif + +#if defined(CONFIG_STM32F7_TIM1_ADC2) +# if CONFIG_STM32F7_ADC2_TIMTRIG == 0 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T1CC1 +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 1 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T1CC2 +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 2 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T1CC3 +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 3 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T1CC4 +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 4 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T1TRGO +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 5 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T1TRGO2 +# else +# error "CONFIG_STM32F7_ADC2_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32F7_TIM2_ADC2) +# if CONFIG_STM32F7_ADC2_TIMTRIG == 0 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T2CC1 +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 1 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T2CC2 +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 2 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T2CC3 +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 3 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T2CC4 +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 4 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T2TRGO +# else +# error "CONFIG_STM32F7_ADC2_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32F7_TIM3_ADC2) +# if CONFIG_STM32F7_ADC2_TIMTRIG == 0 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T3CC1 +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 1 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T3CC2 +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 2 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T3CC3 +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 3 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T3CC4 +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 4 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T3TRGO +# else +# error "CONFIG_STM32F7_ADC2_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32F7_TIM4_ADC2) +# if CONFIG_STM32F7_ADC2_TIMTRIG == 0 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T4CC1 +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 1 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T4CC2 +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 2 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T4CC3 +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 3 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T4CC4 +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 4 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T4TRGO +# else +# error "CONFIG_STM32F7_ADC2_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32F7_TIM5_ADC2) +# if CONFIG_STM32F7_ADC2_TIMTRIG == 0 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T5CC1 +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 1 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T5CC2 +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 2 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T5CC3 +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 3 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T5CC4 +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 4 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T5TRGO +# else +# error "CONFIG_STM32F7_ADC2_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32F7_TIM6_ADC2) +# if CONFIG_STM32F7_ADC2_TIMTRIG == 0 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T6CC1 +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 1 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T6CC2 +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 2 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T6CC3 +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 3 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T6CC4 +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 4 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T6TRGO +# else +# error "CONFIG_STM32F7_ADC2_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32F7_TIM8_ADC2) +# if CONFIG_STM32F7_ADC2_TIMTRIG == 0 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T8CC1 +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 1 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T8CC2 +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 2 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T8CC3 +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 3 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T8CC4 +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 4 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T8TRGO +# elif CONFIG_STM32F7_ADC2_TIMTRIG == 5 +# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T8TRGO2 +# else +# error "CONFIG_STM32F7_ADC2_TIMTRIG is out of range" +# endif +#endif + +#if defined(CONFIG_STM32F7_TIM1_ADC3) +# if CONFIG_STM32F7_ADC3_TIMTRIG == 0 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T1CC1 +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 1 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T1CC2 +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 2 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T1CC3 +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 3 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T1CC4 +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 4 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T1TRGO +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 5 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T1TRGO2 +# else +# error "CONFIG_STM32F7_ADC3_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32F7_TIM2_ADC3) +# if CONFIG_STM32F7_ADC3_TIMTRIG == 0 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T2CC1 +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 1 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T2CC2 +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 2 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T2CC3 +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 3 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T2CC4 +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 4 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T2TRGO +# else +# error "CONFIG_STM32F7_ADC3_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32F7_TIM3_ADC3) +# if CONFIG_STM32F7_ADC3_TIMTRIG == 0 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T3CC1 +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 1 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T3CC2 +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 2 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T3CC3 +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 3 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T3CC4 +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 4 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T3TRGO +# else +# error "CONFIG_STM32F7_ADC3_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32F7_TIM4_ADC3) +# if CONFIG_STM32F7_ADC3_TIMTRIG == 0 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T4CC1 +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 1 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T4CC2 +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 2 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T4CC3 +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 3 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T4CC4 +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 4 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T4TRGO +# else +# error "CONFIG_STM32F7_ADC3_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32F7_TIM5_ADC3) +# if CONFIG_STM32F7_ADC3_TIMTRIG == 0 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T5CC1 +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 1 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T5CC2 +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 2 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T5CC3 +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 3 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T5CC4 +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 4 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T5TRGO +# else +# error "CONFIG_STM32F7_ADC3_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32F7_TIM6_ADC3) +# if CONFIG_STM32F7_ADC3_TIMTRIG == 0 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T6CC1 +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 1 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T6CC2 +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 2 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T6CC3 +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 3 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T6CC4 +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 4 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T6TRGO +# else +# error "CONFIG_STM32F7_ADC3_TIMTRIG is out of range" +# endif +#elif defined(CONFIG_STM32F7_TIM8_ADC3) +# if CONFIG_STM32F7_ADC3_TIMTRIG == 0 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T8CC1 +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 1 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T8CC2 +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 2 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T8CC3 +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 3 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T8CC4 +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 4 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T8TRGO +# elif CONFIG_STM32F7_ADC3_TIMTRIG == 5 +# define ADC3_EXTSEL_VALUE ADC3_EXTSEL_T8TRGO2 +# else +# error "CONFIG_STM32F7_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: stm32_adcinitialize + * + * 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 can device structure reference on succcess; a NULL on failure + * + ****************************************************************************/ + +struct adc_dev_s; +struct adc_dev_s *stm32_adcinitialize(int intf, FAR const uint8_t *chanlist, + int nchannels); +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif /* __ASSEMBLY__ */ + +#endif /* CONFIG_STM32F7_ADC1 || CONFIG_STM32F7_ADC2 || + * CONFIG_STM32F7_ADC3 + */ +#endif /* __ARCH_ARM_SRC_STM32F7_STM32_ADC_H */