Paparazzi UAS  v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
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
67 
68 
69 /* Set the default sample rate */
70 #if !defined(ADC_SAMPLE_RATE)
71 #if defined(STM32H7XX)
72 #define ADC_SAMPLE_RATE ADC_SMPR_SMP_384P5
73 #elif defined(STM32F3XX)
74 #define ADC_SAMPLE_RATE ADC_SMPR_SMP_601P5
75 #else
76 #define ADC_SAMPLE_RATE ADC_SAMPLE_480
77 #endif
78 #endif
79 
80 // Create channel map
82 #ifdef AD1_1_CHANNEL
84 #endif
85 #ifdef AD1_2_CHANNEL
87 #endif
88 #ifdef AD1_3_CHANNEL
90 #endif
91 #ifdef AD1_4_CHANNEL
93 #endif
94 #ifdef AD1_5_CHANNEL
96 #endif
97 #ifdef AD1_6_CHANNEL
98  AD1_6_CHANNEL,
99 #endif
100 #ifdef AD1_7_CHANNEL
102 #endif
103 #ifdef AD1_8_CHANNEL
104  AD1_8_CHANNEL,
105 #endif
106 #ifdef AD1_9_CHANNEL
108 #endif
109 #ifdef AD1_10_CHANNEL
110  AD1_10_CHANNEL,
111 #endif
112 #ifdef AD1_11_CHANNEL
113  AD1_11_CHANNEL,
114 #endif
115 #ifdef AD1_12_CHANNEL
116  AD1_12_CHANNEL,
117 #endif
118 #ifdef AD1_13_CHANNEL
119  AD1_13_CHANNEL,
120 #endif
121 #ifdef AD1_14_CHANNEL
122  AD1_14_CHANNEL,
123 #endif
124 #ifdef AD1_15_CHANNEL
125  AD1_15_CHANNEL,
126 #endif
127 #ifdef AD1_16_CHANNEL
128  AD1_16_CHANNEL,
129 #endif
130 };
131 
133 ADCDriver *adcp_err = NULL;
134 
135 // adc_samples buffer
136 // FIXME compute size to have to correct number of samples ?
137 #ifndef ADC_BUF_DEPTH
138 #define ADC_BUF_DEPTH (MAX_AV_NB_SAMPLE/2)
139 #endif
140 static IN_DMA_SECTION(adcsample_t adc_samples[ADC_NUM_CHANNELS * MAX_AV_NB_SAMPLE]);
141 
142 #if USE_AD1
143 static ADCConversionGroup adc1_group;
147 #endif
148 #if USE_AD2
149 #error ADC2_not implemented in ChibiOS
150 #endif
151 #if USE_AD3
152 #error ADC3_not implemented in ChibiOS
153 #endif
154 
155 #if USE_ADC_WATCHDOG
156 // watchdog structure with adc bank and callback
157 static struct {
158  ADCDriver *adc;
159  adc_channels_num_t channel;
160  adcsample_t vmin;
161  adc_watchdog_callback cb;
162 } adc_watchdog;
163 #endif
164 
175 static void adc_configure(ADCConversionGroup *cfg, uint8_t num_channels, const uint8_t channels[], uint32_t sample_rate,
176  adccallback_t end_cb, adcerrorcallback_t error_cb)
177 {
178  // Set the general configuration
179  cfg->circular = true;
180  cfg->num_channels = num_channels;
181  cfg->end_cb = end_cb;
182  cfg->error_cb = error_cb;
183 
184  // Set to 16bits by default else try 12bit
185 #if defined(ADC_CFGR_RES_16BITS)
186  cfg->cfgr = ADC_CFGR_CONT | ADC_CFGR_RES_16BITS;
187 #elif defined(ADC_CFGR_RES_12BITS)
188  cfg->cfgr = ADC_CFGR_CONT | ADC_CFGR_RES_12BITS;
189 #else
190  cfg->sqr1 = ADC_SQR1_NUM_CH(num_channels);
191  cfg->cr2 = ADC_CR2_SWSTART;
192 
193 #if defined(ADC_CR2_TSVREFE)
194  cfg->cr2 |= ADC_CR2_TSVREFE;
195 #endif
196 #endif
197 
198  // Go through all the channels
199  for (uint8_t i = 0; i < num_channels; i++) {
200  uint8_t chan = channels[i];
201 
202 #if defined(STM32H7XX) || defined(STM32F3XX) || defined(STM32G4XX) || defined(STM32L4XX)
203  cfg->pcsel |= (1 << chan);
204  cfg->smpr[chan / 10] |= sample_rate << (3 * (chan % 10));
205 
206  if (i < 4) {
207  cfg->sqr[0] |= chan << (6 * (i + 1));
208  } else if (i < 9) {
209  cfg->sqr[1] |= chan << (6 * (i - 4));
210  } else {
211  cfg->sqr[2] |= chan << (6 * (i - 9));
212  }
213 #else
214  if (chan < 10) {
215  cfg->smpr2 |= sample_rate << (3 * chan);
216  } else {
217  cfg->smpr1 |= sample_rate << (3 * (chan - 10));
218  }
219 
220  if (i < 6) {
221  cfg->sqr3 |= chan << (5 * i);
222  } else if (i < 12) {
223  cfg->sqr2 |= chan << (5 * (i - 6));
224  } else {
225  cfg->sqr3 |= chan << (5 * (i - 12));
226  }
227 #endif
228  }
229 }
230 
243 void adc1callback(ADCDriver *adcp)
244 {
245  if (adcp->state != ADC_STOP) {
246 #if USE_AD1
247  const size_t n = ADC_BUF_DEPTH / 2U;
248  // depending on half buffer that has just been filled
249  // if adcIsBufferComplete return true, the last filled
250  // half buffer start in the middle of buffer, else, is start at
251  // beginiing of buffer
252  const adcsample_t *buffer = adc_samples + (adcIsBufferComplete(adcp) ?
253  n *ADC_NUM_CHANNELS : 0U);
254  cacheBufferInvalidate(adc_samples, sizeof(adc_samples));
255 
256  for (int channel = 0; channel < ADC_NUM_CHANNELS; channel++) {
257  if (adc1_buffers[channel] != NULL) {
258  adc1_sum_tmp[channel] = 0;
259  if (n > 0) {
260  adc1_samples_tmp[channel] = n;
261  } else {
262  adc1_samples_tmp[channel] = 1;
263  }
264  for (unsigned int sample = 0; sample < n; sample++) {
265  adc1_sum_tmp[channel] += buffer[channel + sample * ADC_NUM_CHANNELS];
266  }
267  }
268  }
269  chSysLockFromISR();
270  for (int channel = 0; channel < ADC_NUM_CHANNELS; channel++) {
271  if (adc1_buffers[channel] != NULL) {
272  adc1_buffers[channel]->sum = adc1_sum_tmp[channel];
273  adc1_buffers[channel]->av_nb_sample = adc1_samples_tmp[channel];
274  }
275  }
276 #if USE_ADC_WATCHDOG
277 #pragma GCC diagnostic push
278 #pragma GCC diagnostic ignored "-Wtype-limits" // remove warning when ADC_NUM_CHANNELS is 0 and test always false
279  if ((adc_watchdog.adc == adcp) &&
280  (adc_watchdog.channel < ADC_NUM_CHANNELS) &&
281  (adc_watchdog.cb != NULL)) {
282  if (adc1_buffers[adc_watchdog.channel]->sum <
283  (adc1_buffers[adc_watchdog.channel]->av_nb_sample * adc_watchdog.vmin)) {
284  adc_watchdog.cb();
285  }
286  }
287 #pragma GCC diagnostic pop
288 #endif // USE_ADC_WATCHDOG
289 
290  chSysUnlockFromISR();
291 #endif
292  }
293 }
294 
295 
301 static void adcerrorcallback(ADCDriver *adcp, adcerror_t err)
302 {
303  chSysLockFromISR();
304  adcp_err = adcp;
305  adc_error_flag = err;
306  chSysUnlockFromISR();
307 }
308 
312 void adc_buf_channel(uint8_t adc_channel, struct adc_buf *s, uint8_t av_nb_sample)
313 {
314  // check for out-of-bounds access
315 #pragma GCC diagnostic push
316 #pragma GCC diagnostic ignored "-Wtype-limits" // remove warning when ADC_NUM_CHANNELS is 0 and test always true
317  if (adc_channel >= ADC_NUM_CHANNELS) { return; }
318 #pragma GCC diagnostic pop
319  adc1_buffers[adc_channel] = s;
320  if (av_nb_sample <= MAX_AV_NB_SAMPLE) {
321  s->av_nb_sample = av_nb_sample;
322  } else {
323  s->av_nb_sample = MAX_AV_NB_SAMPLE;
324  }
325 }
326 
332 void adc_init(void)
333 {
334  /* Init GPIO ports for ADC operation
335  */
336 #if USE_ADC_1
337  PRINT_CONFIG_MSG("Info: Using ADC_1");
339 #endif
340 #if USE_ADC_2
341  PRINT_CONFIG_MSG("Info: Using ADC_2");
343 #endif
344 #if USE_ADC_3
345  PRINT_CONFIG_MSG("Info: Using ADC_3");
347 #endif
348 #if USE_ADC_4
349  PRINT_CONFIG_MSG("Info: Using ADC_4");
351 #endif
352 #if USE_ADC_5
353  PRINT_CONFIG_MSG("Info: Using ADC_5");
355 #endif
356 #if USE_ADC_6
357  PRINT_CONFIG_MSG("Info: Using ADC_6");
358  gpio_setup_pin_analog(ADC_6_GPIO_PORT, ADC_6_GPIO_PIN);
359 #endif
360 #if USE_ADC_7
361  PRINT_CONFIG_MSG("Info: Using ADC_7");
363 #endif
364 #if USE_ADC_8
365  PRINT_CONFIG_MSG("Info: Using ADC_8");
366  gpio_setup_pin_analog(ADC_8_GPIO_PORT, ADC_8_GPIO_PIN);
367 #endif
368 #if USE_ADC_9
369  PRINT_CONFIG_MSG("Info: Using ADC_9");
371 #endif
372 
373 #if USE_ADC_WATCHDOG
374  adc_watchdog.adc = NULL;
375  adc_watchdog.cb = NULL;
376  adc_watchdog.channel = 0;
377  adc_watchdog.vmin = (1 << 12) - 1; // max adc
378 #endif
379 
380  // Configure the ADC structure
382 
383  // Start ADC in continious conversion mode
384  adcStart(&ADCD1, NULL);
385  adcStartConversion(&ADCD1, &adc1_group, adc_samples, ADC_BUF_DEPTH);
386 }
387 
388 #if USE_ADC_WATCHDOG
389 void register_adc_watchdog(ADCDriver *adc, adc_channels_num_t channel, adcsample_t vmin,
390  adc_watchdog_callback cb)
391 {
392  for (int i = 0; i < NB_ADC1_CHANNELS; i++) { // FIXME when more than ADC1 will be in use
393  if (adc_channel_map[i] == channel) {
394  adc_watchdog.adc = adc;
395  adc_watchdog.channel = i;
396  adc_watchdog.vmin = vmin;
397  adc_watchdog.cb = cb;
398  break;
399  }
400  }
401 }
402 #endif
arch independent ADC (Analog to Digital Converter) API
uint32_t sum
Definition: adc.h:54
#define MAX_AV_NB_SAMPLE
Definition: adc.h:40
uint8_t av_nb_sample
Definition: adc.h:57
Generic interface for all ADC hardware drivers, independent from microcontroller architecture.
Definition: adc.h:53
#define ADC_4_GPIO_PORT
Definition: board.h:191
#define ADC_4_GPIO_PIN
Definition: board.h:192
#define AD1_4_CHANNEL
Definition: board.h:189
static struct adc_buf * adc1_buffers[ADC_NUM_CHANNELS]
Definition: adc_arch.c:144
void adc1callback(ADCDriver *adcp)
Adc1 callback.
Definition: adc_arch.c:243
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:312
static IN_DMA_SECTION(adcsample_t adc_samples[ADC_NUM_CHANNELS *MAX_AV_NB_SAMPLE])
void adc_init(void)
Adc init.
Definition: adc_arch.c:332
static uint32_t adc1_sum_tmp[ADC_NUM_CHANNELS]
Definition: adc_arch.c:145
#define ADC_BUF_DEPTH
Definition: adc_arch.c:138
#define ADC_SAMPLE_RATE
#endif
Definition: adc_arch.c:76
static uint8_t adc1_samples_tmp[ADC_NUM_CHANNELS]
Definition: adc_arch.c:146
static void adcerrorcallback(ADCDriver *adcp, adcerror_t err)
Adc error callback.
Definition: adc_arch.c:301
static void adc_configure(ADCConversionGroup *cfg, uint8_t num_channels, const uint8_t channels[], uint32_t sample_rate, adccallback_t end_cb, adcerrorcallback_t error_cb)
Configure the ADC conversion group depending on the architecture.
Definition: adc_arch.c:175
static ADCConversionGroup adc1_group
Definition: adc_arch.c:143
static const uint8_t adc_channel_map[ADC_NUM_CHANNELS]
Definition: adc_arch.c:81
ADCDriver * adcp_err
Definition: adc_arch.c:133
uint8_t adc_error_flag
Definition: adc_arch.c:132
@ NB_ADC1_CHANNELS
Definition: adc_arch.h:90
#define ADC_NUM_CHANNELS
Definition: adc_arch.h:93
void gpio_setup_pin_analog(ioportid_t port, uint16_t pin)
Setup a gpio for analog use.
Definition: gpio_arch.c:90
#define ADC_7_GPIO_PORT
Definition: chimera.h:190
#define AD1_7_CHANNEL
Definition: chimera.h:188
#define ADC_7_GPIO_PIN
Definition: chimera.h:191
#define AD1_1_CHANNEL
Definition: cjmcu.h:62
#define ADC_1_GPIO_PORT
Definition: cjmcu.h:64
#define ADC_1_GPIO_PIN
Definition: cjmcu.h:65
#define AD1_2_CHANNEL
#define ADC_2_GPIO_PIN
#define ADC_2_GPIO_PORT
Some architecture independent helper functions for GPIOs.
PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
#define ADC_5_GPIO_PORT
Definition: board.h:287
#define AD1_5_CHANNEL
Definition: board.h:285
#define ADC_5_GPIO_PIN
Definition: board.h:288
static uint32_t s
#define AD1_3_CHANNEL
Definition: lisa_l_1.0.h:148
#define ADC_3_GPIO_PIN
Definition: lisa_l_1.0.h:151
#define ADC_3_GPIO_PORT
Definition: lisa_l_1.0.h:150
#define ADC_9_GPIO_PORT
#define ADC_9_GPIO_PIN
#define AD1_9_CHANNEL
float vmin
Specific RAM section for DMA usage on F7.
#define error_cb
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
Definition: vl53l1_types.h:78
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.
Definition: vl53l1_types.h:98