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)
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/>.
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"
45 #ifndef ADC1_DMA_CHANNEL
46 #define ADC1_DMA_CHANNEL NULL
48 #ifndef ADC2_DMA_CHANNEL
49 #define ADC2_DMA_CHANNEL NULL
51 #ifndef ADC3_DMA_CHANNEL
52 #define ADC3_DMA_CHANNEL NULL
54 #ifndef ADC4_DMA_CHANNEL
55 #define ADC4_DMA_CHANNEL NULL
57 #ifndef ADC5_DMA_CHANNEL
58 #define ADC5_DMA_CHANNEL NULL
61 const adcDevice_t adcHardware
[ADCDEV_COUNT
] = {
64 .rccADC
= RCC_AHB2(ADC12
),
65 #if !defined(USE_DMA_SPEC)
66 .dmaResource
= (dmaResource_t
*)ADC1_DMA_CHANNEL
,
67 .channel
= DMA_REQUEST_ADC1
,
72 .rccADC
= RCC_AHB2(ADC12
),
73 #if !defined(USE_DMA_SPEC)
74 .dmaResource
= (dmaResource_t
*)ADC2_DMA_CHANNEL
,
75 .channel
= DMA_REQUEST_ADC2
,
80 .rccADC
= RCC_AHB2(ADC345
),
81 #if !defined(USE_DMA_SPEC)
82 .dmaResource
= (dmaResource_t
*)ADC3_DMA_CHANNEL
,
83 .channel
= DMA_REQUEST_ADC3
,
88 .rccADC
= RCC_AHB2(ADC345
),
89 #if !defined(USE_DMA_SPEC)
90 .dmaResource
= (dmaResource_t
*)ADC3_DMA_CHANNEL
,
91 .channel
= DMA_REQUEST_ADC4
,
96 .rccADC
= RCC_AHB2(ADC345
),
97 #if !defined(USE_DMA_SPEC)
98 .dmaResource
= (dmaResource_t
*)ADC5_DMA_CHANNEL
,
99 .channel
= DMA_REQUEST_ADC5
,
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 },
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.
186 #ifdef USE_ADC_INTERNAL
192 static void handleError(void)
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
) {
230 if (HAL_ADCEx_Calibration_Start(hadc
, ADC_SINGLE_ENDED
) != HAL_OK
) {
235 int adcFindTagMapEntry(ioTag_t tag
)
237 for (int i
= 0; i
< ADC_TAG_MAP_COUNT
; i
++) {
238 if (adcTagMap
[i
].tag
== tag
) {
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();
284 for (int i
= 0; i
< ADC_CHANNEL_COUNT
; i
++) {
288 if (i
== ADC_TEMPSENSOR
) {
289 map
= ADC_TAG_MAP_TEMPSENSOR
;
291 } else if (i
== ADC_VREFINT
) {
292 map
= ADC_TAG_MAP_VREFINT
;
295 if (!adcOperatingConfig
[i
].tag
) {
299 map
= adcFindTagMapEntry(adcOperatingConfig
[i
].tag
);
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
310 || !adcDevice
[dev
].dmaResource
313 // Instance not activated
316 if (adcTagMap
[map
].devices
& (1 << dev
)) {
317 // Found an activated ADC instance for this input pin
322 if (dev
== ADCDEV_COUNT
) {
323 // No valid device found, go next channel.
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
)) {
354 adc
->ADCHandle
.Instance
= adc
->ADCx
;
356 if (HAL_ADC_DeInit(&adc
->ADCHandle
) != HAL_OK
) {
357 // ADC de-initialization Error
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
)) {
373 RCC_ClockCmd(adc
->rccADC
, ENABLE
);
375 int configuredAdcChannels
= BITCOUNT(adc
->channelBits
);
377 adcInitDevice(adc
, configuredAdcChannels
);
379 // Configure channels
383 for (int adcChan
= 0; adcChan
< ADC_CHANNEL_COUNT
; adcChan
++) {
385 if (!adcOperatingConfig
[adcChan
].enabled
) {
389 if (adcOperatingConfig
[adcChan
].adcDevice
!= dev
) {
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
) {
409 // Configure DMA for this ADC peripheral
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
))) {
419 adc
->DmaHandle
.Instance
= (DMA_ARCH_TYPE
*)dmaSpec
->ref
;
420 adc
->DmaHandle
.Init
.Request
= dmaSpec
->channel
;
422 dmaIdentifier
= dmaGetIdentifier(adc
->dmaResource
);
423 adc
->DmaHandle
.Instance
= (DMA_ARCH_TYPE
*)adc
->dmaResource
;
424 adc
->DmaHandle
.Init
.Request
= adc
->channel
;
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
);
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.
465 for (int dev
= 0; dev
< ADCDEV_COUNT
; dev
++) {
467 adcDevice_t
*adc
= &adcDevice
[dev
];
469 if (!(adc
->ADCx
&& adc
->channelBits
)) {
473 // Start conversion in DMA mode
475 if (HAL_ADC_Start_DMA(&adc
->ADCHandle
, (uint32_t *)&adcConversionBuffer
[dmaBufferIndex
], BITCOUNT(adc
->channelBits
)) != HAL_OK
) {
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)
502 void adcInternalStartConversion(void)
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
);
524 uint16_t adcInternalReadTempsensor(void)
526 uint16_t value
= adcInternalRead(ADC_TEMPSENSOR
);
527 adcPrivateTemp
= __HAL_ADC_CALC_TEMPERATURE(adcPrivateVref
, value
, ADC_RESOLUTION_12B
);
530 #endif // USE_ADC_INTERNAL