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 "common/utils.h"
31 #include "drivers/adc_impl.h"
32 #include "drivers/dma.h"
33 #include "drivers/dma_reqmap.h"
34 #include "drivers/io.h"
35 #include "drivers/rcc.h"
36 #include "drivers/sensor.h"
37 #include "drivers/time.h"
43 const adcDevice_t adcHardware
[] = {
44 { .ADCx
= ADC1
, .rccADC
= RCC_AHB(ADC12
),
45 #if !defined(USE_DMA_SPEC)
46 .dmaResource
= (dmaResource_t
*)DMA1_Channel1
,
49 #ifdef ADC24_DMA_REMAP
50 { .ADCx
= ADC2
, .rccADC
= RCC_AHB(ADC12
),
51 #if !defined(USE_DMA_SPEC)
52 .dmaResource
= (dmaResource_t
*)DMA2_Channel3
,
56 { .ADCx
= ADC2
, .rccADC
= RCC_AHB(ADC12
),
57 #if !defined(USE_DMA_SPEC)
58 .dmaResource
= (dmaResource_t
*)DMA2_Channel1
,
62 { .ADCx
= ADC3
, .rccADC
= RCC_AHB(ADC34
),
63 #if !defined(USE_DMA_SPEC)
64 .dmaResource
= (dmaResource_t
*)DMA2_Channel5
,
69 const adcTagMap_t adcTagMap
[] = {
70 { DEFIO_TAG_E__PA0
, ADC_DEVICES_1
, ADC_Channel_1
}, // ADC1
71 { DEFIO_TAG_E__PA1
, ADC_DEVICES_1
, ADC_Channel_2
}, // ADC1
72 { DEFIO_TAG_E__PA2
, ADC_DEVICES_1
, ADC_Channel_3
}, // ADC1
73 { DEFIO_TAG_E__PA3
, ADC_DEVICES_1
, ADC_Channel_4
}, // ADC1
74 { DEFIO_TAG_E__PA4
, ADC_DEVICES_2
, ADC_Channel_1
}, // ADC2
75 { DEFIO_TAG_E__PA5
, ADC_DEVICES_2
, ADC_Channel_2
}, // ADC2
76 { DEFIO_TAG_E__PA6
, ADC_DEVICES_2
, ADC_Channel_3
}, // ADC2
77 { DEFIO_TAG_E__PA7
, ADC_DEVICES_4
, ADC_Channel_4
}, // ADC2
78 { DEFIO_TAG_E__PB0
, ADC_DEVICES_3
, ADC_Channel_12
}, // ADC3
79 { DEFIO_TAG_E__PB1
, ADC_DEVICES_3
, ADC_Channel_1
}, // ADC3
80 { DEFIO_TAG_E__PB2
, ADC_DEVICES_2
, ADC_Channel_12
}, // ADC2
81 { DEFIO_TAG_E__PB12
, ADC_DEVICES_4
, ADC_Channel_3
}, // ADC4
82 { DEFIO_TAG_E__PB13
, ADC_DEVICES_3
, ADC_Channel_5
}, // ADC3
83 { DEFIO_TAG_E__PB14
, ADC_DEVICES_4
, ADC_Channel_4
}, // ADC4
84 { DEFIO_TAG_E__PB15
, ADC_DEVICES_4
, ADC_Channel_5
}, // ADC4
85 { DEFIO_TAG_E__PC0
, ADC_DEVICES_12
, ADC_Channel_6
}, // ADC12
86 { DEFIO_TAG_E__PC1
, ADC_DEVICES_12
, ADC_Channel_7
}, // ADC12
87 { DEFIO_TAG_E__PC2
, ADC_DEVICES_12
, ADC_Channel_8
}, // ADC12
88 { DEFIO_TAG_E__PC3
, ADC_DEVICES_12
, ADC_Channel_9
}, // ADC12
89 { DEFIO_TAG_E__PC4
, ADC_DEVICES_2
, ADC_Channel_5
}, // ADC2
90 { DEFIO_TAG_E__PC5
, ADC_DEVICES_2
, ADC_Channel_11
}, // ADC2
91 { DEFIO_TAG_E__PD8
, ADC_DEVICES_4
, ADC_Channel_12
}, // ADC4
92 { DEFIO_TAG_E__PD9
, ADC_DEVICES_4
, ADC_Channel_13
}, // ADC4
93 { DEFIO_TAG_E__PD10
, ADC_DEVICES_34
, ADC_Channel_7
}, // ADC34
94 { DEFIO_TAG_E__PD11
, ADC_DEVICES_34
, ADC_Channel_8
}, // ADC34
95 { DEFIO_TAG_E__PD12
, ADC_DEVICES_34
, ADC_Channel_9
}, // ADC34
96 { DEFIO_TAG_E__PD13
, ADC_DEVICES_34
, ADC_Channel_10
}, // ADC34
97 { DEFIO_TAG_E__PD14
, ADC_DEVICES_34
, ADC_Channel_11
}, // ADC34
98 { DEFIO_TAG_E__PE7
, ADC_DEVICES_3
, ADC_Channel_13
}, // ADC3
99 { DEFIO_TAG_E__PE8
, ADC_DEVICES_34
, ADC_Channel_6
}, // ADC34
100 { DEFIO_TAG_E__PE9
, ADC_DEVICES_3
, ADC_Channel_2
}, // ADC3
101 { DEFIO_TAG_E__PE10
, ADC_DEVICES_3
, ADC_Channel_14
}, // ADC3
102 { DEFIO_TAG_E__PE11
, ADC_DEVICES_3
, ADC_Channel_15
}, // ADC3
103 { DEFIO_TAG_E__PE12
, ADC_DEVICES_3
, ADC_Channel_16
}, // ADC3
104 { DEFIO_TAG_E__PE13
, ADC_DEVICES_3
, ADC_Channel_3
}, // ADC3
105 { DEFIO_TAG_E__PE14
, ADC_DEVICES_4
, ADC_Channel_1
}, // ADC4
106 { DEFIO_TAG_E__PE15
, ADC_DEVICES_4
, ADC_Channel_2
}, // ADC4
107 { DEFIO_TAG_E__PF2
, ADC_DEVICES_12
, ADC_Channel_10
}, // ADC12
108 { DEFIO_TAG_E__PF4
, ADC_DEVICES_1
, ADC_Channel_5
}, // ADC1
111 void adcInit(const adcConfig_t
*config
)
113 ADC_InitTypeDef ADC_InitStructure
;
114 DMA_InitTypeDef DMA_InitStructure
;
116 uint8_t adcChannelCount
= 0;
118 memset(&adcOperatingConfig
, 0, sizeof(adcOperatingConfig
));
120 if (config
->vbat
.enabled
) {
121 adcOperatingConfig
[ADC_BATTERY
].tag
= config
->vbat
.ioTag
;
124 if (config
->rssi
.enabled
) {
125 adcOperatingConfig
[ADC_RSSI
].tag
= config
->rssi
.ioTag
; //RSSI_ADC_CHANNEL;
128 if (config
->external1
.enabled
) {
129 adcOperatingConfig
[ADC_EXTERNAL1
].tag
= config
->external1
.ioTag
; //EXTERNAL1_ADC_CHANNEL;
132 if (config
->current
.enabled
) {
133 adcOperatingConfig
[ADC_CURRENT
].tag
= config
->current
.ioTag
; //CURRENT_METER_ADC_CHANNEL;
136 ADCDevice device
= ADC_CFG_TO_DEV(config
->device
);
138 if (device
== ADCINVALID
) {
142 #ifdef ADC24_DMA_REMAP
143 SYSCFG_DMAChannelRemapConfig(SYSCFG_DMARemap_ADC2ADC4
, ENABLE
);
145 adcDevice_t adc
= adcHardware
[device
];
147 bool adcActive
= false;
148 for (int i
= 0; i
< ADC_CHANNEL_COUNT
; i
++) {
149 if (!adcVerifyPin(adcOperatingConfig
[i
].tag
, device
)) {
154 IOInit(IOGetByTag(adcOperatingConfig
[i
].tag
), OWNER_ADC_BATT
+ i
, 0);
155 IOConfigGPIO(IOGetByTag(adcOperatingConfig
[i
].tag
), IO_CONFIG(GPIO_Mode_AN
, 0, GPIO_OType_OD
, GPIO_PuPd_NOPULL
));
156 adcOperatingConfig
[i
].adcChannel
= adcChannelByTag(adcOperatingConfig
[i
].tag
);
157 adcOperatingConfig
[i
].dmaIndex
= adcChannelCount
++;
158 adcOperatingConfig
[i
].sampleTime
= ADC_SampleTime_601Cycles5
;
159 adcOperatingConfig
[i
].enabled
= true;
166 if ((device
== ADCDEV_1
) || (device
== ADCDEV_2
)) {
167 // enable clock for ADC1+2
168 RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div256
); // 72 MHz divided by 256 = 281.25 kHz
170 // enable clock for ADC3+4
171 RCC_ADCCLKConfig(RCC_ADC34PLLCLK_Div256
); // 72 MHz divided by 256 = 281.25 kHz
174 RCC_ClockCmd(adc
.rccADC
, ENABLE
);
176 #if defined(USE_DMA_SPEC)
177 const dmaChannelSpec_t
*dmaSpec
= dmaGetChannelSpecByPeripheral(DMA_PERIPH_ADC
, device
, config
->dmaopt
[device
]);
179 if (!dmaSpec
|| !dmaAllocate(dmaGetIdentifier(dmaSpec
->ref
), OWNER_ADC
, RESOURCE_INDEX(device
))) {
183 dmaEnable(dmaGetIdentifier(dmaSpec
->ref
));
185 DMA_DeInit((DMA_ARCH_TYPE
*)dmaSpec
->ref
);
187 if (!dmaAllocate(dmaGetIdentifier(adc
.dmaResource
), OWNER_ADC
, 0)) {
191 dmaEnable(dmaGetIdentifier(adc
.dmaResource
));
193 xDMA_DeInit(adc
.dmaResource
);
196 DMA_StructInit(&DMA_InitStructure
);
197 DMA_InitStructure
.DMA_PeripheralBaseAddr
= (uint32_t)&adc
.ADCx
->DR
;
198 DMA_InitStructure
.DMA_MemoryBaseAddr
= (uint32_t)adcValues
;
199 DMA_InitStructure
.DMA_DIR
= DMA_DIR_PeripheralSRC
;
200 DMA_InitStructure
.DMA_BufferSize
= adcChannelCount
;
201 DMA_InitStructure
.DMA_PeripheralInc
= DMA_PeripheralInc_Disable
;
202 DMA_InitStructure
.DMA_MemoryInc
= adcChannelCount
> 1 ? DMA_MemoryInc_Enable
: DMA_MemoryInc_Disable
;
203 DMA_InitStructure
.DMA_PeripheralDataSize
= DMA_PeripheralDataSize_HalfWord
;
204 DMA_InitStructure
.DMA_MemoryDataSize
= DMA_MemoryDataSize_HalfWord
;
205 DMA_InitStructure
.DMA_Mode
= DMA_Mode_Circular
;
206 DMA_InitStructure
.DMA_Priority
= DMA_Priority_High
;
207 DMA_InitStructure
.DMA_M2M
= DMA_M2M_Disable
;
209 #if defined(USE_DMA_SPEC)
210 xDMA_Init(dmaSpec
->ref
, &DMA_InitStructure
);
211 xDMA_Cmd(dmaSpec
->ref
, ENABLE
);
213 xDMA_Init(adc
.dmaResource
, &DMA_InitStructure
);
214 xDMA_Cmd(adc
.dmaResource
, ENABLE
);
219 ADC_VoltageRegulatorCmd(adc
.ADCx
, ENABLE
);
221 ADC_SelectCalibrationMode(adc
.ADCx
, ADC_CalibrationMode_Single
);
222 ADC_StartCalibration(adc
.ADCx
);
223 while (ADC_GetCalibrationStatus(adc
.ADCx
) != RESET
);
224 ADC_VoltageRegulatorCmd(adc
.ADCx
, DISABLE
);
226 ADC_CommonInitTypeDef ADC_CommonInitStructure
;
228 ADC_CommonStructInit(&ADC_CommonInitStructure
);
229 ADC_CommonInitStructure
.ADC_Mode
= ADC_Mode_Independent
;
230 ADC_CommonInitStructure
.ADC_Clock
= ADC_Clock_SynClkModeDiv4
;
231 ADC_CommonInitStructure
.ADC_DMAAccessMode
= ADC_DMAAccessMode_1
;
232 ADC_CommonInitStructure
.ADC_DMAMode
= ADC_DMAMode_Circular
;
233 ADC_CommonInitStructure
.ADC_TwoSamplingDelay
= 0;
234 ADC_CommonInit(adc
.ADCx
, &ADC_CommonInitStructure
);
236 ADC_StructInit(&ADC_InitStructure
);
238 ADC_InitStructure
.ADC_ContinuousConvMode
= ADC_ContinuousConvMode_Enable
;
239 ADC_InitStructure
.ADC_Resolution
= ADC_Resolution_12b
;
240 ADC_InitStructure
.ADC_ExternalTrigConvEvent
= ADC_ExternalTrigConvEvent_0
;
241 ADC_InitStructure
.ADC_ExternalTrigEventEdge
= ADC_ExternalTrigEventEdge_None
;
242 ADC_InitStructure
.ADC_DataAlign
= ADC_DataAlign_Right
;
243 ADC_InitStructure
.ADC_OverrunMode
= ADC_OverrunMode_Disable
;
244 ADC_InitStructure
.ADC_AutoInjMode
= ADC_AutoInjec_Disable
;
245 ADC_InitStructure
.ADC_NbrOfRegChannel
= adcChannelCount
;
247 ADC_Init(adc
.ADCx
, &ADC_InitStructure
);
250 for (int i
= 0; i
< ADC_CHANNEL_COUNT
; i
++) {
251 if (!adcOperatingConfig
[i
].enabled
) {
254 ADC_RegularChannelConfig(adc
.ADCx
, adcOperatingConfig
[i
].adcChannel
, rank
++, adcOperatingConfig
[i
].sampleTime
);
257 ADC_Cmd(adc
.ADCx
, ENABLE
);
259 while (!ADC_GetFlagStatus(adc
.ADCx
, ADC_FLAG_RDY
));
261 ADC_DMAConfig(adc
.ADCx
, ADC_DMAMode_Circular
);
263 ADC_DMACmd(adc
.ADCx
, ENABLE
);
265 ADC_StartConversion(adc
.ADCx
);
268 void adcGetChannelValues(void)