arch/stm32f0l0g0/adc: add timer trigger support

add ADC external trigger from TIMER for stm32-m0 chips

Signed-off-by: raiden00pl <raiden00@railab.me>
This commit is contained in:
raiden00pl 2025-06-13 12:15:19 +02:00 committed by Alan C. Assis
parent 64c7354853
commit 89e8c0c425
4 changed files with 560 additions and 17 deletions

View file

@ -1233,6 +1233,12 @@ config STM32F0L0G0_STM32C0
select STM32F0L0G0_HAVE_ADC1_DMA
select STM32F0L0G0_HAVE_IP_USART_V2
select STM32F0L0G0_HAVE_IP_EXTI_V2
select STM32F0L0G0_HAVE_TIM1
select STM32F0L0G0_HAVE_TIM2
select STM32F0L0G0_HAVE_TIM3
select STM32F0L0G0_HAVE_TIM14
select STM32F0L0G0_HAVE_TIM16
select STM32F0L0G0_HAVE_TIM17
config STM32F0L0G0_STM32F03X
bool
@ -1340,6 +1346,7 @@ config ARCH_CHIP_STM32C091XX
select STM32F0L0G0_STM32C0
select STM32F0L0G0_HAVE_USART3
select STM32F0L0G0_HAVE_USART4
select STM32F0L0G0_HAVE_TIM15
config ARCH_CHIP_STM32C092XX
bool
@ -2729,6 +2736,109 @@ config STM32F0L0G0_PWM_MULTICHAN
---help---
Specifies that the PWM driver supports multiple output channels per timer.
config STM32F0L0G0_TIM1_ADC
bool "TIM1 ADC"
default n
depends on STM32F0L0G0_TIM1 && STM32F0L0G0_ADC
---help---
Reserve timer 1 for use by ADC
choice
prompt "Select TIM1 ADC channel"
default STM32F0L0G0_TIM1_ADC1
depends on STM32F0L0G0_TIM1_ADC
config STM32F0L0G0_TIM1_ADC1
bool "TIM1 ADC channel 1"
depends on STM32F0L0G0_ADC1
select STM32F0L0G0_HAVE_ADC1_TIMER
---help---
Reserve TIM1 to trigger ADC1
endchoice
config STM32F0L0G0_TIM2_ADC
bool "TIM2 ADC"
default n
depends on STM32F0L0G0_TIM2 && STM32F0L0G0_ADC
---help---
Reserve timer 1 for use by ADC
choice
prompt "Select TIM2 ADC channel"
default STM32F0L0G0_TIM2_ADC1
depends on STM32F0L0G0_TIM2_ADC
config STM32F0L0G0_TIM2_ADC1
bool "TIM2 ADC channel 1"
depends on STM32F0L0G0_ADC1
select STM32F0L0G0_HAVE_ADC1_TIMER
---help---
Reserve TIM2 to trigger ADC1
endchoice
config STM32F0L0G0_TIM3_ADC
bool "TIM3 ADC"
default n
depends on STM32F0L0G0_TIM3 && STM32F0L0G0_ADC
---help---
Reserve timer 1 for use by ADC
choice
prompt "Select TIM3 ADC channel"
default STM32F0L0G0_TIM3_ADC1
depends on STM32F0L0G0_TIM3_ADC
config STM32F0L0G0_TIM3_ADC1
bool "TIM3 ADC channel 1"
depends on STM32F0L0G0_ADC1
select STM32F0L0G0_HAVE_ADC1_TIMER
---help---
Reserve TIM3 to trigger ADC1
endchoice
config STM32F0L0G0_TIM15_ADC
bool "TIM15 ADC"
default n
depends on STM32F0L0G0_TIM15 && STM32F0L0G0_ADC
---help---
Reserve timer 1 for use by ADC
choice
prompt "Select TIM15 ADC channel"
default STM32F0L0G0_TIM15_ADC1
depends on STM32F0L0G0_TIM15_ADC
config STM32F0L0G0_TIM15_ADC1
bool "TIM15 ADC channel 1"
depends on STM32F0L0G0_ADC1
select STM32F0L0G0_HAVE_ADC1_TIMER
---help---
Reserve TIM15 to trigger ADC1
endchoice
config STM32F0L0G0_HAVE_ADC1_TIMER
bool
config STM32F0L0G0_ADC1_SAMPLE_FREQUENCY
int "ADC1 Sampling Frequency"
default 100
depends on STM32F0L0G0_HAVE_ADC1_TIMER
---help---
ADC1 sampling frequency. Default: 100Hz
config STM32F0L0G0_ADC1_TIMTRIG
int "ADC1 Timer Trigger"
default 0
range 0 5
depends on STM32F0L0G0_HAVE_ADC1_TIMER
---help---
Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO 5:TRGO2.
This option must match with the MCU's supported EXTSEL.
endmenu # Timer Configuration
menu "FDCAN driver configuration"
@ -3309,6 +3419,13 @@ config STM32F0L0G0_ADC1_DMA_CFG
---help---
0 - ADC1 DMA in One Shot Mode, 1 - ADC1 DMA in Circular Mode
config STM32F0L0G0_ADC1_EXTSEL
bool "ADC1 external trigger for regular group"
depends on STM32F0L0G0_ADC1 && !STM32F0L0G0_HAVE_ADC1_TIMER
default n
---help---
Enable EXTSEL for ADC1.
endmenu
menu "SPI Configuration"

