You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2020/11/06 21:31:38 UTC
[incubator-nuttx] branch master updated: Add injected channel
support.
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/incubator-nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new a5d340a Add injected channel support.
a5d340a is described below
commit a5d340a5df64edc7d179c6a220dc0fe096ffc31e
Author: Daniel P. Carvalho <da...@gmail.com>
AuthorDate: Fri Nov 6 16:56:00 2020 -0300
Add injected channel support.
---
arch/arm/src/stm32l4/Kconfig | 224 ++++++--
arch/arm/src/stm32l4/hardware/stm32l4_adc.h | 171 +++---
arch/arm/src/stm32l4/stm32l4_adc.c | 777 ++++++++++++++++++----------
arch/arm/src/stm32l4/stm32l4_adc.h | 371 ++++++++++++-
include/nuttx/analog/ioctl.h | 5 +
5 files changed, 1156 insertions(+), 392 deletions(-)
diff --git a/arch/arm/src/stm32l4/Kconfig b/arch/arm/src/stm32l4/Kconfig
index 086616e..e8a831c 100644
--- a/arch/arm/src/stm32l4/Kconfig
+++ b/arch/arm/src/stm32l4/Kconfig
@@ -3603,26 +3603,26 @@ config STM32L4_TIM1_ADC
channel it is assigned to.
choice
- prompt "Select TIM1 ADC channel"
+ prompt "Select ADC to trigger"
default STM32L4_TIM1_ADC1
depends on STM32L4_TIM1_ADC
config STM32L4_TIM1_ADC1
- bool "TIM1 ADC channel 1"
+ bool "TIM1 trigger ADC1"
depends on STM32L4_ADC1
select STM32L4_HAVE_ADC1_TIMER
---help---
Reserve TIM1 to trigger ADC1
config STM32L4_TIM1_ADC2
- bool "TIM1 ADC channel 2"
+ bool "TIM1 trigger ADC2"
depends on STM32L4_ADC2
select STM32L4_HAVE_ADC2_TIMER
---help---
Reserve TIM1 to trigger ADC2
config STM32L4_TIM1_ADC3
- bool "TIM1 ADC channel 3"
+ bool "TIM1 trigger ADC3"
depends on STM32L4_ADC3
select STM32L4_HAVE_ADC3_TIMER
---help---
@@ -3630,6 +3630,14 @@ config STM32L4_TIM1_ADC3
endchoice
+config STM32L4_TIM1_ADC_CHAN
+ int "TIM1 channel"
+ default 1
+ range 1 4
+ depends on STM32L4_TIM1_ADC
+ ---help---
+ Values 1:CC1 2:CC2 3:CC3 4:CC4
+
config STM32L4_TIM2_ADC
bool "TIM2 ADC"
default n
@@ -3645,26 +3653,26 @@ config STM32L4_TIM2_ADC
channel it is assigned to.
choice
- prompt "Select TIM2 ADC channel"
+ prompt "Select ADC to trigger"
default STM32L4_TIM2_ADC1
depends on STM32L4_TIM2_ADC
config STM32L4_TIM2_ADC1
- bool "TIM2 ADC channel 1"
+ bool "TIM2 trigger ADC1"
depends on STM32L4_ADC1
select STM32L4_HAVE_ADC1_TIMER
---help---
Reserve TIM2 to trigger ADC1
config STM32L4_TIM2_ADC2
- bool "TIM2 ADC channel 2"
+ bool "TIM2 trigger ADC2"
depends on STM32L4_ADC2
select STM32L4_HAVE_ADC2_TIMER
---help---
Reserve TIM2 to trigger ADC2
config STM32L4_TIM2_ADC3
- bool "TIM2 ADC channel 3"
+ bool "TIM2 trigger ADC3"
depends on STM32L4_ADC3
select STM32L4_HAVE_ADC3_TIMER
---help---
@@ -3672,6 +3680,14 @@ config STM32L4_TIM2_ADC3
endchoice
+config STM32L4_TIM2_ADC_CHAN
+ int "TIM2 channel"
+ default 1
+ range 1 4
+ depends on STM32L4_TIM2_ADC
+ ---help---
+ Values 1:CC1 2:CC2 3:CC3 4:CC4
+
config STM32L4_TIM3_ADC
bool "TIM3 ADC"
default n
@@ -3687,26 +3703,26 @@ config STM32L4_TIM3_ADC
channel it is assigned to.
choice
- prompt "Select TIM3 ADC channel"
+ prompt "Select ADC to trigger"
default STM32L4_TIM3_ADC1
depends on STM32L4_TIM3_ADC
config STM32L4_TIM3_ADC1
- bool "TIM3 ADC channel 1"
+ bool "TIM3 trigger ADC1"
depends on STM32L4_ADC1
select STM32L4_HAVE_ADC1_TIMER
---help---
Reserve TIM3 to trigger ADC1
config STM32L4_TIM3_ADC2
- bool "TIM3 ADC channel 2"
+ bool "TIM3 trigger ADC2"
depends on STM32L4_ADC2
select STM32L4_HAVE_ADC2_TIMER
---help---
Reserve TIM3 to trigger ADC2
config STM32L4_TIM3_ADC3
- bool "TIM3 ADC channel 3"
+ bool "TIM3 trigger ADC3"
depends on STM32L4_ADC3
select STM32L4_HAVE_ADC3_TIMER
---help---
@@ -3714,6 +3730,14 @@ config STM32L4_TIM3_ADC3
endchoice
+config STM32L4_TIM3_ADC_CHAN
+ int "TIM3 channel"
+ default 1
+ range 1 4
+ depends on STM32L4_TIM3_ADC
+ ---help---
+ Values 1:CC2 2:CC2 3:CC3 4:CC4
+
config STM32L4_TIM4_ADC
bool "TIM4 ADC"
default n
@@ -3729,26 +3753,26 @@ config STM32L4_TIM4_ADC
channel it is assigned to.
choice
- prompt "Select TIM4 ADC channel"
+ prompt "Select ADC to trigger"
default STM32L4_TIM4_ADC1
depends on STM32L4_TIM4_ADC
config STM32L4_TIM4_ADC1
- bool "TIM4 ADC channel 1"
+ bool "TIM4 trigger ADC1"
depends on STM32L4_ADC1
select STM32L4_HAVE_ADC1_TIMER
---help---
Reserve TIM4 to trigger ADC1
config STM32L4_TIM4_ADC2
- bool "TIM4 ADC channel 2"
+ bool "TIM4 trigger ADC2"
depends on STM32L4_ADC2
select STM32L4_HAVE_ADC2_TIMER
---help---
Reserve TIM4 to trigger ADC2
config STM32L4_TIM4_ADC3
- bool "TIM4 ADC channel 3"
+ bool "TIM4 trigger ADC3"
depends on STM32L4_ADC3
select STM32L4_HAVE_ADC3_TIMER
---help---
@@ -3756,6 +3780,14 @@ config STM32L4_TIM4_ADC3
endchoice
+config STM32L4_TIM4_ADC_CHAN
+ int "TIM4 channel"
+ default 1
+ range 1 4
+ depends on STM32L4_TIM4_ADC
+ ---help---
+ Values 1:CC2 2:CC2 3:CC3 4:CC4
+
config STM32L4_TIM6_ADC
bool "TIM6 ADC"
default n
@@ -3771,26 +3803,26 @@ config STM32L4_TIM6_ADC
channel it is assigned to.
choice
- prompt "Select TIM6 ADC channel"
+ prompt "Select ADC to trigger"
default STM32L4_TIM6_ADC1
depends on STM32L4_TIM6_ADC
config STM32L4_TIM6_ADC1
- bool "TIM6 ADC channel 1"
+ bool "TIM6 trigger ADC1"
depends on STM32L4_ADC1
select STM32L4_HAVE_ADC1_TIMER
---help---
Reserve TIM6 to trigger ADC1
config STM32L4_TIM6_ADC2
- bool "TIM6 ADC channel 2"
+ bool "TIM6 trigger ADC2"
depends on STM32L4_ADC2
select STM32L4_HAVE_ADC2_TIMER
---help---
Reserve TIM6 to trigger ADC2
config STM32L4_TIM6_ADC3
- bool "TIM6 ADC channel 3"
+ bool "TIM6 trigger ADC3"
depends on STM32L4_ADC3
select STM32L4_HAVE_ADC3_TIMER
---help---
@@ -3798,6 +3830,14 @@ config STM32L4_TIM6_ADC3
endchoice
+config STM32L4_TIM6_ADC_CHAN
+ int "TIM6 channel"
+ default 1
+ range 1 4
+ depends on STM32L4_TIM6_ADC
+ ---help---
+ Values 1:CC2 2:CC2 3:CC3 4:CC4
+
config STM32L4_TIM8_ADC
bool "TIM8 ADC"
default n
@@ -3813,26 +3853,26 @@ config STM32L4_TIM8_ADC
channel it is assigned to.
choice
- prompt "Select TIM8 ADC channel"
+ prompt "Select ADC to trigger"
default STM32L4_TIM8_ADC1
depends on STM32L4_TIM8_ADC
config STM32L4_TIM8_ADC1
- bool "TIM8 ADC channel 1"
+ bool "TIM8 trigger ADC1"
depends on STM32L4_ADC1
select STM32L4_HAVE_ADC1_TIMER
---help---
Reserve TIM8 to trigger ADC1
config STM32L4_TIM8_ADC2
- bool "TIM8 ADC channel 2"
+ bool "TIM8 trigger ADC2"
depends on STM32L4_ADC2
select STM32L4_HAVE_ADC2_TIMER
---help---
Reserve TIM8 to trigger ADC2
config STM32L4_TIM8_ADC3
- bool "TIM8 ADC channel 3"
+ bool "TIM8 trigger ADC3"
depends on STM32L4_ADC3
select STM32L4_HAVE_ADC3_TIMER
---help---
@@ -3840,6 +3880,14 @@ config STM32L4_TIM8_ADC3
endchoice
+config STM32L4_TIM8_ADC_CHAN
+ int "TIM8 channel"
+ default 1
+ range 1 4
+ depends on STM32L4_TIM8_ADC
+ ---help---
+ Values 1:CC2 2:CC2 3:CC3 4:CC4
+
config STM32L4_TIM15_ADC
bool "TIM15 ADC"
default n
@@ -3855,26 +3903,26 @@ config STM32L4_TIM15_ADC
channel it is assigned to.
choice
- prompt "Select TIM15 ADC channel"
+ prompt "Select ADC to trigger"
default STM32L4_TIM15_ADC1
depends on STM32L4_TIM15_ADC
config STM32L4_TIM15_ADC1
- bool "TIM15 ADC channel 1"
+ bool "TIM15 trigger ADC1"
depends on STM32L4_ADC1
select STM32L4_HAVE_ADC1_TIMER
---help---
Reserve TIM15 to trigger ADC1
config STM32L4_TIM15_ADC2
- bool "TIM15 ADC channel 2"
+ bool "TIM15 trigger ADC2"
depends on STM32L4_ADC2
select STM32L4_HAVE_ADC2_TIMER
---help---
Reserve TIM15 to trigger ADC2
config STM32L4_TIM15_ADC3
- bool "TIM15 ADC channel 3"
+ bool "TIM15 trigger ADC3"
depends on STM32L4_ADC3
select STM32L4_HAVE_ADC3_TIMER
---help---
@@ -3882,6 +3930,14 @@ config STM32L4_TIM15_ADC3
endchoice
+config STM32L4_TIM15_ADC_CHAN
+ int "TIM15 channel"
+ default 1
+ range 1 4
+ depends on STM32L4_TIM15_ADC
+ ---help---
+ Values 1:CC2 2:CC2 3:CC3 4:CC4
+
config STM32L4_HAVE_ADC1_TIMER
bool
@@ -3898,14 +3954,6 @@ config STM32L4_ADC1_SAMPLE_FREQUENCY
---help---
ADC1 sampling frequency. Default: 100Hz
-config STM32L4_ADC1_TIMTRIG
- int "ADC1 Timer Trigger"
- default 0
- range 0 4
- depends on STM32L4_HAVE_ADC1_TIMER
- ---help---
- Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO
-
config STM32L4_ADC2_SAMPLE_FREQUENCY
int "ADC2 Sampling Frequency"
default 100
@@ -3913,14 +3961,6 @@ config STM32L4_ADC2_SAMPLE_FREQUENCY
---help---
ADC2 sampling frequency. Default: 100Hz
-config STM32L4_ADC2_TIMTRIG
- int "ADC2 Timer Trigger"
- default 0
- range 0 4
- depends on STM32L4_HAVE_ADC2_TIMER
- ---help---
- Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO
-
config STM32L4_ADC3_SAMPLE_FREQUENCY
int "ADC3 Sampling Frequency"
default 100
@@ -3928,14 +3968,6 @@ config STM32L4_ADC3_SAMPLE_FREQUENCY
---help---
ADC3 sampling frequency. Default: 100Hz
-config STM32L4_ADC3_TIMTRIG
- int "ADC3 Timer Trigger"
- default 0
- range 0 4
- depends on STM32L4_HAVE_ADC3_TIMER
- ---help---
- Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO
-
config STM32L4_TIM1_DAC
bool "TIM1 DAC"
default n
@@ -5150,6 +5182,94 @@ config STM32L4_ADC3_OUTPUT_DFSDM
---help---
Route ADC3 output directly to DFSDM parallel inputs.
+menu "STM32L4 ADCx triggering Configuration"
+
+config STM32L4_ADC1_TIMTRIG
+ int "ADC1 regular channel trigger"
+ default 0
+ range 0 4
+ depends on STM32L4_HAVE_ADC1_TIMER
+ ---help---
+ Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO
+
+config STM32L4_ADC2_TIMTRIG
+ int "ADC2 Timer Trigger"
+ default 0
+ range 0 4
+ depends on STM32L4_HAVE_ADC2_TIMER
+ ---help---
+ Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO
+
+config STM32L4_ADC3_TIMTRIG
+ int "ADC3 Timer Trigger"
+ default 0
+ range 0 4
+ depends on STM32L4_HAVE_ADC3_TIMER
+ ---help---
+ Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO
+
+config STM32L4_ADC1_INJ_CHAN
+ int "ADC1 configured injected channels"
+ depends on STM32L4_ADC1
+ range 0 4
+ default 0
+ ---help---
+ Number of configured ADC1 injected channels.
+
+config STM32L4_ADC2_INJ_CHAN
+ int "ADC2 configured injected channels"
+ depends on STM32L4_ADC2
+ range 0 4
+ default 0
+ ---help---
+ Number of configured ADC2 injected channels.
+
+config STM32L4_ADC3_INJ_CHAN
+ int "ADC3 configured injected channels"
+ depends on STM32L4_ADC3
+ range 0 4
+ default 0
+ ---help---
+ Number of configured ADC3 injected channels.
+
+if STM32L4_ADC1_INJ_CHAN > 0
+
+config STM32L4_ADC1_JTIMTRIG
+ int "ADC1 external trigger for injected channels"
+ default 0
+ range 0 5
+ depends on STM32L4_HAVE_ADC1_TIMER
+ ---help---
+ Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO 5:TRGO2
+
+endif
+
+if STM32L4_ADC2_INJ_CHAN > 0
+
+config STM32L4_ADC2_JTIMTRIG
+ int "ADC2 external trigger for injected channels"
+ default 0
+ range 0 5
+ depends on STM32L4_HAVE_ADC2_TIMER
+ ---help---
+ Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO 5:TRGO2
+
+endif
+
+if STM32L4_ADC3_INJ_CHAN > 0
+
+config STM32L4_ADC3_JTIMTRIG
+ int "ADC3 external trigger for injected channels"
+ default 0
+ range 0 5
+ depends on STM32L4_HAVE_ADC3_TIMER
+ ---help---
+ Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO 5:TRGO2
+
+endif
+
+endmenu #STM32L4 ADCx triggering Configuration
+
endmenu
menu "DAC Configuration"
diff --git a/arch/arm/src/stm32l4/hardware/stm32l4_adc.h b/arch/arm/src/stm32l4/hardware/stm32l4_adc.h
index 5db9b10..5fa3e9a 100644
--- a/arch/arm/src/stm32l4/hardware/stm32l4_adc.h
+++ b/arch/arm/src/stm32l4/hardware/stm32l4_adc.h
@@ -50,8 +50,9 @@
************************************************************************************/
/* Register Offsets *****************************************************************/
-/* Register Offsets for each ADC (ADC1-3). At offset 0x0000 for master and offset 0x0100
- * for slave.
+
+/* Register Offsets for each ADC (ADC1-3). At offset 0x0000 for master and offset
+ * 0x0100 for slave.
*/
#define STM32L4_ADC_ISR_OFFSET 0x0000 /* ADC interrupt and status register */
@@ -187,6 +188,7 @@
#endif
/* Register Bitfield Definitions ****************************************************/
+
/* ADC interrupt and status register (ISR) and ADC interrupt enable register (IER) */
#define ADC_INT_ADRDY (1 << 0) /* Bit 0: ADC ready */
@@ -223,51 +225,53 @@
#define ADC_CFGR_DFSDMCFG (1 << 2) /* Bit 2: DFSDM mode configuration */
#define ADC_CFGR_RES_SHIFT (3) /* Bits 3-4: Data resolution */
#define ADC_CFGR_RES_MASK (3 << ADC_CFGR_RES_SHIFT)
-# define ADC_CFGR_RES_12BIT (0 << ADC_CFGR_RES_SHIFT) /* 12-bit resolution */
-# define ADC_CFGR_RES_10BIT (1 << ADC_CFGR_RES_SHIFT) /* 10-bit resolution */
-# define ADC_CFGR_RES_8BIT (2 << ADC_CFGR_RES_SHIFT) /* 8-bit resolution */
-# define ADC_CFGR_RES_6BIT (3 << ADC_CFGR_RES_SHIFT) /* 6-bit resolution */
-#define ADC_CFGR_ALIGN (1 << 5) /* Bit 5: Data Alignment */
-#define ADC_CFGR_EXTSEL_SHIFT (6) /* Bits 6-9: External Event Select for regular group */
+# define ADC_CFGR_RES_12BIT (0 << ADC_CFGR_RES_SHIFT) /* 12-bit resolution */
+# define ADC_CFGR_RES_10BIT (1 << ADC_CFGR_RES_SHIFT) /* 10-bit resolution */
+# define ADC_CFGR_RES_8BIT (2 << ADC_CFGR_RES_SHIFT) /* 8-bit resolution */
+# define ADC_CFGR_RES_6BIT (3 << ADC_CFGR_RES_SHIFT) /* 6-bit resolution */
+#define ADC_CFGR_ALIGN (1 << 5) /* Bit 5: Data Alignment */
+#define ADC_CFGR_EXTSEL_SHIFT (6) /* Bits 6-9: External Event Select for regular group */
#define ADC_CFGR_EXTSEL_MASK (15 << ADC_CFGR_EXTSEL_SHIFT)
-# define ADC_CFGR_EXTSEL(event) ((event) << ADC_CFGR_EXTSEL_SHIFT) /* Event = 0..15 */
-# define ADC_CFGR_EXTSEL_T1CC1 (0x0 << ADC_CFGR_EXTSEL_SHIFT) /* 0000: Timer 1 CC1 event */
-# define ADC_CFGR_EXTSEL_T1CC2 (0x01 << ADC_CFGR_EXTSEL_SHIFT) /* 0001: Timer 1 CC2 event */
-# define ADC_CFGR_EXTSEL_T1CC3 (0x02 << ADC_CFGR_EXTSEL_SHIFT) /* 0010: Timer 1 CC3 event */
-# define ADC_CFGR_EXTSEL_T2CC2 (0x03 << ADC_CFGR_EXTSEL_SHIFT) /* 0011: Timer 2 CC2 event */
-# define ADC_CFGR_EXTSEL_T3TRGO (0x04 << ADC_CFGR_EXTSEL_SHIFT) /* 0100: Timer 3 TRGO event */
+# define ADC_CFGR_EXTSEL(event) ((event) << ADC_CFGR_EXTSEL_SHIFT)/* Event = 0..15 */
+# define ADC_CFGR_EXTSEL_T1CC1 (0x0 << ADC_CFGR_EXTSEL_SHIFT) /* 0000: Timer 1 CC1 event */
+# define ADC_CFGR_EXTSEL_T1CC2 (0x01 << ADC_CFGR_EXTSEL_SHIFT) /* 0001: Timer 1 CC2 event */
+# define ADC_CFGR_EXTSEL_T1CC3 (0x02 << ADC_CFGR_EXTSEL_SHIFT) /* 0010: Timer 1 CC3 event */
+# define ADC_CFGR_EXTSEL_T2CC2 (0x03 << ADC_CFGR_EXTSEL_SHIFT) /* 0011: Timer 2 CC2 event */
+# define ADC_CFGR_EXTSEL_T3TRGO (0x04 << ADC_CFGR_EXTSEL_SHIFT) /* 0100: Timer 3 TRGO event */
# if !defined(CONFIG_STM32L4_STM32L4X3)
-# define ADC_CFGR_EXTSEL_T4CC4 (0x05 << ADC_CFGR_EXTSEL_SHIFT) /* 0101: Timer 4 CC4 event */
+# define ADC_CFGR_EXTSEL_T4CC4 (0x05 << ADC_CFGR_EXTSEL_SHIFT) /* 0101: Timer 4 CC4 event */
# endif
-# define ADC_CFGR_EXTSEL_EXTI11 (0x06 << ADC_CFGR_EXTSEL_SHIFT) /* 0110: EXTI line 11 */
+# define ADC_CFGR_EXTSEL_EXTI11 (0x06 << ADC_CFGR_EXTSEL_SHIFT) /* 0110: EXTI line 11 */
# if !defined(CONFIG_STM32L4_STM32L4X3)
-# define ADC_CFGR_EXTSEL_T8TRGO (0x07 << ADC_CFGR_EXTSEL_SHIFT) /* 0111: Timer 8 TRGO event */
-# define ADC_CFGR_EXTSEL_T8TRGO2 (0x08 << ADC_CFGR_EXTSEL_SHIFT) /* 1000: Timer 8 TRGO2 event */
+# define ADC_CFGR_EXTSEL_T8TRGO (0x07 << ADC_CFGR_EXTSEL_SHIFT) /* 0111: Timer 8 TRGO event */
+# define ADC_CFGR_EXTSEL_T8TRGO2 (0x08 << ADC_CFGR_EXTSEL_SHIFT) /* 1000: Timer 8 TRGO2 event */
# endif
-# define ADC_CFGR_EXTSEL_T1TRGO (0x09 << ADC_CFGR_EXTSEL_SHIFT) /* 1001: Timer 1 TRGO event */
-# define ADC_CFGR_EXTSEL_T1TRGO2 (0x0a << ADC_CFGR_EXTSEL_SHIFT) /* 1010: Timer 1 TRGO2 event */
-# define ADC_CFGR_EXTSEL_T2TRGO (0x0b << ADC_CFGR_EXTSEL_SHIFT) /* 1011: Timer 2 TRGO event */
+# define ADC_CFGR_EXTSEL_T1TRGO (0x09 << ADC_CFGR_EXTSEL_SHIFT) /* 1001: Timer 1 TRGO event */
+# define ADC_CFGR_EXTSEL_T1TRGO2 (0x0a << ADC_CFGR_EXTSEL_SHIFT) /* 1010: Timer 1 TRGO2 event */
+# define ADC_CFGR_EXTSEL_T2TRGO (0x0b << ADC_CFGR_EXTSEL_SHIFT) /* 1011: Timer 2 TRGO event */
# if !defined(CONFIG_STM32L4_STM32L4X3)
-# define ADC_CFGR_EXTSEL_T4TRGO (0x0c << ADC_CFGR_EXTSEL_SHIFT) /* 1100: Timer 4 TRGO event */
+# define ADC_CFGR_EXTSEL_T4TRGO (0x0c << ADC_CFGR_EXTSEL_SHIFT) /* 1100: Timer 4 TRGO event */
# endif
-# define ADC_CFGR_EXTSEL_T6TRGO (0x0d << ADC_CFGR_EXTSEL_SHIFT) /* 1101: Timer 6 TRGO event */
-# define ADC_CFGR_EXTSEL_T15TRGO (0x0e << ADC_CFGR_EXTSEL_SHIFT) /* 1110: Timer 15 TRGO event */
+# define ADC_CFGR_EXTSEL_T6TRGO (0x0d << ADC_CFGR_EXTSEL_SHIFT) /* 1101: Timer 6 TRGO event */
+# define ADC_CFGR_EXTSEL_T15TRGO (0x0e << ADC_CFGR_EXTSEL_SHIFT) /* 1110: Timer 15 TRGO event */
# if !defined(CONFIG_STM32L4_STM32L4X3)
-# define ADC_CFGR_EXTSEL_T3CC4 (0x0f << ADC_CFGR_EXTSEL_SHIFT) /* 1111: Timer 3 CC4 event */
+# define ADC_CFGR_EXTSEL_T3CC4 (0x0f << ADC_CFGR_EXTSEL_SHIFT) /* 1111: Timer 3 CC4 event */
# endif
-#define ADC_CFGR_EXTEN_SHIFT (10) /* Bits 10-11: External trigger/polarity selection regular channels */
+#define ADC_CFGR_EXTEN_SHIFT (10) /* Bits 10-11: External trigger/polarity selection regular channels */
#define ADC_CFGR_EXTEN_MASK (3 << ADC_CFGR_EXTEN_SHIFT)
-# define ADC_CFGR_EXTEN_NONE (0 << ADC_CFGR_EXTEN_SHIFT) /* Trigger detection disabled */
-# define ADC_CFGR_EXTEN_RISING (1 << ADC_CFGR_EXTEN_SHIFT) /* Trigger detection on the rising edge */
-# define ADC_CFGR_EXTEN_FALLING (2 << ADC_CFGR_EXTEN_SHIFT) /* Trigger detection on the falling edge */
-# define ADC_CFGR_EXTEN_BOTH (3 << ADC_CFGR_EXTEN_SHIFT) /* Trigger detection on both edges */
-#define ADC_CFGR_OVRMOD (1 << 12) /* Bit 12: Overrun Mode */
-#define ADC_CFGR_CONT (1 << 13) /* Bit 13: Continuous mode for regular conversions */
-#define ADC_CFGR_AUTDLY (1 << 14) /* Bit 14: Delayed conversion mode */
-#define ADC_CFGR_DISCEN (1 << 16) /* Bit 16: Discontinuous mode on regular channels */
-#define ADC_CFGR_DISCNUM_SHIFT (17) /* Bits 17-19: Discontinuous mode channel count */
+# define ADC_CFGR_EXTEN_NONE (0 << ADC_CFGR_EXTEN_SHIFT) /* Trigger detection disabled */
+# define ADC_CFGR_EXTEN_RISING (1 << ADC_CFGR_EXTEN_SHIFT) /* Trigger detection on the rising edge */
+# define ADC_CFGR_EXTEN_FALLING (2 << ADC_CFGR_EXTEN_SHIFT) /* Trigger detection on the falling edge */
+# define ADC_CFGR_EXTEN_BOTH (3 << ADC_CFGR_EXTEN_SHIFT) /* Trigger detection on both edges */
+#define ADC_CFGR_OVRMOD (1 << 12) /* Bit 12: Overrun Mode */
+#define ADC_CFGR_CONT (1 << 13) /* Bit 13: Continuous mode for regular conversions */
+#define ADC_CFGR_AUTDLY (1 << 14) /* Bit 14: Delayed conversion mode */
+#define ADC_CFGR_DISCEN (1 << 16) /* Bit 16: Discontinuous mode on regular channels */
+#define ADC_CFGR_DISCNUM_SHIFT (17) /* Bits 17-19: Discontinuous mode channel count */
#define ADC_CFGR_DISCNUM_MASK (7 << ADC_CFGR_DISCNUM_SHIFT)
-# define ADC_CFGR_DISCNUM(n) (((n) - 1) << ADC_CFGR_DISCNUM_SHIFT) /* n = 1..8 channels */
+# define ADC_CFGR_DISCNUM(n) (((n) - 1) << ADC_CFGR_DISCNUM_SHIFT)
+ /* n = 1..8 channels */
+
#define ADC_CFGR_JDISCEN (1 << 20) /* Bit 20: Discontinuous mode on injected channels */
#define ADC_CFGR_JQM (1 << 21) /* Bit 21: JSQR queue mode */
#define ADC_CFGR_AWD1SGL (1 << 22) /* Bit 22: Enable watchdog on single/all channels */
@@ -293,11 +297,12 @@
# define ADC_CFGR2_OVSR_64X (5 << ADC_CFGR2_OVSR_SHIFT) /* 64X oversampling */
# define ADC_CFGR2_OVSR_128X (6 << ADC_CFGR2_OVSR_SHIFT) /* 128X oversampling */
# define ADC_CFGR2_OVSR_256X (7 << ADC_CFGR2_OVSR_SHIFT) /* 256X oversampling */
-#define ADC_CFGR2_OVSS_SHIFT (5) /* Bits 5-8: Oversampling shift */
+#define ADC_CFGR2_OVSS_SHIFT (5) /* Bits 5-8: Oversampling shift */
#define ADC_CFGR2_OVSS_MASK (0xf << ADC_CFGR2_OVSS_SHIFT)
-# define ADC_CFGR2_OVSS(value) ((value) << ADC_CFGR2_OVSS_SHIFT) /* Value = 0..8 */
-#define ADC_CFGR2_TROVS (1 << 9) /* Bit 9: Triggered Regular Oversampling */
-#define ADC_CFGR2_ROVSM (1 << 10) /* Bit 10: Regular Oversampling mode */
+# define ADC_CFGR2_OVSS(value) ((value) << ADC_CFGR2_OVSS_SHIFT)
+ /* Value = 0..8 */
+#define ADC_CFGR2_TROVS (1 << 9) /* Bit 9: Triggered Regular Oversampling */
+#define ADC_CFGR2_ROVSM (1 << 10) /* Bit 10: Regular Oversampling mode */
/* ADC sample time register 1 */
@@ -446,30 +451,49 @@
/* ADC injected sequence register */
-#define ADC_JSQR_JL_SHIFT (0) /* Bits 0-1: Injected Sequence length */
+#define ADC_JSQR_JL_SHIFT (0) /* Bits 0-1: Injected Sequence length */
#define ADC_JSQR_JL_MASK (3 << ADC_JSQR_JL_SHIFT)
-# define ADC_JSQR_JL(n) (((n)-1) << ADC_JSQR_JL_SHIFT) /* n=1..4 */
-#define ADC_JSQR_JEXTSEL_SHIFT (2) /* Bits 2-5: External Trigger Selection for injected group */
+# define ADC_JSQR_JL(n) (((n)-1) << ADC_JSQR_JL_SHIFT)
+ /* n=1..4 */
+#define ADC_JSQR_JEXTSEL_SHIFT (2) /* Bits 2-5: External Trigger Selection for injected group */
#define ADC_JSQR_JEXTSEL_MASK (15 << ADC_JSQR_JEXTSEL_SHIFT)
-# define ADC_JSQR_JEXTSEL(event) ((event) << ADC_JSQR_JEXTSEL_SHIFT) /* Event = 0..15 */
-#define ADC_JSQR_JEXTEN_SHIFT (6) /* Bits 6-7: External trigger selection for injected greoup */
+# define ADC_JSQR_JEXTSEL(event) ((event) << ADC_JSQR_JEXTSEL_SHIFT)
+ /* Event = 0..15 */
+# define ADC_JEXTSEL_T1TRGO ADC_JSQR_JEXTSEL(0) /* 0000 TIM1_TRGO */
+# define ADC_JEXTSEL_T1CC4 ADC_JSQR_JEXTSEL(1) /* 0001 TIM1_CH4 */
+# define ADC_JEXTSEL_T2TRGO ADC_JSQR_JEXTSEL(2) /* 0010 TIM2_TRGO */
+# define ADC_JEXTSEL_T2CC1 ADC_JSQR_JEXTSEL(3) /* 0011 TIM2_CH1 */
+# define ADC_JEXTSEL_T3CC4 ADC_JSQR_JEXTSEL(4) /* 0100 TIM3_CH4 */
+# define ADC_JEXTSEL_T4TRGO ADC_JSQR_JEXTSEL(5) /* 0101 TIM4_TRGO */
+# define ADC_JEXTSEL_EXTI15 ADC_JSQR_JEXTSEL(6) /* 0110 EXTI line 15 */
+# define ADC_JEXTSEL_T8CC4 ADC_JSQR_JEXTSEL(7) /* 0111 TIM8_CH4 */
+# define ADC_JEXTSEL_T1TRGO2 ADC_JSQR_JEXTSEL(8) /* 1000 TIM1_TRGO2 */
+# define ADC_JEXTSEL_T8TRGO ADC_JSQR_JEXTSEL(9) /* 1001 TIM8_TRGO */
+# define ADC_JEXTSEL_T8TRGO2 ADC_JSQR_JEXTSEL(10) /* 1010 TIM8_TRG02 */
+# define ADC_JEXTSEL_T3CC3 ADC_JSQR_JEXTSEL(11) /* 1011 TIM3_CH3 */
+# define ADC_JEXTSEL_T3TRGO ADC_JSQR_JEXTSEL(12) /* 1011 TIM3_TRGO */
+# define ADC_JEXTSEL_T3CC1 ADC_JSQR_JEXTSEL(13) /* 1101 TIM3_CH1 */
+# define ADC_JEXTSEL_T6TRGO ADC_JSQR_JEXTSEL(14) /* 1110 TIM6_TRGO */
+# define ADC_JEXTSEL_T15TRGO ADC_JSQR_JEXTSEL(15) /* 1111 TIM15_TRGO */
+#define ADC_JSQR_JEXTEN_SHIFT (6) /* Bits 6-7: External trigger selection for injected greoup */
#define ADC_JSQR_JEXTEN_MASK (3 << ADC_JSQR_JEXTEN_SHIFT)
# define ADC_JSQR_JEXTEN_NONE (0 << ADC_JSQR_JEXTEN_SHIFT) /* 00: Trigger detection disabled */
# define ADC_JSQR_JEXTEN_RISING (1 << ADC_JSQR_JEXTEN_SHIFT) /* 01: Trigger detection on the rising edge */
# define ADC_JSQR_JEXTEN_FALLING (2 << ADC_JSQR_JEXTEN_SHIFT) /* 10: Trigger detection on the falling edge */
# define ADC_JSQR_JEXTEN_BOTH (3 << ADC_JSQR_JEXTEN_SHIFT) /* 11: Trigger detection on both the rising and falling edges */
-#define ADC_JSQR_JSQ1_SHIFT (8) /* Bits 8-12: 1st conversion in injected sequence */
+#define ADC_JSQR_JSQ_SHIFT (6)
+#define ADC_JSQR_JSQ1_SHIFT (8) /* Bits 8-12: 1st conversion in injected sequence */
#define ADC_JSQR_JSQ1_MASK (0x1f << ADC_JSQR_JSQ1_SHIFT)
-# define ADC_JSQR_JSQ1(ch) ((ch) << ADC_JSQR_JSQ1_SHIFT) /* Channel number 1..18 */
-#define ADC_JSQR_JSQ2_SHIFT (14) /* Bits 14-18: 2nd conversion in injected sequence */
+# define ADC_JSQR_JSQ1(ch) ((ch) << ADC_JSQR_JSQ1_SHIFT)/* Channel number 1..18 */
+#define ADC_JSQR_JSQ2_SHIFT (14) /* Bits 14-18: 2nd conversion in injected sequence */
#define ADC_JSQR_JSQ2_MASK (0x1f << ADC_JSQR_JSQ2_MASK)
# define ADC_JSQR_JSQ2(ch) ((ch) << ADC_JSQR_JSQ2_MASK) /* Channel number 1..18 */
-#define ADC_JSQR_JSQ3_SHIFT (20) /* Bits 20-24: 3rd conversion in injected sequence */
+#define ADC_JSQR_JSQ3_SHIFT (20) /* Bits 20-24: 3rd conversion in injected sequence */
#define ADC_JSQR_JSQ3_MASK (0x1f << ADC_JSQR_JSQ3_SHIFT)
-# define ADC_JSQR_JSQ3(ch) ((ch) << ADC_JSQR_JSQ3_SHIFT) /* Channel number 1..18 */
-#define ADC_JSQR_JSQ4_SHIFT (26) /* Bits 26-30: 4th conversion in injected sequence */
+# define ADC_JSQR_JSQ3(ch) ((ch) << ADC_JSQR_JSQ3_SHIFT)/* Channel number 1..18 */
+#define ADC_JSQR_JSQ4_SHIFT (26) /* Bits 26-30: 4th conversion in injected sequence */
#define ADC_JSQR_JSQ4_MASK (0x1f << ADC_JSQR_JSQ4_SHIFT)
-# define ADC_JSQR_JSQ4(ch) ((ch) << ADC_JSQR_JSQ4_SHIFT) /* Channel number 1..18 */
+# define ADC_JSQR_JSQ4(ch) ((ch) << ADC_JSQR_JSQ4_SHIFT)/* Channel number 1..18 */
/* ADC offset register 1, 2, 3, and 4 */
@@ -541,33 +565,34 @@
/* Common control register */
#ifndef CONFIG_STM32L4_STM32L4X3
-# define ADC_CCR_DUAL_SHIFT (0) /* Bits 0-4: Dual ADC mode selection */
+# define ADC_CCR_DUAL_SHIFT (0) /* Bits 0-4: Dual ADC mode selection */
# define ADC_CCR_DUAL_MASK (31 << ADC_CCR_DUAL_SHIFT)
-# define ADC_CCR_DUAL_IND (0 << ADC_CCR_DUAL_SHIFT) /* Independent mode */
-# define ADC_CCR_DUAL_DUAL (1 << ADC_CCR_DUAL_SHIFT) /* Dual mode, master/slave ADCs together */
-# define ADC_CCR_DUAL_SIMINJ (1 << ADC_CCR_DUAL_SHIFT) /* Combined regular sim. + injected sim. */
-# define ADC_CCR_DUAL_SIMALT (2 << ADC_CCR_DUAL_SHIFT) /* Combined regular sim. + alternate trigger */
-# define ADC_CCR_DUAL_INJECTED (5 << ADC_CCR_DUAL_SHIFT) /* Injected simultaneous mode only */
-# define ADC_CCR_DUAL_SIM (6 << ADC_CCR_DUAL_SHIFT) /* Regular simultaneous mode only */
-# define ADC_CCR_DUAL_INTERLEAVE (7 << ADC_CCR_DUAL_SHIFT) /* Interleaved mode only */
-# define ADC_CCR_DUAL_ALT (9 << ADC_CCR_DUAL_SHIFT) /* Alternate trigger mode only */
-# define ADC_CCR_DELAY_SHIFT (8) /* Bits 8-11: Delay between 2 sampling phases */
+# define ADC_CCR_DUAL_IND (0 << ADC_CCR_DUAL_SHIFT) /* Independent mode */
+# define ADC_CCR_DUAL_DUAL (1 << ADC_CCR_DUAL_SHIFT) /* Dual mode, master/slave ADCs together */
+# define ADC_CCR_DUAL_SIMINJ (1 << ADC_CCR_DUAL_SHIFT) /* Combined regular sim. + injected sim. */
+# define ADC_CCR_DUAL_SIMALT (2 << ADC_CCR_DUAL_SHIFT) /* Combined regular sim. + alternate trigger */
+# define ADC_CCR_DUAL_INJECTED (5 << ADC_CCR_DUAL_SHIFT) /* Injected simultaneous mode only */
+# define ADC_CCR_DUAL_SIM (6 << ADC_CCR_DUAL_SHIFT) /* Regular simultaneous mode only */
+# define ADC_CCR_DUAL_INTERLEAVE (7 << ADC_CCR_DUAL_SHIFT) /* Interleaved mode only */
+# define ADC_CCR_DUAL_ALT (9 << ADC_CCR_DUAL_SHIFT) /* Alternate trigger mode only */
+# define ADC_CCR_DELAY_SHIFT (8) /* Bits 8-11: Delay between 2 sampling phases */
# define ADC_CCR_DELAY_MASK (15 << ADC_CCR_DELAY_SHIFT)
-# define ADC_CCR_DELAY(n) (((n)-1) << ADC_CCR_DELAY_SHIFT) /* n * TADCCLK, 1-13 */
-# define ADC_CCR_DMACFG (1 << 13) /* Bit 13: DMA configuration (for dual ADC mode) */
-# define ADC_CCR_MDMA_SHIFT (14) /* Bits 14-15: Direct memory access mode for dual ADC mode */
+# define ADC_CCR_DELAY(n) (((n)-1) << ADC_CCR_DELAY_SHIFT)
+ /* n * TADCCLK, 1-13 */
+# define ADC_CCR_DMACFG (1 << 13) /* Bit 13: DMA configuration (for dual ADC mode) */
+# define ADC_CCR_MDMA_SHIFT (14) /* Bits 14-15: Direct memory access mode for dual ADC mode */
# define ADC_CCR_MDMA_MASK (3 << ADC_CCR_MDMA_SHIFT)
-# define ADC_CCR_MDMA_DISABLE (0 << ADC_CCR_MDMA_SHIFT) /* MDMA mode disabled */
-# define ADC_CCR_MDMA_10_12 (2 << ADC_CCR_MDMA_SHIFT) /* MDMA mode enabled (12 / 10-bit) */
-# define ADC_CCR_MDMA_6_8 (3 << ADC_CCR_MDMA_SHIFT) /* MDMA mode enabled (8 / 6-bit) */
+# define ADC_CCR_MDMA_DISABLE (0 << ADC_CCR_MDMA_SHIFT) /* MDMA mode disabled */
+# define ADC_CCR_MDMA_10_12 (2 << ADC_CCR_MDMA_SHIFT) /* MDMA mode enabled (12 / 10-bit) */
+# define ADC_CCR_MDMA_6_8 (3 << ADC_CCR_MDMA_SHIFT) /* MDMA mode enabled (8 / 6-bit) */
#endif
-#define ADC_CCR_CKMODE_SHIFT (16) /* Bits 16-17: ADC clock mode */
+#define ADC_CCR_CKMODE_SHIFT (16) /* Bits 16-17: ADC clock mode */
#define ADC_CCR_CKMODE_MASK (3 << ADC_CCR_CKMODE_SHIFT)
# define ADC_CCR_CKMODE_ASYCH (0 << ADC_CCR_CKMODE_SHIFT) /* Asynchronous clock mode */
# define ADC_CCR_CKMODE_SYNCH_DIV1 (1 << ADC_CCR_CKMODE_SHIFT) /* Synchronous clock mode divided by 1 */
# define ADC_CCR_CKMODE_SYNCH_DIV2 (2 << ADC_CCR_CKMODE_SHIFT) /* Synchronous clock mode divided by 2 */
# define ADC_CCR_CKMODE_SYNCH_DIV4 (3 << ADC_CCR_CKMODE_SHIFT) /* Synchronous clock mode divided by 4 */
-#define ADC_CCR_PRESC_SHIFT (18) /* Bits 18-21: ADC prescaler */
+#define ADC_CCR_PRESC_SHIFT (18) /* Bits 18-21: ADC prescaler */
#define ADC_CCR_PRESC_MASK (3 << ADC_CCR_PRESC_SHIFT)
# define ADC_CCR_PRESC_NOT_DIV (0 << ADC_CCR_PRESC_SHIFT) /* Input ADC clock not divided */
# define ADC_CCR_PRESC_DIV2 (1 << ADC_CCR_PRESC_SHIFT) /* Input ADC clock divided by 2 */
@@ -581,9 +606,9 @@
# define ADC_CCR_PRESC_DIV64 (9 << ADC_CCR_PRESC_SHIFT) /* Input ADC clock divided by 64 */
# define ADC_CCR_PRESC_DIV128 (10 << ADC_CCR_PRESC_SHIFT) /* Input ADC clock divided by 128 */
# define ADC_CCR_PRESC_DIV256 (11 << ADC_CCR_PRESC_SHIFT) /* Input ADC clock divided by 256 */
-#define ADC_CCR_VREFEN (1 << 22) /* Bit 22: VREFINT enable */
-#define ADC_CCR_TSEN (1 << 23) /* Bit 23: Temperature sensor enable */
-#define ADC_CCR_VBATEN (1 << 24) /* Bit 22: VBAT enable */
+#define ADC_CCR_VREFEN (1 << 22) /* Bit 22: VREFINT enable */
+#define ADC_CCR_TSEN (1 << 23) /* Bit 23: Temperature sensor enable */
+#define ADC_CCR_VBATEN (1 << 24) /* Bit 22: VBAT enable */
/* Common regular data register for dual mode */
diff --git a/arch/arm/src/stm32l4/stm32l4_adc.c b/arch/arm/src/stm32l4/stm32l4_adc.c
index c777ed2..522dab6 100644
--- a/arch/arm/src/stm32l4/stm32l4_adc.c
+++ b/arch/arm/src/stm32l4/stm32l4_adc.c
@@ -155,48 +155,14 @@
#define ADC_EXTERNAL_CHAN_MIN 1
#define ADC_EXTERNAL_CHAN_MAX 16
-/* ADCx_EXTSEL_VALUE can be set by this driver (look at stm32l4_adc.h) or
- * by board specific logic in board.h file.
- */
-
-#define ADC_EXTREG_EXTSEL_MASK ADC_CFGR_EXTSEL_MASK
-#define ADC_EXTREG_EXTEN_MASK ADC_CFGR_EXTEN_MASK
-#define ADC_EXTREG_EXTEN_DEFAULT ADC_CFGR_EXTEN_RISING
-
-#ifdef ADC1_EXTSEL_VALUE
-# define ADC1_HAVE_EXTCFG 1
-# define ADC1_EXTCFG_VALUE (ADC1_EXTSEL_VALUE | ADC_EXTREG_EXTEN_DEFAULT)
-#else
-# undef ADC1_HAVE_EXTCFG
-#endif
-#ifdef ADC2_EXTSEL_VALUE
-# define ADC2_HAVE_EXTCFG 1
-# define ADC2_EXTCFG_VALUE (ADC2_EXTSEL_VALUE | ADC_EXTREG_EXTEN_DEFAULT)
-#else
-# undef ADC2_HAVE_EXTCFG
-#endif
-#ifdef ADC3_EXTSEL_VALUE
-# define ADC3_HAVE_EXTCFG 1
-# define ADC3_EXTCFG_VALUE (ADC3_EXTSEL_VALUE | ADC_EXTREG_EXTEN_DEFAULT)
-#else
-# undef ADC3_HAVE_EXTCFG
-#endif
-#ifdef ADC4_EXTSEL_VALUE
-# define ADC4_HAVE_EXTCFG 1
-# define ADC4_EXTCFG_VALUE (ADC4_EXTSEL_VALUE | ADC_EXTREG_EXTEN_DEFAULT)
-#else
-# undef ADC4_HAVE_EXTCFG
-#endif
-
-#if defined(ADC1_HAVE_EXTCFG) || defined(ADC2_HAVE_EXTCFG) || \
- defined(ADC3_HAVE_EXTCFG) || defined(ADC3_HAVE_EXTCFG)
-# define ADC_HAVE_EXTCFG
-#endif
-
/* ADC resolution supported */
#define HAVE_ADC_RESOLUTION
+/* Max 4 injected channels */
+
+#define ADC_INJ_MAX_SAMPLES 4
+
/*****************************************************************************
* Private Types
*****************************************************************************/
@@ -212,8 +178,11 @@ struct stm32_dev_s
FAR const struct adc_callback_s *cb;
uint8_t irq; /* Interrupt generated by this ADC block */
#endif
- uint8_t nchannels; /* Number of channels */
- uint8_t cchannels; /* Number of configured channels */
+ uint8_t nchannels; /* Number of regular channels */
+ uint8_t cchannels; /* Number of configured regular channels */
+#ifdef ADC_HAVE_INJECTED
+ uint8_t cjchannels; /* Number of configured injected channels */
+#endif
uint8_t intf; /* ADC interface number */
uint8_t current; /* Current ADC channel being converted */
#ifdef HAVE_ADC_RESOLUTION
@@ -228,15 +197,17 @@ struct stm32_dev_s
bool hasdfsdm; /* True: This ADC routes its output to DFSDM */
#endif
#ifdef ADC_HAVE_TIMER
- uint8_t trigger; /* Timer trigger channel: 0=CC1, 1=CC2, 2=CC3,
- * 3=CC4, 4=TRGO, 5=TRGO2 */
+ uint8_t channel; /* Timer channel: 1=CC1, 2=CC2, 3=CC3, 4=CC4 */
#endif
xcpt_t isr; /* Interrupt handler for this ADC block */
uint32_t base; /* Base address of registers unique to this ADC
* block */
-#if defined(ADC_HAVE_TIMER) || defined(ADC_HAVE_EXTCFG)
+#ifdef ADC_HAVE_EXTCFG
uint32_t extcfg; /* External event configuration for regular group */
#endif
+#ifdef ADC_HAVE_JEXTCFG
+ uint32_t jextcfg; /* External event configuration for injected group */
+#endif
#ifdef ADC_HAVE_TIMER
uint32_t tbase; /* Base address of timer used by this ADC block */
uint32_t pclck; /* The PCLK frequency that drives this timer */
@@ -258,6 +229,12 @@ struct stm32_dev_s
/* List of selected ADC channels to sample */
uint8_t chanlist[ADC_MAX_SAMPLES];
+
+#ifdef ADC_HAVE_INJECTED
+ /* List of selected ADC injected channels to sample */
+
+ uint8_t jchanlist[ADC_INJ_MAX_SAMPLES];
+#endif
};
/*****************************************************************************
@@ -292,6 +269,9 @@ static void adc_enable(FAR struct stm32_dev_s *priv);
static uint32_t adc_sqrbits(FAR struct stm32_dev_s *priv, int first,
int last, int offset);
static int adc_set_ch(FAR struct adc_dev_s *dev, uint8_t ch);
+#ifdef ADC_HAVE_INJECTED
+static int adc_inj_set_ch(FAR struct adc_dev_s *dev, uint8_t ch);
+#endif
static bool adc_internal(FAR struct stm32_dev_s * priv,
uint32_t *adc_ccr);
#ifdef HAVE_ADC_RESOLUTION
@@ -299,6 +279,9 @@ static int adc_resolution_set(FAR struct adc_dev_s *dev, uint8_t res);
#endif
static void adc_sample_time_set(FAR struct adc_dev_s *dev);
static void adc_startconv(FAR struct stm32_dev_s *priv, bool enable);
+#ifdef ADC_HAVE_INJECTED
+static void adc_inj_startconv(FAR struct stm32_dev_s *priv, bool enable);
+#endif
#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);
@@ -315,13 +298,19 @@ static void adc_dmaconvcallback(DMA_HANDLE handle, uint8_t isr,
static int adc_offset_set(FAR struct stm32_dev_s *priv, uint8_t ch,
uint8_t i, uint16_t offset);
#endif
-#if defined(ADC_HAVE_EXTCFG) || defined(CONFIG_STM32L4_ADC_LL_OPS)
+#ifdef ADC_HAVE_EXTCFG
static int adc_extsel_set(FAR struct stm32_dev_s *priv, uint32_t extcfg);
#endif
+#ifdef ADC_HAVE_JEXTCFG
+static int adc_jextsel_set(FAR struct stm32_dev_s *priv,
+ uint32_t jextcfg);
+#endif
+
#ifdef CONFIG_PM
static int adc_pm_prepare(struct pm_callback_s *cb, int domain,
enum pm_state_e state);
#endif
+
#ifdef CONFIG_STM32L4_ADC_LL_OPS
static void adc_llops_intack(FAR struct stm32_adc_dev_s *dev,
uint32_t source);
@@ -339,9 +328,21 @@ static int adc_llops_offset_set(FAR struct stm32_adc_dev_s *dev,
static int adc_regbufregister(FAR struct stm32_adc_dev_s *dev,
uint16_t *buffer, uint8_t len);
# endif
+# ifdef ADC_HAVE_EXTCFG
static int adc_llops_extsel_set(FAR struct stm32_adc_dev_s *dev,
- uint32_t extcfg);
+ uint32_t extcfg);
+# endif
+# ifdef ADC_HAVE_JEXTCFG
+static void adc_llops_jextsel_set(FAR struct stm32_adc_dev_s *dev,
+ uint32_t jextcfg);
+# endif
static void adc_llops_dumpregs(FAR struct stm32_adc_dev_s *dev);
+# ifdef ADC_HAVE_INJECTED
+static uint32_t adc_llops_injget(FAR struct stm32_adc_dev_s *dev,
+ uint8_t chan);
+static void adc_llops_inj_startconv(FAR struct stm32_adc_dev_s *dev,
+ bool enable);
+# endif
#endif /* CONFIG_STM32L4_ADC_LL_OPS */
/* ADC Interrupt Handler */
@@ -397,7 +398,16 @@ static const struct stm32_adc_ops_s g_adc_llops =
# ifdef ADC_HAVE_DMA
.regbuf_reg = adc_regbufregister,
# endif
+# ifdef ADC_HAVE_INJECTED
+ .inj_get = adc_llops_injget,
+ .inj_startconv = adc_llops_inj_startconv,
+# endif
+# ifdef ADC_HAVE_EXTCFG
.extsel_set = adc_llops_extsel_set,
+# endif
+# ifdef ADC_HAVE_JEXTCFG
+ .jextsel_set = adc_llops_jextsel_set,
+# endif
.dump_regs = adc_llops_dumpregs
};
#endif /* CONFIG_STM32L4_ADC_LL_OPS */
@@ -422,8 +432,11 @@ static struct stm32_dev_s g_adcpriv1 =
#if defined(ADC1_HAVE_TIMER) || defined(ADC1_HAVE_EXTCFG)
.extcfg = ADC1_EXTCFG_VALUE,
#endif
+#ifdef ADC1_HAVE_JEXTCFG
+ .jextcfg = ADC1_JEXTCFG_VALUE,
+#endif
#ifdef ADC1_HAVE_TIMER
- .trigger = CONFIG_STM32L4_ADC1_TIMTRIG,
+ .channel = ADC1_TIMER_CHANNEL,
.tbase = ADC1_TIMER_BASE,
.pclck = ADC1_TIMER_PCLK_FREQUENCY,
.freq = CONFIG_STM32L4_ADC1_SAMPLE_FREQUENCY,
@@ -471,8 +484,11 @@ static struct stm32_dev_s g_adcpriv2 =
#if defined(ADC2_HAVE_TIMER) || defined(ADC2_HAVE_EXTCFG)
.extcfg = ADC2_EXTCFG_VALUE,
#endif
+#ifdef ADC2_HAVE_JEXTCFG
+ .jextcfg = ADC2_JEXTCFG_VALUE,
+#endif
#ifdef ADC2_HAVE_TIMER
- .trigger = CONFIG_STM32L4_ADC2_TIMTRIG,
+ .channel = ADC2_TIMER_CHANNEL,
.tbase = ADC2_TIMER_BASE,
.pclck = ADC2_TIMER_PCLK_FREQUENCY,
.freq = CONFIG_STM32L4_ADC2_SAMPLE_FREQUENCY,
@@ -520,8 +536,11 @@ static struct stm32_dev_s g_adcpriv3 =
#if defined(ADC3_HAVE_TIMER) || defined(ADC3_HAVE_EXTCFG)
.extcfg = ADC3_EXTCFG_VALUE,
#endif
+#ifdef ADC3_HAVE_JEXTCFG
+ .jextcfg = ADC3_JEXTCFG_VALUE,
+#endif
#ifdef ADC3_HAVE_TIMER
- .trigger = CONFIG_STM32L4_ADC3_TIMTRIG,
+ .channel = ADC3_TIMER_CHANNEL,
.tbase = ADC3_TIMER_BASE,
.pclck = ADC3_TIMER_PCLK_FREQUENCY,
.freq = CONFIG_STM32L4_ADC3_SAMPLE_FREQUENCY,
@@ -789,6 +808,7 @@ static void adc_timstart(FAR struct stm32_dev_s *priv, bool enable)
{
/* Start the counter */
+ tim_modifyreg(priv, STM32L4_GTIM_EGR_OFFSET, 0, GTIM_EGR_UG);
tim_modifyreg(priv, STM32L4_GTIM_CR1_OFFSET, 0, GTIM_CR1_CEN);
}
else
@@ -824,14 +844,12 @@ static int adc_timinit(FAR struct stm32_dev_s *priv)
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;
+ uint16_t ccmr_orig = 0;
+ uint16_t ccmr_val = 0;
+ uint16_t ccmr_mask = 0xff;
+ uint16_t ccer_val;
+ uint8_t ccmr_offset = STM32L4_GTIM_CCMR1_OFFSET;
+ uint32_t channel = priv->channel - 1;
/* If the timer base address is zero, then this ADC was not configured to
* use a timer.
@@ -917,6 +935,10 @@ static int adc_timinit(FAR struct stm32_dev_s *priv)
setbits = GTIM_CR1_EDGE;
tim_modifyreg(priv, STM32L4_GTIM_CR1_OFFSET, clrbits, setbits);
+ /* Set the ARR Preload Bit */
+
+ tim_modifyreg(priv, STM32L4_GTIM_CR1_OFFSET, 0, GTIM_CR1_ARPE);
+
/* Set the reload and prescaler values */
tim_putreg(priv, STM32L4_GTIM_PSC_OFFSET, prescaler - 1);
@@ -930,186 +952,62 @@ static int adc_timinit(FAR struct stm32_dev_s *priv)
tim_putreg(priv, STM32L4_ATIM_BDTR_OFFSET, ATIM_BDTR_MOE); /* Check me */
}
- /* TIMx event generation: Bit 0 UG: Update generation */
+ /* Handle channel specific setup */
- tim_putreg(priv, STM32L4_GTIM_EGR_OFFSET, GTIM_EGR_UG);
+ /* Assume that channel is disabled and polarity is active high */
- /* Handle channel specific setup */
+ ccer_val = tim_getreg(priv, STM32L4_GTIM_CCER_OFFSET);
+ ccer_val &= ~(3 << (channel << 2));
- ocmode1 = 0;
- ocmode2 = 0;
+ ccmr_val = (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR1_OC1M_SHIFT) |
+ (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC1S_SHIFT) |
+ ATIM_CCMR1_OC1PE;
+ ccer_val |= ATIM_CCER_CC1E << (channel << 2);
- switch (priv->trigger)
+ if (channel & 1)
{
- 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 */
+ ccmr_val <<= 8;
+ ccmr_mask <<= 8;
+ }
- egr = ATIM_EGR_CC1G;
+ if (channel > 1)
+ {
+ ccmr_offset = STM32L4_GTIM_CCMR2_OFFSET;
+ }
- /* Set the duty cycle by writing to the CCR register for this
- * channel
- */
+ ccmr_orig = tim_getreg(priv, ccmr_offset);
+ ccmr_orig &= ~ccmr_mask;
+ ccmr_orig |= ccmr_val;
+ tim_putreg(priv, ccmr_offset, ccmr_orig);
+ tim_putreg(priv, STM32L4_GTIM_CCER_OFFSET, ccer_val);
+ switch (channel)
+ {
+ case 0: /* TIMx CC1 */
+ {
tim_putreg(priv, STM32L4_GTIM_CCR1_OFFSET, (uint16_t)(reload >> 1));
}
break;
- case 1: /* TimerX CC2 event */
+ case 1: /* TIMx CC2 */
{
- ccenable = ATIM_CCER_CC2E;
- ocmode1 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC2S_SHIFT) |
- (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR1_OC2M_SHIFT) |
- ATIM_CCMR1_OC2PE;
-
- /* Set the event CC2 */
-
- egr = ATIM_EGR_CC2G;
-
- /* Set the duty cycle by writing to the CCR register for this
- * channel
- */
-
tim_putreg(priv, STM32L4_GTIM_CCR2_OFFSET, (uint16_t)(reload >> 1));
}
break;
- case 2: /* TimerX CC3 event */
+ case 2: /* TIMx CC3 */
{
- ccenable = ATIM_CCER_CC3E;
- ocmode2 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR2_CC3S_SHIFT) |
- (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR2_OC3M_SHIFT) |
- ATIM_CCMR2_OC3PE;
-
- /* Set the event CC3 */
-
- egr = ATIM_EGR_CC3G;
-
- /* Set the duty cycle by writing to the CCR register for this
- * channel
- */
-
tim_putreg(priv, STM32L4_GTIM_CCR3_OFFSET, (uint16_t)(reload >> 1));
}
break;
- case 3: /* TimerX CC4 event */
- {
- ccenable = ATIM_CCER_CC4E;
- ocmode2 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR2_CC4S_SHIFT) |
- (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR2_OC4M_SHIFT) |
- ATIM_CCMR2_OC4PE;
-
- /* Set the event CC4 */
-
- egr = ATIM_EGR_CC4G;
-
- /* Set the duty cycle by writing to the CCR register for this
- * channel
- */
-
- tim_putreg(priv, STM32L4_GTIM_CCR4_OFFSET, (uint16_t)(reload >> 1));
- }
- break;
-
- case 4: /* TimerX TRGO event */
+ case 3: /* TIMx CC4 */
{
- /* TODO: TRGO support not yet implemented */
-
- /* Set the event TRGO */
-
- ccenable = 0;
- egr = GTIM_EGR_TG;
-
- /* Set the duty cycle by writing to the CCR register for this
- * channel
- */
-
tim_putreg(priv, STM32L4_GTIM_CCR4_OFFSET, (uint16_t)(reload >> 1));
}
break;
-
- default:
- aerr("ERROR: No such trigger: %d\n", priv->trigger);
- return -EINVAL;
- }
-
- /* Disable the Channel by resetting the CCxE Bit in the CCER register */
-
- ccer = tim_getreg(priv, STM32L4_GTIM_CCER_OFFSET);
- ccer &= ~ccenable;
- tim_putreg(priv, STM32L4_GTIM_CCER_OFFSET, ccer);
-
- /* Fetch the CR2, CCMR1, and CCMR2 register (already have ccer) */
-
- cr2 = tim_getreg(priv, STM32L4_GTIM_CR2_OFFSET);
- ccmr1 = tim_getreg(priv, STM32L4_GTIM_CCMR1_OFFSET);
- ccmr2 = tim_getreg(priv, STM32L4_GTIM_CCMR2_OFFSET);
-
- /* Reset the Output Compare Mode Bits and set the select output compare
- * mode
- */
-
- ccmr1 &= ~(ATIM_CCMR1_CC1S_MASK | ATIM_CCMR1_OC1M_MASK | ATIM_CCMR1_OC1PE |
- ATIM_CCMR1_CC2S_MASK | ATIM_CCMR1_OC2M_MASK | ATIM_CCMR1_OC2PE);
- ccmr2 &= ~(ATIM_CCMR2_CC3S_MASK | ATIM_CCMR2_OC3M_MASK | ATIM_CCMR2_OC3PE |
- ATIM_CCMR2_CC4S_MASK | ATIM_CCMR2_OC4M_MASK | ATIM_CCMR2_OC4PE);
- ccmr1 |= ocmode1;
- ccmr2 |= ocmode2;
-
- /* Reset the output polarity level of all channels (selects high
- * polarity)
- */
-
- ccer &= ~(ATIM_CCER_CC1P | ATIM_CCER_CC2P |
- ATIM_CCER_CC3P | ATIM_CCER_CC4P);
-
- /* Enable the output state of the selected channel (only) */
-
- ccer &= ~(ATIM_CCER_CC1E | ATIM_CCER_CC2E |
- ATIM_CCER_CC3E | ATIM_CCER_CC4E);
- ccer |= ccenable;
-
- if (priv->tbase == STM32L4_TIM1_BASE || priv->tbase == STM32L4_TIM8_BASE)
- {
- /* Reset output N polarity level, output N state, output compare state,
- * output compare N idle state.
- */
-
- ccer &= ~(ATIM_CCER_CC1NE | ATIM_CCER_CC1NP |
- ATIM_CCER_CC2NE | ATIM_CCER_CC2NP |
- ATIM_CCER_CC3NE | ATIM_CCER_CC3NP |
- ATIM_CCER_CC4NP);
-
- /* Reset the output compare and output compare N IDLE State */
-
- cr2 &= ~(ATIM_CR2_OIS1 | ATIM_CR2_OIS1N |
- ATIM_CR2_OIS2 | ATIM_CR2_OIS2N |
- ATIM_CR2_OIS3 | ATIM_CR2_OIS3N |
- ATIM_CR2_OIS4);
- }
- else
- {
- ccer &= ~(GTIM_CCER_CC1NP | GTIM_CCER_CC2NP | GTIM_CCER_CC3NP);
}
- /* Save the modified register values */
-
- tim_putreg(priv, STM32L4_GTIM_CR2_OFFSET, cr2);
- tim_putreg(priv, STM32L4_GTIM_CCMR1_OFFSET, ccmr1);
- tim_putreg(priv, STM32L4_GTIM_CCMR2_OFFSET, ccmr2);
- tim_putreg(priv, STM32L4_GTIM_CCER_OFFSET, ccer);
- tim_putreg(priv, STM32L4_GTIM_EGR_OFFSET, egr);
-
- /* Set the ARR Preload Bit */
-
- tim_modifyreg(priv, STM32L4_GTIM_CR1_OFFSET, 0, GTIM_CR1_ARPE);
-
/* Enable the timer counter */
adc_timstart(priv, true);
@@ -1210,6 +1108,55 @@ static void adc_startconv(FAR struct stm32_dev_s *priv, bool enable)
adc_putreg(priv, STM32L4_ADC_CR_OFFSET, regval);
}
+#ifdef ADC_HAVE_INJECTED
+
+/*****************************************************************************
+ * Name: adc_inj_startconv
+ *
+ * Description:
+ * Start (or stop) the ADC injected conversion process
+ *
+ * Input Parameters:
+ * priv - A reference to the ADC block status
+ * enable - True: Start conversion
+ *
+ * Returned Value:
+ *
+ *****************************************************************************/
+
+static void adc_inj_startconv(FAR struct stm32_dev_s *priv, bool enable)
+{
+ uint32_t regval;
+
+ ainfo("inj enable: %d\n", enable ? 1 : 0);
+
+ if (enable)
+ {
+ /* Start the conversion of regular channels */
+
+ adc_modifyreg(priv, STM32L4_ADC_CR_OFFSET, 0, ADC_CR_JADSTART);
+ }
+ else
+ {
+ regval = adc_getreg(priv, STM32L4_ADC_CR_OFFSET);
+
+ /* Is a conversion ongoing? */
+
+ if ((regval & ADC_CR_JADSTART) != 0)
+ {
+ /* Stop the conversion */
+
+ adc_putreg(priv, STM32L4_ADC_CR_OFFSET, regval | ADC_CR_JADSTP);
+
+ /* Wait for the conversion to stop */
+
+ while ((adc_getreg(priv, STM32L4_ADC_CR_OFFSET) &
+ ADC_CR_JADSTP) != 0);
+ }
+ }
+}
+#endif /* ADC_HAVE_INJECTED */
+
/*****************************************************************************
* Name: adc_rccreset
*
@@ -1429,7 +1376,19 @@ static int adc_setup(FAR struct adc_dev_s *dev)
/* Configuration of the channel conversions */
- adc_set_ch(dev, 0);
+ if (priv->cchannels > 0)
+ {
+ adc_set_ch(dev, 0);
+ }
+
+#ifdef ADC_HAVE_INJECTED
+ /* Configuration of the injected channel conversions */
+
+ if (priv->cjchannels > 0)
+ {
+ adc_inj_set_ch(dev, 0);
+ }
+#endif
/* ADC CCR configuration */
@@ -1472,26 +1431,15 @@ static int adc_setup(FAR struct adc_dev_s *dev)
}
#endif
- /* Set ADEN to wake up the ADC from Power Down. */
-
- adc_enable(priv);
+#ifdef ADC_HAVE_JEXTCFG
+ /* Configure external event for injected group when ADC enabled */
-#ifdef ADC_HAVE_TIMER
- if (priv->tbase != 0)
- {
- ret = adc_timinit(priv);
- if (ret < 0)
- {
- aerr("ERROR: adc_timinit failed: %d\n", ret);
- }
- }
+ adc_jextsel_set(priv, priv->jextcfg);
#endif
- leave_critical_section(flags);
-
- /* Dump regs */
+ /* Set ADEN to wake up the ADC from Power Down. */
- adc_dumpregs(priv);
+ adc_enable(priv);
/* As default conversion is started here.
*
@@ -1504,7 +1452,16 @@ static int adc_setup(FAR struct adc_dev_s *dev)
#ifndef CONFIG_STM32L4_ADC_NO_STARTUP_CONV
/* Start regular conversion */
- adc_startconv(priv, true);
+ if (priv->cchannels > 0)
+ {
+ adc_startconv(priv, true);
+ }
+
+# ifdef ADC_HAVE_INJECTED
+ /* Start injected conversion */
+
+ adc_inj_startconv(priv, true);
+# endif
#endif
/* Enable the ADC interrupt */
@@ -1514,6 +1471,23 @@ static int adc_setup(FAR struct adc_dev_s *dev)
up_enable_irq(priv->irq);
#endif
+ /* Dump regs */
+
+ adc_dumpregs(priv);
+
+#ifdef ADC_HAVE_TIMER
+ if (priv->tbase != 0)
+ {
+ ret = adc_timinit(priv);
+ if (ret < 0)
+ {
+ aerr("ERROR: adc_timinit failed: %d\n", ret);
+ }
+ }
+#endif
+
+ leave_critical_section(flags);
+
return ret;
}
@@ -1570,7 +1544,16 @@ static void adc_rxint(FAR struct adc_dev_s *dev, bool enable)
{
/* Enable end of conversion interrupt */
- regval |= ADC_INT_EOC;
+ if (priv->cchannels > 0)
+ {
+ regval |= ADC_INT_EOC;
+ }
+
+#ifdef ADC_HAVE_INJECTED
+ /* Enable end of sequence injected interrupt */
+
+ regval |= ADC_INT_JEOS;
+#endif
}
else
{
@@ -1630,7 +1613,7 @@ static void adc_sample_time_set(FAR struct adc_dev_s *dev)
* Name: adc_extsel_set
*****************************************************************************/
-#if defined(ADC_HAVE_EXTCFG) || defined(CONFIG_STM32L4_ADC_LL_OPS)
+#ifdef ADC_HAVE_EXTCFG
static int adc_extsel_set(FAR struct stm32_dev_s *priv, uint32_t extcfg)
{
uint32_t exten = 0;
@@ -1640,8 +1623,8 @@ static int adc_extsel_set(FAR struct stm32_dev_s *priv, uint32_t extcfg)
/* Get EXTEN and EXTSEL from input */
- exten = (extcfg & ADC_EXTREG_EXTEN_MASK);
- extsel = (extcfg & ADC_EXTREG_EXTSEL_MASK);
+ exten = (extcfg & ADC_CFGR_EXTEN_MASK);
+ extsel = (extcfg & ADC_CFGR_EXTSEL_MASK);
/* EXTSEL selection: These bits select the external event used
* to trigger the start of conversion of a regular group. NOTE:
@@ -1654,7 +1637,7 @@ static int adc_extsel_set(FAR struct stm32_dev_s *priv, uint32_t extcfg)
if (exten > 0)
{
setbits = (extsel | exten);
- clrbits = (ADC_EXTREG_EXTEN_MASK | ADC_EXTREG_EXTSEL_MASK);
+ clrbits = (ADC_CFGR_EXTEN_MASK | ADC_CFGR_EXTSEL_MASK);
ainfo("Initializing extsel = 0x%08x\n", extsel);
@@ -1668,6 +1651,47 @@ static int adc_extsel_set(FAR struct stm32_dev_s *priv, uint32_t extcfg)
#endif
/*****************************************************************************
+ * Name: adc_jextsel_set
+ *****************************************************************************/
+
+#if defined(ADC_HAVE_JEXTCFG)
+static int adc_jextsel_set(FAR struct stm32_dev_s *priv, uint32_t jextcfg)
+{
+ uint32_t jexten = 0;
+ uint32_t jextsel = 0;
+ uint32_t setbits = 0;
+ uint32_t clrbits = 0;
+
+ /* Get JEXTEN and JEXTSEL from input */
+
+ jexten = (jextcfg & ADC_JSQR_JEXTEN_MASK);
+ jextsel = (jextcfg & ADC_JSQR_JEXTSEL_MASK);
+
+ /* JEXTSEL selection: These bits select the external event used
+ * to trigger the start of conversion of a injected group. NOTE:
+ *
+ * - The position with of the JEXTSEL field varies from one STM32L4 MCU
+ * to another.
+ * - The width of the JEXTSEL field varies from one STM32 MCU to another.
+ */
+
+ if (jexten > 0)
+ {
+ setbits = (jexten | jextsel);
+ clrbits = (ADC_JSQR_JEXTEN_MASK | ADC_JSQR_JEXTSEL_MASK);
+
+ ainfo("Initializing jextsel = 0x%08x\n", jextsel);
+
+ /* Write register */
+
+ adc_modifyreg(priv, STM32L4_ADC_JSQR_OFFSET, clrbits, setbits);
+ }
+
+ return OK;
+}
+#endif
+
+/*****************************************************************************
* Name: adc_dumpregs
*****************************************************************************/
@@ -1690,6 +1714,10 @@ static void adc_dumpregs(FAR struct stm32_dev_s *priv)
ainfo("SMPR1: 0x%08x SMPR2: 0x%08x\n",
adc_getreg(priv, STM32L4_ADC_SMPR1_OFFSET),
adc_getreg(priv, STM32L4_ADC_SMPR2_OFFSET));
+
+#ifdef ADC_HAVE_INJECTED
+ ainfo("JSQR: 0x%08x\n", adc_getreg(priv, STM32L4_ADC_JSQR_OFFSET));
+#endif
}
/*****************************************************************************
@@ -1867,6 +1895,40 @@ static int adc_set_ch(FAR struct adc_dev_s *dev, uint8_t ch)
return OK;
}
+#ifdef ADC_HAVE_INJECTED
+
+/*****************************************************************************
+ * Name: adc_inj_set_ch
+ *****************************************************************************/
+
+static int adc_inj_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 clrbits;
+ uint32_t setbits;
+ int i;
+
+ /* Configure injected sequence length */
+
+ setbits = ADC_JSQR_JL(priv->cjchannels);
+ clrbits = ADC_JSQR_JEXTSEL_MASK | ADC_JSQR_JL_MASK;
+
+ /* Configure injected channels */
+
+ for (i = 0 ; i < priv->cjchannels; i += 1)
+ {
+ setbits |= priv->jchanlist[i] << (ADC_JSQR_JSQ1_SHIFT +
+ ADC_JSQR_JSQ_SHIFT * i);
+ }
+
+ /* Write register */
+
+ adc_modifyreg(priv, STM32L4_ADC_JSQR_OFFSET, clrbits, setbits);
+
+ return OK;
+}
+#endif /* ADC_HAVE_INJECTED */
+
/*****************************************************************************
* Name: adc_ioctl
*
@@ -1892,7 +1954,23 @@ static int adc_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg)
switch (cmd)
{
case ANIOC_TRIGGER:
- adc_startconv(priv, true);
+ {
+ /* Start regular conversion if regular channels configured */
+
+ if (priv->cchannels > 0)
+ {
+ adc_startconv(priv, true);
+ }
+
+#ifdef ADC_HAVE_INJECTED
+ /* Start injected conversion if injected channels configured */
+
+ if (priv->cjchannels > 0)
+ {
+ adc_inj_startconv(priv, true);
+ }
+#endif
+ }
break;
case ANIOC_WDOG_UPPER: /* Set watchdog upper threshold */
@@ -1945,6 +2023,30 @@ static int adc_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg)
}
break;
+ case ANIOC_STM32L4_TRIGGER_REG:
+
+ /* Start regular conversion if regular channels configured */
+
+ if (priv->cchannels > 0)
+ {
+ adc_startconv(priv, true);
+ }
+
+ break;
+
+#ifdef ADC_HAVE_INJECTED
+ case ANIOC_STM32L4_TRIGGER_INJ:
+
+ /* Start injected conversion if injected channels configured */
+
+ if (priv->cjchannels > 0)
+ {
+ adc_inj_startconv(priv, true);
+ }
+
+ break;
+#endif
+
default:
aerr("ERROR: Unknown cmd: %d\n", cmd);
ret = -ENOTTY;
@@ -1972,6 +2074,9 @@ static int adc_interrupt(FAR struct adc_dev_s *dev, uint32_t adcisr)
{
FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
int32_t value;
+#ifdef ADC_HAVE_INJECTED
+ int32_t i;
+#endif
/* Identifies the interruption AWD or OVR */
@@ -2034,6 +2139,25 @@ static int adc_interrupt(FAR struct adc_dev_s *dev, uint32_t adcisr)
}
}
+ /* JEOS: Injected end of sequence */
+
+#ifdef ADC_HAVE_INJECTED
+ if ((adcisr & ADC_INT_JEOS) != 0)
+ {
+ for (i = 0; i < priv->cjchannels; i++)
+ {
+ value = adc_getreg(priv, STM32L4_ADC_JDR1_OFFSET + (4 * i)) &
+ ADC_JDR_MASK;
+
+ if (priv->cb != NULL)
+ {
+ DEBUGASSERT(priv->cb->au_receive != NULL);
+ priv->cb->au_receive(dev, priv->jchanlist[i], value);
+ }
+ }
+ }
+#endif
+
return OK;
}
@@ -2341,6 +2465,20 @@ static int adc_llops_offset_set(FAR struct stm32_adc_dev_s *dev, uint8_t ch,
}
/*****************************************************************************
+ * Name: adc_llops_jextsel_set
+ *****************************************************************************/
+
+#ifdef ADC_HAVE_JEXTCFG
+static void adc_llops_jextsel_set(FAR struct stm32_adc_dev_s *dev,
+ uint32_t jextcfg)
+{
+ FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev;
+
+ adc_jextsel_set(priv, jextcfg);
+}
+#endif
+
+/*****************************************************************************
* Name: adc_regbufregister
*****************************************************************************/
@@ -2368,6 +2506,7 @@ static int adc_regbufregister(FAR struct stm32_adc_dev_s *dev,
* Name: adc_llops_extsel_set
*****************************************************************************/
+#ifdef ADC_HAVE_EXTCFG
static int adc_llops_extsel_set(FAR struct stm32_adc_dev_s *dev,
uint32_t extcfg)
{
@@ -2377,6 +2516,46 @@ static int adc_llops_extsel_set(FAR struct stm32_adc_dev_s *dev,
return ret;
}
+#endif
+
+/*****************************************************************************
+ * Name: adc_llops_injget
+ *****************************************************************************/
+
+#ifdef ADC_HAVE_INJECTED
+static uint32_t adc_llops_injget(FAR struct stm32_adc_dev_s *dev,
+ uint8_t chan)
+{
+ FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev;
+ uint32_t regval = 0;
+
+ if (chan > priv->cjchannels - 1)
+ {
+ /* REVISIT: return valute with MSB set to indicate error ? */
+
+ goto errout;
+ }
+
+ regval = adc_getreg(priv, STM32L4_ADC_JDR1_OFFSET + (4 * chan)) &
+ ADC_JDR_MASK;
+
+errout:
+ return regval;
+}
+
+/*****************************************************************************
+ * Name: adc_llops_inj_startconv
+ *****************************************************************************/
+
+static void adc_llops_inj_startconv(FAR struct stm32_adc_dev_s *dev,
+ bool enable)
+{
+ FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev;
+
+ adc_inj_startconv(priv, enable);
+}
+
+#endif /* ADC_HAVE_INJECTED */
/*****************************************************************************
* Name: adc_llops_dumpregs
@@ -2401,20 +2580,42 @@ static void adc_llops_dumpregs(FAR struct stm32_adc_dev_s *dev)
* 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
+ * The logic allow initialize ADC regular and injected channels.
+ *
+ * The number of injected channels for given ADC is selected from Kconfig
+ * with CONFIG_STM32L4_ADCx_INJECTED_CHAN definitions
+ *
+ * The number of regular channels is obtained from the equation:
+ *
+ * cr_channels = channels - cj_channels
+ *
+ * where:
+ * cr_channels - regular channels
+ * cj_channels - injected channels
+ * channels - this function parameter
+ *
+ * The chanlist array store both regular channels and injected channels
+ * configuration so that regular channels are the first in order:
+ *
+ * # regular channels start from here
+ * chanlist[0] -> ADC_SQRx_SQ1
+ * chanlist[1] -> ADC_SQRx_SQ2
* ...
- * chanlist[15]-> ADC_SQR1_SQ16
+ * # injected channels start from here
+ * chanlist[channels - (y - 1)] -> ADC_JSQR_JSQ1
+ * ...
+ * chanlist[channels] -> ADC_JSQR_ISQy
+ *
+ * where:
+ * y = CONFIG_STM32L4_ADCx_INJECTED_CHAN, and y > 0
*
- * up to
- * chanlist[nchannels]
+ * If CONFIG_STM32L4_ADCx_INJECTED_CHAN = 0, then all channels from chanlist
+ * are regular channels.
*
* Input Parameters:
- * intf - Could be {1,2,3} for ADC1, ADC2, or ADC3
- * chanlist - The list of channels
- * cchannels - Number of channels
+ * intf - Could be {1,2,3,4} for ADC1, ADC2, ADC3 or ADC4
+ * chanlist - The list of channels (regular + injected)
+ * channels - Number of channels (regular + injected)
*
* Returned Value:
* Valid ADC device structure reference on success; a NULL on failure
@@ -2426,28 +2627,70 @@ struct adc_dev_s *stm32l4_adc_initialize(int intf, FAR
{
FAR struct adc_dev_s *dev;
FAR struct stm32_dev_s *priv;
-
- ainfo("intf: %d cchannels: %d\n", intf, cchannels);
+ uint8_t crchannels = 0;
+ uint8_t cjchannels = 0;
+#ifdef ADC_HAVE_INJECTED
+ FAR uint8_t *jchanlist = NULL;
+#endif
switch (intf)
{
#ifdef CONFIG_STM32L4_ADC1
case 1:
- ainfo("ADC1 selected\n");
- dev = &g_adcdev1;
- break;
+ {
+ ainfo("ADC1 selected\n");
+ cjchannels = CONFIG_STM32L4_ADC1_INJ_CHAN;
+ crchannels = cchannels - cjchannels;
+ ainfo(" Reg. chan: %d Inj chan: %d\n", crchannels, cjchannels);
+# ifdef ADC_HAVE_INJECTED
+ if (cjchannels > 0)
+ {
+ jchanlist = (FAR uint8_t *)chanlist + crchannels;
+ }
+
+# endif
+ dev = &g_adcdev1;
+ }
+
+ break;
#endif
#ifdef CONFIG_STM32L4_ADC2
case 2:
- ainfo("ADC2 selected\n");
- dev = &g_adcdev2;
- break;
+ {
+ ainfo("ADC2 selected\n");
+ cjchannels = CONFIG_STM32L4_ADC2_INJ_CHAN;
+ crchannels = cchannels - cjchannels;
+ ainfo(" Reg. chan: %d Inj chan: %d\n", crchannels, cjchannels);
+# ifdef ADC_HAVE_INJECTED
+ if (cjchannels > 0)
+ {
+ jchanlist = (FAR uint8_t *)chanlist + crchannels;
+ }
+
+# endif
+ dev = &g_adcdev2;
+ }
+
+ break;
#endif
#ifdef CONFIG_STM32L4_ADC3
case 3:
- ainfo("ADC3 selected\n");
- dev = &g_adcdev3;
- break;
+ {
+ ainfo("ADC3 selected\n");
+ cjchannels = CONFIG_STM32L4_ADC3_INJ_CHAN;
+ crchannels = cchannels - cjchannels;
+ ainfo(" Reg. chan: %d Inj chan: %d\n", crchannels, cjchannels);
+# ifdef ADC_HAVE_INJECTED
+ if (cjchannels > 0)
+ {
+ jchanlist = (FAR uint8_t *)chanlist + crchannels;
+ }
+
+# endif
+ dev = &g_adcdev3;
+ }
+
+ break;
#endif
default:
aerr("ERROR: No ADC interface defined\n");
@@ -2458,18 +2701,28 @@ struct adc_dev_s *stm32l4_adc_initialize(int intf, FAR
priv = (FAR struct stm32_dev_s *)dev->ad_priv;
-#ifndef CONFIG_STM32L4_ADC_NOIRQ
- priv->cb = NULL;
-#endif
-
- DEBUGASSERT(cchannels <= ADC_MAX_SAMPLES);
- if (cchannels > ADC_MAX_SAMPLES)
+ DEBUGASSERT(crchannels <= ADC_MAX_SAMPLES);
+ if (crchannels > ADC_MAX_SAMPLES)
{
- cchannels = ADC_MAX_SAMPLES;
+ crchannels = ADC_MAX_SAMPLES;
}
- priv->cchannels = cchannels;
- memcpy(priv->chanlist, chanlist, cchannels);
+ priv->cchannels = crchannels;
+ memcpy(priv->chanlist, chanlist, crchannels);
+
+#ifdef ADC_HAVE_INJECTED
+ /* Configure injected channels */
+
+ DEBUGASSERT(cjchannels <= ADC_INJ_MAX_SAMPLES);
+
+ priv->cjchannels = cjchannels;
+ memcpy(priv->jchanlist, jchanlist, cjchannels);
+
+#endif
+
+#ifndef CONFIG_STM32L4_ADC_NOIRQ
+ priv->cb = NULL;
+#endif
#ifdef CONFIG_PM
if (pm_register(&priv->pm_callback) != OK)
diff --git a/arch/arm/src/stm32l4/stm32l4_adc.h b/arch/arm/src/stm32l4/stm32l4_adc.h
index eecc455..61d66a8 100644
--- a/arch/arm/src/stm32l4/stm32l4_adc.h
+++ b/arch/arm/src/stm32l4/stm32l4_adc.h
@@ -161,6 +161,14 @@
# undef ADC3_HAVE_DMA
#endif
+/* Injected channels support */
+
+#if (defined(CONFIG_STM32L4_ADC1) && (CONFIG_STM32L4_ADC1_INJ_CHAN > 0)) || \
+ (defined(CONFIG_STM32L4_ADC2) && (CONFIG_STM32L4_ADC2_INJ_CHAN > 0)) || \
+ (defined(CONFIG_STM32L4_ADC3) && (CONFIG_STM32L4_ADC3_INJ_CHAN > 0))
+# define ADC_HAVE_INJECTED
+#endif
+
/* Timer configuration: If a timer trigger is specified, then get
* information about the timer.
*/
@@ -169,30 +177,37 @@
# define ADC1_HAVE_TIMER 1
# define ADC1_TIMER_BASE STM32L4_TIM1_BASE
# define ADC1_TIMER_PCLK_FREQUENCY STM32L4_APB2_TIM1_CLKIN
+# define ADC1_TIMER_CHANNEL CONFIG_STM32L4_TIM1_ADC_CHAN
#elif defined(CONFIG_STM32L4_TIM2_ADC1)
# define ADC1_HAVE_TIMER 1
# define ADC1_TIMER_BASE STM32L4_TIM2_BASE
# define ADC1_TIMER_PCLK_FREQUENCY STM32L4_APB1_TIM2_CLKIN
+# define ADC1_TIMER_CHANNEL CONFIG_STM32L4_TIM2_ADC_CHAN
#elif defined(CONFIG_STM32L4_TIM3_ADC1)
# define ADC1_HAVE_TIMER 1
# define ADC1_TIMER_BASE STM32L4_TIM3_BASE
# define ADC1_TIMER_PCLK_FREQUENCY STM32L4_APB1_TIM3_CLKIN
+# define ADC1_TIMER_CHANNEL CONFIG_STM32L4_TIM3_ADC_CHAN
#elif defined(CONFIG_STM32L4_TIM4_ADC1)
# define ADC1_HAVE_TIMER 1
# define ADC1_TIMER_BASE STM32L4_TIM4_BASE
# define ADC1_TIMER_PCLK_FREQUENCY STM32L4_APB1_TIM4_CLKIN
+# define ADC1_TIMER_CHANNEL CONFIG_STM32L4_TIM4_ADC_CHAN
#elif defined(CONFIG_STM32L4_TIM6_ADC1)
# define ADC1_HAVE_TIMER 1
# define ADC1_TIMER_BASE STM32L4_TIM6_BASE
# define ADC1_TIMER_PCLK_FREQUENCY STM32L4_APB1_TIM6_CLKIN
+# define ADC1_TIMER_CHANNEL CONFIG_STM32L4_TIM6_ADC_CHAN
#elif defined(CONFIG_STM32L4_TIM8_ADC1)
# define ADC1_HAVE_TIMER 1
# define ADC1_TIMER_BASE STM32L4_TIM8_BASE
# define ADC1_TIMER_PCLK_FREQUENCY STM32L4_APB2_TIM8_CLKIN
+# define ADC1_TIMER_CHANNEL CONFIG_STM32L4_TIM8_ADC_CHAN
#elif defined(CONFIG_STM32L4_TIM15_ADC1)
# define ADC1_HAVE_TIMER 1
# define ADC1_TIMER_BASE STM32L4_TIM15_BASE
# define ADC1_TIMER_PCLK_FREQUENCY STM32L4_APB2_TIM15_CLKIN
+# define ADC1_TIMER_CHANNEL CONFIG_STM32L4_TIM15_ADC_CHAN
#else
# undef ADC1_HAVE_TIMER
#endif
@@ -211,30 +226,37 @@
# define ADC2_HAVE_TIMER 1
# define ADC2_TIMER_BASE STM32L4_TIM1_BASE
# define ADC2_TIMER_PCLK_FREQUENCY STM32L4_APB2_TIM1_CLKIN
+# define ADC2_TIMER_CHANNEL CONFIG_STM32L4_TIM1_ADC_CHAN
#elif defined(CONFIG_STM32L4_TIM2_ADC2)
# define ADC2_HAVE_TIMER 1
# define ADC2_TIMER_BASE STM32L4_TIM2_BASE
# define ADC2_TIMER_PCLK_FREQUENCY STM32L4_APB1_TIM2_CLKIN
+# define ADC2_TIMER_CHANNEL CONFIG_STM32L4_TIM2_ADC_CHAN
#elif defined(CONFIG_STM32L4_TIM3_ADC2)
# define ADC2_HAVE_TIMER 1
# define ADC2_TIMER_BASE STM32L4_TIM3_BASE
# define ADC2_TIMER_PCLK_FREQUENCY STM32L4_APB1_TIM3_CLKIN
+# define ADC2_TIMER_CHANNEL CONFIG_STM32L4_TIM3_ADC_CHAN
#elif defined(CONFIG_STM32L4_TIM4_ADC2)
# define ADC2_HAVE_TIMER 1
# define ADC2_TIMER_BASE STM32L4_TIM4_BASE
# define ADC2_TIMER_PCLK_FREQUENCY STM32L4_APB1_TIM4_CLKIN
+# define ADC2_TIMER_CHANNEL CONFIG_STM32L4_TIM4_ADC_CHAN
#elif defined(CONFIG_STM32L4_TIM6_ADC2)
# define ADC2_HAVE_TIMER 1
# define ADC2_TIMER_BASE STM32L4_TIM6_BASE
# define ADC2_TIMER_PCLK_FREQUENCY STM32L4_APB1_TIM6_CLKIN
+# define ADC2_TIMER_CHANNEL CONFIG_STM32L4_TIM6_ADC_CHAN
#elif defined(CONFIG_STM32L4_TIM8_ADC2)
# define ADC2_HAVE_TIMER 1
# define ADC2_TIMER_BASE STM32L4_TIM8_BASE
# define ADC2_TIMER_PCLK_FREQUENCY STM32L4_APB2_TIM8_CLKIN
+# define ADC2_TIMER_CHANNEL CONFIG_STM32L4_TIM8_ADC_CHAN
#elif defined(CONFIG_STM32L4_TIM15_ADC2)
# define ADC2_HAVE_TIMER 1
# define ADC2_TIMER_BASE STM32L4_TIM15_BASE
# define ADC2_TIMER_PCLK_FREQUENCY STM32L4_APB2_TIM15_CLKIN
+# define ADC2_TIMER_CHANNEL CONFIG_STM32L4_TIM15_ADC_CHAN
#else
# undef ADC2_HAVE_TIMER
#endif
@@ -253,30 +275,37 @@
# define ADC3_HAVE_TIMER 1
# define ADC3_TIMER_BASE STM32L4_TIM1_BASE
# define ADC3_TIMER_PCLK_FREQUENCY STM32L4_APB2_TIM1_CLKIN
+# define ADC3_TIMER_CHANNEL CONFIG_STM32L4_TIM1_ADC_CHAN
#elif defined(CONFIG_STM32L4_TIM2_ADC3)
# define ADC3_HAVE_TIMER 1
# define ADC3_TIMER_BASE STM32L4_TIM2_BASE
# define ADC3_TIMER_PCLK_FREQUENCY STM32L4_APB1_TIM2_CLKIN
+# define ADC3_TIMER_CHANNEL CONFIG_STM32L4_TIM1_ADC_CHAN
#elif defined(CONFIG_STM32L4_TIM3_ADC3)
# define ADC3_HAVE_TIMER 1
# define ADC3_TIMER_BASE STM32L4_TIM3_BASE
# define ADC3_TIMER_PCLK_FREQUENCY STM32L4_APB1_TIM3_CLKIN
+# define ADC3_TIMER_CHANNEL CONFIG_STM32L4_TIM3_ADC_CHAN
#elif defined(CONFIG_STM32L4_TIM4_ADC3)
# define ADC3_HAVE_TIMER 1
# define ADC3_TIMER_BASE STM32L4_TIM4_BASE
# define ADC3_TIMER_PCLK_FREQUENCY STM32L4_APB1_TIM4_CLKIN
+# define ADC3_TIMER_CHANNEL CONFIG_STM32L4_TIM4_ADC_CHAN
#elif defined(CONFIG_STM32L4_TIM6_ADC3)
# define ADC3_HAVE_TIMER 1
# define ADC3_TIMER_BASE STM32L4_TIM6_BASE
# define ADC3_TIMER_PCLK_FREQUENCY STM32L4_APB1_TIM6_CLKIN
+# define ADC3_TIMER_CHANNEL CONFIG_STM32L4_TIM6_ADC_CHAN
#elif defined(CONFIG_STM32L4_TIM8_ADC3)
# define ADC3_HAVE_TIMER 1
# define ADC3_TIMER_BASE STM32L4_TIM8_BASE
# define ADC3_TIMER_PCLK_FREQUENCY STM32L4_APB2_TIM8_CLKIN
+# define ADC3_TIMER_CHANNEL CONFIG_STM32L4_TIM8_ADC_CHAN
#elif defined(CONFIG_STM32L4_TIM15_ADC3)
# define ADC3_HAVE_TIMER 1
# define ADC3_TIMER_BASE STM32L4_TIM15_BASE
# define ADC3_TIMER_PCLK_FREQUENCY STM32L4_APB2_TIM15_CLKIN
+# define ADC3_TIMER_CHANNEL CONFIG_STM32L4_TIM15_ADC_CHAN
#else
# undef ADC3_HAVE_TIMER
#endif
@@ -426,7 +455,13 @@
/* EXTSEL configuration ******************************************************/
-/* Configure external event for regular group */
+/* ADCx_EXTSEL_VALUE can be set by this driver or by board specific logic in
+ * board.h file.
+ */
+
+#ifndef ADC_EXTREG_EXTEN_DEFAULT
+# define ADC_EXTREG_EXTEN_DEFAULT ADC_CFGR_EXTEN_RISING
+#endif
#if defined(CONFIG_STM32L4_TIM1_ADC1)
# if CONFIG_STM32L4_ADC1_TIMTRIG == 0
@@ -740,10 +775,306 @@
# endif
#endif
+#ifdef ADC1_EXTSEL_VALUE
+# define ADC1_HAVE_EXTCFG 1
+# define ADC1_EXTCFG_VALUE (ADC1_EXTSEL_VALUE | ADC_EXTREG_EXTEN_DEFAULT)
+#else
+# undef ADC1_HAVE_EXTCFG
+#endif
+#ifdef ADC2_EXTSEL_VALUE
+# define ADC2_HAVE_EXTCFG 1
+# define ADC2_EXTCFG_VALUE (ADC2_EXTSEL_VALUE | ADC_EXTREG_EXTEN_DEFAULT)
+#else
+# undef ADC2_HAVE_EXTCFG
+#endif
+#ifdef ADC3_EXTSEL_VALUE
+# define ADC3_HAVE_EXTCFG 1
+# define ADC3_EXTCFG_VALUE (ADC3_EXTSEL_VALUE | ADC_EXTREG_EXTEN_DEFAULT)
+#else
+# undef ADC3_HAVE_EXTCFG
+#endif
+
+#if defined(ADC1_HAVE_EXTCFG) || defined(ADC2_HAVE_EXTCFG) || \
+ defined(ADC3_HAVE_EXTCFG) || defined(ADC3_HAVE_EXTCFG)
+# define ADC_HAVE_EXTCFG
+#endif
+
+/* JEXTSEL configuration *****************************************************/
+
+#ifndef ADC_JEXTREG_JEXTEN_DEFAULT
+# define ADC_JEXTREG_JEXTEN_DEFAULT ADC_JSQR_JEXTEN_RISING
+#endif
+
+#if (CONFIG_STM32L4_ADC1_INJ_CHAN > 0) && defined(CONFIG_STM32L4_TIM1)
+# if CONFIG_STM32L4_ADC1_JTIMTRIG == 3
+# define ADC1_JEXTSEL_VALUE ADC_JEXTSEL_T1CC4
+# elif CONFIG_STM32L4_ADC1_JTIMTRIG == 4
+# define ADC1_JEXTSEL_VALUE ADC_JEXTSEL_T1TRGO
+# elif CONFIG_STM32L4_ADC1_JTIMTRIG == 5
+# define ADC1_JEXTSEL_VALUE ADC_JEXTSEL_T1TRGO2
+# else
+# error "CONFIG_STM32L4_ADC1_TIMTRIG is out of range"
+# endif
+#endif
+
+#if (CONFIG_STM32L4_ADC1_INJ_CHAN > 0) && defined(CONFIG_STM32L4_TIM2)
+# if CONFIG_STM32L4_ADC1_JTIMTRIG == 0
+# define ADC1_JEXTSEL_VALUE ADC_JEXTSEL_T2CC1
+# elif CONFIG_STM32L4_ADC1_JTIMTRIG == 4
+# define ADC1_JEXTSEL_VALUE ADC_JEXTSEL_T2TRGO
+# else
+# error "CONFIG_STM32L4_ADC1_TIMTRIG is out of range"
+# endif
+#endif
+
+#if (CONFIG_STM32L4_ADC1_INJ_CHAN > 0) && defined(CONFIG_STM32L4_TIM3)
+# if CONFIG_STM32L4_ADC1_JTIMTRIG == 0
+# define ADC1_JEXTSEL_VALUE ADC_JEXTSEL_T3CC1
+# elif CONFIG_STM32L4_ADC1_JTIMTRIG == 2
+# define ADC1_JEXTSEL_VALUE ADC_JEXTSEL_T3CC3
+# elif CONFIG_STM32L4_ADC1_JTIMTRIG == 3
+# define ADC1_JEXTSEL_VALUE ADC_JEXTSEL_T3CC4
+# elif CONFIG_STM32L4_ADC1_JTIMTRIG == 4
+# define ADC1_JEXTSEL_VALUE ADC_JEXTSEL_T3TRGO
+# else
+# error "CONFIG_STM32L4_ADC1_TIMTRIG is out of range"
+# endif
+#endif
+
+#if (CONFIG_STM32L4_ADC1_INJ_CHAN > 0) && defined(CONFIG_STM32L4_TIM4)
+# if CONFIG_STM32L4_ADC1_JTIMTRIG == 4
+# define ADC1_JEXTSEL_VALUE ADC_JEXTSEL_T4TRGO
+# else
+# error "CONFIG_STM32L4_ADC1_TIMTRIG is out of range"
+# endif
+#endif
+
+#if (CONFIG_STM32L4_ADC1_INJ_CHAN > 0) && defined(CONFIG_STM32L4_TIM6)
+# if CONFIG_STM32L4_ADC1_JTIMTRIG == 4
+# define ADC1_JEXTSEL_VALUE ADC_JEXTSEL_T6TRGO
+# else
+# error "CONFIG_STM32L4_ADC1_TIMTRIG is out of range"
+# endif
+#endif
+
+#if (CONFIG_STM32L4_ADC1_INJ_CHAN > 0) && defined(CONFIG_STM32L4_TIM8)
+# if CONFIG_STM32L4_ADC1_JTIMTRIG == 3
+# define ADC1_JEXTSEL_VALUE ADC_JEXTSEL_T8CC4
+# elif CONFIG_STM32L4_ADC1_JTIMTRIG == 4
+# define ADC1_JEXTSEL_VALUE ADC_JEXTSEL_T8TRGO
+# elif CONFIG_STM32L4_ADC1_JTIMTRIG == 5
+# define ADC1_JEXTSEL_VALUE ADC_JEXTSEL_T8TRGO2
+# else
+# error "CONFIG_STM32L4_ADC1_TIMTRIG is out of range"
+# endif
+#endif
+
+#if (CONFIG_STM32L4_ADC1_INJ_CHAN > 0) && defined(CONFIG_STM32L4_TIM15)
+# if CONFIG_STM32L4_ADC1_JTIMTRIG == 4
+# define ADC1_JEXTSEL_VALUE ADC_JEXTSEL_T15TRGO
+# else
+# error "CONFIG_STM32L4_ADC1_TIMTRIG is out of range"
+# endif
+#endif
+
+#ifdef ADC1_JEXTSEL_VALUE
+# define ADC1_HAVE_JEXTCFG 1
+# define ADC1_JEXTCFG_VALUE (ADC1_JEXTSEL_VALUE | ADC_JEXTREG_JEXTEN_DEFAULT)
+#endif
+
+#ifdef CONFIG_STM32L4_ADC2
+#if (CONFIG_STM32L4_ADC2_INJ_CHAN > 0) && defined(CONFIG_STM32L4_TIM1)
+# if CONFIG_STM32L4_ADC2_JTIMTRIG == 3
+# define ADC2_JEXTSEL_VALUE ADC_JEXTSEL_T1CC4
+# elif CONFIG_STM32L4_ADC2_JTIMTRIG == 4
+# define ADC2_JEXTSEL_VALUE ADC_JEXTSEL_T1TRGO
+# elif CONFIG_STM32L4_ADC2_JTIMTRIG == 5
+# define ADC2_JEXTSEL_VALUE ADC_JEXTSEL_T1TRGO2
+# else
+# error "CONFIG_STM32L4_ADC2_TIMTRIG is out of range"
+# endif
+#endif
+#endif
+
+#ifdef CONFIG_STM32L4_ADC2
+#if (CONFIG_STM32L4_ADC2_INJ_CHAN > 0) && defined(CONFIG_STM32L4_TIM2)
+# if CONFIG_STM32L4_ADC2_JTIMTRIG == 0
+# define ADC2_JEXTSEL_VALUE ADC_JEXTSEL_T2CC1
+# elif CONFIG_STM32L4_ADC2_JTIMTRIG == 4
+# define ADC2_JEXTSEL_VALUE ADC_JEXTSEL_T2TRGO
+# else
+# error "CONFIG_STM32L4_ADC2_TIMTRIG is out of range"
+# endif
+#endif
+#endif
+
+#ifdef CONFIG_STM32L4_ADC2
+#if (CONFIG_STM32L4_ADC2_INJ_CHAN > 0) && defined(CONFIG_STM32L4_TIM3)
+# if CONFIG_STM32L4_ADC2_JTIMTRIG == 0
+# define ADC2_JEXTSEL_VALUE ADC_JEXTSEL_T3CC1
+# elif CONFIG_STM32L4_ADC2_JTIMTRIG == 2
+# define ADC2_JEXTSEL_VALUE ADC_JEXTSEL_T3CC3
+# elif CONFIG_STM32L4_ADC2_JTIMTRIG == 3
+# define ADC2_JEXTSEL_VALUE ADC_JEXTSEL_T3CC4
+# elif CONFIG_STM32L4_ADC2_JTIMTRIG == 4
+# define ADC2_JEXTSEL_VALUE ADC_JEXTSEL_T3TRGO
+# else
+# error "CONFIG_STM32L4_ADC2_TIMTRIG is out of range"
+# endif
+#endif
+#endif
+
+#ifdef CONFIG_STM32L4_ADC2
+#if (CONFIG_STM32L4_ADC2_INJ_CHAN > 0) && defined(CONFIG_STM32L4_TIM4)
+# if CONFIG_STM32L4_ADC2_JTIMTRIG == 4
+# define ADC2_JEXTSEL_VALUE ADC_JEXTSEL_T4TRGO
+# else
+# error "CONFIG_STM32L4_ADC2_TIMTRIG is out of range"
+# endif
+#endif
+#endif
+
+#ifdef CONFIG_STM32L4_ADC2
+#if (CONFIG_STM32L4_ADC2_INJ_CHAN > 0) && defined(CONFIG_STM32L4_TIM6)
+# if CONFIG_STM32L4_ADC2_JTIMTRIG == 4
+# define ADC2_JEXTSEL_VALUE ADC_JEXTSEL_T6TRGO
+# else
+# error "CONFIG_STM32L4_ADC2_TIMTRIG is out of range"
+# endif
+#endif
+#endif
+
+#ifdef CONFIG_STM32L4_ADC2
+#if (CONFIG_STM32L4_ADC2_INJ_CHAN > 0) && defined(CONFIG_STM32L4_TIM8)
+# if CONFIG_STM32L4_ADC2_JTIMTRIG == 3
+# define ADC2_JEXTSEL_VALUE ADC_JEXTSEL_T8CC4
+# elif CONFIG_STM32L4_ADC2_JTIMTRIG == 4
+# define ADC2_JEXTSEL_VALUE ADC_JEXTSEL_T8TRGO
+# elif CONFIG_STM32L4_ADC2_JTIMTRIG == 5
+# define ADC2_JEXTSEL_VALUE ADC_JEXTSEL_T8TRGO2
+# else
+# error "CONFIG_STM32L4_ADC2_TIMTRIG is out of range"
+# endif
+#endif
+#endif
+
+#ifdef CONFIG_STM32L4_ADC2
+#if (CONFIG_STM32L4_ADC2_INJ_CHAN > 0) && defined(CONFIG_STM32L4_TIM15)
+# if CONFIG_STM32L4_ADC2_JTIMTRIG == 4
+# define ADC2_JEXTSEL_VALUE ADC_JEXTSEL_T15TRGO
+# else
+# error "CONFIG_STM32L4_ADC2_TIMTRIG is out of range"
+# endif
+#endif
+#endif
+
+#ifdef ADC2_JEXTSEL_VALUE
+# define ADC2_HAVE_JEXTCFG 1
+# define ADC2_JEXTCFG_VALUE (ADC2_JEXTSEL_VALUE | ADC_JEXTREG_JEXTEN_DEFAULT)
+#endif
+
+#ifdef CONFIG_STM32L4_ADC3
+#if (CONFIG_STM32L4_ADC3_INJ_CHAN > 0) && defined(CONFIG_STM32L4_TIM1)
+# if CONFIG_STM32L4_ADC3_JTIMTRIG == 3
+# define ADC3_JEXTSEL_VALUE ADC_JEXTSEL_T1CC4
+# elif CONFIG_STM32L4_ADC3_JTIMTRIG == 4
+# define ADC3_JEXTSEL_VALUE ADC_JEXTSEL_T1TRGO
+# elif CONFIG_STM32L4_ADC3_JTIMTRIG == 5
+# define ADC3_JEXTSEL_VALUE ADC_JEXTSEL_T1TRGO2
+# else
+# error "CONFIG_STM32L4_ADC3_TIMTRIG is out of range"
+# endif
+#endif
+#endif
+
+#ifdef CONFIG_STM32L4_ADC3
+#if (CONFIG_STM32L4_ADC3_INJ_CHAN > 0) && defined(CONFIG_STM32L4_TIM2)
+# if CONFIG_STM32L4_ADC3_JTIMTRIG == 0
+# define ADC3_JEXTSEL_VALUE ADC_JEXTSEL_T2CC1
+# elif CONFIG_STM32L4_ADC3_JTIMTRIG == 4
+# define ADC3_JEXTSEL_VALUE ADC_JEXTSEL_T2TRGO
+# else
+# error "CONFIG_STM32L4_ADC3_TIMTRIG is out of range"
+# endif
+#endif
+#endif
+
+#ifdef CONFIG_STM32L4_ADC3
+#if (CONFIG_STM32L4_ADC3_INJ_CHAN > 0) && defined(CONFIG_STM32L4_TIM3)
+# if CONFIG_STM32L4_ADC3_JTIMTRIG == 0
+# define ADC3_JEXTSEL_VALUE ADC_JEXTSEL_T3CC1
+# elif CONFIG_STM32L4_ADC3_JTIMTRIG == 2
+# define ADC3_JEXTSEL_VALUE ADC_JEXTSEL_T3CC3
+# elif CONFIG_STM32L4_ADC3_JTIMTRIG == 3
+# define ADC3_JEXTSEL_VALUE ADC_JEXTSEL_T3CC4
+# elif CONFIG_STM32L4_ADC3_JTIMTRIG == 4
+# define ADC3_JEXTSEL_VALUE ADC_JEXTSEL_T3TRGO
+# else
+# error "CONFIG_STM32L4_ADC3_TIMTRIG is out of range"
+# endif
+#endif
+#endif
+
+#ifdef CONFIG_STM32L4_ADC3
+#if (CONFIG_STM32L4_ADC3_INJ_CHAN > 0) && defined(CONFIG_STM32L4_TIM4)
+# if CONFIG_STM32L4_ADC3_JTIMTRIG == 4
+# define ADC3_JEXTSEL_VALUE ADC_JEXTSEL_T4TRGO
+# else
+# error "CONFIG_STM32L4_ADC3_TIMTRIG is out of range"
+# endif
+#endif
+#endif
+
+#ifdef CONFIG_STM32L4_ADC3
+#if (CONFIG_STM32L4_ADC3_INJ_CHAN > 0) && defined(CONFIG_STM32L4_TIM6)
+# if CONFIG_STM32L4_ADC3_JTIMTRIG == 4
+# define ADC3_JEXTSEL_VALUE ADC_JEXTSEL_T6TRGO
+# else
+# error "CONFIG_STM32L4_ADC3_TIMTRIG is out of range"
+# endif
+#endif
+#endif
+
+#ifdef CONFIG_STM32L4_ADC3
+#if (CONFIG_STM32L4_ADC3_INJ_CHAN > 0) && defined(CONFIG_STM32L4_TIM8)
+# if CONFIG_STM32L4_ADC3_JTIMTRIG == 3
+# define ADC3_JEXTSEL_VALUE ADC_JEXTSEL_T8CC4
+# elif CONFIG_STM32L4_ADC3_JTIMTRIG == 4
+# define ADC3_JEXTSEL_VALUE ADC_JEXTSEL_T8TRGO
+# elif CONFIG_STM32L4_ADC3_JTIMTRIG == 5
+# define ADC3_JEXTSEL_VALUE ADC_JEXTSEL_T8TRGO2
+# else
+# error "CONFIG_STM32L4_ADC3_TIMTRIG is out of range"
+# endif
+#endif
+#endif
+
+#ifdef CONFIG_STM32L4_ADC3
+#if (CONFIG_STM32L4_ADC3_INJ_CHAN > 0) && defined(CONFIG_STM32L4_TIM15)
+# if CONFIG_STM32L4_ADC3_JTIMTRIG == 4
+# define ADC3_JEXTSEL_VALUE ADC_JEXTSEL_T15TRGO
+# else
+# error "CONFIG_STM32L4_ADC3_TIMTRIG is out of range"
+# endif
+#endif
+#endif
+
+#ifdef ADC3_JEXTSEL_VALUE
+# define ADC3_HAVE_JEXTCFG 1
+# define ADC3_JEXTCFG_VALUE (ADC3_JEXTSEL_VALUE | ADC_JEXTREG_JEXTEN_DEFAULT)
+#endif
+
+#if defined(ADC1_HAVE_JEXTCFG) || defined(ADC2_HAVE_JEXTCFG) || \
+ defined(ADC3_HAVE_JEXTCFG)
+# define ADC_HAVE_JEXTCFG
+#endif
+
/* ADC interrupts ************************************************************/
#define ADC_ISR_EOC ADC_INT_EOC
#define ADC_IER_EOC ADC_INT_EOC
+#define ADC_ISR_EOS ADC_INT_EOS
+#define ADC_IER_EOS ADC_INT_EOS
#define ADC_ISR_AWD ADC_INT_AWD1
#define ADC_IER_AWD ADC_INT_AWD1
#define ADC_ISR_JEOC ADC_INT_JEOC
@@ -753,10 +1084,10 @@
#define ADC_ISR_JEOS ADC_INT_JEOS
#define ADC_IER_JEOS ADC_INT_JEOS
-#define ADC_ISR_ALLINTS (ADC_ISR_EOC | ADC_ISR_AWD | ADC_ISR_JEOC | \
- ADC_ISR_JEOS | ADC_ISR_OVR)
-#define ADC_IER_ALLINTS (ADC_IER_EOC | ADC_IER_AWD | ADC_IER_JEOC | \
- ADC_IER_JEOS | ADC_IER_OVR)
+#define ADC_ISR_ALLINTS (ADC_ISR_EOC | ADC_ISR_EOS | ADC_ISR_AWD | \
+ ADC_ISR_JEOC | ADC_ISR_JEOS | ADC_ISR_OVR)
+#define ADC_IER_ALLINTS (ADC_IER_EOC | ADC_IER_EOS | ADC_IER_AWD | \
+ ADC_IER_JEOC | ADC_IER_JEOS | ADC_IER_OVR)
/* Low-level ops helpers *****************************************************/
@@ -770,10 +1101,14 @@
(adc)->llops->int_dis(adc, source)
#define ADC_REGDATA_GET(adc) \
(adc)->llops->val_get(adc)
+#define ADC_INJDATA_GET(adc, chan) \
+ (adc)->llops->inj_get(adc, chan)
#define ADC_REGBUF_REGISTER(adc, buffer, len) \
(adc)->llops->regbuf_reg(adc, buffer, len)
#define ADC_REG_STARTCONV(adc, state) \
(adc)->llops->reg_startconv(adc, state)
+#define ADC_INJ_STARTCONV(adc, state) \
+ (adc)->llops->inj_startconv(adc, state)
#define ADC_OFFSET_SET(adc, ch, i, o) \
(adc)->llops->offset_set(adc, ch, i, o)
#define ADC_EXTSEL_SET(adc, extcfg) \
@@ -781,6 +1116,16 @@
#define ADC_DUMP_REGS(adc) \
(adc)->llops->dump_regs(adc)
+/* IOCTL Commands ************************************************************
+ *
+ * Cmd: ANIOC_STM32L4_TRIGGER_REG Arg:
+ * Cmd: ANIOC_STM32L4_TRIGGER_INJ Arg:
+ *
+ */
+
+#define ANIOC_STM32L4_TRIGGER_REG _ANIOC(AN_STM32L4_FIRST + 0)
+#define ANIOC_STM32L4_TRIGGER_INJ _ANIOC(AN_STM32L4_FIRST + 1)
+
/*****************************************************************************
* Public Types
*****************************************************************************/
@@ -842,6 +1187,22 @@ struct stm32_adc_ops_s
int (*extsel_set)(FAR struct stm32_adc_dev_s *dev, uint32_t extcfg);
+#ifdef ADC_HAVE_JEXTCFG
+ /* Configure the ADC external trigger for injected conversion */
+
+ void (*jextsel_set)(FAR struct stm32_adc_dev_s *dev, uint32_t jextcfg);
+#endif
+
+#ifdef ADC_HAVE_INJECTED
+ /* Get current ADC injected data register */
+
+ uint32_t (*inj_get)(FAR struct stm32_adc_dev_s *dev, uint8_t chan);
+
+ /* Start/stop injected conversion */
+
+ void (*inj_startconv)(FAR struct stm32_adc_dev_s *dev, bool state);
+#endif
+
/* Dump ADC regs */
void (*dump_regs)(FAR struct stm32_adc_dev_s *dev);
diff --git a/include/nuttx/analog/ioctl.h b/include/nuttx/analog/ioctl.h
index 92b1988..2527983 100644
--- a/include/nuttx/analog/ioctl.h
+++ b/include/nuttx/analog/ioctl.h
@@ -91,6 +91,11 @@
AN_LMP92001_NCMDS)
#define AN_ADS7828_NCMDS 6
+/* See arch/arm/src/stm32l4/stm32l4_adc.h */
+
+#define AN_STM32L4_FIRST (AN_ADS7828_FIRST + AN_ADS7828_NCMDS)
+#define AN_STM32L4_NCMDS 2
+
/****************************************************************************
* Public Function Prototypes
****************************************************************************/