Merge pull request #11494 from haslinghuis/dshot_gpio
[betaflight.git] / src / main / drivers / adc_stm32g4xx.c
blobe3780b5fc71030505ca207e4f0da3b14c290c65b
1 /*
2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
8 * any later version.
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
21 #include <stdbool.h>
22 #include <stdint.h>
23 #include <string.h>
25 #include "platform.h"
27 #ifdef USE_ADC
29 #include "build/debug.h"
31 #include "drivers/dma_reqmap.h"
32 #include "drivers/io.h"
33 #include "drivers/io_impl.h"
34 #include "drivers/rcc.h"
35 #include "drivers/resource.h"
36 #include "drivers/dma.h"
38 #include "drivers/sensor.h"
40 #include "drivers/adc.h"
41 #include "drivers/adc_impl.h"
43 #include "pg/adc.h"
45 #ifndef ADC1_DMA_CHANNEL
46 #define ADC1_DMA_CHANNEL NULL
47 #endif
48 #ifndef ADC2_DMA_CHANNEL
49 #define ADC2_DMA_CHANNEL NULL
50 #endif
51 #ifndef ADC3_DMA_CHANNEL
52 #define ADC3_DMA_CHANNEL NULL
53 #endif
54 #ifndef ADC4_DMA_CHANNEL
55 #define ADC4_DMA_CHANNEL NULL
56 #endif
57 #ifndef ADC5_DMA_CHANNEL
58 #define ADC5_DMA_CHANNEL NULL
59 #endif
61 const adcDevice_t adcHardware[ADCDEV_COUNT] = {
63 .ADCx = ADC1,
64 .rccADC = RCC_AHB2(ADC12),
65 #if !defined(USE_DMA_SPEC)
66 .dmaResource = (dmaResource_t *)ADC1_DMA_CHANNEL,
67 .channel = DMA_REQUEST_ADC1,
68 #endif
71 .ADCx = ADC2,
72 .rccADC = RCC_AHB2(ADC12),
73 #if !defined(USE_DMA_SPEC)
74 .dmaResource = (dmaResource_t *)ADC2_DMA_CHANNEL,
75 .channel = DMA_REQUEST_ADC2,
76 #endif
79 .ADCx = ADC3,
80 .rccADC = RCC_AHB2(ADC345),
81 #if !defined(USE_DMA_SPEC)
82 .dmaResource = (dmaResource_t *)ADC3_DMA_CHANNEL,
83 .channel = DMA_REQUEST_ADC3,
84 #endif
87 .ADCx = ADC4,
88 .rccADC = RCC_AHB2(ADC345),
89 #if !defined(USE_DMA_SPEC)
90 .dmaResource = (dmaResource_t *)ADC3_DMA_CHANNEL,
91 .channel = DMA_REQUEST_ADC4,
92 #endif
95 .ADCx = ADC5,
96 .rccADC = RCC_AHB2(ADC345),
97 #if !defined(USE_DMA_SPEC)
98 .dmaResource = (dmaResource_t *)ADC5_DMA_CHANNEL,
99 .channel = DMA_REQUEST_ADC5,
100 #endif
104 adcDevice_t adcDevice[ADCDEV_COUNT];
106 /* note these could be packed up for saving space */
107 const adcTagMap_t adcTagMap[] = {
108 #ifdef USE_ADC_INTERNAL
109 // Pseudo entries for internal sensor.
110 // Keep these at the beginning for easy indexing by ADC_TAG_MAP_{VREFINT,TEMPSENSOR}
111 #define ADC_TAG_MAP_VREFINT 0
112 #define ADC_TAG_MAP_TEMPSENSOR 1
113 // VREFINT is available on all ADC instances except ADC2
114 // Here, for simplicity, we force VREFINT on ADC1.
115 { DEFIO_TAG_E__NONE, ADC_DEVICES_1, ADC_CHANNEL_VREFINT, 18 },
116 // TEMPSENSOR is available on ADC1 or ADC5
117 // Here, for simplicity, we force TEMPSENSOR on ADC1.
118 { DEFIO_TAG_E__NONE, ADC_DEVICES_1, ADC_CHANNEL_TEMPSENSOR_ADC1, 16 },
119 #endif
120 // Inputs available for all packages under 100 pin or smaller
122 { DEFIO_TAG_E__PA0, ADC_DEVICES_12, ADC_CHANNEL_1, 1 },
123 { DEFIO_TAG_E__PA1, ADC_DEVICES_12, ADC_CHANNEL_2, 2 },
124 { DEFIO_TAG_E__PA2, ADC_DEVICES_1, ADC_CHANNEL_3, 3 },
125 { DEFIO_TAG_E__PA3, ADC_DEVICES_1, ADC_CHANNEL_4, 4 },
126 { DEFIO_TAG_E__PA4, ADC_DEVICES_2, ADC_CHANNEL_17, 17 },
127 { DEFIO_TAG_E__PA5, ADC_DEVICES_2, ADC_CHANNEL_13, 13 },
128 { DEFIO_TAG_E__PA6, ADC_DEVICES_2, ADC_CHANNEL_3, 3 },
129 { DEFIO_TAG_E__PA7, ADC_DEVICES_2, ADC_CHANNEL_4, 4 },
130 { DEFIO_TAG_E__PA8, ADC_DEVICES_5, ADC_CHANNEL_1, 1 },
131 { DEFIO_TAG_E__PA9, ADC_DEVICES_5, ADC_CHANNEL_2, 2 },
133 { DEFIO_TAG_E__PB0, ADC_DEVICES_1, ADC_CHANNEL_15, 15 },
134 { DEFIO_TAG_E__PB0, ADC_DEVICES_3, ADC_CHANNEL_12, 12 }, // 2nd entry
135 { DEFIO_TAG_E__PB1, ADC_DEVICES_1, ADC_CHANNEL_12, 12 },
136 { DEFIO_TAG_E__PB1, ADC_DEVICES_3, ADC_CHANNEL_1, 1 }, // 2nd entry
137 { DEFIO_TAG_E__PB2, ADC_DEVICES_2, ADC_CHANNEL_12, 12 },
138 { DEFIO_TAG_E__PB11, ADC_DEVICES_12, ADC_CHANNEL_14, 14 },
139 { DEFIO_TAG_E__PB12, ADC_DEVICES_1, ADC_CHANNEL_11, 11 },
140 { DEFIO_TAG_E__PB12, ADC_DEVICES_4, ADC_CHANNEL_3, 3 }, // 2nd entry
141 { DEFIO_TAG_E__PB13, ADC_DEVICES_5, ADC_CHANNEL_3, 3 },
142 { DEFIO_TAG_E__PB14, ADC_DEVICES_1, ADC_CHANNEL_5, 5 },
143 { DEFIO_TAG_E__PB14, ADC_DEVICES_4, ADC_CHANNEL_4, 4 }, // 2nd entry
144 { DEFIO_TAG_E__PB15, ADC_DEVICES_2, ADC_CHANNEL_15, 15 },
145 { DEFIO_TAG_E__PB15, ADC_DEVICES_4, ADC_CHANNEL_5, 5 }, // 2nd entry
147 { DEFIO_TAG_E__PC0, ADC_DEVICES_12, ADC_CHANNEL_6, 6 },
148 { DEFIO_TAG_E__PC1, ADC_DEVICES_12, ADC_CHANNEL_7, 7 },
149 { DEFIO_TAG_E__PC2, ADC_DEVICES_12, ADC_CHANNEL_8, 8 },
150 { DEFIO_TAG_E__PC3, ADC_DEVICES_12, ADC_CHANNEL_9, 9 },
151 { DEFIO_TAG_E__PC4, ADC_DEVICES_2, ADC_CHANNEL_5, 5 },
152 { DEFIO_TAG_E__PC5, ADC_DEVICES_2, ADC_CHANNEL_11, 11 },
154 { DEFIO_TAG_E__PD8, ADC_DEVICES_2, ADC_CHANNEL_15, 15 },
155 { DEFIO_TAG_E__PD8, ADC_DEVICES_4, ADC_CHANNEL_12, 12 }, // 2nd entry
156 { DEFIO_TAG_E__PD9, ADC_DEVICES_4, ADC_CHANNEL_12, 12 },
157 { DEFIO_TAG_E__PD9, ADC_DEVICES_5, ADC_CHANNEL_13, 13 }, // 2nd entry
158 { DEFIO_TAG_E__PD10, ADC_DEVICES_345, ADC_CHANNEL_7, 7 },
159 { DEFIO_TAG_E__PD11, ADC_DEVICES_345, ADC_CHANNEL_8, 8 },
160 { DEFIO_TAG_E__PD12, ADC_DEVICES_345, ADC_CHANNEL_9, 9 },
161 { DEFIO_TAG_E__PD13, ADC_DEVICES_345, ADC_CHANNEL_10, 10 },
162 { DEFIO_TAG_E__PD14, ADC_DEVICES_345, ADC_CHANNEL_11, 11 },
164 { DEFIO_TAG_E__PE7, ADC_DEVICES_3, ADC_CHANNEL_4, 4 },
165 { DEFIO_TAG_E__PE8, ADC_DEVICES_345, ADC_CHANNEL_6, 6 },
166 { DEFIO_TAG_E__PE9, ADC_DEVICES_3, ADC_CHANNEL_2, 2 },
167 { DEFIO_TAG_E__PE10, ADC_DEVICES_345, ADC_CHANNEL_14, 14,},
168 { DEFIO_TAG_E__PE11, ADC_DEVICES_345, ADC_CHANNEL_15, 15,},
169 { DEFIO_TAG_E__PE12, ADC_DEVICES_345, ADC_CHANNEL_16, 16,},
170 { DEFIO_TAG_E__PE13, ADC_DEVICES_3, ADC_CHANNEL_3, 3,},
171 { DEFIO_TAG_E__PE14, ADC_DEVICES_4, ADC_CHANNEL_1, 1,},
172 { DEFIO_TAG_E__PE15, ADC_DEVICES_4, ADC_CHANNEL_2, 2,},
174 // Inputs available for packages larger than 100-pin are not listed
177 // An array to convert rank number to encoded rank code for HAL.
178 // Note that the table only list possible values, as rank for any single conversion
179 // will not exceed maximum number of input sources (ADC_CHANNEL_COUNT).
180 static uint32_t adcRegularRank[] = {
181 0, // ranks is counted by 1-origin; dodge zero.
182 ADC_REGULAR_RANK_1,
183 ADC_REGULAR_RANK_2,
184 ADC_REGULAR_RANK_3,
185 ADC_REGULAR_RANK_4,
186 #ifdef USE_ADC_INTERNAL
187 ADC_REGULAR_RANK_5,
188 ADC_REGULAR_RANK_6,
189 #endif
192 static void handleError(void)
194 while (true) {
198 // Note on sampling time.
199 // Temperature sensor has minimum sample time of 9us.
200 // With prescaler = 4 at 200MHz (AHB1), fADC = 50MHz (tcycle = 0.02us), 9us = 450cycles < 810
202 void adcInitDevice(adcDevice_t *adcdev, int channelCount)
204 ADC_HandleTypeDef *hadc = &adcdev->ADCHandle; // For clarity
206 hadc->Instance = adcdev->ADCx;
208 // DeInit is done in adcInit().
210 hadc->Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV4;
211 hadc->Init.Resolution = ADC_RESOLUTION_12B;
212 hadc->Init.DataAlign = ADC_DATAALIGN_RIGHT;
213 hadc->Init.GainCompensation = 0;
214 hadc->Init.ScanConvMode = ADC_SCAN_ENABLE;
215 hadc->Init.EOCSelection = ADC_EOC_SEQ_CONV;
216 hadc->Init.LowPowerAutoWait = DISABLE;
217 hadc->Init.ContinuousConvMode = ENABLE;
218 hadc->Init.NbrOfConversion = channelCount;
219 hadc->Init.DiscontinuousConvMode = DISABLE;
220 hadc->Init.ExternalTrigConv = ADC_SOFTWARE_START;
221 hadc->Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
222 hadc->Init.DMAContinuousRequests = ENABLE;
223 hadc->Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
224 hadc->Init.OversamplingMode = DISABLE;
226 if (HAL_ADC_Init(hadc) != HAL_OK) {
227 handleError();
230 if (HAL_ADCEx_Calibration_Start(hadc, ADC_SINGLE_ENDED) != HAL_OK) {
231 handleError();
235 int adcFindTagMapEntry(ioTag_t tag)
237 for (int i = 0; i < ADC_TAG_MAP_COUNT; i++) {
238 if (adcTagMap[i].tag == tag) {
239 return i;
242 return -1;
245 void adcInitCalibrationValues(void)
247 adcVREFINTCAL = *(uint16_t *)VREFINT_CAL_ADDR;
248 adcTSCAL1 = *TEMPSENSOR_CAL1_ADDR;
249 adcTSCAL2 = *TEMPSENSOR_CAL2_ADDR;
250 adcTSSlopeK = (TEMPSENSOR_CAL2_TEMP - TEMPSENSOR_CAL1_TEMP) * 1000 / (adcTSCAL2 - adcTSCAL1);
253 // ADC conversion result DMA buffer
254 // Need this separate from the main adcValue[] array, because channels are numbered
255 // by ADC instance order that is different from ADC_xxx numbering.
257 volatile DMA_RAM_R uint16_t adcConversionBuffer[ADC_CHANNEL_COUNT] __attribute__((aligned(32)));
259 void adcInit(const adcConfig_t *config)
261 memset(adcOperatingConfig, 0, sizeof(adcOperatingConfig));
262 memcpy(adcDevice, adcHardware, sizeof(adcDevice));
264 if (config->vbat.enabled) {
265 adcOperatingConfig[ADC_BATTERY].tag = config->vbat.ioTag;
268 if (config->rssi.enabled) {
269 adcOperatingConfig[ADC_RSSI].tag = config->rssi.ioTag; //RSSI_ADC_CHANNEL;
272 if (config->external1.enabled) {
273 adcOperatingConfig[ADC_EXTERNAL1].tag = config->external1.ioTag; //EXTERNAL1_ADC_CHANNEL;
276 if (config->current.enabled) {
277 adcOperatingConfig[ADC_CURRENT].tag = config->current.ioTag; //CURRENT_METER_ADC_CHANNEL;
280 #ifdef USE_ADC_INTERNAL
281 adcInitCalibrationValues();
282 #endif
284 for (int i = 0; i < ADC_CHANNEL_COUNT; i++) {
285 int map;
286 int dev;
288 if (i == ADC_TEMPSENSOR) {
289 map = ADC_TAG_MAP_TEMPSENSOR;
290 dev = ADCDEV_1;
291 } else if (i == ADC_VREFINT) {
292 map = ADC_TAG_MAP_VREFINT;
293 dev = ADCDEV_1;
294 } else {
295 if (!adcOperatingConfig[i].tag) {
296 continue;
299 map = adcFindTagMapEntry(adcOperatingConfig[i].tag);
300 if (map < 0) {
301 continue;
304 // Found a tag map entry for this input pin
305 // Find an ADC device that can handle this input pin
307 for (dev = 0; dev < ADCDEV_COUNT; dev++) {
308 if (!adcDevice[dev].ADCx
309 #ifndef USE_DMA_SPEC
310 || !adcDevice[dev].dmaResource
311 #endif
313 // Instance not activated
314 continue;
316 if (adcTagMap[map].devices & (1 << dev)) {
317 // Found an activated ADC instance for this input pin
318 break;
322 if (dev == ADCDEV_COUNT) {
323 // No valid device found, go next channel.
324 continue;
328 // At this point, map is an entry for the input pin and dev is a valid ADCx for the pin for input i
330 adcOperatingConfig[i].adcDevice = dev;
331 adcOperatingConfig[i].adcChannel = adcTagMap[map].channel;
332 adcOperatingConfig[i].sampleTime = ADC_SAMPLETIME_640CYCLES_5;
333 adcOperatingConfig[i].enabled = true;
335 adcDevice[dev].channelBits |= (1 << adcTagMap[map].channelOrdinal);
337 // Configure a pin for ADC
338 if (adcOperatingConfig[i].tag) {
339 IOInit(IOGetByTag(adcOperatingConfig[i].tag), OWNER_ADC_BATT + i, 0);
340 IOConfigGPIO(IOGetByTag(adcOperatingConfig[i].tag), IO_CONFIG(GPIO_MODE_ANALOG, 0, GPIO_NOPULL));
344 // DeInit ADCx with inputs
345 // We have to batch call DeInit() for all devices as DeInit() initializes ADCx_COMMON register.
347 for (int dev = 0; dev < ADCDEV_COUNT; dev++) {
348 adcDevice_t *adc = &adcDevice[dev];
350 if (!(adc->ADCx && adc->channelBits)) {
351 continue;
354 adc->ADCHandle.Instance = adc->ADCx;
356 if (HAL_ADC_DeInit(&adc->ADCHandle) != HAL_OK) {
357 // ADC de-initialization Error
358 handleError();
362 // Configure ADCx with inputs
364 int dmaBufferIndex = 0;
366 for (int dev = 0; dev < ADCDEV_COUNT; dev++) {
367 adcDevice_t *adc = &adcDevice[dev];
369 if (!(adc->ADCx && adc->channelBits)) {
370 continue;
373 RCC_ClockCmd(adc->rccADC, ENABLE);
375 int configuredAdcChannels = BITCOUNT(adc->channelBits);
377 adcInitDevice(adc, configuredAdcChannels);
379 // Configure channels
381 int rank = 1;
383 for (int adcChan = 0; adcChan < ADC_CHANNEL_COUNT; adcChan++) {
385 if (!adcOperatingConfig[adcChan].enabled) {
386 continue;
389 if (adcOperatingConfig[adcChan].adcDevice != dev) {
390 continue;
393 adcOperatingConfig[adcChan].dmaIndex = dmaBufferIndex++;
395 ADC_ChannelConfTypeDef sConfig;
397 sConfig.Channel = adcOperatingConfig[adcChan].adcChannel; /* Sampled channel number */
398 sConfig.Rank = adcRegularRank[rank++]; /* Rank of sampled channel number ADCx_CHANNEL */
399 sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5; /* Sampling time (number of clock cycles unit) */
400 sConfig.SingleDiff = ADC_SINGLE_ENDED; /* Single-ended input channel */
401 sConfig.OffsetNumber = ADC_OFFSET_NONE; /* No offset subtraction */
402 sConfig.Offset = 0; /* Parameter discarded because offset correction is disabled */
404 if (HAL_ADC_ConfigChannel(&adc->ADCHandle, &sConfig) != HAL_OK) {
405 handleError();
409 // Configure DMA for this ADC peripheral
411 #ifdef USE_DMA_SPEC
412 const dmaChannelSpec_t *dmaSpec = dmaGetChannelSpecByPeripheral(DMA_PERIPH_ADC, dev, config->dmaopt[dev]);
414 dmaIdentifier_e dmaIdentifier = dmaGetIdentifier(dmaSpec->ref);
415 if (!dmaSpec || !dmaAllocate(dmaIdentifier, OWNER_ADC, RESOURCE_INDEX(dev))) {
416 return;
419 adc->DmaHandle.Instance = (DMA_ARCH_TYPE *)dmaSpec->ref;
420 adc->DmaHandle.Init.Request = dmaSpec->channel;
421 #else
422 dmaIdentifier = dmaGetIdentifier(adc->dmaResource);
423 adc->DmaHandle.Instance = (DMA_ARCH_TYPE *)adc->dmaResource;
424 adc->DmaHandle.Init.Request = adc->channel;
425 #endif
426 adc->DmaHandle.Init.Direction = DMA_PERIPH_TO_MEMORY;
427 adc->DmaHandle.Init.PeriphInc = DMA_PINC_DISABLE;
428 adc->DmaHandle.Init.MemInc = DMA_MINC_ENABLE;
429 adc->DmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
430 adc->DmaHandle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
431 adc->DmaHandle.Init.Mode = DMA_CIRCULAR;
432 adc->DmaHandle.Init.Priority = DMA_PRIORITY_MEDIUM;
434 // Deinitialize & Initialize the DMA for new transfer
436 // dmaEnable must be called before calling HAL_DMA_Init,
437 // to enable clock for associated DMA if not already done so.
438 dmaEnable(dmaIdentifier);
440 HAL_DMA_DeInit(&adc->DmaHandle);
441 HAL_DMA_Init(&adc->DmaHandle);
443 // Associate the DMA handle
445 __HAL_LINKDMA(&adc->ADCHandle, DMA_Handle, adc->DmaHandle);
447 #ifdef USE_ADC_INTERRUPT
448 // XXX No interrupt used, so we can skip this.
449 // If interrupt is needed in any case, use dmaXXX facility instead,
450 // using dmaIdentifier obtained above.
452 // NVIC configuration for DMA Input data interrupt
454 HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 1, 0);
455 HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
456 #endif
459 // Start channels.
460 // This must be done after channel configuration is complete, as HAL_ADC_ConfigChannel
461 // throws an error when configuring internal channels if ADC1 or ADC2 are already enabled.
463 dmaBufferIndex = 0;
465 for (int dev = 0; dev < ADCDEV_COUNT; dev++) {
467 adcDevice_t *adc = &adcDevice[dev];
469 if (!(adc->ADCx && adc->channelBits)) {
470 continue;
473 // Start conversion in DMA mode
475 if (HAL_ADC_Start_DMA(&adc->ADCHandle, (uint32_t *)&adcConversionBuffer[dmaBufferIndex], BITCOUNT(adc->channelBits)) != HAL_OK) {
476 handleError();
479 dmaBufferIndex += BITCOUNT(adc->channelBits);
483 void adcGetChannelValues(void)
485 // Transfer values in conversion buffer into adcValues[]
486 // Cache coherency should be maintained by MPU facility
488 for (int i = 0; i < ADC_CHANNEL_INTERNAL_FIRST_ID; i++) {
489 if (adcOperatingConfig[i].enabled) {
490 adcValues[adcOperatingConfig[i].dmaIndex] = adcConversionBuffer[adcOperatingConfig[i].dmaIndex];
495 #ifdef USE_ADC_INTERNAL
497 bool adcInternalIsBusy(void)
499 return false;
502 void adcInternalStartConversion(void)
504 return;
507 uint16_t adcInternalRead(int channel)
509 int dmaIndex = adcOperatingConfig[channel].dmaIndex;
511 return adcConversionBuffer[dmaIndex];
514 int adcPrivateVref = -1;
515 int adcPrivateTemp = -1;
517 uint16_t adcInternalReadVrefint(void)
519 uint16_t value = adcInternalRead(ADC_VREFINT);
520 adcPrivateVref = __HAL_ADC_CALC_VREFANALOG_VOLTAGE(value, ADC_RESOLUTION_12B);
521 return value;
524 uint16_t adcInternalReadTempsensor(void)
526 uint16_t value = adcInternalRead(ADC_TEMPSENSOR);
527 adcPrivateTemp = __HAL_ADC_CALC_TEMPERATURE(adcPrivateVref, value, ADC_RESOLUTION_12B);
528 return value;
530 #endif // USE_ADC_INTERNAL
531 #endif // USE_ADC