Paparazzi UAS  v5.0.5_stable-7-g4b8bbb7
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
adc_arch.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2010-2012 The Paparazzi Team
3  *
4  * This file is part of paparazzi.
5  *
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, write to
18  * the Free Software Foundation, 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  *
21  */
22 
38 /*
39  For better understanding of timer and GPIO settings:
40 
41  Table of GPIO pins available per ADC:
42 
43  ADC1/2: ADC3:
44  C0 -> PA0 C0 -> PA0
45  C1 -> PA1 C1 -> PA1
46  C2 -> PA2 C2 -> PA2
47  C3 -> PA3 C3 -> PA3
48  C4 -> PA4 C4 -> PF6
49  C5 -> PA5 C5 -> PF7
50  C6 -> PA6 C6 -> PF8
51  C7 -> PA7 C7 -> PF9
52  C8 -> PB0 C8 -> PF10
53  C9 -> PB1
54  C10 -> PC0 C10 -> PC0
55  C11 -> PC1 C11 -> PC1
56  C12 -> PC2 C12 -> PC2
57  C13 -> PC3 C13 -> PC3
58  C14 -> PC4
59  C15 -> PC5
60 
61  Table of timers available per ADC (from libstm/src/stm32_adc.c):
62 
63  T1_TRGO: Timer1 TRGO event (ADC1, ADC2 and ADC3)
64  T1_CC4: Timer1 capture compare4 (ADC1, ADC2 and ADC3)
65  T2_TRGO: Timer2 TRGO event (ADC1 and ADC2)
66  T2_CC1: Timer2 capture compare1 (ADC1 and ADC2)
67  T3_CC4: Timer3 capture compare4 (ADC1 and ADC2)
68  T4_TRGO: Timer4 TRGO event (ADC1 and ADC2)
69  TIM8_CC4: External interrupt line 15 or Timer8 capture compare4 event (ADC1 and ADC2)
70  T4_CC3: Timer4 capture compare3 (ADC3 only)
71  T8_CC2: Timer8 capture compare2 (ADC3 only)
72  T8_CC4: Timer8 capture compare4 (ADC3 only)
73  T5_TRGO: Timer5 TRGO event (ADC3 only)
74  T5_CC4: Timer5 capture compare4 (ADC3 only)
75 
76  By setting ADC_ExternalTrigInjecConv_None, injected conversion
77  is started by software instead of external trigger for any ADC.
78 
79  Table of APB per Timer (from libstm/src/stm32_tim.c):
80 
81  RCC_APB1: TIM2, TIM3, TIM4, TIM5, TIM7 (non-advanced timers)
82  RCC_APB2: TIM1, TIM8 (advanced timers)
83 
84 */
85 
86 #include "mcu_periph/adc.h"
87 
88 #include <libopencm3/stm32/rcc.h>
89 #include <libopencm3/stm32/gpio.h>
90 #if defined(STM32F1)
91 #include <libopencm3/stm32/f1/adc.h>
92 #define ADC_SAMPLE_TIME ADC_SMPR_SMP_41DOT5CYC
93 #elif defined(STM32F4)
94 #include <libopencm3/stm32/f4/adc.h>
95 #define ADC_SAMPLE_TIME ADC_SMPR_SMP_56CYC
96 #endif
97 #include <libopencm3/cm3/nvic.h>
98 #include <libopencm3/stm32/timer.h>
99 #include <string.h>
100 #include "std.h"
101 #include "led.h"
102 #include BOARD_CONFIG
103 
105 
106 /* Static functions */
107 
108 static inline void adc_init_single(uint32_t adc,
109  uint8_t chan1, uint8_t chan2,
110  uint8_t chan3, uint8_t chan4);
111 
112 static inline void adc_push_sample(struct adc_buf * buf,
113  uint16_t sample);
114 
115 static inline void adc_init_rcc( void );
116 static inline void adc_init_irq( void );
117 
118 #ifdef USE_AD2
119 #error NOT_IMPLEMENTED__currently_only_ADC1_is_supported
120 #endif
121 
122 /*
123  Only 4 ADC channels may be enabled at the same time
124  on each ADC, as there are only 4 injection registers.
125 */
126 
127 // ADCx_GPIO_INIT
128 // {{{
129 
130 /*
131  GPIO mapping for ADC1 pins (PB.1, PB.0, PC.5, PC.3).
132  Can be changed by predefining ADC1_GPIO_INIT.
133 */
134 #ifdef USE_AD1
135 #ifndef ADC1_GPIO_INIT
136 #define ADC1_GPIO_INIT() { \
137  gpio_set_mode(GPIOB, GPIO_MODE_INPUT, \
138  GPIO_CNF_INPUT_ANALOG, \
139  GPIO1 | GPIO0); \
140  gpio_set_mode(GPIOC, GPIO_MODE_INPUT, \
141  GPIO_CNF_INPUT_ANALOG, \
142  GPIO5 | GPIO3); \
143  }
144 #endif // ADC1_GPIO_INIT
145 #endif // USE_AD1
146 
147 /*
148  GPIO mapping for ADC2 pins.
149  Can be changed by predefining ADC2_GPIO_INIT.
150  Uses the same GPIOs as ADC1 (lisa specific).
151 */
152 #ifdef USE_AD2
153 #ifndef ADC2_GPIO_INIT
154 #define ADC2_GPIO_INIT() { \
155  gpio_set_mode(GPIOB, GPIO_MODE_INPUT, \
156  GPIO_CNF_INPUT_ANALOG, \
157  GPIO1 | GPIO0); \
158  gpio_set_mode(GPIOC, GPIO_MODE_INPUT, \
159  GPIO_CNF_INPUT_ANALOG, \
160  GPIO5 | GPIO3); \
161  }
162 #endif // ADC2_GPIO_INIT
163 #endif // USE_AD2
164 
165 
166 /*
167  Currently, the enums adc1_channels and adc2_channels only
168  serve to resolve the number of channels on each ADC.
169 */
170 
171 /*
172  Separate buffers for each ADC.
173  Every ADC has a list of buffers, one for each active
174  channel.
175 */
176 
177 #ifdef USE_AD1
178 static struct adc_buf * adc1_buffers[NB_ADC1_CHANNELS];
180 #endif
181 #ifdef USE_AD2
182 static struct adc_buf * adc2_buffers[NB_ADC2_CHANNELS];
184 #endif
185 
186 
192 
203 
204 /*
205  TODO: Extend interface to allow adressing a
206  specific ADC (at least ADC1 and ADC2)?
207 */
208 void adc_buf_channel(uint8_t adc_channel,
209  struct adc_buf * s,
211 {
212  adc1_buffers[adc_channel] = s;
214 }
215 
216 // #define USE_AD_TIM4
217 /* Configure and enable RCC for peripherals (ADC1, ADC2, Timer) */
218 static inline void adc_init_rcc( void )
219 {
220 #if defined (USE_AD1) || defined (USE_AD2)
221  uint32_t timer;
222  volatile uint32_t *rcc_apbenr;
223  uint32_t rcc_apb;
224 #if defined(USE_AD_TIM4)
225  timer = TIM4;
226  rcc_apbenr = &RCC_APB1ENR;
227  rcc_apb = RCC_APB1ENR_TIM4EN;
228 #elif defined(USE_AD_TIM1)
229  timer = TIM1;
230  rcc_apbenr = &RCC_APB2ENR;
231  rcc_apb = RCC_APB2ENR_TIM1EN;
232 #else
233  timer = TIM2;
234  rcc_apbenr = &RCC_APB1ENR;
235  rcc_apb = RCC_APB1ENR_TIM2EN;
236 #endif
237 
238  /*
239  * Historic Note:
240  * Previously in libstm32 we were setting the ADC clock here.
241  * It was being set to PCLK2 DIV2 resulting in 36MHz clock on the ADC. I am
242  * pretty sure that this is wrong as based on the datasheet the ADC clock
243  * must not exceed 14MHz! Now the clock is being set by the clock init
244  * routine in libopencm3 so we don't have to set up this clock ourselves any
245  * more. This comment is here just as a reminder and may be removed in the
246  * future when we know that everything is working properly.
247  * (by Esden the historian :D)
248  */
249 
250  /* Timer peripheral clock enable. */
251  rcc_peripheral_enable_clock(rcc_apbenr, rcc_apb);
252  /* GPIO peripheral clock enable. */
253 #if defined(STM32F1)
254  rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN |
255  RCC_APB2ENR_IOPCEN);
256 #elif defined(STM32F4)
257  rcc_peripheral_enable_clock(&RCC_AHB1ENR, ADC_GPIO_CLOCK_PORT);
258  adc_set_clk_prescale(ADC_CCR_ADCPRE_BY2);
259 #endif
260 
261  /* Enable ADC peripheral clocks. */
262 #ifdef USE_AD1
263  rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_ADC1EN);
264 #endif
265 #ifdef USE_AD2
266  rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_ADC2EN);
267 #endif
268 
269  /* Time Base configuration */
270  timer_reset(timer);
271  timer_set_mode(timer, TIM_CR1_CKD_CK_INT,
272  TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
273 #if defined(STM32F1)
274  timer_set_period(timer, 0xFF);
275  timer_set_prescaler(timer, 0x8);
276 #elif defined(STM32F4)
277  timer_set_period(timer, 0xFFFF);
278  timer_set_prescaler(timer, 0x53);
279 #endif
280  //timer_set_clock_division(timer, 0x0);
281  /* Generate TRGO on every update. */
282  timer_set_master_mode(timer, TIM_CR2_MMS_UPDATE);
283  timer_enable_counter(timer);
284 
285 #endif // defined (USE_AD1) || defined (USE_AD2)
286 }
287 
288 /* Configure and enable ADC interrupt */
289 static inline void adc_init_irq( void )
290 {
291 #if defined(STM32F1)
292  nvic_set_priority(NVIC_ADC1_2_IRQ, 0);
293  nvic_enable_irq(NVIC_ADC1_2_IRQ);
294 #elif defined(STM32F4)
295  nvic_set_priority(NVIC_ADC_IRQ, 0);
296  nvic_enable_irq(NVIC_ADC_IRQ);
297 #endif
298 }
299 
309 static inline void adc_init_single(uint32_t adc,
310  uint8_t chan1, uint8_t chan2,
311  uint8_t chan3, uint8_t chan4)
312 {
313  uint8_t num_channels, rank;
314  uint8_t channels[4];
315 
316  // Paranoia, must be down for 2+ ADC clock cycles before calibration
317  adc_off(adc);
318 
319  /* enable adc clock */
320  if (adc == ADC1) {
321 #ifdef USE_AD1
322  num_channels = NB_ADC1_CHANNELS;
323  ADC1_GPIO_INIT();
324 #endif
325  }
326  else if (adc == ADC2) {
327 #ifdef USE_AD2
328  num_channels = NB_ADC2_CHANNELS;
329  ADC2_GPIO_INIT();
330 #endif
331  }
332 
333  /* Configure ADC */
334 
335  /* Explicitly setting most registers, reset/default values are correct for most */
336 
337  /* Set CR1 register. */
338 
339  /* Clear AWDEN */
340  adc_disable_analog_watchdog_regular(adc);
341  /* Clear JAWDEN */
342  adc_disable_analog_watchdog_injected(adc);
343  /* Clear DISCEN */
344  adc_disable_discontinuous_mode_regular(adc);
345  /* Clear JDISCEN */
346  adc_disable_discontinuous_mode_injected(adc);
347  /* Clear JAUTO */
348  adc_disable_automatic_injected_group_conversion(adc);
349  /* Set SCAN */
350  adc_enable_scan_mode(adc);
351  /* Enable ADC<X> JEOC interrupt (Set JEOCIE) */
352  adc_enable_eoc_interrupt_injected(adc);
353  /* Clear AWDIE */
354  adc_disable_awd_interrupt(adc);
355  /* Clear EOCIE */
356  adc_disable_eoc_interrupt(adc);
357 
358  /* Set CR2 register. */
359 
360  /* Clear TSVREFE */
361 #if defined(STM32F1)
362  adc_disable_temperature_sensor(adc);
363 #elif defined(STM32F4)
364  adc_disable_temperature_sensor();
365 #endif
366  /* Clear EXTTRIG */
367  adc_disable_external_trigger_regular(adc);
368  /* Clear ALIGN */
369  adc_set_right_aligned(adc);
370  /* Clear DMA */
371  adc_disable_dma(adc);
372  /* Clear CONT */
373  adc_set_single_conversion_mode(adc);
374 
375  rank = 3;
376  if (chan1) {
377  adc_set_sample_time(adc, adc_channel_map[0], ADC_SAMPLE_TIME);
378  channels[rank] = adc_channel_map[0];
379  rank--;
380  }
381  if (chan2) {
382  adc_set_sample_time(adc, adc_channel_map[1], ADC_SAMPLE_TIME);
383  channels[rank] = adc_channel_map[1];
384  rank--;
385  }
386  if (chan3) {
387  adc_set_sample_time(adc, adc_channel_map[2], ADC_SAMPLE_TIME);
388  channels[rank] = adc_channel_map[2];
389  rank--;
390  }
391  if (chan4) {
392  adc_set_sample_time(adc, adc_channel_map[3], ADC_SAMPLE_TIME);
393  channels[rank] = adc_channel_map[3];
394  }
395 
396  adc_set_injected_sequence(adc, num_channels, channels);
397 
398 #if USE_AD_TIM4
399 PRINT_CONFIG_MSG("Info: Using TIM4 for ADC")
400 #if defined(STM32F1)
401  adc_enable_external_trigger_injected(adc, ADC_CR2_JEXTSEL_TIM4_TRGO);
402 #elif defined(STM32F4)
403  adc_enable_external_trigger_injected(adc, ADC_CR2_JEXTSEL_TIM4_TRGO, ADC_CR2_JEXTEN_BOTH_EDGES);
404 #endif
405 #elif USE_AD_TIM1
406 PRINT_CONFIG_MSG("Info: Using TIM1 for ADC")
407 #if defined(STM32F1)
408  adc_enable_external_trigger_injected(adc, ADC_CR2_JEXTSEL_TIM1_TRGO);
409 #elif defined(STM32F4)
410  adc_enable_external_trigger_injected(adc, ADC_CR2_JEXTSEL_TIM1_TRGO, ADC_CR2_JEXTEN_BOTH_EDGES);
411 #endif
412 #else
413 PRINT_CONFIG_MSG("Info: Using default TIM2 for ADC")
414 #if defined(STM32F1)
415  adc_enable_external_trigger_injected(adc, ADC_CR2_JEXTSEL_TIM2_TRGO);
416 #elif defined(STM32F4)
417  adc_enable_external_trigger_injected(adc, ADC_CR2_JEXTSEL_TIM2_TRGO, ADC_CR2_JEXTEN_BOTH_EDGES);
418 #endif
419 #endif
420 
421  /* Enable ADC<X> */
422  adc_power_on(adc);
423 #if defined(STM32F1)
424  /* Enable ADC<X> reset calibaration register */
425  adc_reset_calibration(adc);
426  /* Check the end of ADC<X> reset calibration */
427  while ((ADC_CR2(adc) & ADC_CR2_RSTCAL) != 0);
428  /* Start ADC<X> calibaration */
429  adc_calibration(adc);
430  /* Check the end of ADC<X> calibration */
431  while ((ADC_CR2(adc) & ADC_CR2_CAL) != 0);
432 #endif
433 } // adc_init_single
434 
435 
436 void adc_init( void ) {
437 
438  /* initialize buffer pointers with 0 (not set).
439  buffer null pointers will be ignored in interrupt
440  handler, which is important as there are no
441  buffers registered at the time the ADC trigger
442  interrupt is enabled.
443  */
445 #ifdef USE_AD1
446  for(channel = 0; channel < NB_ADC1_CHANNELS; channel++)
447  adc1_buffers[channel] = NULL;
448  volatile uint32_t* tmp_channels_1[] = {
449  &ADC_JDR1(ADC1),
450  &ADC_JDR2(ADC1),
451  &ADC_JDR3(ADC1),
452  &ADC_JDR4(ADC1)
453  };
454 #ifdef USE_AD1_1
455  adc_injected_channels[ADC1_C1] = tmp_channels_1[NB_ADC1_CHANNELS-1-ADC1_C1];
456 #endif
457 #ifdef USE_AD1_2
458  adc_injected_channels[ADC1_C2] = tmp_channels_1[NB_ADC1_CHANNELS-1-ADC1_C2];
459 #endif
460 #ifdef USE_AD1_3
461  adc_injected_channels[ADC1_C3] = tmp_channels_1[NB_ADC1_CHANNELS-1-ADC1_C3];
462 #endif
463 #ifdef USE_AD1_4
464  adc_injected_channels[ADC1_C4] = tmp_channels_1[NB_ADC1_CHANNELS-1-ADC1_C4];
465 #endif
466 
467 #endif // USE_AD1
468 
469 #ifdef USE_AD2
470  for(channel = 0; channel < NB_ADC2_CHANNELS; channel++)
471  adc2_buffers[channel] = NULL;
472  volatile uint32_t* tmp_channels_2[] = {
473  &ADC_JDR1(ADC2),
474  &ADC_JDR2(ADC2),
475  &ADC_JDR3(ADC2),
476  &ADC_JDR4(ADC2)
477  };
478 #ifdef USE_AD2_1
479  adc_injected_channels[ADC2_C1] = tmp_channels_2[NB_ADC2_CHANNELS-1-ADC2_C1];
480 #endif
481 #ifdef USE_AD2_2
482  adc_injected_channels[ADC2_C2] = tmp_channels_2[NB_ADC2_CHANNELS-1-ADC2_C2];
483 #endif
484 #ifdef USE_AD2_3
485  adc_injected_channels[ADC2_C3] = tmp_channels_2[NB_ADC2_CHANNELS-1-ADC2_C3];
486 #endif
487 #ifdef USE_AD2_4
488  adc_injected_channels[ADC2_C4] = tmp_channels_2[NB_ADC2_CHANNELS-1-ADC2_C4];
489 #endif
490 
491 #endif // USE_AD2
492 
498 
499  adc_init_rcc();
500  adc_init_irq();
501 
502  // adc_init_single(ADCx, c1, c2, c3, c4)
503 #ifdef USE_AD1
505 #ifdef USE_AD1_1
506  1,
507 #else
508  0,
509 #endif
510 #ifdef USE_AD1_2
511  1,
512 #else
513  0,
514 #endif
515 #ifdef USE_AD1_3
516  1,
517 #else
518  0,
519 #endif
520 #ifdef USE_AD1_4
521  1
522 #else
523  0
524 #endif
525  );
526 #endif // USE_AD1
527 
528 #ifdef USE_AD2
529  adc_init_single(ADC2,
530 #ifdef USE_AD2_1
531  1,
532 #else
533  0,
534 #endif
535 #ifdef USE_AD2_2
536  1,
537 #else
538  0,
539 #endif
540 #ifdef USE_AD2_3
541  1,
542 #else
543  0,
544 #endif
545 #ifdef USE_AD2_4
546  1
547 #else
548  0
549 #endif
550  );
551 #endif // USE_AD2
552 
553 }
554 
555 static inline void adc_push_sample(struct adc_buf * buf, uint16_t value) {
556  uint8_t new_head = buf->head + 1;
557 
558  if (new_head >= buf->av_nb_sample) {
559  new_head = 0;
560  }
561  buf->sum -= buf->values[new_head];
562  buf->values[new_head] = value;
563  buf->sum += value;
564  buf->head = new_head;
565 }
566 
570 #if defined(STM32F1)
571 void adc1_2_isr(void)
572 #elif defined(STM32F4)
573 void adc_isr(void)
574 #endif
575 {
576  uint8_t channel = 0;
578  struct adc_buf * buf;
579 
580 #ifdef USE_AD1
581  // Clear Injected End Of Conversion
582  ADC_SR(ADC1) &= ~ADC_SR_JEOC;
583  for(channel = 0; channel < NB_ADC1_CHANNELS; channel++) {
584  buf = adc1_buffers[channel];
585  if(buf) {
586  value = *adc_injected_channels[channel];
587  adc_push_sample(buf, value);
588  }
589  }
591 #endif
592 #ifdef USE_AD2
593  // Clear Injected End Of Conversion
594  ADC_SR(ADC2) &= ~ADC_SR_JEOC;
595  for(channel = 0; channel < NB_ADC2_CHANNELS; channel++) {
596  buf = adc2_buffers[channel];
597  if(buf) {
598  value = *adc_injected_channels[channel];
599  adc_push_sample(buf, value);
600  }
601  }
603 #endif
604 }
#define ADC1
Definition: LPC21xx.h:370
unsigned short uint16_t
Definition: types.h:16
#define ADC_GPIO_CLOCK_PORT
Definition: apogee_0.99.h:132
uint16_t value
ADC1+2 interrupt hander.
Definition: adc_arch.c:577
void adc_buf_channel(uint8_t adc_channel, struct adc_buf *s, uint8_t av_nb_sample)
Registers a buffer to be used to store the specified converted channel Usage:
Definition: adc_arch.c:59
static uint8_t adc_channel_map[4]
Maps integer value x to ADC_Channel_y.
Definition: adc_arch.c:202
uint16_t values[MAX_AV_NB_SAMPLE]
Definition: adc.h:62
#define BOARD_ADC_CHANNEL_3
Definition: apogee_0.99.h:69
#define USE_AD1_2
Definition: booz_1.0.h:128
#define BOARD_ADC_CHANNEL_4
Definition: apogee_0.99.h:70
#define BOARD_ADC_CHANNEL_2
Definition: apogee_0.99.h:68
uint8_t av_nb_sample
Definition: adc.h:64
arch independent ADC (Analog to Digital Converter) API
uint32_t sum
Definition: adc.h:61
#define FALSE
Definition: imu_chimu.h:141
#define ADC1_GPIO_INIT(gpio)
Definition: apogee_0.99.h:136
volatile uint8_t adc_new_data_trigger
Definition: adc_arch.c:104
static void adc_init_single(uint32_t adc, uint8_t chan1, uint8_t chan2, uint8_t chan3, uint8_t chan4)
Enable selected channels on specified ADC.
Definition: adc_arch.c:309
Generic interface for all ADC hardware drivers, independent from microcontroller architecture.
Definition: adc.h:60
unsigned long uint32_t
Definition: types.h:18
#define BOARD_ADC_CHANNEL_1
Definition: apogee_0.99.h:67
static void adc_push_sample(struct adc_buf *buf, uint16_t sample)
Definition: adc_arch.c:555
#define USE_AD1_4
Definition: apogee_0.99.h:121
#define USE_AD1_3
Definition: lisa_l_1.0.h:140
struct adc_buf * buf
Definition: adc_arch.c:578
unsigned char uint8_t
Definition: types.h:14
void adc_init(void)
Starts conversions.
Definition: adc_arch.c:194
static void adc_init_irq(void)
Definition: adc_arch.c:289
arch independent LED (Light Emitting Diodes) API
#define USE_AD1_1
Definition: lisa_l_1.0.h:138
volatile uint32_t * adc_injected_channels[4]
Maps integer value x to ADC_InjectedChannel_x.
Definition: adc_arch.c:191
static uint8_t channel
Definition: ADS8344.c:80
uint8_t head
Definition: adc.h:63
static void adc_init_rcc(void)
Definition: adc_arch.c:218