This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 89e8c0c425839af3b3e30397bbce5c3970c40170
Author: raiden00pl <raide...@railab.me>
AuthorDate: Fri Jun 13 12:15:19 2025 +0200

    arch/stm32f0l0g0/adc: add timer trigger support
    
    add ADC external trigger from TIMER for stm32-m0 chips
    
    Signed-off-by: raiden00pl <raide...@railab.me>
---
 arch/arm/src/stm32f0l0g0/Kconfig              | 117 ++++++++++
 arch/arm/src/stm32f0l0g0/hardware/stm32_tim.h |   4 -
 arch/arm/src/stm32f0l0g0/stm32_adc.c          | 322 +++++++++++++++++++++++++-
 arch/arm/src/stm32f0l0g0/stm32_adc.h          | 134 ++++++++++-
 4 files changed, 560 insertions(+), 17 deletions(-)

diff --git a/arch/arm/src/stm32f0l0g0/Kconfig b/arch/arm/src/stm32f0l0g0/Kconfig
index d672a44588..fe2b96e8ad 100644
--- a/arch/arm/src/stm32f0l0g0/Kconfig
+++ b/arch/arm/src/stm32f0l0g0/Kconfig
@@ -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"
diff --git a/arch/arm/src/stm32f0l0g0/hardware/stm32_tim.h 
b/arch/arm/src/stm32f0l0g0/hardware/stm32_tim.h
index 41952b81ba..7546bc72cd 100644
--- a/arch/arm/src/stm32f0l0g0/hardware/stm32_tim.h
+++ b/arch/arm/src/stm32f0l0g0/hardware/stm32_tim.h
@@ -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 *********************************************************/
diff --git a/arch/arm/src/stm32f0l0g0/stm32_adc.c 
b/arch/arm/src/stm32f0l0g0/stm32_adc.c
index c84a623dd8..5546ea15ea 100644
--- a/arch/arm/src/stm32f0l0g0/stm32_adc.c
+++ b/arch/arm/src/stm32f0l0g0/stm32_adc.c
@@ -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 */
 
diff --git a/arch/arm/src/stm32f0l0g0/stm32_adc.h 
b/arch/arm/src/stm32f0l0g0/stm32_adc.h
index f620c4cf1e..ed9afe8d8a 100644
--- a/arch/arm/src/stm32f0l0g0/stm32_adc.h
+++ b/arch/arm/src/stm32f0l0g0/stm32_adc.h
@@ -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 ***********************************************************/
 

Reply via email to