Paparazzi UAS  v4.0.4_stable-3-gf39211a
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
adc_arch.c
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (C) 2010 The Paparazzi Team
4  *
5  * This file is part of paparazzi.
6  *
7  * paparazzi is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * paparazzi is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with paparazzi; see the file COPYING. If not, write to
19  * the Free Software Foundation, 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  *
22  */
23 
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 #include <stm32/rcc.h>
88 #include <stm32/misc.h>
89 #include <stm32/adc.h>
90 #include <stm32/gpio.h>
91 #include <stm32/rcc.h>
92 #include <stm32/tim.h>
93 #include <string.h>
94 #include "std.h"
95 #include "led.h"
96 #include BOARD_CONFIG
97 
98 void adc1_2_irq_handler(void);
99 
101 
102 /* Static functions */
103 
104 static inline void adc_init_single(ADC_TypeDef * adc_t,
105  uint8_t chan1, uint8_t chan2,
106  uint8_t chan3, uint8_t chan4);
107 
108 static inline void adc_push_sample(struct adc_buf * buf,
109  uint16_t sample);
110 
111 static inline void adc_init_rcc( void );
112 static inline void adc_init_irq( void );
113 
114 #ifdef USE_AD2
115 #error NOT_IMPLEMENTED__currently_only_ADC1_is_supported
116 #endif
117 
118 /*
119  Only 4 ADC channels may be enabled at the same time
120  on each ADC, as there are only 4 injection registers.
121 */
122 
123 // ADCx_GPIO_INIT
124 // {{{
125 
126 /*
127  GPIO mapping for ADC1 pins (PB.1, PB.0, PC.5, PC.3).
128  Can be changed by predefining ADC1_GPIO_INIT.
129 */
130 #ifdef USE_AD1
131 #ifndef ADC1_GPIO_INIT
132 #define ADC1_GPIO_INIT(gpio) { \
133  (gpio).GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_0; \
134  (gpio).GPIO_Mode = GPIO_Mode_AIN; \
135  GPIO_Init(GPIOB, (&gpio)); \
136  (gpio).GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_3; \
137  GPIO_Init(GPIOC, (&gpio)); \
138 }
139 #endif // ADC1_GPIO_INIT
140 #endif // USE_AD1
141 
142 /*
143  GPIO mapping for ADC2 pins.
144  Can be changed by predefining ADC2_GPIO_INIT.
145  Uses the same GPIOs as ADC1 (lisa specific).
146 */
147 #ifdef USE_AD2
148 #define ADC2_GPIO_INIT(gpio) { \
149  (gpio).GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; \
150  (gpio).GPIO_Mode = GPIO_Mode_AIN; \
151  GPIO_Init(GPIOB, (&gpio)); \
152  (gpio).GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_5; \
153  GPIO_Init(GPIOC, (&gpio)); \
154  }
155 #ifndef ADC2_GPIO_INIT
156 #define ADC2_GPIO_INIT(gpio) { }
157 #endif // ADC2_GPIO_INIT
158 #endif // USE_AD2
159 
160 // }}}
161 
162 /*
163  Currently, the enums adc1_channels and adc2_channels only
164  serve to resolve the number of channels on each ADC.
165 */
166 
167 /*
168  Separate buffers for each ADC.
169  Every ADC has a list of buffers, one for each active
170  channel.
171 */
172 
173 #ifdef USE_AD1
174 static struct adc_buf * adc1_buffers[NB_ADC1_CHANNELS];
175 #endif
176 #ifdef USE_AD2
177 static struct adc_buf * adc2_buffers[NB_ADC2_CHANNELS];
178 #endif
179 
180 /*
181  Static mapping from channel index to channel injection
182  index:
183 */
184 
185 /*
186  Maps integer value x to ADC_InjectedChannel_x,
187  so they can be iterated safely
188 */
190 /*
191  Maps integer value x to ADC_Channel_y, like
192 
193  0 --> ADC_Channel_5
194  1 --> ADC_Channel_8
195  2 --> ADC_Channel_13
196 
197  so they can be iterated incrementally.
198 */
200 
201 /*
202  TODO: Extend interface to allow adressing a
203  specific ADC (at least ADC1 and ADC2)?
204 */
205 void adc_buf_channel(uint8_t adc_channel,
206  struct adc_buf * s,
208 {
209  adc1_buffers[adc_channel] = s;
211 }
212 
213 // #define USE_AD_TIM4
214 /* Configure and enable RCC for peripherals (ADC1, ADC2, Timer) */
215 static inline void adc_init_rcc( void )
216 { // {{{
217 #if defined (USE_AD1) || defined (USE_AD2)
218  TIM_TypeDef * timer;
219  uint32_t rcc_apb;
220 #if defined(USE_AD_TIM4)
221  timer = TIM4;
222  rcc_apb = RCC_APB1Periph_TIM4;
223 #elif defined(USE_AD_TIM1)
224  timer = TIM1;
225  rcc_apb = RCC_APB2Periph_TIM1;
226 #else
227  timer = TIM2;
228  rcc_apb = RCC_APB1Periph_TIM2;
229 #endif
230 
231  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
232 
233  RCC_ADCCLKConfig(RCC_PCLK2_Div2);
234  RCC_APB1PeriphClockCmd(rcc_apb, ENABLE);
235  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB |
236  RCC_APB2Periph_GPIOC, ENABLE);
237 #ifdef USE_AD1
238  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
239 #endif
240 #ifdef USE_AD2
241  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);
242 #endif
243 
244  /* Time Base configuration */
245  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
246  TIM_TimeBaseStructure.TIM_Period = 0xFF;
247  TIM_TimeBaseStructure.TIM_Prescaler = 0x8;
248  TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
249  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
250  TIM_TimeBaseInit(timer, &TIM_TimeBaseStructure);
251  TIM_SelectOutputTrigger(timer, TIM_TRGOSource_Update);
252  TIM_Cmd(timer, ENABLE);
253 
254 #endif // defined (USE_AD1) || defined (USE_AD2)
255 } // }}}
256 
257 /* Configure and enable ADC interrupt */
258 static inline void adc_init_irq( void )
259 { // {{{
260  NVIC_InitTypeDef nvic;
261  nvic.NVIC_IRQChannel = ADC1_2_IRQn;
262  nvic.NVIC_IRQChannelPreemptionPriority = 0;
263  nvic.NVIC_IRQChannelSubPriority = 0;
264  nvic.NVIC_IRQChannelCmd = ENABLE;
265  NVIC_Init(&nvic);
266 } // }}}
267 
268 /*
269  Usage:
270 
271  adc_init_single(ADC1, 1, 1, 0, 0);
272 
273  ... would enable ADC1, enabling channels 1 and 2,
274  but not 3 and 4.
275 */
276 static inline void adc_init_single(ADC_TypeDef * adc_t,
277  uint8_t chan1, uint8_t chan2,
278  uint8_t chan3, uint8_t chan4)
279 {
280  GPIO_InitTypeDef gpio;
281  ADC_InitTypeDef adc;
282  uint8_t num_channels, rank;
283 
284  // Paranoia, must be down for 2+ ADC clock cycles before calibration
285  ADC_Cmd(adc_t, DISABLE);
286 
287  /* enable adc_t clock */
288  if (adc_t == ADC1) {
289 #ifdef USE_AD1
290  num_channels = NB_ADC1_CHANNELS;
291  ADC1_GPIO_INIT(gpio);
292 #endif
293  }
294  else if (adc_t == ADC2) {
295 #ifdef USE_AD2
296  num_channels = NB_ADC2_CHANNELS;
297  ADC2_GPIO_INIT(gpio);
298 #endif
299  }
300 
301  /* Configure ADC */
302 
303  adc.ADC_Mode = ADC_Mode_Independent;
304  adc.ADC_ScanConvMode = ENABLE;
305  adc.ADC_ContinuousConvMode = DISABLE;
306  adc.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
307  adc.ADC_DataAlign = ADC_DataAlign_Right;
308  adc.ADC_NbrOfChannel = 0; // No. of channels in regular mode
309  ADC_Init(adc_t, &adc);
310 
311  ADC_InjectedSequencerLengthConfig(adc_t, num_channels);
312 
313  rank = 1;
314  if (chan1) {
315  ADC_InjectedChannelConfig(adc_t, adc_channel_map[0], rank,
316  ADC_SampleTime_41Cycles5);
317  rank++;
318  }
319  if (chan2) {
320  ADC_InjectedChannelConfig(adc_t, adc_channel_map[1], rank,
321  ADC_SampleTime_41Cycles5);
322  rank++;
323  }
324  if (chan3) {
325  ADC_InjectedChannelConfig(adc_t, adc_channel_map[2], rank,
326  ADC_SampleTime_41Cycles5);
327  rank++;
328  }
329  if (chan4) {
330  ADC_InjectedChannelConfig(adc_t, adc_channel_map[3], rank,
331  ADC_SampleTime_41Cycles5);
332  }
333 
334 
335  ADC_ExternalTrigInjectedConvCmd(adc_t, ENABLE);
336 #if defined(USE_AD_TIM4)
337  ADC_ExternalTrigInjectedConvConfig(adc_t, ADC_ExternalTrigInjecConv_T4_TRGO);
338 #elif defined(USE_AD_TIM1)
339  ADC_ExternalTrigInjectedConvConfig(adc_t, ADC_ExternalTrigInjecConv_T1_TRGO);
340 #else
341  ADC_ExternalTrigInjectedConvConfig(adc_t, ADC_ExternalTrigInjecConv_T2_TRGO);
342 #endif
343 
344  /* Enable ADC<X> JEOC interrupt */
345  ADC_ITConfig(adc_t, ADC_IT_JEOC, ENABLE);
346 
347  /* Enable ADC<X> */
348  ADC_Cmd(adc_t, ENABLE);
349 
350  /* Enable ADC<X> reset calibaration register */
351  ADC_ResetCalibration(adc_t);
352 
353  /* Check the end of ADC<X> reset calibration */
354  while (ADC_GetResetCalibrationStatus(adc_t)) ;
355  /* Start ADC<X> calibaration */
356  ADC_StartCalibration(adc_t);
357  /* Check the end of ADC<X> calibration */
358  while (ADC_GetCalibrationStatus(adc_t)) ;
359 
360 } // adc_init_single
361 
362 void adc_init( void ) {
363 
364  /* initialize buffer pointers with 0 (not set).
365  buffer null pointers will be ignored in interrupt
366  handler, which is important as there are no
367  buffers registered at the time the ADC trigger
368  interrupt is enabled.
369  */
371 #ifdef USE_AD1
372  for(channel = 0; channel < NB_ADC1_CHANNELS; channel++)
373  adc1_buffers[channel] = NULL;
374 #endif
375 #ifdef USE_AD2
376  for(channel = 0; channel < NB_ADC2_CHANNELS; channel++)
377  adc2_buffers[channel] = NULL;
378 #endif
379 
381  adc_injected_channels[0] = ADC_InjectedChannel_1;
382  adc_injected_channels[1] = ADC_InjectedChannel_2;
383  adc_injected_channels[2] = ADC_InjectedChannel_3;
384  adc_injected_channels[3] = ADC_InjectedChannel_4;
387  // FIXME for now we get battery voltage this way
388  // adc_channel_map[2] = BOARD_ADC_CHANNEL_3;
391 
392  adc_init_rcc();
393  adc_init_irq();
394 
395 // adc_init_single(ADCx, c1, c2, c3, c4)
396 // {{{
397 #ifdef USE_AD1
399 #ifdef USE_AD1_1
400  1,
401 #else
402  0,
403 #endif
404 #ifdef USE_AD1_2
405  1,
406 #else
407  0,
408 #endif
409 #ifdef USE_AD1_3
410  1,
411 #else
412  0,
413 #endif
414 #ifdef USE_AD1_4
415  1
416 #else
417  0
418 #endif
419  );
420 #endif // USE_AD1
421 
422 #ifdef USE_AD2
423  adc_init_single(ADC2,
424 #ifdef USE_AD2_1
425  1,
426 #else
427  0,
428 #endif
429 #ifdef USE_AD2_2
430  1,
431 #else
432  0,
433 #endif
434 #ifdef USE_AD2_3
435  1,
436 #else
437  0,
438 #endif
439 #ifdef USE_AD2_4
440  1
441 #else
442  0
443 #endif
444  );
445 #endif // USE_AD2
446 
447 // }}}
448 }
449 
450 static inline void adc_push_sample(struct adc_buf * buf, uint16_t value) {
451  uint8_t new_head = buf->head + 1;
452 
453  if (new_head >= buf->av_nb_sample) { new_head = 0; }
454  buf->sum -= buf->values[new_head];
455  buf->values[new_head] = value;
456  buf->sum += value;
457  buf->head = new_head;
458 }
459 
464 {
465  uint8_t channel = 0;
466  uint16_t value = 0;
467  struct adc_buf * buf;
468 
469 #ifdef USE_AD1
470  // Clear Injected End Of Conversion
471  ADC_ClearITPendingBit(ADC1, ADC_IT_JEOC);
472  for(channel = 0; channel < NB_ADC1_CHANNELS; channel++) {
473  buf = adc1_buffers[channel];
474  if(buf) {
475  value = ADC_GetInjectedConversionValue(ADC1, adc_injected_channels[channel]);
476  adc_push_sample(buf, value);
477  }
478  }
480 #endif
481 #ifdef USE_AD2
482  // Clear Injected End Of Conversion
483  ADC_ClearITPendingBit(ADC2, ADC_IT_JEOC);
484  for(channel = 0; channel < NB_ADC2_CHANNELS; channel++) {
485  buf = adc2_buffers[channel];
486  if(buf) {
487  value = ADC_GetInjectedConversionValue(ADC2, adc_injected_channels[channel]);
488  adc_push_sample(buf, value);
489  }
490  }
492 #endif
493 }
#define ADC1
Definition: LPC21xx.h:338
unsigned short uint16_t
Definition: types.h:16
uint8_t adc_new_data_trigger
Definition: adc_arch.c:100
static uint8_t adc_injected_channels[4]
Definition: adc_arch.c:189
static uint8_t adc_channel_map[4]
Definition: adc_arch.c:199
void adc1_2_irq_handler(void)
This is the driver for the analog to digital converters on STM32.
Definition: adc_arch.c:463
uint16_t values[MAX_AV_NB_SAMPLE]
Definition: adc.h:62
#define BOARD_ADC_CHANNEL_4
Definition: lisa_l_1.0.h:40
static void adc_init_single(ADC_TypeDef *adc_t, uint8_t chan1, uint8_t chan2, uint8_t chan3, uint8_t chan4)
Definition: adc_arch.c:276
#define BOARD_ADC_CHANNEL_1
Definition: lisa_l_1.0.h:35
#define USE_AD1_2
Definition: booz_1.0.h:128
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 BOARD_ADC_CHANNEL_2
Definition: lisa_l_1.0.h:36
void adc_buf_channel(uint8_t adc_channel __attribute__((unused)), struct adc_buf *s __attribute__((unused)), uint8_t av_nb_sample __attribute__((unused)))
Definition: adc_arch.c:3
Generic interface for all ADC hardware drivers, independent from microcontroller architecture.
Definition: adc.h:60
static volatile uint8_t channel
unsigned long uint32_t
Definition: types.h:18
static void adc_push_sample(struct adc_buf *buf, uint16_t sample)
Definition: adc_arch.c:450
unsigned char uint8_t
Definition: types.h:14
void adc_init(void)
Starts conversions.
Definition: adc_arch.c:189
static void adc_init_irq(void)
Definition: adc_arch.c:258
arch independent LED (Light Emitting Diodes) API
#define USE_AD1_4
Definition: logom_2.6.h:175
#define BOARD_ADC_CHANNEL_3
Definition: lisa_l_1.0.h:39
uint8_t head
Definition: adc.h:63
static void adc_init_rcc(void)
Definition: adc_arch.c:215