From ea69db0400b178a398fb86a872aa8e0a2d3c69c1 Mon Sep 17 00:00:00 2001 From: Dominic Clifton Date: Sun, 9 Aug 2020 16:58:07 +0200 Subject: [PATCH] Allow H7 targets to specify an ADC device for each channel and a default ADC device in case of resource re-mapping conflict. This allows a single ADC device to be used for all channels, which can free up DMA channels. For the H7 this makes much more sense because the TEMP and VREF channels are ALWAYS on ADC3, so using ADC3 for other pins is optimal. The previous behaviour was to use the first instance for that supported the pin. This behavour is only used when the configured default DMA device does not support the pin. e.g. ``` possible. ``` The above config would no-longer use ADC1 for anything, as ADC2 and ADC3 can satisfy all the ADC requirements. --- src/main/drivers/adc_stm32h7xx.c | 38 ++++++++++++++++++++------------ src/main/pg/adc.c | 28 +++++++++++++++++++++++ src/main/pg/adc.h | 3 +++ 3 files changed, 55 insertions(+), 14 deletions(-) diff --git a/src/main/drivers/adc_stm32h7xx.c b/src/main/drivers/adc_stm32h7xx.c index c45bad816..0069859a9 100644 --- a/src/main/drivers/adc_stm32h7xx.c +++ b/src/main/drivers/adc_stm32h7xx.c @@ -281,18 +281,22 @@ void adcInit(const adcConfig_t *config) if (config->vbat.enabled) { adcOperatingConfig[ADC_BATTERY].tag = config->vbat.ioTag; + adcOperatingConfig[ADC_BATTERY].adcDevice = config->vbat.device; } if (config->rssi.enabled) { adcOperatingConfig[ADC_RSSI].tag = config->rssi.ioTag; //RSSI_ADC_CHANNEL; + adcOperatingConfig[ADC_RSSI].adcDevice = config->rssi.device; } if (config->external1.enabled) { adcOperatingConfig[ADC_EXTERNAL1].tag = config->external1.ioTag; //EXTERNAL1_ADC_CHANNEL; + adcOperatingConfig[ADC_EXTERNAL1].adcDevice = config->external1.device; } if (config->current.enabled) { adcOperatingConfig[ADC_CURRENT].tag = config->current.ioTag; //CURRENT_METER_ADC_CHANNEL; + adcOperatingConfig[ADC_CURRENT].adcDevice = config->current.device; } #ifdef USE_ADC_INTERNAL @@ -331,24 +335,30 @@ void adcInit(const adcConfig_t *config) // Found a tag map entry for this input pin // Find an ADC device that can handle this input pin - for (dev = 0; dev < ADCDEV_COUNT; dev++) { - if (!adcDevice[dev].ADCx + bool useConfiguredDevice = (dev != ADCINVALID) && (adcTagMap[map].devices & (1 << dev)); + + if (!useConfiguredDevice) { + // If the ADC was configured to use a specific device, but that device was not active, then try and find another active instance that works for the pin. + + for (dev = 0; dev < ADCDEV_COUNT; dev++) { + if (!adcDevice[dev].ADCx #ifndef USE_DMA_SPEC - || !adcDevice[dev].dmaResource + || !adcDevice[dev].dmaResource #endif - ) { - // Instance not activated + ) { + // Instance not activated + continue; + } + if (adcTagMap[map].devices & (1 << dev)) { + // Found an activated ADC instance for this input pin + break; + } + } + + if (dev == ADCDEV_COUNT) { + // No valid device found, go next channel. continue; } - if (adcTagMap[map].devices & (1 << dev)) { - // Found an activated ADC instance for this input pin - break; - } - } - - if (dev == ADCDEV_COUNT) { - // No valid device found, go next channel. - continue; } } diff --git a/src/main/pg/adc.c b/src/main/pg/adc.c index ff9280dd3..b6105c018 100644 --- a/src/main/pg/adc.c +++ b/src/main/pg/adc.c @@ -58,21 +58,49 @@ void pgResetFn_adcConfig(adcConfig_t *adcConfig) #ifdef VBAT_ADC_PIN adcConfig->vbat.enabled = true; adcConfig->vbat.ioTag = IO_TAG(VBAT_ADC_PIN); +#if defined(STM32H7) +#ifdef VBAT_ADC_INSTANCE + adcConfig->vbat.device = ADC_DEV_TO_CFG(adcDeviceByInstance(VBAT_ADC_INSTANCE)); +#else + adcConfig->vbat.device = adcConfig->device; +#endif +#endif #endif #ifdef EXTERNAL1_ADC_PIN adcConfig->external1.enabled = true; adcConfig->external1.ioTag = IO_TAG(EXTERNAL1_ADC_PIN); +#if defined(STM32H7) +#ifdef EXTERNAL1_ADC_INSTANCE + adcConfig->external1.device = ADC_DEV_TO_CFG(adcDeviceByInstance(EXTERNAL1_ADC_INSTANCE)); +#else + adcConfig->external1.device = adcConfig->device; +#endif +#endif #endif #ifdef CURRENT_METER_ADC_PIN adcConfig->current.enabled = true; adcConfig->current.ioTag = IO_TAG(CURRENT_METER_ADC_PIN); +#if defined(STM32H7) +#ifdef CURRENT_METER_ADC_INSTANCE + adcConfig->current.device = ADC_DEV_TO_CFG(adcDeviceByInstance(CURRENT_METER_ADC_INSTANCE)); +#else + adcConfig->current.device = adcConfig->device; +#endif +#endif #endif #ifdef RSSI_ADC_PIN adcConfig->rssi.enabled = true; adcConfig->rssi.ioTag = IO_TAG(RSSI_ADC_PIN); +#if defined(STM32H7) +#ifdef RSSI_ADC_INSTANCE + adcConfig->rssi.device = ADC_DEV_TO_CFG(adcDeviceByInstance(RSSI_ADC_INSTANCE)); +#else + adcConfig->rssi.device = adcConfig->device; +#endif +#endif #endif adcConfig->vrefIntCalibration = 0; diff --git a/src/main/pg/adc.h b/src/main/pg/adc.h index dbe8f35e6..8953a94c0 100644 --- a/src/main/pg/adc.h +++ b/src/main/pg/adc.h @@ -31,6 +31,9 @@ typedef struct adcChannelConfig_t { bool enabled; ioTag_t ioTag; +#if defined(STM32H7) + int8_t device; // ADCDevice +#endif } adcChannelConfig_t; typedef struct adcConfig_s {