dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pios_internal_adc.c
Go to the documentation of this file.
1 
14 /*
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 3 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful, but
21  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23  * for more details.
24  *
25  * You should have received a copy of the GNU General Public License along
26  * with this program; if not, see <http://www.gnu.org/licenses/>
27  */
28 
29 #include <pios_internal_adc_priv.h>
30 
31 #if defined(PIOS_INCLUDE_ADC)
32 
33 // Private types
34 enum pios_internal_adc_dev_magic {
35  PIOS_INTERNAL_ADC_DEV_MAGIC = 0x58375124,
36 };
37 
38 struct pios_internal_adc_dev {
39  enum pios_internal_adc_dev_magic magic;
40 
41  const struct pios_internal_adc_cfg * cfg;
42  uint8_t number_used_master_channels;
43  uint8_t number_used_slave_channels;
44  uint8_t regular_group_size;
45  struct adc_accumulator **channel_map;
46  struct adc_accumulator *accumulator;
47  uint16_t dma_half_buffer_index;
48  uint16_t dma_transfer_size;
49  uint16_t *raw_data_buffer;
50  uint32_t accumulator_increment;
51  uint32_t accumulator_scan_size;
52 };
53 
54 int32_t PIOS_INTERNAL_ADC_Init(uintptr_t *internal_adc_id,
55  const struct pios_internal_adc_cfg *cfg);
56 static void PIOS_INTERNAL_ADC_PinConfig(struct pios_internal_adc_dev *adc_dev);
57 static void PIOS_INTERNAL_DMAConfig(struct pios_internal_adc_dev *adc_dev);
58 static void PIOS_INTERNAL_ADC_Converter_Config(
59  struct pios_internal_adc_dev *adc_dev);
60 static int32_t PIOS_INTERNAL_ADC_PinGet(uintptr_t internal_adc_id, uint32_t pin);
61 static uint8_t PIOS_INTERNAL_ADC_NumberOfChannels(uintptr_t internal_adc_id);
62 static float PIOS_INTERNAL_ADC_LSB_Voltage(uintptr_t internal_adc_id);
63 
65  .get_pin = PIOS_INTERNAL_ADC_PinGet,
66  .number_of_channels = PIOS_INTERNAL_ADC_NumberOfChannels,
67  .lsb_voltage = PIOS_INTERNAL_ADC_LSB_Voltage,
68 };
69 
70 struct adc_accumulator {
71  volatile uint32_t accumulator;
72  volatile uint32_t count;
73 };
74 
79 static bool PIOS_INTERNAL_ADC_validate(struct pios_internal_adc_dev * dev)
80 {
81  if (dev == NULL )
82  return false;
83 
84  return (dev->magic == PIOS_INTERNAL_ADC_DEV_MAGIC);
85 }
86 
90 static struct pios_internal_adc_dev * PIOS_INTERNAL_ADC_Allocate()
91 {
92  struct pios_internal_adc_dev *adc_dev = (struct pios_internal_adc_dev *)PIOS_malloc(sizeof(*adc_dev));
93  if (!adc_dev)
94  return (NULL );
95  adc_dev->magic = PIOS_INTERNAL_ADC_DEV_MAGIC;
96  return (adc_dev);
97 }
98 
103 static void PIOS_INTERNAL_ADC_PinConfig(struct pios_internal_adc_dev *adc_dev)
104 {
105  if (!PIOS_INTERNAL_ADC_validate(adc_dev)) {
106  return;
107  }
108  /* Setup analog pins */
109  GPIO_InitTypeDef GPIO_InitStructure;
110  GPIO_StructInit(&GPIO_InitStructure);
111  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
112  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
113 
114  for (int32_t i = 0; i < adc_dev->cfg->adc_pin_count; i++) {
115  if (adc_dev->cfg->adc_pins[i].port == NULL )
116  continue;
117  GPIO_InitStructure.GPIO_Pin = adc_dev->cfg->adc_pins[i].pin;
118  GPIO_Init(adc_dev->cfg->adc_pins[i].port, (GPIO_InitTypeDef*) &GPIO_InitStructure);
119  }
120 }
125 static void PIOS_INTERNAL_DMAConfig(struct pios_internal_adc_dev *adc_dev)
126 {
127  if (!PIOS_INTERNAL_ADC_validate(adc_dev)) {
128  return;
129  }
130  /* Disable interrupts */
131  DMA_ITConfig(adc_dev->cfg->dma.rx.channel, adc_dev->cfg->dma.irq.flags, DISABLE);
132 
133  /* Configure DMA channel */
134  DMA_DeInit(adc_dev->cfg->dma.rx.channel);
135  DMA_InitTypeDef DMAInit = adc_dev->cfg->dma.rx.init;
136  if (adc_dev->cfg->adc_dev_slave) {
137  if (adc_dev->cfg->adc_dev_master == ADC1 )
138  DMAInit.DMA_PeripheralBaseAddr = (uint32_t) &ADC1_2->CDR;
139  else
140  DMAInit.DMA_PeripheralBaseAddr = (uint32_t) &ADC3_4->CDR;
141 
142  } else
143  DMAInit.DMA_PeripheralBaseAddr = (uint32_t) &adc_dev->cfg->adc_dev_master->DR;
144 
145  DMAInit.DMA_MemoryBaseAddr = (uint32_t) adc_dev->raw_data_buffer;
146  DMAInit.DMA_BufferSize = adc_dev->dma_transfer_size;
147  DMAInit.DMA_DIR = DMA_DIR_PeripheralSRC;
148  DMAInit.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
149  DMAInit.DMA_MemoryInc = DMA_MemoryInc_Enable;
150  if (adc_dev->cfg->adc_dev_slave) {
151  DMAInit.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
152  DMAInit.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
153  } else {
154  DMAInit.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
155  DMAInit.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
156  }
157  DMAInit.DMA_Mode = DMA_Mode_Circular;
158  DMAInit.DMA_M2M = DMA_M2M_Disable;
159 
160  DMA_Init(adc_dev->cfg->dma.rx.channel, &DMAInit); /* channel is actually stream ... */
161 
162  /* enable DMA */
163  DMA_Cmd(adc_dev->cfg->dma.rx.channel, ENABLE);
164 
165  /* configure for double-buffered mode and interrupt on every buffer flip */
166  DMA_ITConfig(adc_dev->cfg->dma.rx.channel, DMA_IT_TC, ENABLE);
167  DMA_ITConfig(adc_dev->cfg->dma.rx.channel, DMA_IT_HT, ENABLE);
168 
169  /* Configure DMA interrupt */
170  NVIC_InitTypeDef NVICInit = adc_dev->cfg->dma.irq.init;
171  NVIC_Init(&NVICInit);
172 }
173 
178 static void PIOS_INTERNAL_ADC_Converter_Config(
179  struct pios_internal_adc_dev *adc_dev)
180 {
181  ADC_DeInit(adc_dev->cfg->adc_dev_master);
182  if (adc_dev->cfg->adc_dev_slave)
183  ADC_DeInit(adc_dev->cfg->adc_dev_slave);
184 
185  if (adc_dev->cfg->adc_dev_master == ADC1 || adc_dev->cfg->adc_dev_master == ADC2 )
186  RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div32);
187  else
188  RCC_ADCCLKConfig(RCC_ADC34PLLCLK_Div32);
189 
190  ADC_VoltageRegulatorCmd(adc_dev->cfg->adc_dev_master, ENABLE);
191  PIOS_DELAY_WaituS(10);
192  ADC_SelectCalibrationMode(adc_dev->cfg->adc_dev_master, ADC_CalibrationMode_Single);
193  ADC_StartCalibration(adc_dev->cfg->adc_dev_master);
194  while (ADC_GetCalibrationStatus(adc_dev->cfg->adc_dev_master) != RESET)
195  ;
196  /* Slave calibration */
197  if (adc_dev->cfg->adc_dev_slave) {
198  ADC_VoltageRegulatorCmd(adc_dev->cfg->adc_dev_slave, ENABLE);
199  PIOS_DELAY_WaituS(10);
200  ADC_SelectCalibrationMode(adc_dev->cfg->adc_dev_slave, ADC_CalibrationMode_Single);
201  ADC_StartCalibration(adc_dev->cfg->adc_dev_slave);
202  while (ADC_GetCalibrationStatus(adc_dev->cfg->adc_dev_slave) != RESET)
203  ;
204  }
205 
206  /* Do common ADC init */
207  ADC_CommonInitTypeDef ADC_CommonInitStructure;
208  ADC_CommonStructInit(&ADC_CommonInitStructure);
209  if (adc_dev->cfg->adc_dev_slave) {
210  ADC_CommonInitStructure.ADC_Mode = ADC_Mode_RegSimul;
211  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1;
212  } else {
213  ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
214  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
215  }
216 
217  ADC_CommonInitStructure.ADC_Clock = ADC_Clock_AsynClkMode;
218  ADC_CommonInitStructure.ADC_DMAMode = ADC_DMAMode_Circular;
219  ADC_CommonInitStructure.ADC_TwoSamplingDelay = 0;
220  if (adc_dev->cfg->adc_dev_slave == NULL )
221  ADC_DMAConfig(adc_dev->cfg->adc_dev_master, ADC_DMAMode_Circular);
222  ADC_CommonInit(adc_dev->cfg->adc_dev_master, &ADC_CommonInitStructure);
223 
224  ADC_InitTypeDef ADC_InitStructure;
225  ADC_StructInit(&ADC_InitStructure);
226  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
227  ADC_InitStructure.ADC_ContinuousConvMode = ADC_ContinuousConvMode_Enable;
228  ADC_InitStructure.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_0;
229  ADC_InitStructure.ADC_ExternalTrigEventEdge = ADC_ExternalTrigEventEdge_None;
230  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Left;
231 
232  ADC_InitStructure.ADC_NbrOfRegChannel = adc_dev->regular_group_size;
233 
234  ADC_Init(adc_dev->cfg->adc_dev_master, &ADC_InitStructure);
235 
236  if (adc_dev->cfg->adc_dev_slave)
237  ADC_Init(adc_dev->cfg->adc_dev_slave, &ADC_InitStructure);
238 
239  /* Enable DMA request */
240  ADC_DMACmd(adc_dev->cfg->adc_dev_master, ENABLE);
241 
242  /* Configure input scan
243  * channel_map indexing corresponds to each conversion slot in order
244  * in single channel mode this corresponds to 0,1,2,3...
245  * in dual channel mode this corresponds to 0,2,4...
246  * 1,3,5...
247  * channel_map value is a pointer to an accumulator, if the same channel is used multiple times the same accumulator is used
248  *
249  * Input scan is setup to repeat channels if needed, i.e if a channel has more conversions to make the other will repeat conversions
250  * example:
251  * 2 ADC1 pins to convert pinA1, pinA2
252  * 3 ADC2 pins to convert pinB1, pinB2, pinB3
253  * input scan becomes:
254  * pinA1, pinA2, pinA1
255  * pinB1, pinB2, pinB3
256  */
257  uint32_t current_index = 0;
258  if (!adc_dev->cfg->adc_dev_slave) {
259  for (uint32_t i = 0; i < adc_dev->cfg->adc_pin_count; i++) {
260  ADC_RegularChannelConfig(adc_dev->cfg->adc_dev_master, adc_dev->cfg->adc_pins[i].adc_channel, current_index + 1, ADC_SampleTime_61Cycles5); /* XXX this is totally arbitrary... */
261  adc_dev->channel_map[current_index] = &adc_dev->accumulator[current_index];
262  ++current_index;
263  }
264  } else {
265  bool again = true;
266  current_index = 0;
267  uint32_t acc_index = 0;
268  while (again) {
269  for (uint32_t i = 0; i < adc_dev->cfg->adc_pin_count; i++) {
270  if (adc_dev->cfg->adc_pins[i].is_master_channel) {
271  ADC_RegularChannelConfig(adc_dev->cfg->adc_dev_master, adc_dev->cfg->adc_pins[i].adc_channel, current_index + 1, ADC_SampleTime_61Cycles5); /* XXX this is totally arbitrary... */
272  adc_dev->channel_map[acc_index] = &adc_dev->accumulator[i];
273  ++current_index;
274  acc_index += 2;
275  if (current_index
276  == (adc_dev->number_used_master_channels > adc_dev->number_used_slave_channels ?
277  adc_dev->number_used_master_channels : adc_dev->number_used_slave_channels)) {
278  again = false;
279  break;
280  }
281  }
282  }
283  }
284  again = true;
285  current_index = 0;
286  acc_index = 1;
287  while (again) {
288  for (uint32_t i = 0; i < adc_dev->cfg->adc_pin_count; i++) {
289  if (!adc_dev->cfg->adc_pins[i].is_master_channel) {
290  ADC_RegularChannelConfig(adc_dev->cfg->adc_dev_slave, adc_dev->cfg->adc_pins[i].adc_channel, current_index + 1, ADC_SampleTime_61Cycles5); /* XXX this is totally arbitrary... */
291  adc_dev->channel_map[acc_index] = &adc_dev->accumulator[i];
292  ++current_index;
293  acc_index += 2;
294  if (current_index
295  == (adc_dev->number_used_master_channels > adc_dev->number_used_slave_channels ?
296  adc_dev->number_used_master_channels : adc_dev->number_used_slave_channels)) {
297  again = false;
298  break;
299  }
300  }
301  }
302  }
303  }
304  ADC_Cmd(adc_dev->cfg->adc_dev_master, ENABLE);
305  if (adc_dev->cfg->adc_dev_slave)
306  ADC_Cmd(adc_dev->cfg->adc_dev_slave, ENABLE);
307  while (!ADC_GetFlagStatus(adc_dev->cfg->adc_dev_master, ADC_FLAG_RDY))
308  ;
309  if (adc_dev->cfg->adc_dev_slave)
310  while (!ADC_GetFlagStatus(adc_dev->cfg->adc_dev_slave, ADC_FLAG_RDY))
311  ;
312  ADC_StartConversion(adc_dev->cfg->adc_dev_master);
313 }
314 
318 int32_t PIOS_INTERNAL_ADC_Init(uintptr_t * internal_adc_id, const struct pios_internal_adc_cfg * cfg)
319 {
320  PIOS_DEBUG_Assert(internal_adc_id); PIOS_DEBUG_Assert(cfg);
321 
322  struct pios_internal_adc_dev * adc_dev;
323  adc_dev = PIOS_INTERNAL_ADC_Allocate();
324  if (adc_dev == NULL )
325  return -1;
326  adc_dev->cfg = cfg;
327 
328  *internal_adc_id = (uintptr_t) adc_dev;
329  adc_dev->number_used_master_channels = 0;
330  adc_dev->number_used_slave_channels = 0;
331 
332  for (uint8_t i = 0; i < adc_dev->cfg->adc_pin_count; ++i) {
333  if (adc_dev->cfg->adc_pins[i].is_master_channel)
334  ++adc_dev->number_used_master_channels;
335  else
336  ++adc_dev->number_used_slave_channels;
337  }
338  adc_dev->regular_group_size = adc_dev->number_used_master_channels > adc_dev->number_used_slave_channels ? adc_dev->number_used_master_channels : adc_dev->number_used_slave_channels;
339  if (adc_dev->cfg->adc_dev_slave) {
340  // DMA transfer size in units defined by DMA_PeripheralDataSize, 32bits for dual mode and 16bits for single mode
341  adc_dev->dma_transfer_size = 2 * adc_dev->cfg->oversampling * adc_dev->regular_group_size;
342  // DMA half buffer index (buffer is 16bit array),
343  // one should think that the half buffer index was half the transfer size but need to remember that the first is 16bit and the second 32bit
344  adc_dev->dma_half_buffer_index = adc_dev->dma_transfer_size;
345  adc_dev->accumulator_increment = 2;
346  adc_dev->accumulator_scan_size = adc_dev->regular_group_size * 2;
347  adc_dev->raw_data_buffer = PIOS_malloc(adc_dev->dma_transfer_size * sizeof(uint32_t));
348  } else {
349  // DMA transfer size in units defined by DMA_PeripheralDataSize, 32bits for dual mode and 16bits for single mode
350  adc_dev->dma_transfer_size = 2 * adc_dev->cfg->oversampling * adc_dev->cfg->adc_pin_count;
351  // DMA half buffer index (buffer is 16bit array),
352  // half buffer index is half the transfer size because they are both 16bit based here
353  adc_dev->dma_half_buffer_index = adc_dev->cfg->oversampling * adc_dev->cfg->adc_pin_count;
354  ;
355  adc_dev->accumulator_increment = 1;
356  adc_dev->accumulator_scan_size = adc_dev->regular_group_size;
357  adc_dev->raw_data_buffer = PIOS_malloc(adc_dev->dma_transfer_size * sizeof(uint16_t));
358  }
359  if (adc_dev->raw_data_buffer == NULL )
360  return -1;
361 
362  adc_dev->accumulator = PIOS_malloc(adc_dev->cfg->adc_pin_count * sizeof(struct adc_accumulator));
363  if (adc_dev->accumulator == NULL )
364  return -1;
365  if (adc_dev->cfg->adc_dev_slave)
366  adc_dev->channel_map = PIOS_malloc(adc_dev->regular_group_size * 2 * sizeof(struct adc_accumulator *));
367  else
368  adc_dev->channel_map = PIOS_malloc(adc_dev->regular_group_size * sizeof(struct adc_accumulator *));
369  if (adc_dev->channel_map == NULL )
370  return -1;
371 
372  PIOS_INTERNAL_ADC_PinConfig(adc_dev);
373  PIOS_INTERNAL_DMAConfig(adc_dev);
374  PIOS_INTERNAL_ADC_Converter_Config(adc_dev);
375 
376  return 0;
377 }
378 
384 static uint8_t PIOS_INTERNAL_ADC_NumberOfChannels(uintptr_t internal_adc_id)
385 {
386  struct pios_internal_adc_dev * adc_dev = (struct pios_internal_adc_dev *) internal_adc_id;
387  if (!PIOS_INTERNAL_ADC_validate(adc_dev))
388  return 0;
389  return adc_dev->cfg->adc_pin_count;
390 
391 }
392 
399 static int32_t PIOS_INTERNAL_ADC_PinGet(uintptr_t internal_adc_id, uint32_t pin)
400 {
401  struct pios_internal_adc_dev * adc_dev = (struct pios_internal_adc_dev *) internal_adc_id;
402  int32_t result;
403  /* Check if pin exists */
404  if (pin >= adc_dev->cfg->adc_pin_count) {
405  return -1;
406  }
407  result = adc_dev->accumulator[pin].accumulator / (adc_dev->accumulator[pin].count ? : 1);
408  adc_dev->accumulator[pin].accumulator = result;
409  adc_dev->accumulator[pin].count = 1;
410  return result;
411 }
412 
416 static void accumulate(struct pios_internal_adc_dev *adc_dev, uint16_t *buffer)
417 {
418  uint16_t *sp;
419  /*
420  * Accumulate sampled values.
421  */
422  for (uint32_t i = 0; i < adc_dev->cfg->oversampling; ++i) {
423  sp = buffer + adc_dev->regular_group_size * i * adc_dev->accumulator_increment;
424  for (uint8_t scan_index = 0; scan_index < adc_dev->accumulator_scan_size; ++scan_index) {
425  adc_dev->channel_map[scan_index]->accumulator += *sp;
426  adc_dev->channel_map[scan_index]->count++;
427  sp++;
428  /*
429  * If the accumulator reaches half-full, rescale in order to
430  * make more space.
431  */
432  if (adc_dev->channel_map[scan_index]->accumulator >= (1 << 31)) {
433  adc_dev->channel_map[scan_index]->accumulator /= 2;
434  adc_dev->channel_map[scan_index]->count /= 2;
435  }
436 
437  }
438  }
439 }
440 
446 void PIOS_INTERNAL_ADC_DMA_Handler(uintptr_t internal_adc_id)
447 {
448  struct pios_internal_adc_dev * adc_dev = (struct pios_internal_adc_dev *) internal_adc_id;
449 
450  if (!PIOS_INTERNAL_ADC_validate(adc_dev)) {
451  PIOS_Assert(0);
452  }
453 
454  /* terminal count, buffer has flipped */
455  if (DMA_GetFlagStatus(adc_dev->cfg->full_flag)) { // whole double buffer filled
456  DMA_ClearFlag(adc_dev->cfg->full_flag);
457  accumulate(adc_dev, adc_dev->raw_data_buffer + adc_dev->dma_half_buffer_index);
458  } else if (DMA_GetFlagStatus(adc_dev->cfg->half_flag /*DMA1_IT_HT1*/)) {
459  DMA_ClearFlag(adc_dev->cfg->half_flag);
460  accumulate(adc_dev, adc_dev->raw_data_buffer);
461  } else {
462  // This should not happen, probably due to transfer errors
463  DMA_ClearFlag(adc_dev->cfg->dma.irq.flags /*DMA1_FLAG_GL1*/);
464  }
465 }
466 
470 static float PIOS_INTERNAL_ADC_LSB_Voltage(uintptr_t internal_adc_id)
471 {
472  struct pios_internal_adc_dev * adc_dev = (struct pios_internal_adc_dev *) internal_adc_id;
473  if (!PIOS_INTERNAL_ADC_validate(adc_dev)) {
474  return 0;
475  }
476  return VREF_PLUS / (((uint32_t)1 << 16) - 16);
477 }
478 #endif /* PIOS_INCLUDE_ADC */
479 
const uint8_t count
Definition: panel.c:515
int32_t PIOS_INTERNAL_ADC_Init(uintptr_t *internal_adc_id, const struct pios_internal_adc_cfg *cfg)
#define PIOS_DEBUG_Assert(test)
Definition: pios_debug.h:51
void * PIOS_malloc(size_t size)
Definition: pios_heap.c:125
void PIOS_INTERNAL_ADC_DMA_Handler()
static struct flyingpicmd_cfg_fa cfg
Definition: main.c:49
const struct pios_adc_driver pios_internal_adc_driver
#define VREF_PLUS
Definition: pios_board.h:222
uint8_t i
Definition: msp_messages.h:97
ADC private definitions.
uint32_t magic
#define PIOS_Assert(test)
Definition: pios_debug.h:52
int32_t(* get_pin)(uintptr_t id, uint32_t pin)
Definition: pios_adc.h:41
int32_t PIOS_DELAY_WaituS(uint32_t uS)
Definition: pios_delay.c:116