Paparazzi UAS  v6.1.0_stable
Paparazzi is a free software Unmanned Aircraft System.
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
adc_arch.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2013 AggieAir, A Remote Sensing Unmanned Aerial System for Scientific Applications
3  * Utah State University, http://aggieair.usu.edu/
4  *
5  * Michal Podhradsky (michal.podhradsky@aggiemail.usu.edu)
6  * Calvin Coopmans (c.r.coopmans@ieee.org)
7  *
8  * Copyright (C) 2015 Gautier Hattenberger, Alexandre Bustico
9  *
10  * This file is part of paparazzi.
11  *
12  * paparazzi is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2, or (at your option)
15  * any later version.
16  *
17  * paparazzi is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with paparazzi; see the file COPYING. If not, write to
24  * the Free Software Foundation, 59 Temple Place - Suite 330,
25  * Boston, MA 02111-1307, USA.
26  */
53 #include "mcu_periph/adc.h"
54 #include "mcu_periph/gpio.h"
55 #include "hal.h"
56 #include "std.h"
57 #include "mcu_periph/ram_arch.h"
58 
59 
60 // Macros to automatically enable the correct ADC
61 // FIXME we can't use NB_ADC1_CHANNELS it is not a macro
62 //#if NB_ADC1_CHANNELS != 0
63 #ifndef USE_AD1
64 #define USE_AD1 1
65 #endif
66 
68 
69 // architecture dependent settings
70 #if defined(__STM32F10x_H) || defined(__STM32F105xC_H) || defined (__STM32F107xC_H)
71 // STM32F1xx
72 #define ADC_SAMPLE_RATE ADC_SAMPLE_41P5
73 #define ADC_CR2_CFG ADC_CR2_TSVREFE
74 #elif defined(__STM32F4xx_H) || defined(__STM32F7xx_H)
75 // STM32F4xx | STM32F7xx
76 #define ADC_SAMPLE_RATE ADC_SAMPLE_480
77 #define ADC_CR2_CFG ADC_CR2_SWSTART
78 #elif defined(__STM32F373xC_H)
79 #define ADC_SAMPLE_RATE ADC_SAMPLE_239P5
80 #define ADC_CR2_CFG ADC_CR2_SWSTART
81 #elif defined(__STM32F3xx_H)
82 #define ADC_SAMPLE_RATE ADC_SMPR_SMP_601P5
83 #endif
84 
85 
86 // Create channel map
88 #ifdef AD1_1_CHANNEL
90 #endif
91 #ifdef AD1_2_CHANNEL
93 #endif
94 #ifdef AD1_3_CHANNEL
96 #endif
97 #ifdef AD1_4_CHANNEL
99 #endif
100 #ifdef AD1_5_CHANNEL
102 #endif
103 #ifdef AD1_6_CHANNEL
104  AD1_6_CHANNEL,
105 #endif
106 #ifdef AD1_7_CHANNEL
108 #endif
109 #ifdef AD1_8_CHANNEL
110  AD1_8_CHANNEL,
111 #endif
112 #ifdef AD1_9_CHANNEL
114 #endif
115 #ifdef AD1_10_CHANNEL
116  AD1_10_CHANNEL,
117 #endif
118 #ifdef AD1_11_CHANNEL
119  AD1_11_CHANNEL,
120 #endif
121 #ifdef AD1_12_CHANNEL
122  AD1_12_CHANNEL,
123 #endif
124 #ifdef AD1_13_CHANNEL
125  AD1_13_CHANNEL,
126 #endif
127 #ifdef AD1_14_CHANNEL
128  AD1_14_CHANNEL,
129 #endif
130 #ifdef AD1_15_CHANNEL
131  AD1_15_CHANNEL,
132 #endif
133 #ifdef AD1_16_CHANNEL
134  AD1_16_CHANNEL,
135 #endif
136 };
137 
139 ADCDriver *adcp_err = NULL;
140 
141 // adc_samples buffer
142 // FIXME compute size to have to correct number of samples ?
143 #ifndef ADC_BUF_DEPTH
144 #define ADC_BUF_DEPTH (MAX_AV_NB_SAMPLE/2)
145 #endif
146 static IN_DMA_SECTION(adcsample_t adc_samples[ADC_NUM_CHANNELS * ADC_BUF_DEPTH]);
147 
148 #if USE_AD1
152 #endif
153 #if USE_AD2
154 #error ADC2_not implemented in ChibiOS
155 #endif
156 #if USE_AD3
157 #error ADC3_not implemented in ChibiOS
158 #endif
159 
160 #if USE_ADC_WATCHDOG
161 // watchdog structure with adc bank and callback
162 static struct {
163  ADCDriver *adc;
164  adc_channels_num_t channel;
165  adcsample_t vmin;
166  adc_watchdog_callback cb;
167 } adc_watchdog;
168 #endif
169 
170 // From libopencm3
171 static void adc_regular_sequence(uint32_t *sqr1, uint32_t *sqr2, uint32_t *sqr3, uint8_t length, const uint8_t channel[])
172 {
173  uint32_t first6 = 0;
174  uint32_t second6 = 0;
175  uint32_t third6 = ADC_SQR1_NUM_CH(length);
176  uint8_t i = 0;
177 
178  for (i = 1; i <= length; i++) {
179  if (i <= 6) {
180  first6 |= (channel[i - 1] << ((i - 1) * 5));
181  }
182  if ((i > 6) && (i <= 12)) {
183  second6 |= (channel[i - 1] << ((i - 6 - 1) * 5));
184  }
185  if ((i > 12) && (i <= 18)) {
186  third6 |= (channel[i - 1] << ((i - 12 - 1) * 5));
187  }
188  }
189  *sqr3 = first6;
190  *sqr2 = second6;
191  *sqr1 = third6;
192 }
193 
194 // From libopencm3
195 static void adc_sample_time_on_all_channels(uint32_t *smpr1, uint32_t *smpr2, uint8_t time)
196 {
197  uint8_t i;
198  uint32_t reg32 = 0;
199 
200  for (i = 0; i <= 9; i++) {
201  reg32 |= (time << (i * 3));
202  }
203  *smpr2 = reg32;
204 
205  reg32 = 0;
206  for (i = 10; i <= 17; i++) {
207  reg32 |= (time << ((i - 10) * 3));
208  }
209  *smpr1 = reg32;
210 }
211 
224 void adc1callback(ADCDriver *adcp)
225 {
226  if (adcp->state != ADC_STOP) {
227 #if USE_AD1
228  const size_t n = ADC_BUF_DEPTH / 2U;
229  // depending on half buffer that has just been filled
230  // if adcIsBufferComplete return true, the last filled
231  // half buffer start in the middle of buffer, else, is start at
232  // beginiing of buffer
233  const adcsample_t *buffer = adc_samples + (adcIsBufferComplete(adcp) ?
234  n * ADC_NUM_CHANNELS : 0U);
235 
236  for (int channel = 0; channel < ADC_NUM_CHANNELS; channel++) {
237  if (adc1_buffers[channel] != NULL) {
238  adc1_sum_tmp[channel] = 0;
239  if (n > 0) {
240  adc1_samples_tmp[channel] = n;
241  } else {
242  adc1_samples_tmp[channel] = 1;
243  }
244  for (unsigned int sample = 0; sample < n; sample++) {
245  adc1_sum_tmp[channel] += buffer[channel + sample * ADC_NUM_CHANNELS];
246  }
247  }
248  }
249  chSysLockFromISR();
250  for (int channel = 0; channel < ADC_NUM_CHANNELS; channel++) {
251  if (adc1_buffers[channel] != NULL) {
252  adc1_buffers[channel]->sum = adc1_sum_tmp[channel];
253  adc1_buffers[channel]->av_nb_sample = adc1_samples_tmp[channel];
254  }
255  }
256 #if USE_ADC_WATCHDOG
257 #pragma GCC diagnostic push
258 #pragma GCC diagnostic ignored "-Wtype-limits" // remove warning when ADC_NUM_CHANNELS is 0 and test always false
259  if ((adc_watchdog.adc == adcp) &&
260  (adc_watchdog.channel < ADC_NUM_CHANNELS) &&
261  (adc_watchdog.cb != NULL)) {
262  if (adc1_buffers[adc_watchdog.channel]->sum <
263  (adc1_buffers[adc_watchdog.channel]->av_nb_sample * adc_watchdog.vmin)) {
264  adc_watchdog.cb();
265  }
266  }
267 #pragma GCC diagnostic pop
268 #endif // USE_ADC_WATCHDOG
269 
270  chSysUnlockFromISR();
271 #endif
272  }
273 }
274 
275 
281 static void adcerrorcallback(ADCDriver *adcp, adcerror_t err)
282 {
283  chSysLockFromISR();
284  adcp_err = adcp;
285  adc_error_flag = err;
286  chSysUnlockFromISR();
287 }
288 
292 void adc_buf_channel(uint8_t adc_channel, struct adc_buf *s, uint8_t av_nb_sample)
293 {
294  // check for out-of-bounds access
295 #pragma GCC diagnostic push
296 #pragma GCC diagnostic ignored "-Wtype-limits" // remove warning when ADC_NUM_CHANNELS is 0 and test always true
297  if (adc_channel >= ADC_NUM_CHANNELS) { return; }
298 #pragma GCC diagnostic pop
299  adc1_buffers[adc_channel] = s;
300  if (av_nb_sample <= MAX_AV_NB_SAMPLE) {
301  s->av_nb_sample = av_nb_sample;
302  } else {
303  s->av_nb_sample = MAX_AV_NB_SAMPLE;
304  }
305 }
306 
311 static ADCConversionGroup adcgrpcfg;
312 
318 void adc_init(void)
319 {
320  /* Init GPIO ports for ADC operation
321  */
322 #if USE_ADC_1
323  PRINT_CONFIG_MSG("Info: Using ADC_1");
325 #endif
326 #if USE_ADC_2
327  PRINT_CONFIG_MSG("Info: Using ADC_2");
329 #endif
330 #if USE_ADC_3
331  PRINT_CONFIG_MSG("Info: Using ADC_3");
333 #endif
334 #if USE_ADC_4
335  PRINT_CONFIG_MSG("Info: Using ADC_4");
337 #endif
338 #if USE_ADC_5
339  PRINT_CONFIG_MSG("Info: Using ADC_5");
341 #endif
342 #if USE_ADC_6
343  PRINT_CONFIG_MSG("Info: Using ADC_6");
344  gpio_setup_pin_analog(ADC_6_GPIO_PORT, ADC_6_GPIO_PIN);
345 #endif
346 #if USE_ADC_7
347  PRINT_CONFIG_MSG("Info: Using ADC_7");
349 #endif
350 #if USE_ADC_8
351  PRINT_CONFIG_MSG("Info: Using ADC_8");
352  gpio_setup_pin_analog(ADC_8_GPIO_PORT, ADC_8_GPIO_PIN);
353 #endif
354 #if USE_ADC_9
355  PRINT_CONFIG_MSG("Info: Using ADC_9");
357 #endif
358 
359  // Configuration register
360  uint32_t sqr1, sqr2, sqr3;
362 
363  uint32_t smpr1, smpr2;
364  adc_sample_time_on_all_channels(&smpr1, &smpr2, ADC_SAMPLE_RATE);
365 
366 #if USE_ADC_WATCHDOG
367  adc_watchdog.adc = NULL;
368  adc_watchdog.cb = NULL;
369  adc_watchdog.channel = 0;
370  adc_watchdog.vmin = (1 << 12) - 1; // max adc
371 #endif
372 
373  adcgrpcfg.circular = TRUE;
374  adcgrpcfg.num_channels = ADC_NUM_CHANNELS;
375  adcgrpcfg.end_cb = adc1callback;
376  adcgrpcfg.error_cb = adcerrorcallback;
377 #if defined(__STM32F373xC_H)
378  adcgrpcfg.u.adc.smpr[0] = smpr1;
379  adcgrpcfg.u.adc.smpr[1] = smpr2;
380  adcgrpcfg.u.adc.sqr[0] = sqr1;
381  adcgrpcfg.u.adc.sqr[1] = sqr2;
382  adcgrpcfg.u.adc.sqr[2] = sqr3;
383  adcgrpcfg.u.adc.cr1 = 0;
384  adcgrpcfg.u.adc.cr2 = ADC_CR2_CFG;
385 #elif defined(__STM32F3xx_H)
386  //TODO: check if something needs to be done with the other regs (can be found in ~/paparazzi/sw/ext/chibios/os/hal/ports/STM32/LLD/ADCv3)
387 #warning ADCs not tested with stm32f30
388  // cfgr
389  // tr1
390 
391  adcgrpcfg.smpr[0] = smpr1; // is this even correct?
392  adcgrpcfg.smpr[1] = smpr2;
393  adcgrpcfg.sqr[0] = sqr1;
394  adcgrpcfg.sqr[1] = sqr2;
395  adcgrpcfg.sqr[2] = sqr3;
396 #else
397  adcgrpcfg.cr2 = ADC_CR2_CFG;
398  adcgrpcfg.cr1 = 0;
399  adcgrpcfg.smpr1 = smpr1;
400  adcgrpcfg.smpr2 = smpr2;
401  adcgrpcfg.sqr1 = sqr1;
402  adcgrpcfg.sqr2 = sqr2;
403  adcgrpcfg.sqr3 = sqr3;
404 #endif
405 
406  // Start ADC in continious conversion mode
407  adcStart(&ADCD1, NULL);
408  adcStartConversion(&ADCD1, &adcgrpcfg, adc_samples, ADC_BUF_DEPTH);
409 }
410 
411 #if USE_ADC_WATCHDOG
412 void register_adc_watchdog(ADCDriver *adc, adc_channels_num_t channel, adcsample_t vmin,
413  adc_watchdog_callback cb)
414 {
415  for (int i = 0; i < NB_ADC1_CHANNELS; i++) { // FIXME when more than ADC1 will be in use
416  if (adc_channel_map[i] == channel) {
417  adc_watchdog.adc = adc;
418  adc_watchdog.channel = i;
419  adc_watchdog.vmin = vmin;
420  adc_watchdog.cb = cb;
421  break;
422  }
423  }
424 }
425 #endif
ADC_9_GPIO_PIN
#define ADC_9_GPIO_PIN
Definition: nucleo144_f767zi.h:135
uint32_t
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
Definition: vl53l1_types.h:78
uint8_t
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.
Definition: vl53l1_types.h:98
AD1_5_CHANNEL
#define AD1_5_CHANNEL
Definition: board.h:281
AD1_1_CHANNEL
#define AD1_1_CHANNEL
Definition: cjmcu.h:62
ADC_1_GPIO_PIN
#define ADC_1_GPIO_PIN
Definition: cjmcu.h:65
AD1_9_CHANNEL
#define AD1_9_CHANNEL
Definition: nucleo144_f767zi.h:132
ADC_5_GPIO_PORT
#define ADC_5_GPIO_PORT
Definition: board.h:283
ADC_7_GPIO_PIN
#define ADC_7_GPIO_PIN
Definition: chimera.h:191
adc_buf_channel
void adc_buf_channel(uint8_t adc_channel, struct adc_buf *s, uint8_t av_nb_sample)
Link between ChibiOS ADC drivers and Paparazzi adc_buffers.
Definition: adc_arch.c:292
adc1callback
void adc1callback(ADCDriver *adcp)
Adc1 callback.
Definition: adc_arch.c:224
ADC_2_GPIO_PIN
#define ADC_2_GPIO_PIN
Definition: crazybee_f4_1.0.h:216
adc_sample_time_on_all_channels
static void adc_sample_time_on_all_channels(uint32_t *smpr1, uint32_t *smpr2, uint8_t time)
Definition: adc_arch.c:195
s
static uint32_t s
Definition: light_scheduler.c:33
ADC_BUF_DEPTH
#define ADC_BUF_DEPTH
Definition: adc_arch.c:144
AD1_4_CHANNEL
#define AD1_4_CHANNEL
Definition: board.h:192
adc.h
arch independent ADC (Analog to Digital Converter) API
AD1_7_CHANNEL
#define AD1_7_CHANNEL
Definition: chimera.h:188
adc_buf::sum
uint32_t sum
Definition: adc.h:54
adc_channel_map
static const uint8_t adc_channel_map[ADC_NUM_CHANNELS]
#endif
Definition: adc_arch.c:87
adc_error_flag
uint8_t adc_error_flag
Definition: adc_arch.c:138
ADC_7_GPIO_PORT
#define ADC_7_GPIO_PORT
Definition: chimera.h:190
adcgrpcfg
static ADCConversionGroup adcgrpcfg
Configuration structure must be global.
Definition: adc_arch.c:311
std.h
ADC_3_GPIO_PIN
#define ADC_3_GPIO_PIN
Definition: lisa_l_1.0.h:151
AD1_2_CHANNEL
#define AD1_2_CHANNEL
Definition: crazybee_f4_1.0.h:213
IN_DMA_SECTION
static IN_DMA_SECTION(adcsample_t adc_samples[ADC_NUM_CHANNELS *ADC_BUF_DEPTH])
adcerrorcallback
static void adcerrorcallback(ADCDriver *adcp, adcerror_t err)
Adc error callback.
Definition: adc_arch.c:281
NB_ADC1_CHANNELS
@ NB_ADC1_CHANNELS
Definition: adc_arch.h:90
adc_buf::av_nb_sample
uint8_t av_nb_sample
Definition: adc.h:57
ADC_2_GPIO_PORT
#define ADC_2_GPIO_PORT
Definition: crazybee_f4_1.0.h:215
ADC_3_GPIO_PORT
#define ADC_3_GPIO_PORT
Definition: lisa_l_1.0.h:150
ADC_5_GPIO_PIN
#define ADC_5_GPIO_PIN
Definition: board.h:284
adc_regular_sequence
static void adc_regular_sequence(uint32_t *sqr1, uint32_t *sqr2, uint32_t *sqr3, uint8_t length, const uint8_t channel[])
Definition: adc_arch.c:171
ADC_9_GPIO_PORT
#define ADC_9_GPIO_PORT
Definition: nucleo144_f767zi.h:134
PRINT_CONFIG_MSG
PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
adc_init
void adc_init(void)
Adc init.
Definition: adc_arch.c:318
gpio.h
MAX_AV_NB_SAMPLE
#define MAX_AV_NB_SAMPLE
Definition: adc.h:40
ram_arch.h
vmin
float vmin
Definition: obstacle_avoidance.c:120
gpio_setup_pin_analog
void gpio_setup_pin_analog(ioportid_t port, uint16_t pin)
Setup a gpio for analog use.
Definition: gpio_arch.c:86
ADC_4_GPIO_PIN
#define ADC_4_GPIO_PIN
Definition: board.h:195
ADC_NUM_CHANNELS
#define ADC_NUM_CHANNELS
Definition: adc_arch.h:93
AD1_3_CHANNEL
#define AD1_3_CHANNEL
Definition: lisa_l_1.0.h:148
adc1_samples_tmp
static uint8_t adc1_samples_tmp[ADC_NUM_CHANNELS]
Definition: adc_arch.c:151
ADC_1_GPIO_PORT
#define ADC_1_GPIO_PORT
Definition: cjmcu.h:64
TRUE
#define TRUE
Definition: std.h:4
adc1_sum_tmp
static uint32_t adc1_sum_tmp[ADC_NUM_CHANNELS]
Definition: adc_arch.c:150
ADC_4_GPIO_PORT
#define ADC_4_GPIO_PORT
Definition: board.h:194
adcp_err
ADCDriver * adcp_err
Definition: adc_arch.c:139
adc1_buffers
static struct adc_buf * adc1_buffers[ADC_NUM_CHANNELS]
Definition: adc_arch.c:149
adc_buf
Generic interface for all ADC hardware drivers, independent from microcontroller architecture.
Definition: adc.h:53