From e264029fbc9957318130bd523522bdb3f8549215 Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Thu, 4 Mar 2021 17:58:56 -0800 Subject: [PATCH] STM32H7 Slow ADC (#2421) * extract * guard * put some back * put back * slow is actually 500hz so slow is fine here * no magic * fix printFullAdcReport * cast * implement h7 adc ish * analog switches * bad merge * no map avg on h7 * fix master while we're at it Co-authored-by: Matthew Kennedy --- .github/workflows/gen-configs.yaml | 2 +- firmware/config/stm32h7ems/efifeatures.h | 3 + firmware/hw_layer/adc/adc_inputs.cpp | 3 +- .../hw_layer/ports/stm32/stm32_adc_v4.cpp | 108 ++++++++++++++++++ .../ports/stm32/stm32h7/cfg/halconf.h | 4 - .../ports/stm32/stm32h7/cfg/mcuconf.h | 2 +- .../hw_layer/ports/stm32/stm32h7/hw_ports.mk | 3 +- 7 files changed, 116 insertions(+), 9 deletions(-) create mode 100644 firmware/hw_layer/ports/stm32/stm32_adc_v4.cpp diff --git a/.github/workflows/gen-configs.yaml b/.github/workflows/gen-configs.yaml index 7f35a71104..0ddd108b16 100644 --- a/.github/workflows/gen-configs.yaml +++ b/.github/workflows/gen-configs.yaml @@ -15,7 +15,7 @@ jobs: fetch-depth: 0 - name: Install Tools - run: sudo apt-get install ncftp sshpass + run: sudo apt-get install ncftp sshpass mtools - name: Generate Enum Strings working-directory: ./firmware/ diff --git a/firmware/config/stm32h7ems/efifeatures.h b/firmware/config/stm32h7ems/efifeatures.h index 264d69813a..4395403e13 100644 --- a/firmware/config/stm32h7ems/efifeatures.h +++ b/firmware/config/stm32h7ems/efifeatures.h @@ -2,6 +2,9 @@ #pragma once +#undef EFI_MAP_AVERAGING +#define EFI_MAP_AVERAGING FALSE + #undef EFI_USE_FAST_ADC #define EFI_USE_FAST_ADC FALSE diff --git a/firmware/hw_layer/adc/adc_inputs.cpp b/firmware/hw_layer/adc/adc_inputs.cpp index a4d6ee9f7e..b9da15549f 100644 --- a/firmware/hw_layer/adc/adc_inputs.cpp +++ b/firmware/hw_layer/adc/adc_inputs.cpp @@ -240,7 +240,7 @@ adc_channel_mode_e getAdcMode(adc_channel_e hwChannel) { } #endif // EFI_USE_FAST_ADC - return ADC_OFF; + return ADC_SLOW; } #if EFI_USE_FAST_ADC @@ -321,7 +321,6 @@ static void printAdcValue(int channel) { scheduleMsg(&logger, "adc voltage : %.2f", volts); } - static uint32_t slowAdcConversionCount = 0; static uint32_t slowAdcErrorsCount = 0; diff --git a/firmware/hw_layer/ports/stm32/stm32_adc_v4.cpp b/firmware/hw_layer/ports/stm32/stm32_adc_v4.cpp new file mode 100644 index 0000000000..7636824aa4 --- /dev/null +++ b/firmware/hw_layer/ports/stm32/stm32_adc_v4.cpp @@ -0,0 +1,108 @@ +/** + * @file stm32_adc_v4.cpp + * @brief Port implementation for the STM32 "v4" ADC found on the STM32H7 + * + * @date February 25, 2021 + * @author Matthew Kennedy, (c) 2021 + */ + +#include "global.h" +#include "hal.h" +#include "mpu_util.h" + +void portInitAdc() { + // Init slow ADC + adcStart(&ADCD1, NULL); + + // Connect the analog switches between {PA0_C, PA1_C, PC2_C, PC3_C} and their non-C counterparts + // This lets us use normal (non-direct) analog on those channels + SYSCFG->PMCR &= ~(SYSCFG_PMCR_PA0SO | SYSCFG_PMCR_PA1SO | SYSCFG_PMCR_PC2SO | SYSCFG_PMCR_PC3SO); +} + +float getMcuTemperature() { + // Ugh, internal temp sensor is wired to ADC3, which makes it nearly useless on the H7. + return 0; +} + +// TODO: use a define instead of magic number +#define ADC_SAMPLING_SLOW (7) + +// Sample the 16 channels that line up with the STM32F4/F7 +constexpr size_t slowChannelCount = 16; + +// Conversion group for slow channels +// This simply samples every channel in sequence +static constexpr ADCConversionGroup convGroupSlow = { + .circular = FALSE, + .num_channels = slowChannelCount, + .end_cb = nullptr, + .error_cb = nullptr, + .cfgr = 0, + .cfgr2 = 0, // no oversampling (yet) + .ccr = 0, + .pcsel = 0xFFFFFFFF, // enable analog switches on all channels + // Thresholds aren't used + .ltr1 = 0, .htr1 = 0, .ltr2 = 0, .htr2 = 0, .ltr3 = 0, .htr3 = 0, + .smpr = { + // Configure all channels to use ADC_SAMPLING_SLOW time + ADC_SMPR1_SMP_AN0(ADC_SAMPLING_SLOW) | + ADC_SMPR1_SMP_AN1(ADC_SAMPLING_SLOW) | + ADC_SMPR1_SMP_AN2(ADC_SAMPLING_SLOW) | + ADC_SMPR1_SMP_AN3(ADC_SAMPLING_SLOW) | + ADC_SMPR1_SMP_AN4(ADC_SAMPLING_SLOW) | + ADC_SMPR1_SMP_AN5(ADC_SAMPLING_SLOW) | + ADC_SMPR1_SMP_AN6(ADC_SAMPLING_SLOW) | + ADC_SMPR1_SMP_AN7(ADC_SAMPLING_SLOW) | + ADC_SMPR1_SMP_AN8(ADC_SAMPLING_SLOW) | + ADC_SMPR1_SMP_AN9(ADC_SAMPLING_SLOW), + ADC_SMPR2_SMP_AN10(ADC_SAMPLING_SLOW) | + ADC_SMPR2_SMP_AN11(ADC_SAMPLING_SLOW) | + ADC_SMPR2_SMP_AN12(ADC_SAMPLING_SLOW) | + ADC_SMPR2_SMP_AN13(ADC_SAMPLING_SLOW) | + ADC_SMPR2_SMP_AN14(ADC_SAMPLING_SLOW) | + ADC_SMPR2_SMP_AN15(ADC_SAMPLING_SLOW) | + ADC_SMPR2_SMP_AN16(ADC_SAMPLING_SLOW) | + ADC_SMPR2_SMP_AN17(ADC_SAMPLING_SLOW) | + ADC_SMPR2_SMP_AN18(ADC_SAMPLING_SLOW) | + ADC_SMPR2_SMP_AN19(ADC_SAMPLING_SLOW) + }, + .sqr = { + // The seemingly insane values here exist to put the values + // in the buffer in the same order as the ADCv2 (F4/F7) ADC + ADC_SQR1_SQ1_N(16) | // PA0 (aka PA0_C) + ADC_SQR1_SQ2_N(17) | // PA1 (aka PA1_C) + ADC_SQR1_SQ3_N(14) | // PA2 + ADC_SQR1_SQ4_N(15), // PA3 + ADC_SQR2_SQ5_N(18) | // PA4 + ADC_SQR2_SQ6_N(19) | // PA5 + ADC_SQR2_SQ7_N(3) | // PA6 + ADC_SQR2_SQ8_N(7) | // PA7 + ADC_SQR2_SQ9_N(9), // PB0 + ADC_SQR3_SQ10_N(5) | // PB1 + ADC_SQR3_SQ11_N(10) | // PC0 + ADC_SQR3_SQ12_N(11) | // PC1 + ADC_SQR3_SQ13_N(12) | // PC2 (aka PC2_C) + ADC_SQR3_SQ14_N(13), // PC3 (aka PC3_C) + ADC_SQR4_SQ15_N(4) | // PC4 + ADC_SQR4_SQ16_N(8) // PC5 + }, +}; + +static NO_CACHE adcsample_t slowSampleBuffer[slowChannelCount]; + +bool readSlowAnalogInputs(adcsample_t* convertedSamples) { + msg_t result = adcConvert(&ADCD1, &convGroupSlow, slowSampleBuffer, 1); + + // If something went wrong - try again later + if (result != MSG_OK) { + return false; + } + + // V4 ADC can oversample in hardware, so no need to oversample in software + for (int i = 0; i < slowChannelCount; i++) { + // Convert from 16b result to 12b result + convertedSamples[i] = slowSampleBuffer[i] >> 4; + } + + return true; +} diff --git a/firmware/hw_layer/ports/stm32/stm32h7/cfg/halconf.h b/firmware/hw_layer/ports/stm32/stm32h7/cfg/halconf.h index 61ff6e9787..05506323d7 100644 --- a/firmware/hw_layer/ports/stm32/stm32h7/cfg/halconf.h +++ b/firmware/hw_layer/ports/stm32/stm32h7/cfg/halconf.h @@ -35,10 +35,6 @@ #include "rusefi_halconf.h" -// TODO: implement ADC on H7 -#undef HAL_USE_ADC -#define HAL_USE_ADC FALSE - /** * @brief Enables the cryptographic subsystem. */ diff --git a/firmware/hw_layer/ports/stm32/stm32h7/cfg/mcuconf.h b/firmware/hw_layer/ports/stm32/stm32h7/cfg/mcuconf.h index 96fc96092a..8fef640764 100644 --- a/firmware/hw_layer/ports/stm32/stm32h7/cfg/mcuconf.h +++ b/firmware/hw_layer/ports/stm32/stm32h7/cfg/mcuconf.h @@ -225,7 +225,7 @@ */ #define STM32_ADC_DUAL_MODE FALSE #define STM32_ADC_COMPACT_SAMPLES FALSE -#define STM32_ADC_USE_ADC12 FALSE +#define STM32_ADC_USE_ADC12 TRUE #define STM32_ADC_USE_ADC3 FALSE #define STM32_ADC_ADC12_DMA_STREAM STM32_DMA_STREAM_ID_ANY #define STM32_ADC_ADC3_BDMA_STREAM STM32_BDMA_STREAM_ID_ANY diff --git a/firmware/hw_layer/ports/stm32/stm32h7/hw_ports.mk b/firmware/hw_layer/ports/stm32/stm32h7/hw_ports.mk index 7d3cf3edd6..2d03cf6fbd 100644 --- a/firmware/hw_layer/ports/stm32/stm32h7/hw_ports.mk +++ b/firmware/hw_layer/ports/stm32/stm32h7/hw_ports.mk @@ -3,7 +3,8 @@ include $(PROJECT_DIR)/hw_layer/ports/stm32/stm32_common.mk HW_LAYER_EMS += $(PROJECT_DIR)/hw_layer/ports/stm32/stm32h7/stm32h7xx_hal_flash.c \ $(PROJECT_DIR)/hw_layer/ports/stm32/stm32h7/stm32h7xx_hal_flash_ex.c -HW_LAYER_EMS_CPP += $(PROJECT_DIR)/hw_layer/ports/stm32/stm32h7/mpu_util.cpp +HW_LAYER_EMS_CPP += $(PROJECT_DIR)/hw_layer/ports/stm32/stm32h7/mpu_util.cpp \ + $(PROJECT_DIR)/hw_layer/ports/stm32/stm32_adc_v4.cpp \ DDEFS += -DSTM32H743xx MCU = cortex-m7