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/>.
27 #include "build/debug.h"
30 #include "drivers/time.h"
32 #include "drivers/io.h"
37 #include "drivers/sensor.h"
38 #include "drivers/accgyro/accgyro.h"
44 static adcDevice_t adcHardware
[ADCDEV_COUNT
] = {
47 .rccADC
= RCC_AHB1(ADC12
),
48 .rccDMA
= RCC_AHB1(DMA2
),
49 .DMAy_Streamx
= DMA2_Stream0
,
50 .channel
= DMA_REQUEST_ADC1
,
56 .rccADC
= RCC_AHB1(ADC12
),
57 .rccDMA
= RCC_AHB1(DMA2
),
58 .DMAy_Streamx
= DMA2_Stream1
,
59 .channel
= DMA_REQUEST_ADC2
,
63 #if !(defined(STM32H7A3xx) || defined(STM32H7A3xxQ)) // These MCUs do not support ADC3
66 .rccADC
= RCC_AHB4(ADC3
),
67 .rccDMA
= RCC_AHB1(DMA2
),
68 .DMAy_Streamx
= DMA2_Stream2
,
69 .channel
= DMA_REQUEST_ADC3
,
76 adcDevice_t adcDevice
[ADCDEV_COUNT
];
78 /* note these could be packed up for saving space */
79 const adcTagMap_t adcTagMap
[] = {
80 { DEFIO_TAG_E__PC0
, ADC_CHANNEL_10
},
81 { DEFIO_TAG_E__PC1
, ADC_CHANNEL_11
},
82 { DEFIO_TAG_E__PC2
, ADC_CHANNEL_0
},
83 { DEFIO_TAG_E__PC3
, ADC_CHANNEL_1
},
84 { DEFIO_TAG_E__PC4
, ADC_CHANNEL_4
},
85 { DEFIO_TAG_E__PC5
, ADC_CHANNEL_8
},
86 { DEFIO_TAG_E__PB0
, ADC_CHANNEL_9
},
87 { DEFIO_TAG_E__PB1
, ADC_CHANNEL_5
},
88 { DEFIO_TAG_E__PA0
, ADC_CHANNEL_16
},
89 { DEFIO_TAG_E__PA1
, ADC_CHANNEL_17
},
90 { DEFIO_TAG_E__PA2
, ADC_CHANNEL_14
},
91 { DEFIO_TAG_E__PA3
, ADC_CHANNEL_15
},
92 { DEFIO_TAG_E__PA4
, ADC_CHANNEL_18
},
93 { DEFIO_TAG_E__PA5
, ADC_CHANNEL_19
},
94 { DEFIO_TAG_E__PA6
, ADC_CHANNEL_3
},
95 { DEFIO_TAG_E__PA7
, ADC_CHANNEL_7
},
98 // Translate rank number x to ADC_REGULAR_RANK_x (Note that array index is 0-origin)
99 static const uint32_t adcRegularRankMap
[] = {
118 ADCDevice
adcDeviceByInstance(ADC_TypeDef
*instance
)
120 if (instance
== ADC1
)
123 if (instance
== ADC2
)
126 if (instance
== ADC3
)
132 static void adcInstanceInit(ADCDevice adcDevice
)
134 adcDevice_t
* adc
= &adcHardware
[adcDevice
];
136 RCC_ClockCmd(adc
->rccDMA
, ENABLE
);
137 RCC_ClockCmd(adc
->rccADC
, ENABLE
);
139 adc
->ADCHandle
.Instance
= adc
->ADCx
;
141 adc
->ADCHandle
.Init
.ClockPrescaler
= ADC_CLOCK_SYNC_PCLK_DIV4
;
142 adc
->ADCHandle
.Init
.Resolution
= ADC_RESOLUTION_12B
;
143 adc
->ADCHandle
.Init
.ContinuousConvMode
= ENABLE
;
144 adc
->ADCHandle
.Init
.ExternalTrigConv
= ADC_EXTERNALTRIG_T1_CC1
;
145 adc
->ADCHandle
.Init
.ExternalTrigConvEdge
= ADC_EXTERNALTRIGCONVEDGE_NONE
;
146 adc
->ADCHandle
.Init
.NbrOfConversion
= adc
->usedChannelCount
;
147 adc
->ADCHandle
.Init
.ScanConvMode
= adc
->usedChannelCount
> 1 ? ENABLE
: DISABLE
; // 1=scan more that one channel in group
148 adc
->ADCHandle
.Init
.DiscontinuousConvMode
= DISABLE
;
149 adc
->ADCHandle
.Init
.NbrOfDiscConversion
= 0;
150 adc
->ADCHandle
.Init
.EOCSelection
= DISABLE
;
151 adc
->ADCHandle
.Init
.LowPowerAutoWait
= DISABLE
;
153 // Enable circular DMA.
154 adc
->ADCHandle
.Init
.ConversionDataManagement
= ADC_CONVERSIONDATA_DMA_CIRCULAR
;
156 adc
->ADCHandle
.Init
.Overrun
= ADC_OVR_DATA_OVERWRITTEN
;
157 adc
->ADCHandle
.Init
.OversamplingMode
= DISABLE
;
159 if (HAL_ADC_Init(&adc
->ADCHandle
) != HAL_OK
) {
163 if (HAL_ADCEx_Calibration_Start(&adc
->ADCHandle
, ADC_CALIB_OFFSET
, ADC_SINGLE_ENDED
) != HAL_OK
) {
167 adc
->DmaHandle
.Init
.Request
= adc
->channel
;
168 adc
->DmaHandle
.Init
.Direction
= DMA_PERIPH_TO_MEMORY
;
169 adc
->DmaHandle
.Init
.PeriphInc
= DMA_PINC_DISABLE
;
170 adc
->DmaHandle
.Init
.MemInc
= ((adc
->usedChannelCount
> 1) || (ADC_AVERAGE_N_SAMPLES
> 1)) ? DMA_MINC_ENABLE
: DMA_MINC_DISABLE
;
171 adc
->DmaHandle
.Init
.PeriphDataAlignment
= DMA_PDATAALIGN_HALFWORD
;
172 adc
->DmaHandle
.Init
.MemDataAlignment
= DMA_MDATAALIGN_HALFWORD
;
173 adc
->DmaHandle
.Init
.Mode
= DMA_CIRCULAR
;
174 adc
->DmaHandle
.Init
.Priority
= DMA_PRIORITY_HIGH
;
175 adc
->DmaHandle
.Init
.FIFOMode
= DMA_FIFOMODE_DISABLE
;
176 adc
->DmaHandle
.Init
.FIFOThreshold
= DMA_FIFO_THRESHOLD_FULL
;
177 adc
->DmaHandle
.Init
.MemBurst
= DMA_MBURST_SINGLE
;
178 adc
->DmaHandle
.Init
.PeriphBurst
= DMA_PBURST_SINGLE
;
179 adc
->DmaHandle
.Instance
= adc
->DMAy_Streamx
;
181 if (HAL_DMA_Init(&adc
->DmaHandle
) != HAL_OK
) {
185 __HAL_LINKDMA(&adc
->ADCHandle
, DMA_Handle
, adc
->DmaHandle
);
188 for (int i
= ADC_CHN_1
; i
< ADC_CHN_COUNT
; i
++) {
189 if (!adcConfig
[i
].enabled
|| adcConfig
[i
].adcDevice
!= adcDevice
) {
193 ADC_ChannelConfTypeDef sConfig
;
194 sConfig
.Channel
= adcConfig
[i
].adcChannel
;
195 sConfig
.Rank
= adcRegularRankMap
[rank
++];
196 sConfig
.SamplingTime
= adcConfig
[i
].sampleTime
;
197 sConfig
.SingleDiff
= ADC_SINGLE_ENDED
;
198 sConfig
.OffsetNumber
= ADC_OFFSET_NONE
;
201 if (HAL_ADC_ConfigChannel(&adc
->ADCHandle
, &sConfig
) != HAL_OK
) {
206 if (HAL_ADC_Start_DMA(&adc
->ADCHandle
, (uint32_t*)&adcValues
[adcDevice
], adc
->usedChannelCount
* ADC_AVERAGE_N_SAMPLES
) != HAL_OK
) {
211 void adcHardwareInit(drv_adc_config_t
*init
)
214 int configuredAdcChannels
= 0;
216 for (int i
= ADC_CHN_1
; i
< ADC_CHN_COUNT
; i
++) {
217 if (!adcConfig
[i
].tag
)
220 adcDevice_t
* adc
= &adcHardware
[adcConfig
[i
].adcDevice
];
222 IOInit(IOGetByTag(adcConfig
[i
].tag
), OWNER_ADC
, RESOURCE_ADC_CH1
+ (i
- ADC_CHN_1
), 0);
223 IOConfigGPIO(IOGetByTag(adcConfig
[i
].tag
), IO_CONFIG(GPIO_MODE_ANALOG
, 0, GPIO_NOPULL
));
225 adcConfig
[i
].adcChannel
= adcChannelByTag(adcConfig
[i
].tag
);
226 adcConfig
[i
].dmaIndex
= adc
->usedChannelCount
++;
227 adcConfig
[i
].sampleTime
= ADC_SAMPLETIME_387CYCLES_5
;
228 adcConfig
[i
].enabled
= true;
231 configuredAdcChannels
++;
234 if (configuredAdcChannels
== 0)
237 for (int i
= 0; i
< ADCDEV_COUNT
; i
++) {
238 if (adcHardware
[i
].enabled
) {