View file

@ -27,10 +27,6 @@
* Pre-processor Definitions
****************************************************************************/
#if defined(CONFIG_STM32F0L0G0_STM32F0) || defined(CONFIG_STM32F0L0G0_STM32L0)
#error "Timer definitions should be validated for target before use"
#endif
/* TODO Missing TIM2 definitions available on STM32G0x1 */
/* Register Offsets *********************************************************/

View file

@ -48,6 +48,7 @@
#include "arm_internal.h"
#include "chip.h"
#include "stm32.h"
#include "stm32_tim.h"
#include "stm32_dma.h"
#include "stm32_adc.h"
@ -63,14 +64,6 @@
# error Not tested
#endif
/* At the moment there is no proper implementation for timers external
* trigger.
*/
#if defined(ADC_HAVE_TIMER)
# error not supported yet
#endif
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@ -769,7 +762,316 @@ static void adc_timstart(struct stm32_dev_s *priv, bool enable)
#ifdef ADC_HAVE_TIMER
static int adc_timinit(struct stm32_dev_s *priv)
{
#warning TODO: adc_timinit
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;
}
/* NOTE: EXTSEL configuration is done in adc_reset function */
/* Configure the timer channel to drive the ADC */
/* Calculate optimal values for the timer prescaler and for the timer
* reload register. If freq is the desired frequency, then
*
* reload = timclk / freq
* reload = (pclck / prescaler) / freq
*
* There are many solutions to do this, but the best solution will be the
* one that has the largest reload value and the smallest prescaler value.
* That is the solution that should give us the most accuracy in the timer
* control. Subject to:
*
* 0 <= prescaler <= 65536
* 1 <= reload <= 65535
*
* So (prescaler = pclck / 65535 / freq) would be optimal.
*/
prescaler = (priv->pclck / priv->freq + 65534) / 65535;
/* We need to decrement the prescaler value by one, but only, the value
* does not underflow.
*/
if (prescaler < 1)
{
awarn("WARNING: Prescaler underflowed.\n");
prescaler = 1;
}
/* Check for overflow */
else if (prescaler > 65536)
{
awarn("WARNING: Prescaler overflowed.\n");
prescaler = 65536;
}
timclk = priv->pclck / prescaler;
reload = timclk / priv->freq;
if (reload < 1)
{
awarn("WARNING: Reload value underflowed.\n");
reload = 1;
}
else if (reload > 65535)
{
awarn("WARNING: Reload value overflowed.\n");
reload = 65535;
}
/* Disable the timer until we get it configured */
adc_timstart(priv, false);
/* Set up the timer CR1 register.
*
* Select the Counter Mode == count up:
*
* ATIM_CR1_EDGE: The counter counts up or down depending on the
* direction bit(DIR).
* ATIM_CR1_DIR: 0: count up, 1: count down
*
* Set the clock division to zero for all
*/
clrbits = GTIM_CR1_DIR | GTIM_CR1_CMS_MASK | GTIM_CR1_CKD_MASK;
setbits = GTIM_CR1_EDGE;
tim_modifyreg(priv, STM32_GTIM_CR1_OFFSET, clrbits, setbits);
/* Set the reload and prescaler values */
tim_putreg(priv, STM32_GTIM_PSC_OFFSET, prescaler - 1);
tim_putreg(priv, STM32_GTIM_ARR_OFFSET, reload);
/* Clear the advanced timers repetition counter in TIM1 */
if (priv->tbase == STM32_TIM1_BASE)
{
tim_putreg(priv, STM32_ATIM_RCR_OFFSET, 0);
tim_putreg(priv, STM32_ATIM_BDTR_OFFSET, ATIM_BDTR_MOE); /* Check me */
}
/* TIMx event generation: Bit 0 UG: Update generation */
tim_putreg(priv, STM32_GTIM_EGR_OFFSET, GTIM_EGR_UG);
/* Handle channel specific setup */
ocmode1 = 0;
ocmode2 = 0;
switch (priv->trigger)
{
case 0: /* TimerX CC1 event */
{
ccenable = ATIM_CCER_CC1E;
ocmode1 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC1S_SHIFT) |
(ATIM_CCMR_MODE_PWM1 << ATIM_CCMR1_OC1M_SHIFT) |
ATIM_CCMR1_OC1PE;
/* Set the event CC1 */
egr = ATIM_EGR_CC1G;
/* Set the duty cycle by writing to the CCR register for this
* channel
*/
tim_putreg(priv, STM32_GTIM_CCR1_OFFSET, (uint16_t)(reload >> 1));
}
break;
case 1: /* TimerX CC2 event */
{
ccenable = ATIM_CCER_CC2E;
ocmode1 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC2S_SHIFT) |
(ATIM_CCMR_MODE_PWM1 << ATIM_CCMR1_OC2M_SHIFT) |
ATIM_CCMR1_OC2PE;
/* Set the event CC2 */
egr = ATIM_EGR_CC2G;
/* Set the duty cycle by writing to the CCR register for this
* channel
*/
tim_putreg(priv, STM32_GTIM_CCR2_OFFSET, (uint16_t)(reload >> 1));
}
break;
case 2: /* TimerX CC3 event */
{
ccenable = ATIM_CCER_CC3E;
ocmode2 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR2_CC3S_SHIFT) |
(ATIM_CCMR_MODE_PWM1 << ATIM_CCMR2_OC3M_SHIFT) |
ATIM_CCMR2_OC3PE;
/* Set the event CC3 */
egr = ATIM_EGR_CC3G;
/* Set the duty cycle by writing to the CCR register for this
* channel
*/
tim_putreg(priv, STM32_GTIM_CCR3_OFFSET, (uint16_t)(reload >> 1));
}
break;
case 3: /* TimerX CC4 event */
{
ccenable = ATIM_CCER_CC4E;
ocmode2 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR2_CC4S_SHIFT) |
(ATIM_CCMR_MODE_PWM1 << ATIM_CCMR2_OC4M_SHIFT) |
ATIM_CCMR2_OC4PE;
/* Set the event CC4 */
egr = ATIM_EGR_CC4G;
/* Set the duty cycle by writing to the CCR register for this
* channel
*/
tim_putreg(priv, STM32_GTIM_CCR4_OFFSET, (uint16_t)(reload >> 1));
}
break;
case 4: /* TimerX TRGO event */
{
/* TODO: TRGO support not yet implemented */
/* Set the event TRGO */
ccenable = 0;
egr = GTIM_EGR_TG;
/* Set the duty cycle by writing to the CCR register for this
* channel
*/
tim_putreg(priv, STM32_GTIM_CCR4_OFFSET, (uint16_t)(reload >> 1));
}
break;
default:
aerr("ERROR: No such trigger: %d\n", priv->trigger);
return -EINVAL;
}
/* Disable the Channel by resetting the CCxE Bit in the CCER register */
ccer = tim_getreg(priv, STM32_GTIM_CCER_OFFSET);
ccer &= ~ccenable;
tim_putreg(priv, STM32_GTIM_CCER_OFFSET, ccer);
/* Fetch the CR2, CCMR1, and CCMR2 register (already have ccer) */
cr2 = tim_getreg(priv, STM32_GTIM_CR2_OFFSET);
ccmr1 = tim_getreg(priv, STM32_GTIM_CCMR1_OFFSET);
ccmr2 = tim_getreg(priv, STM32_GTIM_CCMR2_OFFSET);
/* Reset the Output Compare Mode Bits and set the select output compare
* mode
*/
ccmr1 &= ~(ATIM_CCMR1_CC1S_MASK | ATIM_CCMR1_OC1M_MASK | ATIM_CCMR1_OC1PE |
ATIM_CCMR1_CC2S_MASK | ATIM_CCMR1_OC2M_MASK | ATIM_CCMR1_OC2PE);
ccmr2 &= ~(ATIM_CCMR2_CC3S_MASK | ATIM_CCMR2_OC3M_MASK | ATIM_CCMR2_OC3PE |
ATIM_CCMR2_CC4S_MASK | ATIM_CCMR2_OC4M_MASK | ATIM_CCMR2_OC4PE);
ccmr1 |= ocmode1;
ccmr2 |= ocmode2;
/* Reset the output polarity level of all channels (selects high
* polarity)
*/
ccer &= ~(ATIM_CCER_CC1P | ATIM_CCER_CC2P |
ATIM_CCER_CC3P | ATIM_CCER_CC4P);
/* Enable the output state of the selected channel (only) */
ccer &= ~(ATIM_CCER_CC1E | ATIM_CCER_CC2E |
ATIM_CCER_CC3E | ATIM_CCER_CC4E);
ccer |= ccenable;
if (priv->tbase == STM32_TIM1_BASE)
{
/* 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);
}
/* Reset the output compare and output compare N IDLE State */
if (priv->tbase >= STM32_TIM2_BASE && priv->tbase <= STM32_TIM3_BASE)
{
/* Reset output N polarity level, output N state, output compare state,
* output compare N idle state.
*/
ccer &= ~(GTIM_CCER_CC1NE | GTIM_CCER_CC1NP |
GTIM_CCER_CC2NP | GTIM_CCER_CC3NP |
GTIM_CCER_CC4NP);
}
/* 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
@ -1611,7 +1913,7 @@ static int adc_extcfg_set(struct adc_dev_s *dev, uint32_t extcfg)
setbits = (extsel | exten);
clrbits = (ADC_EXTREG_EXTEN_MASK | ADC_EXTREG_EXTSEL_MASK);
ainfo("Initializing extsel = 0x%08x\n", extsel);
ainfo("Initializing extsel = 0x%" PRIx32 "\n", extsel);
/* Write register */

View file

@ -42,9 +42,29 @@
/* Configuration ************************************************************/
/* Timer ADC trigger not supported yet */
/* Timer devices may be used for different purposes. One special purpose is
* to control periodic ADC sampling. If CONFIG_STM32F0L0G0_TIMn is defined
* then CONFIG_STM32F0L0G0_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.
*/
#undef ADC1_HAVE_TIMER
#ifndef CONFIG_STM32F0L0G0_TIM1
# undef CONFIG_STM32F0L0G0_TIM1_ADC
# undef CONFIG_STM32F0L0G0_TIM1_ADC1
#endif
#ifndef CONFIG_STM32F0L0G0_TIM2
# undef CONFIG_STM32F0L0G0_TIM2_ADC
# undef CONFIG_STM32F0L0G0_TIM2_ADC1
#endif
#ifndef CONFIG_STM32F0L0G0_TIM3
# undef CONFIG_STM32F0L0G0_TIM3_ADC
# undef CONFIG_STM32F0L0G0_TIM3_ADC1
#endif
#ifndef CONFIG_STM32F0L0G0_TIM15
# undef CONFIG_STM32F0L0G0_TIM15_ADC
# undef CONFIG_STM32F0L0G0_TIM15_ADC1
#endif
/* Up to 1 ADC interfaces are supported */
@ -67,6 +87,46 @@
# undef ADC1_HAVE_DMA
#endif
/* Timer configuration: If a timer trigger is specified, then get
* information about the timer.
*/
#if defined(CONFIG_STM32F0L0G0_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_STM32F0L0G0_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_STM32F0L0G0_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_STM32F0L0G0_TIM15_ADC1)
# define ADC1_HAVE_TIMER 1
# define ADC1_TIMER_BASE STM32_TIM15_BASE
# define ADC1_TIMER_PCLK_FREQUENCY STM32_APB1_TIM15_CLKIN
#else
# undef ADC1_HAVE_TIMER
#endif
#ifdef ADC1_HAVE_TIMER
# ifndef CONFIG_STM32F0L0G0_ADC1_SAMPLE_FREQUENCY
# error "CONFIG_STM32F0L0G0_ADC1_SAMPLE_FREQUENCY not defined"
# endif
# ifndef CONFIG_STM32F0L0G0_ADC1_TIMTRIG
# error "CONFIG_STM32F0L0G0_ADC1_TIMTRIG not defined"
# warning "Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO"
# endif
#endif
#if defined(ADC1_HAVE_TIMER)
# define ADC_HAVE_TIMER 1
#else
# undef ADC_HAVE_TIMER
#endif
/* EXTSEL */
#if defined(CONFIG_STM32F0L0G0_STM32F0)
@ -97,13 +157,81 @@
/* TRG5 and TRG6 reserved */
# define ADC1_EXTSEL_EXTI11 ADC12_CFGR1_EXTSEL_TRG7
#elif defined(CONFIG_STM32F0L0G0_STM32C0)
# define ADC1_EXTSEL_T1TRGO2 ADC12_CFGR1_EXTSEL_TRG0
# define ADC1_EXTSEL_T1CC4 ADC12_CFGR1_EXTSEL_TRG1
# define ADC1_EXTSEL_T2TRGO ADC12_CFGR1_EXTSEL_TRG2
# define ADC1_EXTSEL_T3TRGO ADC12_CFGR1_EXTSEL_TRG3
# define ADC1_EXTSEL_T15TRGO ADC12_CFGR1_EXTSEL_TRG4
/* TRG5 and TRG6 reserved */
# define ADC1_EXTSEL_EXTI11 ADC12_CFGR1_EXTSEL_TRG7
#else
# error
#endif
/* EXTSEL configuration *****************************************************/
/* TODO */
/* NOTE:
* this configuration if used only if CONFIG_STM32F0L0G0_TIMx_ADCy is
* selected.
* You can still connect the ADC with a timer trigger using the
* CONFIG_STM32F0L0G0_ADCx_EXTSEL option.
*/
#if defined(CONFIG_STM32F0L0G0_TIM1_ADC1)
# if CONFIG_STM32F0L0G0_ADC1_TIMTRIG == 3
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T1CC4
# elif CONFIG_STM32F0L0G0_ADC1_TIMTRIG == 4
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T1TRGO
# elif CONFIG_STM32F0L0G0_ADC1_TIMTRIG == 5
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T1TRGO2
# else
# error "CONFIG_STM32F0L0G0_ADC1_TIMTRIG is out of range"
# endif
#elif defined(CONFIG_STM32F0L0G0_TIM2_ADC1)
# if CONFIG_STM32F0L0G0_ADC1_TIMTRIG == 3
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T2CC4
# elif CONFIG_STM32F0L0G0_ADC1_TIMTRIG == 4
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T2TRGO
# else
# error "CONFIG_STM32F0L0G0_ADC1_TIMTRIG is out of range"
# endif
#elif defined(CONFIG_STM32F0L0G0_TIM3_ADC1)
# if CONFIG_STM32F0L0G0_ADC1_TIMTRIG == 4
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T3TRGO
# else
# error "CONFIG_STM32F0L0G0_ADC1_TIMTRIG is out of range"
# endif
#elif defined(CONFIG_STM32F0L0G0_TIM15_ADC1)
# if CONFIG_STM32F0L0G0_ADC1_TIMTRIG == 4
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T15TRGO
# else
# error "CONFIG_STM32F0L0G0_ADC1_TIMTRIG is out of range"
# endif
#elif defined(CONFIG_STM32F0L0G0_TIM21_ADC1)
# if CONFIG_STM32F0L0G0_ADC1_TIMTRIG == 1
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T21CC2
# elif CONFIG_STM32F0L0G0_ADC1_TIMTRIG == 4
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T21TRGO
# else
# error "CONFIG_STM32F0L0G0_ADC1_TIMTRIG is out of range"
# endif
#endif
/* Regular channels external trigger support */
#ifdef ADC1_EXTSEL_VALUE
# define ADC1_HAVE_EXTCFG 1
# define ADC1_EXTCFG_VALUE (ADC1_EXTSEL_VALUE | ADC_EXTREG_EXTEN_DEFAULT)
#elif defined(CONFIG_STM32F0L0G0_ADC1_EXTSEL)
# define ADC1_HAVE_EXTCFG 1
# define ADC1_EXTCFG_VALUE 0
#else
# undef ADC1_HAVE_EXTCFG
#endif
#if defined(ADC1_HAVE_EXTCFG)
# define ADC_HAVE_EXTCFG
#endif
/* ADC interrupts ***********************************************************/