Merge pull request #10558 from iNavFlight/MrD_Correct-comments-on-OSD-symbols
[inav.git] / src / main / drivers / adc_stm32h7xx.c
blobb9d055f10d3efd3530e57a0a1ba24a647866afd6
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 #include "build/debug.h"
29 #include "platform.h"
30 #include "drivers/time.h"
32 #include "drivers/io.h"
33 #include "io_impl.h"
34 #include "rcc.h"
35 #include "dma.h"
37 #include "drivers/sensor.h"
38 #include "drivers/accgyro/accgyro.h"
40 #include "adc.h"
41 #include "adc_impl.h"
44 static adcDevice_t adcHardware[ADCDEV_COUNT] = {
46 .ADCx = ADC1,
47 .rccADC = RCC_AHB1(ADC12),
48 .rccDMA = RCC_AHB1(DMA2),
49 .DMAy_Streamx = DMA2_Stream0,
50 .channel = DMA_REQUEST_ADC1,
51 .enabled = false,
52 .usedChannelCount = 0
55 .ADCx = ADC2,
56 .rccADC = RCC_AHB1(ADC12),
57 .rccDMA = RCC_AHB1(DMA2),
58 .DMAy_Streamx = DMA2_Stream1,
59 .channel = DMA_REQUEST_ADC2,
60 .enabled = false,
61 .usedChannelCount = 0
63 #if !(defined(STM32H7A3xx) || defined(STM32H7A3xxQ)) // These MCUs do not support ADC3
65 .ADCx = ADC3,
66 .rccADC = RCC_AHB4(ADC3),
67 .rccDMA = RCC_AHB1(DMA2),
68 .DMAy_Streamx = DMA2_Stream2,
69 .channel = DMA_REQUEST_ADC3,
70 .enabled = false,
71 .usedChannelCount = 0
73 #endif // 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[] = {
100 ADC_REGULAR_RANK_1,
101 ADC_REGULAR_RANK_2,
102 ADC_REGULAR_RANK_3,
103 ADC_REGULAR_RANK_4,
104 ADC_REGULAR_RANK_5,
105 ADC_REGULAR_RANK_6,
106 ADC_REGULAR_RANK_7,
107 ADC_REGULAR_RANK_8,
108 ADC_REGULAR_RANK_9,
109 ADC_REGULAR_RANK_10,
110 ADC_REGULAR_RANK_11,
111 ADC_REGULAR_RANK_12,
112 ADC_REGULAR_RANK_13,
113 ADC_REGULAR_RANK_14,
114 ADC_REGULAR_RANK_15,
115 ADC_REGULAR_RANK_16,
118 ADCDevice adcDeviceByInstance(ADC_TypeDef *instance)
120 if (instance == ADC1)
121 return ADCDEV_1;
123 if (instance == ADC2)
124 return ADCDEV_2;
126 if (instance == ADC3)
127 return ADCDEV_3;
129 return ADCINVALID;
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) {
160 return;
163 if (HAL_ADCEx_Calibration_Start(&adc->ADCHandle, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED) != HAL_OK) {
164 return;
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) {
182 return;
185 __HAL_LINKDMA(&adc->ADCHandle, DMA_Handle, adc->DmaHandle);
187 uint8_t rank = 0;
188 for (int i = ADC_CHN_1; i < ADC_CHN_COUNT; i++) {
189 if (!adcConfig[i].enabled || adcConfig[i].adcDevice != adcDevice) {
190 continue;
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;
199 sConfig.Offset = 0;
201 if (HAL_ADC_ConfigChannel(&adc->ADCHandle, &sConfig) != HAL_OK) {
202 return;
206 if (HAL_ADC_Start_DMA(&adc->ADCHandle, (uint32_t*)&adcValues[adcDevice], adc->usedChannelCount * ADC_AVERAGE_N_SAMPLES) != HAL_OK) {
207 return;
211 void adcHardwareInit(drv_adc_config_t *init)
213 UNUSED(init);
214 int configuredAdcChannels = 0;
216 for (int i = ADC_CHN_1; i < ADC_CHN_COUNT; i++) {
217 if (!adcConfig[i].tag)
218 continue;
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;
230 adc->enabled = true;
231 configuredAdcChannels++;
234 if (configuredAdcChannels == 0)
235 return;
237 for (int i = 0; i < ADCDEV_COUNT; i++) {
238 if (adcHardware[i].enabled) {
239 adcInstanceInit(i);