New SPI API supporting DMA
[betaflight.git] / src / main / drivers / adc_stm32f10x.c
blob69061c78d053394b3a92c0f227fc7e0693cde855
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/build_config.h"
31 #include "drivers/sensor.h"
32 #include "adc.h"
33 #include "adc_impl.h"
34 #include "drivers/io.h"
35 #include "rcc.h"
36 #include "dma.h"
38 #include "pg/adc.h"
41 const adcDevice_t adcHardware[] = {
42 { .ADCx = ADC1, .rccADC = RCC_APB2(ADC1), .dmaResource = (dmaResource_t *)DMA1_Channel1 }
45 const adcTagMap_t adcTagMap[] = {
46 { DEFIO_TAG_E__PA0, ADC_Channel_0 }, // ADC12
47 { DEFIO_TAG_E__PA1, ADC_Channel_1 }, // ADC12
48 { DEFIO_TAG_E__PA2, ADC_Channel_2 }, // ADC12
49 { DEFIO_TAG_E__PA3, ADC_Channel_3 }, // ADC12
50 { DEFIO_TAG_E__PA4, ADC_Channel_4 }, // ADC12
51 { DEFIO_TAG_E__PA5, ADC_Channel_5 }, // ADC12
52 { DEFIO_TAG_E__PA6, ADC_Channel_6 }, // ADC12
53 { DEFIO_TAG_E__PA7, ADC_Channel_7 }, // ADC12
54 { DEFIO_TAG_E__PB0, ADC_Channel_8 }, // ADC12
55 { DEFIO_TAG_E__PB1, ADC_Channel_9 }, // ADC12
58 // Driver for STM32F103CB onboard ADC
60 // Naze32
61 // Battery Voltage (VBAT) is connected to PA4 (ADC1_IN4) with 10k:1k divider
62 // RSSI ADC uses CH2 (PA1, ADC1_IN1)
63 // Current ADC uses CH8 (PB1, ADC1_IN9)
65 // NAZE rev.5 hardware has PA5 (ADC1_IN5) on breakout pad on bottom of board
68 void adcInit(const adcConfig_t *config)
71 uint8_t configuredAdcChannels = 0;
73 memset(&adcOperatingConfig, 0, sizeof(adcOperatingConfig));
75 if (config->vbat.enabled) {
76 adcOperatingConfig[ADC_BATTERY].tag = config->vbat.ioTag;
79 if (config->rssi.enabled) {
80 adcOperatingConfig[ADC_RSSI].tag = config->rssi.ioTag; //RSSI_ADC_CHANNEL;
83 if (config->external1.enabled) {
84 adcOperatingConfig[ADC_EXTERNAL1].tag = config->external1.ioTag; //EXTERNAL1_ADC_CHANNEL;
87 if (config->current.enabled) {
88 adcOperatingConfig[ADC_CURRENT].tag = config->current.ioTag; //CURRENT_METER_ADC_CHANNEL;
91 ADCDevice device = adcDeviceByInstance(ADC_INSTANCE);
92 if (device == ADCINVALID)
93 return;
95 const adcDevice_t adc = adcHardware[device];
97 bool adcActive = false;
98 for (int i = 0; i < ADC_CHANNEL_COUNT; i++) {
99 if (!adcOperatingConfig[i].tag)
100 continue;
102 adcActive = true;
103 IOInit(IOGetByTag(adcOperatingConfig[i].tag), OWNER_ADC_BATT + i, 0);
104 IOConfigGPIO(IOGetByTag(adcOperatingConfig[i].tag), IO_CONFIG(GPIO_Mode_AIN, 0));
105 adcOperatingConfig[i].adcChannel = adcChannelByTag(adcOperatingConfig[i].tag);
106 adcOperatingConfig[i].dmaIndex = configuredAdcChannels++;
107 adcOperatingConfig[i].sampleTime = ADC_SampleTime_239Cycles5;
108 adcOperatingConfig[i].enabled = true;
111 if (!adcActive) {
112 return;
115 RCC_ADCCLKConfig(RCC_PCLK2_Div8); // 9MHz from 72MHz APB2 clock(HSE), 8MHz from 64MHz (HSI)
116 RCC_ClockCmd(adc.rccADC, ENABLE);
118 dmaInit(dmaGetIdentifier(adc.dmaResource), OWNER_ADC, 0);
120 xDMA_DeInit(adc.dmaResource);
121 DMA_InitTypeDef DMA_InitStructure;
122 DMA_StructInit(&DMA_InitStructure);
123 DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&adc.ADCx->DR;
124 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)adcValues;
125 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
126 DMA_InitStructure.DMA_BufferSize = configuredAdcChannels;
127 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
128 DMA_InitStructure.DMA_MemoryInc = configuredAdcChannels > 1 ? DMA_MemoryInc_Enable : DMA_MemoryInc_Disable;
129 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
130 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
131 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
132 DMA_InitStructure.DMA_Priority = DMA_Priority_High;
133 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
134 xDMA_Init(adc.dmaResource, &DMA_InitStructure);
135 xDMA_Cmd(adc.dmaResource, ENABLE);
137 ADC_InitTypeDef ADC_InitStructure;
138 ADC_StructInit(&ADC_InitStructure);
139 ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
140 ADC_InitStructure.ADC_ScanConvMode = configuredAdcChannels > 1 ? ENABLE : DISABLE;
141 ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
142 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
143 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
144 ADC_InitStructure.ADC_NbrOfChannel = configuredAdcChannels;
145 ADC_Init(adc.ADCx, &ADC_InitStructure);
147 uint8_t rank = 1;
148 for (int i = 0; i < ADC_CHANNEL_COUNT; i++) {
149 if (!adcOperatingConfig[i].enabled) {
150 continue;
152 ADC_RegularChannelConfig(adc.ADCx, adcOperatingConfig[i].adcChannel, rank++, adcOperatingConfig[i].sampleTime);
155 ADC_DMACmd(adc.ADCx, ENABLE);
156 ADC_Cmd(adc.ADCx, ENABLE);
158 ADC_ResetCalibration(adc.ADCx);
159 while (ADC_GetResetCalibrationStatus(adc.ADCx));
160 ADC_StartCalibration(adc.ADCx);
161 while (ADC_GetCalibrationStatus(adc.ADCx));
163 ADC_SoftwareStartConvCmd(adc.ADCx, ENABLE);
166 void adcGetChannelValues(void)
168 // Nothing to do
170 #endif