diff --git a/arch/arm/src/stm32l4/Kconfig b/arch/arm/src/stm32l4/Kconfig index 086616e3a3..e8a831cdac 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 5db9b10cfb..5fa3e9a71a 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 c777ed2521..522dab6352 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 */ - - tim_putreg(priv, STM32L4_GTIM_EGR_OFFSET, GTIM_EGR_UG); - /* Handle channel specific setup */ - ocmode1 = 0; - ocmode2 = 0; + /* Assume that channel is disabled and polarity is active high */ - switch (priv->trigger) + ccer_val = tim_getreg(priv, STM32L4_GTIM_CCER_OFFSET); + ccer_val &= ~(3 << (channel << 2)); + + 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); + + if (channel & 1) { - case 0: /* TimerX CC1 event */ + ccmr_val <<= 8; + ccmr_mask <<= 8; + } + + if (channel > 1) + { + ccmr_offset = STM32L4_GTIM_CCMR2_OFFSET; + } + + 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 */ { - 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, 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 */ + case 3: /* TIMx CC4 */ { - 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 */ - { - /* 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,10 +1431,50 @@ static int adc_setup(FAR struct adc_dev_s *dev) } #endif +#ifdef ADC_HAVE_JEXTCFG + /* Configure external event for injected group when ADC enabled */ + + adc_jextsel_set(priv, priv->jextcfg); +#endif + /* Set ADEN to wake up the ADC from Power Down. */ adc_enable(priv); +/* As default conversion is started here. + * + * NOTE: (J)ADSTART bit must be set to start ADC conversion + * even if hardware trigger is selected. + * This can be done here during the opening of the ADC device + * or later with ANIOC_TRIGGER ioctl call. + */ + +#ifndef CONFIG_STM32L4_ADC_NO_STARTUP_CONV + /* Start regular conversion */ + + 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 */ + +#ifndef CONFIG_STM32L4_ADC_NOIRQ + ainfo("Enable the ADC interrupt: irq=%d\n", priv->irq); + up_enable_irq(priv->irq); +#endif + + /* Dump regs */ + + adc_dumpregs(priv); + #ifdef ADC_HAVE_TIMER if (priv->tbase != 0) { @@ -1489,31 +1488,6 @@ static int adc_setup(FAR struct adc_dev_s *dev) leave_critical_section(flags); - /* Dump regs */ - - adc_dumpregs(priv); - -/* As default conversion is started here. - * - * NOTE: (J)ADSTART bit must be set to start ADC conversion - * even if hardware trigger is selected. - * This can be done here during the opening of the ADC device - * or later with ANIOC_TRIGGER ioctl call. - */ - -#ifndef CONFIG_STM32L4_ADC_NO_STARTUP_CONV - /* Start regular conversion */ - - adc_startconv(priv, true); -#endif - - /* Enable the ADC interrupt */ - -#ifndef CONFIG_STM32L4_ADC_NOIRQ - ainfo("Enable the ADC interrupt: irq=%d\n", priv->irq); - up_enable_irq(priv->irq); -#endif - 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); @@ -1667,6 +1650,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; } @@ -2340,6 +2464,20 @@ static int adc_llops_offset_set(FAR struct stm32_adc_dev_s *dev, uint8_t ch, return ret; } +/***************************************************************************** + * 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 - * ... - * chanlist[15]-> ADC_SQR1_SQ16 + * The logic allow initialize ADC regular and injected channels. * - * up to - * chanlist[nchannels] + * 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 + * ... + * # 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 + * + * 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,19 +2701,29 @@ struct adc_dev_s *stm32l4_adc_initialize(int intf, FAR priv = (FAR struct stm32_dev_s *)dev->ad_priv; + DEBUGASSERT(crchannels <= ADC_MAX_SAMPLES); + if (crchannels > ADC_MAX_SAMPLES) + { + crchannels = ADC_MAX_SAMPLES; + } + + 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 - DEBUGASSERT(cchannels <= ADC_MAX_SAMPLES); - if (cchannels > ADC_MAX_SAMPLES) - { - cchannels = ADC_MAX_SAMPLES; - } - - priv->cchannels = cchannels; - memcpy(priv->chanlist, chanlist, cchannels); - #ifdef CONFIG_PM if (pm_register(&priv->pm_callback) != OK) { diff --git a/arch/arm/src/stm32l4/stm32l4_adc.h b/arch/arm/src/stm32l4/stm32l4_adc.h index eecc4550fd..61d66a819f 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 92b1988bf3..25279839a8 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 ****************************************************************************/