From 52d909d47999bad343d689c300860f2db0eba1c9 Mon Sep 17 00:00:00 2001 From: hendrixgr Date: Mon, 7 Oct 2013 11:18:48 +0300 Subject: [PATCH] [stm32] support for all 3 ADCs of f4 --- sw/airborne/arch/stm32/mcu_periph/adc_arch.c | 761 +++++++++++-------- sw/airborne/arch/stm32/mcu_periph/adc_arch.h | 27 +- 2 files changed, 467 insertions(+), 321 deletions(-) diff --git a/sw/airborne/arch/stm32/mcu_periph/adc_arch.c b/sw/airborne/arch/stm32/mcu_periph/adc_arch.c index b1cb5cd9d65..542687fad13 100644 --- a/sw/airborne/arch/stm32/mcu_periph/adc_arch.c +++ b/sw/airborne/arch/stm32/mcu_periph/adc_arch.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 The Paparazzi Team + * Copyright (C) 2010-2013 The Paparazzi Team * * This file is part of paparazzi. * @@ -17,9 +17,7 @@ * along with paparazzi; see the file COPYING. If not, write to * the Free Software Foundation, 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. - * */ - /** * @file arch/stm32/mcu_periph/adc_arch.c * @ingroup stm32_arch @@ -41,20 +39,20 @@ Table of GPIO pins available per ADC: ADC1/2: ADC3: - C0 -> PA0 C0 -> PA0 - C1 -> PA1 C1 -> PA1 - C2 -> PA2 C2 -> PA2 - C3 -> PA3 C3 -> PA3 - C4 -> PA4 C4 -> PF6 - C5 -> PA5 C5 -> PF7 - C6 -> PA6 C6 -> PF8 - C7 -> PA7 C7 -> PF9 - C8 -> PB0 C8 -> PF10 + C0 -> PA0 C0 -> PA0 + C1 -> PA1 C1 -> PA1 + C2 -> PA2 C2 -> PA2 + C3 -> PA3 C3 -> PA3 + C4 -> PA4 C4 -> PF6 + C5 -> PA5 C5 -> PF7 + C6 -> PA6 C6 -> PF8 + C7 -> PA7 C7 -> PF9 + C8 -> PB0 C8 -> PF10 C9 -> PB1 - C10 -> PC0 C10 -> PC0 - C11 -> PC1 C11 -> PC1 - C12 -> PC2 C12 -> PC2 - C13 -> PC3 C13 -> PC3 + C10 -> PC0 C10 -> PC0 + C11 -> PC1 C11 -> PC1 + C12 -> PC2 C12 -> PC2 + C13 -> PC3 C13 -> PC3 C14 -> PC4 C15 -> PC5 @@ -101,123 +99,404 @@ #include "led.h" #include BOARD_CONFIG -volatile uint8_t adc_new_data_trigger; +/***************************************************************************************************/ +/*************************** DO NOT EDIT - CONVINIENCE MACROS **********************************/ +/***************************************************************************************************/ -/* Static functions */ +// CONVINIENCE MACROS FOR MAKING EDITING SIMPLER - DO NOT EDIT - IT IS NOT NEEDED! -static inline void adc_init_single(uint32_t adc, - uint8_t chan1, uint8_t chan2, - uint8_t chan3, uint8_t chan4); +#if defined(USE_AD1_1) || defined(USE_AD1_2) || defined(USE_AD1_3) || defined(USE_AD1_4) +#if !defined(USE_AD1) +#define USE_AD1 1 +#endif +//#pragma message "Analog to Digital Coverter 1 active" +#endif -static inline void adc_push_sample(struct adc_buf * buf, - uint16_t sample); +#if defined(USE_AD2_1) || defined(USE_AD2_2) || defined(USE_AD2_3) || defined(USE_AD2_4) +#if !defined(USE_AD2) +#define USE_AD2 1 +#endif +//#pragma message "Analog to Digital Coverter 2 active" +#endif -static inline void adc_init_rcc( void ); -static inline void adc_init_irq( void ); +#if defined(USE_AD3_1) || defined(USE_AD3_2) || defined(USE_AD3_3) || defined(USE_AD3_4) +#if !defined(USE_AD3) +#define USE_AD3 1 +#endif +//#pragma message "Analog to Digital Coverter 3 active" +#endif -#ifdef USE_AD2 -#error NOT_IMPLEMENTED__currently_only_ADC1_is_supported +//#if !defined(USE_ADC_1) +#if !defined(ADC_1_GPIO_CLOCK_PORT) +#define ADC_1_GPIO_CLOCK_PORT 0 +#endif +#if !defined(ADC_1_INIT) +#define ADC_1_INIT() {} #endif +//#endif -/* - Only 4 ADC channels may be enabled at the same time - on each ADC, as there are only 4 injection registers. -*/ +//#if !defined(USE_ADC_2) +#if !defined(ADC_2_GPIO_CLOCK_PORT) +#define ADC_2_GPIO_CLOCK_PORT 0 +#endif +#if !defined(ADC_2_INIT) +#define ADC_2_INIT() {} +#endif +//#endif -// ADCx_GPIO_INIT -// {{{ +//#if !defined(USE_ADC_3) +#if !defined(ADC_3_GPIO_CLOCK_PORT) +#define ADC_3_GPIO_CLOCK_PORT 0 +#endif +#if !defined(ADC_3_INIT) +#define ADC_3_INIT() {} +#endif +//#endif -/* - GPIO mapping for ADC1 pins (PB.1, PB.0, PC.5, PC.3). - Can be changed by predefining ADC1_GPIO_INIT. -*/ -#ifdef USE_AD1 -#ifndef ADC1_GPIO_INIT -#define ADC1_GPIO_INIT() { \ - gpio_set_mode(GPIOB, GPIO_MODE_INPUT, \ - GPIO_CNF_INPUT_ANALOG, \ - GPIO1 | GPIO0); \ - gpio_set_mode(GPIOC, GPIO_MODE_INPUT, \ - GPIO_CNF_INPUT_ANALOG, \ - GPIO5 | GPIO3); \ - } -#endif // ADC1_GPIO_INIT -#endif // USE_AD1 +//#if !defined(USE_ADC_4) +#if !defined(ADC_4_GPIO_CLOCK_PORT) +#define ADC_4_GPIO_CLOCK_PORT 0 +#endif +#if !defined(ADC_4_INIT) +#define ADC_4_INIT() {} +#endif +//#endif -/* - GPIO mapping for ADC2 pins. - Can be changed by predefining ADC2_GPIO_INIT. - Uses the same GPIOs as ADC1 (lisa specific). -*/ -#ifdef USE_AD2 -#ifndef ADC2_GPIO_INIT -#define ADC2_GPIO_INIT() { \ - gpio_set_mode(GPIOB, GPIO_MODE_INPUT, \ - GPIO_CNF_INPUT_ANALOG, \ - GPIO1 | GPIO0); \ - gpio_set_mode(GPIOC, GPIO_MODE_INPUT, \ - GPIO_CNF_INPUT_ANALOG, \ - GPIO5 | GPIO3); \ +//#if !defined(USE_ADC_5) +#if !defined(ADC_5_GPIO_CLOCK_PORT) +#define ADC_5_GPIO_CLOCK_PORT 0 +#endif +#if !defined(ADC_5_INIT) +#define ADC_5_INIT() {} +#endif +//#endif + +//#if !defined(USE_ADC_6) +#if !defined(ADC_6_GPIO_CLOCK_PORT) +#define ADC_6_GPIO_CLOCK_PORT 0 +#endif +#if !defined(ADC_6_INIT) +#define ADC_6_INIT() {} +#endif +//#endif + +//#if !defined(USE_ADC_7) +#if !defined(ADC_7_GPIO_CLOCK_PORT) +#define ADC_7_GPIO_CLOCK_PORT 0 +#endif +#if !defined(ADC_7_INIT) +#define ADC_7_INIT() {} +#endif +//#endif + +//#if !defined(USE_ADC_8) +#if !defined(ADC_8_GPIO_CLOCK_PORT) +#define ADC_8_GPIO_CLOCK_PORT 0 +#endif +#if !defined(ADC_8_INIT) +#define ADC_8_INIT() {} +#endif +//#endif + +//#if !defined(USE_ADC_9) +#if !defined(ADC_9_GPIO_CLOCK_PORT) +#define ADC_9_GPIO_CLOCK_PORT 0 +#endif +#if !defined(ADC_9_INIT) +#define ADC_9_INIT() {} +#endif +//#endif + +//#if !defined(USE_ADC_10) +#if !defined(ADC_10_GPIO_CLOCK_PORT) +#define ADC_10_GPIO_CLOCK_PORT 0 +#endif +#if !defined(ADC_10_INIT) +#define ADC_10_INIT() {} +#endif +//#endif + +//#if !defined(USE_ADC_11) +#if !defined(ADC_11_GPIO_CLOCK_PORT) +#define ADC_11_GPIO_CLOCK_PORT 0 +#endif +#if !defined(ADC_11_INIT) +#define ADC_11_INIT() {} +#endif +//#endif + +//#if !defined(USE_ADC_12) +#if !defined(ADC_12_GPIO_CLOCK_PORT) +#define ADC_12_GPIO_CLOCK_PORT 0 +#endif +#if !defined(ADC_12_INIT) +#define ADC_12_INIT() {} +#endif +//#endif + +#if !defined(ADC_GPIO_CLOCK_PORT) +//#undef ADC_GPIO_CLOCK_PORT +#define ADC_GPIO_CLOCK_PORT ( ADC_1_GPIO_CLOCK_PORT | ADC_2_GPIO_CLOCK_PORT | \ + ADC_3_GPIO_CLOCK_PORT | ADC_4_GPIO_CLOCK_PORT | \ + ADC_5_GPIO_CLOCK_PORT | ADC_6_GPIO_CLOCK_PORT | \ + ADC_7_GPIO_CLOCK_PORT | ADC_8_GPIO_CLOCK_PORT | \ + ADC_9_GPIO_CLOCK_PORT | ADC_10_GPIO_CLOCK_PORT | \ + ADC_11_GPIO_CLOCK_PORT | ADC_12_GPIO_CLOCK_PORT \ + ) +#endif + +#if !defined(ADC1_GPIO_INIT) +#define ADC_GPIO_INIT(gpio) { ADC_1_INIT(); ADC_2_INIT(); ADC_3_INIT(); ADC_4_INIT(); \ + ADC_5_INIT(); ADC_6_INIT(); ADC_7_INIT(); ADC_8_INIT(); \ + ADC_9_INIT(); ADC_10_INIT(); ADC_11_INIT(); ADC_12_INIT(); \ } -#endif // ADC2_GPIO_INIT -#endif // USE_AD2 +#endif +#if !defined(USE_AD1) && !defined(USE_AD2) && !defined(USE_AD3) +#error ALL ADC CONVERTERS INACTIVE +#endif -/* - Currently, the enums adc1_channels and adc2_channels only - serve to resolve the number of channels on each ADC. -*/ +/*****************************************************************************************************/ +/********************************* STATIC FUNCTION PROTOTYPES ***********************************/ +/*****************************************************************************************************/ -/* - Separate buffers for each ADC. - Every ADC has a list of buffers, one for each active - channel. -*/ +static inline void adc_init_single(uint32_t adc, uint8_t nb_channels); + +static inline void adc_push_sample(struct adc_buf * buf, + uint16_t sample); + +static inline void adc_init_rcc( void ); +static inline void adc_init_irq( void ); + + +/*****************************************************************************************************/ +/*********************************** GLOBAL VARIABLES ****************************************/ +/*****************************************************************************************************/ + +/* Only 4 ADC channels may be enabled at the same time + * on each ADC, as there are only 4 injection registers. + * Currently, the enums adc1_channels and adc2_channels only + * serve to resolve the number of channels on each ADC. + * There are 3 separate buffer lists, each holds the addresses of the actual adc buffers + * for the particular adc converter. + */ + +volatile uint8_t adc_new_data_trigger; #ifdef USE_AD1 /// List of buffers, one for each active channel. -static struct adc_buf * adc1_buffers[NB_ADC1_CHANNELS]; +static struct adc_buf * adc1_buffers[4]; +uint8_t nb_adc1_channels = 0; #endif -#ifdef USE_AD2 +#if defined(USE_AD2) && defined(STM32F4) /// List of buffers, one for each active channel. -static struct adc_buf * adc2_buffers[NB_ADC2_CHANNELS]; +static struct adc_buf * adc2_buffers[4]; +uint8_t nb_adc2_channels = 0; +#endif +#if defined(USE_AD3) && defined(STM32F4) +/// List of buffers, one for each active channel. +static struct adc_buf * adc3_buffers[4]; +uint8_t nb_adc3_channels = 0; #endif -/** - * Maps integer value x to ADC_InjectedChannel_x. - * so they can be iterated safely - */ -volatile uint32_t *adc_injected_channels[4]; - /** * Maps integer value x to ADC_Channel_y. - * like e.g. - * - 0 --> ADC_Channel_5 - * - 1 --> ADC_Channel_8 - * - 2 --> ADC_Channel_13 - * - * so they can be iterated incrementally. + * so they can be iterated incrementally + * Example: + * 0 --> ADC_Channel_5 + * 1 --> ADC_Channel_8 + * 2 --> ADC_Channel_13 */ static uint8_t adc_channel_map[4]; -/* - TODO: Extend interface to allow adressing a - specific ADC (at least ADC1 and ADC2)? -*/ -void adc_buf_channel(uint8_t adc_channel, - struct adc_buf * s, - uint8_t av_nb_sample) + +/*****************************************************************************************************/ +/******************************** PUBLIC FUNCTION DEFINITIONS ************************************/ +/*****************************************************************************************************/ + +void adc_init( void ) { + + uint8_t x=0; + + adc_init_rcc(); + adc_init_irq(); + + /* If fewer than 4 channels are active, say 3, then they are placed in to + * injection slots 2,3 and 4 because the stm32 architecture converts injected + * slots 2,3 and 4 and skips slot 1 instead of logicaly converting slots 1,2 + * and 3 and leave slot 4. + * EXAMPLE OF ADC EXECUTION ORDER WHEN WE HAVE SAY 2 ADC INPUTS USED on ADC1 + * The first board adc channel ADC1_1 is mapped to injected channel 3 and ADC1_2 + * to injected channel 4 and because the conversions start from the lowest + * injection channel used, 3 in our case, injected channel 3 data wiil be + * located at JDR1 and 4 to JDR2 so JDR1 = ADC1_1 and JDR2 = ADC1_2. + * That's why "adc_channel_map" has this descending order. + */ +#ifdef USE_AD1 + adc_new_data_trigger = FALSE; + x = 3; nb_adc1_channels = 0; +#if defined(BOARD_ADC_CHANNEL_4) // for backwards compatibility + adc_channel_map[x] = BOARD_ADC_CHANNEL_4; + x--; nb_adc1_channels++; +#elif defined(BOARD_ADC1_CHANNEL_4) // for backwards compatibility + adc_channel_map[x] = BOARD_ADC1_CHANNEL_4; + x--; nb_adc1_channels++; +#elif defined(USE_AD1_4) // the new style + adc_channel_map[x] = USE_AD1_4; + x--; nb_adc1_channels++; +#endif +#if defined(BOARD_ADC_CHANNEL_3) + adc_channel_map[x] = BOARD_ADC_CHANNEL_3; + x--; nb_adc1_channels++; + nb_adc1_channels++; +#elif defined(BOARD_ADC1_CHANNEL_3) + adc_channel_map[x] = BOARD_ADC1_CHANNEL_3; + x--; nb_adc1_channels++; +#elif defined(USE_AD1_3) + adc_channel_map[x] = USE_AD1_3; + x--; nb_adc1_channels++; +#endif +#if defined(BOARD_ADC_CHANNEL_2) + adc_channel_map[x] = BOARD_ADC_CHANNEL_2; + x--; nb_adc1_channels++; +#elif defined(BOARD_ADC1_CHANNEL_2) + adc_channel_map[x] = BOARD_ADC1_CHANNEL_2; + x--; nb_adc1_channels++; +#elif defined(USE_AD1_2) + adc_channel_map[x] = USE_AD1_2; + x--; nb_adc1_channels++; +#endif +#if defined(BOARD_ADC_CHANNEL_1) + adc_channel_map[x] = BOARD_ADC_CHANNEL_1; + nb_adc1_channels++; +#elif defined(BOARD_ADC1_CHANNEL_1) + adc_channel_map[x] = BOARD_ADC1_CHANNEL_1; + nb_adc1_channels++; +#elif defined(USE_AD1_1) + adc_channel_map[x] = USE_AD1_1; + nb_adc1_channels++; +#endif + // initialize buffer pointers with 0 (not set). Buffer null pointers will be ignored in interrupt + // handler, which is important as there are no buffers registered at the time the ADC trigger + // interrupt is enabled. + for(x = 0; x < 4; x++){ adc1_buffers[x] = NULL; } + adc_init_single(ADC1, nb_adc1_channels); +#endif // USE_AD1 + + + +#if defined(USE_AD2) && defined(STM32F4) + adc_new_data_trigger = FALSE; + x = 3; nb_adc2_channels = 0; +#if defined(BOARD_ADC2_CHANNEL_4) + adc_channel_map[x] = BOARD_ADC2_CHANNEL_4; + x--; nb_adc2_channels++; +#elif defined(USE_AD2_4) + adc_channel_map[x] = USE_AD2_4; + x--; nb_adc2_channels++; +#endif +#if defined(BOARD_ADC2_CHANNEL_3) + adc_channel_map[x] = BOARD_ADC2_CHANNEL_3; + x--; nb_adc2_channels++; +#elif defined(USE_AD2_3) + adc_channel_map[x] = USE_AD2_3; + x--; nb_adc2_channels++; +#endif +#if defined(BOARD_ADC2_CHANNEL_2) + adc_channel_map[x] = BOARD_ADC2_CHANNEL_2; + x--; nb_adc2_channels++; +#elif defined(USE_AD2_2) + adc_channel_map[x] = USE_AD2_2; + x--; nb_adc2_channels++; +#endif +#if defined(BOARD_ADC2_CHANNEL_1) + adc_channel_map[x] = BOARD_ADC2_CHANNEL_1; + nb_adc2_channels++; +#elif defined(USE_AD2_1) + adc_channel_map[x] = USE_AD2_1; + nb_adc2_channels++; +#endif + // initialize buffer pointers with 0 (not set). Buffer null pointers will be ignored in interrupt + // handler, which is important as there are no buffers registered at the time the ADC trigger + // interrupt is enabled. + for(x = 0; x < 4; x++){ adc2_buffers[x] = NULL; } + adc_init_single(ADC2, nb_adc2_channels); +#endif // USE_AD2 + + + +#if defined(USE_AD3) && defined(STM32F4) + adc_new_data_trigger = FALSE; + x = 3; nb_adc3_channels = 0; +#if defined(BOARD_ADC3_CHANNEL_4) + adc_channel_map[x] = BOARD_ADC3_CHANNEL_4; + x--; nb_adc3_channels++; +#elif defined(USE_AD3_4) + adc_channel_map[x] = USE_AD3_4; + x--; nb_adc3_channels++; +#endif +#if defined(BOARD_ADC3_CHANNEL_3) + adc_channel_map[x] = BOARD_ADC3_CHANNEL_3; + x--; nb_adc3_channels++; +#elif defined(USE_AD3_3) + adc_channel_map[x] = USE_AD3_3; + x--; nb_adc3_channels++; +#endif +#if defined(BOARD_ADC3_CHANNEL_2) + adc_channel_map[x] = BOARD_ADC3_CHANNEL_2; + x--; nb_adc3_channels++; +#elif defined(USE_AD3_2) + adc_channel_map[x] = USE_AD3_2; + x--; nb_adc3_channels++; +#endif +#if defined(BOARD_ADC3_CHANNEL_1) + adc_channel_map[x] = BOARD_ADC3_CHANNEL_1; + nb_adc3_channels++; +#elif defined(USE_AD3_1) + adc_channel_map[x] = USE_AD3_1; + nb_adc3_channels++; +#endif + // initialize buffer pointers with 0 (not set). Buffer null pointers will be ignored in interrupt + // handler, which is important as there are no buffers registered at the time the ADC trigger + // interrupt is enabled. + for(x = 0; x < 4; x++){ adc3_buffers[x] = NULL; } + adc_init_single(ADC3, nb_adc3_channels); +#endif // USE_AD3 + + return; +} + +void adc_buf_channel(uint8_t adc_channel, struct adc_buf * s, uint8_t av_nb_sample) { - adc1_buffers[adc_channel] = s; + + if (adc_channel < nb_adc1_channels){ + adc1_buffers[adc_channel] = s; + } +#if defined(USE_AD2) && defined(STM32F4) + else if (adc_channel < (nb_adc1_channels+nb_adc2_channels)){ + adc2_buffers[adc_channel-nb_adc1_channels] = s; + } +#endif +#if defined(USE_AD3) && defined(STM32F4) + else if (adc_channel < (nb_adc1_channels+nb_adc2_channels+nb_adc3_channels)){ + adc3_buffers[adc_channel-(nb_adc1_channels+nb_adc2_channels)] = s; + } +#endif + s->av_nb_sample = av_nb_sample; + + return; } -// #define USE_AD_TIM4 -/* Configure and enable RCC for peripherals (ADC1, ADC2, Timer) */ +/*****************************************************************************************************/ +/********************************* PRIVATE FUNCTION DEFINITIONS ************************************/ +/*****************************************************************************************************/ + +/** Configure and enable RCC for peripherals (ADC1, ADC2, Timer) */ static inline void adc_init_rcc( void ) { -#if defined (USE_AD1) || defined (USE_AD2) +#if defined(USE_AD1) || (defined(USE_AD2)&&defined(STM32F4)) || (defined(USE_AD3)&&defined(STM32F4)) uint32_t timer; volatile uint32_t *rcc_apbenr; uint32_t rcc_apb; @@ -235,18 +514,6 @@ static inline void adc_init_rcc( void ) rcc_apb = RCC_APB1ENR_TIM2EN; #endif - /* - * Historic Note: - * Previously in libstm32 we were setting the ADC clock here. - * It was being set to PCLK2 DIV2 resulting in 36MHz clock on the ADC. I am - * pretty sure that this is wrong as based on the datasheet the ADC clock - * must not exceed 14MHz! Now the clock is being set by the clock init - * routine in libopencm3 so we don't have to set up this clock ourselves any - * more. This comment is here just as a reminder and may be removed in the - * future when we know that everything is working properly. - * (by Esden the historian :D) - */ - /* Timer peripheral clock enable. */ rcc_peripheral_enable_clock(rcc_apbenr, rcc_apb); /* GPIO peripheral clock enable. */ @@ -262,9 +529,12 @@ static inline void adc_init_rcc( void ) #ifdef USE_AD1 rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_ADC1EN); #endif -#ifdef USE_AD2 +#if defined(USE_AD2) && defined(STM32F4) rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_ADC2EN); #endif +#if defined(USE_AD3) && defined(STM32F4) + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_ADC3EN); +#endif /* Time Base configuration */ timer_reset(timer); @@ -282,10 +552,10 @@ static inline void adc_init_rcc( void ) timer_set_master_mode(timer, TIM_CR2_MMS_UPDATE); timer_enable_counter(timer); -#endif // defined (USE_AD1) || defined (USE_AD2) +#endif // defined (USE_AD1) || defined (USE_AD2) || (defined(USE_AD3) && defined(STM32F4)) } -/* Configure and enable ADC interrupt */ +/** Configure and enable ADC interrupt */ static inline void adc_init_irq( void ) { #if defined(STM32F1) @@ -295,47 +565,27 @@ static inline void adc_init_irq( void ) nvic_set_priority(NVIC_ADC_IRQ, 0); nvic_enable_irq(NVIC_ADC_IRQ); #endif + + return; } -/** - * Enable selected channels on specified ADC. - * Usage: - * - * adc_init_single(ADC1, 1, 1, 0, 0); - * - * ... would enable ADC1, enabling channels 1 and 2, - * but not 3 and 4. - */ -static inline void adc_init_single(uint32_t adc, - uint8_t chan1, uint8_t chan2, - uint8_t chan3, uint8_t chan4) + +static inline void adc_init_single(uint32_t adc, uint8_t nb_channels) { - uint8_t num_channels, rank; - uint8_t channels[4]; + uint8_t x = 0; // Paranoia, must be down for 2+ ADC clock cycles before calibration adc_off(adc); - /* enable adc clock */ - if (adc == ADC1) { -#ifdef USE_AD1 - num_channels = NB_ADC1_CHANNELS; - ADC1_GPIO_INIT(); -#endif - } - else if (adc == ADC2) { -#ifdef USE_AD2 - num_channels = NB_ADC2_CHANNELS; - ADC2_GPIO_INIT(); +#if defined(ADC1_GPIO_INIT) + ADC1_GPIO_INIT(); +#elif !defined(ADC1_GPIO_INIT) + ADC_GPIO_INIT(); #endif - } /* Configure ADC */ - /* Explicitly setting most registers, reset/default values are correct for most */ - /* Set CR1 register. */ - /* Clear AWDEN */ adc_disable_analog_watchdog_regular(adc); /* Clear JAWDEN */ @@ -356,7 +606,6 @@ static inline void adc_init_single(uint32_t adc, adc_disable_eoc_interrupt(adc); /* Set CR2 register. */ - /* Clear TSVREFE */ #if defined(STM32F1) adc_disable_temperature_sensor(adc); @@ -372,47 +621,30 @@ static inline void adc_init_single(uint32_t adc, /* Clear CONT */ adc_set_single_conversion_mode(adc); - rank = 3; - if (chan1) { - adc_set_sample_time(adc, adc_channel_map[0], ADC_SAMPLE_TIME); - channels[rank] = adc_channel_map[0]; - rank--; - } - if (chan2) { - adc_set_sample_time(adc, adc_channel_map[1], ADC_SAMPLE_TIME); - channels[rank] = adc_channel_map[1]; - rank--; - } - if (chan3) { - adc_set_sample_time(adc, adc_channel_map[2], ADC_SAMPLE_TIME); - channels[rank] = adc_channel_map[2]; - rank--; - } - if (chan4) { - adc_set_sample_time(adc, adc_channel_map[3], ADC_SAMPLE_TIME); - channels[rank] = adc_channel_map[3]; + for (x = (4-nb_channels); x < 4; x++){ + adc_set_sample_time(adc, adc_channel_map[x], ADC_SAMPLE_TIME); } - adc_set_injected_sequence(adc, num_channels, channels); + adc_set_injected_sequence(adc, nb_channels, adc_channel_map); #if USE_AD_TIM4 -PRINT_CONFIG_MSG("Info: Using TIM4 for ADC") + PRINT_CONFIG_MSG("Info: Using TIM4 for ADC") #if defined(STM32F1) - adc_enable_external_trigger_injected(adc, ADC_CR2_JEXTSEL_TIM4_TRGO); + adc_enable_external_trigger_injected(adc, ADC_CR2_JEXTSEL_TIM4_TRGO); #elif defined(STM32F4) adc_enable_external_trigger_injected(adc, ADC_CR2_JEXTSEL_TIM4_TRGO, ADC_CR2_JEXTEN_BOTH_EDGES); #endif #elif USE_AD_TIM1 -PRINT_CONFIG_MSG("Info: Using TIM1 for ADC") + PRINT_CONFIG_MSG("Info: Using TIM1 for ADC") #if defined(STM32F1) - adc_enable_external_trigger_injected(adc, ADC_CR2_JEXTSEL_TIM1_TRGO); + adc_enable_external_trigger_injected(adc, ADC_CR2_JEXTSEL_TIM1_TRGO); #elif defined(STM32F4) adc_enable_external_trigger_injected(adc, ADC_CR2_JEXTSEL_TIM1_TRGO, ADC_CR2_JEXTEN_BOTH_EDGES); #endif #else -PRINT_CONFIG_MSG("Info: Using default TIM2 for ADC") + PRINT_CONFIG_MSG("Info: Using default TIM2 for ADC") #if defined(STM32F1) - adc_enable_external_trigger_injected(adc, ADC_CR2_JEXTSEL_TIM2_TRGO); + adc_enable_external_trigger_injected(adc, ADC_CR2_JEXTSEL_TIM2_TRGO); #elif defined(STM32F4) adc_enable_external_trigger_injected(adc, ADC_CR2_JEXTSEL_TIM2_TRGO, ADC_CR2_JEXTEN_BOTH_EDGES); #endif @@ -430,127 +662,10 @@ PRINT_CONFIG_MSG("Info: Using default TIM2 for ADC") /* Check the end of ADC calibration */ while ((ADC_CR2(adc) & ADC_CR2_CAL) != 0); #endif -} // adc_init_single - - -void adc_init( void ) { - /* initialize buffer pointers with 0 (not set). - buffer null pointers will be ignored in interrupt - handler, which is important as there are no - buffers registered at the time the ADC trigger - interrupt is enabled. - */ - uint8_t channel; -#ifdef USE_AD1 - for(channel = 0; channel < NB_ADC1_CHANNELS; channel++) - adc1_buffers[channel] = NULL; - volatile uint32_t* tmp_channels_1[] = { - &ADC_JDR1(ADC1), - &ADC_JDR2(ADC1), - &ADC_JDR3(ADC1), - &ADC_JDR4(ADC1) - }; -#ifdef USE_AD1_1 - adc_injected_channels[ADC1_C1] = tmp_channels_1[NB_ADC1_CHANNELS-1-ADC1_C1]; -#endif -#ifdef USE_AD1_2 - adc_injected_channels[ADC1_C2] = tmp_channels_1[NB_ADC1_CHANNELS-1-ADC1_C2]; -#endif -#ifdef USE_AD1_3 - adc_injected_channels[ADC1_C3] = tmp_channels_1[NB_ADC1_CHANNELS-1-ADC1_C3]; -#endif -#ifdef USE_AD1_4 - adc_injected_channels[ADC1_C4] = tmp_channels_1[NB_ADC1_CHANNELS-1-ADC1_C4]; -#endif - -#endif // USE_AD1 - -#ifdef USE_AD2 - for(channel = 0; channel < NB_ADC2_CHANNELS; channel++) - adc2_buffers[channel] = NULL; - volatile uint32_t* tmp_channels_2[] = { - &ADC_JDR1(ADC2), - &ADC_JDR2(ADC2), - &ADC_JDR3(ADC2), - &ADC_JDR4(ADC2) - }; -#ifdef USE_AD2_1 - adc_injected_channels[ADC2_C1] = tmp_channels_2[NB_ADC2_CHANNELS-1-ADC2_C1]; -#endif -#ifdef USE_AD2_2 - adc_injected_channels[ADC2_C2] = tmp_channels_2[NB_ADC2_CHANNELS-1-ADC2_C2]; -#endif -#ifdef USE_AD2_3 - adc_injected_channels[ADC2_C3] = tmp_channels_2[NB_ADC2_CHANNELS-1-ADC2_C3]; -#endif -#ifdef USE_AD2_4 - adc_injected_channels[ADC2_C4] = tmp_channels_2[NB_ADC2_CHANNELS-1-ADC2_C4]; -#endif - -#endif // USE_AD2 - - adc_new_data_trigger = FALSE; - adc_channel_map[0] = BOARD_ADC_CHANNEL_1; - adc_channel_map[1] = BOARD_ADC_CHANNEL_2; - adc_channel_map[2] = BOARD_ADC_CHANNEL_3; - adc_channel_map[3] = BOARD_ADC_CHANNEL_4; - - adc_init_rcc(); - adc_init_irq(); - - // adc_init_single(ADCx, c1, c2, c3, c4) -#ifdef USE_AD1 - adc_init_single(ADC1, -#ifdef USE_AD1_1 - 1, -#else - 0, -#endif -#ifdef USE_AD1_2 - 1, -#else - 0, -#endif -#ifdef USE_AD1_3 - 1, -#else - 0, -#endif -#ifdef USE_AD1_4 - 1 -#else - 0 -#endif - ); -#endif // USE_AD1 + return; +} // adc_init_single -#ifdef USE_AD2 - adc_init_single(ADC2, -#ifdef USE_AD2_1 - 1, -#else - 0, -#endif -#ifdef USE_AD2_2 - 1, -#else - 0, -#endif -#ifdef USE_AD2_3 - 1, -#else - 0, -#endif -#ifdef USE_AD2_4 - 1 -#else - 0 -#endif - ); -#endif // USE_AD2 - -} static inline void adc_push_sample(struct adc_buf * buf, uint16_t value) { uint8_t new_head = buf->head + 1; @@ -564,13 +679,14 @@ static inline void adc_push_sample(struct adc_buf * buf, uint16_t value) { buf->head = new_head; } -/** - * ADC1+2 interrupt hander - */ +/*****************************************************************************************************/ +/********************************** ADC INTERRUPT HANDLER ****************************************/ +/*****************************************************************************************************/ + #if defined(STM32F1) void adc1_2_isr(void) #elif defined(STM32F4) -void adc_isr(void) + void adc_isr(void) #endif { uint8_t channel = 0; @@ -578,27 +694,52 @@ void adc_isr(void) struct adc_buf * buf; #ifdef USE_AD1 + //#pragma message "ADC1 active" // Clear Injected End Of Conversion - ADC_SR(ADC1) &= ~ADC_SR_JEOC; - for(channel = 0; channel < NB_ADC1_CHANNELS; channel++) { - buf = adc1_buffers[channel]; - if(buf) { - value = *adc_injected_channels[channel]; - adc_push_sample(buf, value); + if (ADC_SR(ADC1) & ADC_SR_JEOC){ + ADC_SR(ADC1) &= ~ADC_SR_JEOC; + for (channel = 0; channel < nb_adc1_channels; channel++) { + buf = adc1_buffers[channel]; + if (buf) { + value = *(&ADC_JDR1(ADC1)+channel); + adc_push_sample(buf, value); + } } +#if !defined(USE_AD2) && !defined(USE_AD3) + adc_new_data_trigger = 1; +#endif } - adc_new_data_trigger = 1; #endif -#ifdef USE_AD2 - // Clear Injected End Of Conversion - ADC_SR(ADC2) &= ~ADC_SR_JEOC; - for(channel = 0; channel < NB_ADC2_CHANNELS; channel++) { - buf = adc2_buffers[channel]; - if(buf) { - value = *adc_injected_channels[channel]; - adc_push_sample(buf, value); +#if defined(USE_AD2) && defined(STM32F4) + //#pragma message "ADC2 active" + if (ADC_SR(ADC2) & ADC_SR_JEOC){ + ADC_SR(ADC2) &= ~ADC_SR_JEOC; + for (channel = 0; channel < nb_adc2_channels; channel++) { + buf = adc2_buffers[channel]; + if (buf) { + value = *(&ADC_JDR1(ADC2)+channel); + adc_push_sample(buf, value); + } } +#if !defined(USE_AD3) + adc_new_data_trigger = 1; +#endif } - adc_new_data_trigger = 1; #endif +#if defined(USE_AD3) && defined(STM32F4) + //#pragma message "ADC3 active" + if (ADC_SR(ADC3) & ADC_SR_JEOC){ + ADC_SR(ADC3) &= ~ADC_SR_JEOC; + for (channel = 0; channel < nb_adc3_channels; channel++) { + buf = adc3_buffers[channel]; + if (buf) { + value = *(&ADC_JDR1(ADC3)+channel); + adc_push_sample(buf, value); + } + } + adc_new_data_trigger = 1; + } +#endif + + return; } diff --git a/sw/airborne/arch/stm32/mcu_periph/adc_arch.h b/sw/airborne/arch/stm32/mcu_periph/adc_arch.h index 5728fc2fd4b..1e92ae5b2fb 100644 --- a/sw/airborne/arch/stm32/mcu_periph/adc_arch.h +++ b/sw/airborne/arch/stm32/mcu_periph/adc_arch.h @@ -46,10 +46,7 @@ enum adc1_channels { #ifdef USE_AD1_4 ADC1_C4, #endif - NB_ADC1_CHANNELS -}; - -enum adc2_channels { +// NB_ADC1_CHANNELS #ifdef USE_AD2_1 ADC2_C1, #endif @@ -62,14 +59,22 @@ enum adc2_channels { #ifdef USE_AD2_4 ADC2_C4, #endif - NB_ADC2_CHANNELS -}; - -#ifdef NB_ADC -#undef NB_ADC +// NB_ADC2_CHANNELS +#ifdef USE_AD3_1 + ADC3_C1, #endif - -#define NB_ADC (NB_ADC1_CHANNELS + NB_ADC2_CHANNELS) +#ifdef USE_AD3_2 + ADC3_C2, +#endif +#ifdef USE_AD3_3 + ADC3_C3, +#endif +#ifdef USE_AD3_4 + ADC3_C4, +#endif +// NB_ADC3_CHANNELS + NB_ADC +}; #define AdcBank0(x) (x) #define AdcBank1(x) (x+NB_ADC)