From 9d0ecd101774ec361c6790910d48817a2520dfad Mon Sep 17 00:00:00 2001 From: gospar Date: Tue, 23 Dec 2025 14:28:06 +0100 Subject: [PATCH 1/2] initial support for multiple motors --- .../stm32/stm32_adc_utils.cpp | 12 ++- .../hardware_specific/stm32/stm32_adc_utils.h | 4 +- .../stm32/stm32f1/stm32f1_hal.cpp | 46 +++++++---- .../stm32/stm32f4/stm32f4_hal.cpp | 55 +++++++------ .../stm32/stm32f7/stm32f7_hal.cpp | 54 +++++++------ .../stm32/stm32g4/stm32g4_hal.cpp | 79 +++++++++++-------- .../stm32/stm32h7/stm32h7_hal.cpp | 66 +++++++++------- .../stm32/stm32l4/stm32l4_hal.cpp | 77 ++++++++++-------- 8 files changed, 228 insertions(+), 165 deletions(-) diff --git a/src/current_sense/hardware_specific/stm32/stm32_adc_utils.cpp b/src/current_sense/hardware_specific/stm32/stm32_adc_utils.cpp index 8df30a60..bf9a210d 100644 --- a/src/current_sense/hardware_specific/stm32/stm32_adc_utils.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32_adc_utils.cpp @@ -115,9 +115,9 @@ int _findIndexOfLastPinMapADCEntry(int pin) { // each pin can be connected to multiple ADCs // the function will try to find a single ADC that can be used for all pins // if not possible it will return nullptr -ADC_TypeDef* _findBestADCForPins(int numPins, int pins[]) { +ADC_TypeDef* _findBestADCForPins(int numPins, int pins[], ADC_HandleTypeDef adc_handles[]) { - // assuning that there is less than 8 ADCs + // assuning that there is at most 5 ADCs uint8_t pins_at_adc[ADC_COUNT] = {0}; // check how many pins are there and are not set @@ -152,11 +152,19 @@ ADC_TypeDef* _findBestADCForPins(int numPins, int pins[]) { SimpleFOCDebug::print(i+1); SimpleFOCDebug::print(" pins: "); SimpleFOCDebug::println(pins_at_adc[i]); + if (adc_handles[i].Instance != NP) { + SimpleFOCDebug::print("STM32-CS: ADC"); + SimpleFOCDebug::print(i+1); + SimpleFOCDebug::println(" already in use!"); + } } #endif // now take the first ADC that has all pins connected for (int i = 0; i < ADC_COUNT; i++) { + if (adc_handles[i].Instance != NP) { + continue; // ADC already in use + } if (pins_at_adc[i] == no_pins) { return _indexToADC(i); } diff --git a/src/current_sense/hardware_specific/stm32/stm32_adc_utils.h b/src/current_sense/hardware_specific/stm32/stm32_adc_utils.h index 1294e8f1..3e15976e 100644 --- a/src/current_sense/hardware_specific/stm32/stm32_adc_utils.h +++ b/src/current_sense/hardware_specific/stm32/stm32_adc_utils.h @@ -18,8 +18,6 @@ #include "../../../drivers/hardware_specific/stm32/stm32_mcu.h" #include "stm32_mcu.h" - - /* Exported Functions */ /** * @brief Return ADC HAL channel linked to a PinName @@ -43,7 +41,7 @@ int _adcToIndex(ADC_TypeDef *AdcHandle); // functions helping to find the best ADC channel int _findIndexOfFirstPinMapADCEntry(int pin); int _findIndexOfLastPinMapADCEntry(int pin); -ADC_TypeDef* _findBestADCForPins(int num_pins, int pins[]); +ADC_TypeDef* _findBestADCForPins(int num_pins, int pins[], ADC_HandleTypeDef adc_handles[]); // Structure to hold ADC interrupt configuration per ADC instance diff --git a/src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_hal.cpp b/src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_hal.cpp index 8e5d551d..7a265499 100644 --- a/src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_hal.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_hal.cpp @@ -4,9 +4,9 @@ #include "../../../../communication/SimpleFOCDebug.h" #include "../stm32_adc_utils.h" -#define _TRGO_NOT_AVAILABLE 12345 -ADC_HandleTypeDef hadc; +// pointer to the ADC handles used in the project +ADC_HandleTypeDef hadc[ADC_COUNT] = {0}; /** * Function initializing the ADC and the injected channels for the low-side current sensing @@ -22,14 +22,14 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */ - hadc.Instance = _findBestADCForPins(3, cs_params->pins); + auto adc_instance = _findBestADCForPins(3, cs_params->pins, hadc); - if(hadc.Instance == ADC1) __HAL_RCC_ADC1_CLK_ENABLE(); + if(adc_instance == ADC1) __HAL_RCC_ADC1_CLK_ENABLE(); #ifdef ADC2 // if defined ADC2 - else if(hadc.Instance == ADC2) __HAL_RCC_ADC2_CLK_ENABLE(); + else if(adc_instance == ADC2) __HAL_RCC_ADC2_CLK_ENABLE(); #endif #ifdef ADC3 // if defined ADC3 - else if(hadc.Instance == ADC3) __HAL_RCC_ADC3_CLK_ENABLE(); + else if(adc_instance == ADC3) __HAL_RCC_ADC3_CLK_ENABLE(); #endif else{ #ifdef SIMPLEFOC_STM32_DEBUG @@ -38,13 +38,15 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive return -1; // error not a valid ADC instance } - hadc.Init.ScanConvMode = ADC_SCAN_ENABLE; - hadc.Init.ContinuousConvMode = ENABLE; - hadc.Init.DiscontinuousConvMode = DISABLE; - hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START; - hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; - hadc.Init.NbrOfConversion = 1; - HAL_ADC_Init(&hadc); + auto adc_num = _adcToIndex(adc_instance); + hadc[adc_num].Instance = adc_instance; + hadc[adc_num].Init.ScanConvMode = ADC_SCAN_ENABLE; + hadc[adc_num].Init.ContinuousConvMode = ENABLE; + hadc[adc_num].Init.DiscontinuousConvMode = DISABLE; + hadc[adc_num].Init.ExternalTrigConv = ADC_SOFTWARE_START; + hadc[adc_num].Init.DataAlign = ADC_DATAALIGN_RIGHT; + hadc[adc_num].Init.NbrOfConversion = 1; + HAL_ADC_Init(&hadc[adc_num]); /**Configure for the selected ADC regular channel to be converted. */ @@ -102,15 +104,15 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive if (!_isset(cs_params->pins[i])) continue; sConfigInjected.InjectedRank = _getADCInjectedRank(channel_no++); - sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc.Instance); - if (HAL_ADCEx_InjectedConfigChannel(&hadc, &sConfigInjected) != HAL_OK){ + sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc[adc_num].Instance); + if (HAL_ADCEx_InjectedConfigChannel(&hadc[adc_num], &sConfigInjected) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]) , hadc.Instance)); #endif return -1; } } - cs_params->adc_handle = &hadc; + cs_params->adc_handle = &hadc[adc_num]; return 0; } @@ -149,8 +151,18 @@ int _adc_gpio_init(Stm32CurrentSenseParams* cs_params, const int pinA, const int extern "C" { void ADC1_2_IRQHandler(void) { - HAL_ADC_IRQHandler(&hadc); + if (hadc[0].Instance != NP) + HAL_ADC_IRQHandler(&hadc[0]); + if (hadc[1].Instance != NP) + HAL_ADC_IRQHandler(&hadc[1]); } +#ifdef ADC3 + void ADC3_IRQHandler(void) + { + if (hadc[2].Instance != NP) + HAL_ADC_IRQHandler(&hadc[2]); + } +#endif } #endif \ No newline at end of file diff --git a/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_hal.cpp b/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_hal.cpp index 7fd188dd..b8c3bf33 100644 --- a/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_hal.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_hal.cpp @@ -5,9 +5,9 @@ //#define SIMPLEFOC_STM32_DEBUG #include "../../../../communication/SimpleFOCDebug.h" -#define _TRGO_NOT_AVAILABLE 12345 -ADC_HandleTypeDef hadc; +// pointer to the ADC handles used in the project +ADC_HandleTypeDef hadc[ADC_COUNT] = {0}; /** * Function initializing the ADC and the injected channels for the low-side current sensing @@ -23,14 +23,14 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */ - hadc.Instance = _findBestADCForPins(3, cs_params->pins); + auto adc_instance = _findBestADCForPins(3, cs_params->pins, hadc); - if(hadc.Instance == ADC1) __HAL_RCC_ADC1_CLK_ENABLE(); + if(adc_instance == ADC1) __HAL_RCC_ADC1_CLK_ENABLE(); #ifdef ADC2 // if defined ADC2 - else if(hadc.Instance == ADC2) __HAL_RCC_ADC2_CLK_ENABLE(); + else if(adc_instance == ADC2) __HAL_RCC_ADC2_CLK_ENABLE(); #endif #ifdef ADC3 // if defined ADC3 - else if(hadc.Instance == ADC3) __HAL_RCC_ADC3_CLK_ENABLE(); + else if(adc_instance == ADC3) __HAL_RCC_ADC3_CLK_ENABLE(); #endif else{ #ifdef SIMPLEFOC_STM32_DEBUG @@ -39,22 +39,26 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive return -1; // error not a valid ADC instance } + int adc_num = _adcToIndex(adc_instance); + #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: Using ADC: ", _adcToIndex(&hadc)+1); + SIMPLEFOC_DEBUG("STM32-CS: Using ADC: ", adc_num+1); #endif - hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; - hadc.Init.Resolution = ADC_RESOLUTION_12B; - hadc.Init.ScanConvMode = ENABLE; - hadc.Init.ContinuousConvMode = ENABLE; - hadc.Init.DiscontinuousConvMode = DISABLE; - hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; - hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START; // for now - hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; - hadc.Init.NbrOfConversion = 1; - hadc.Init.DMAContinuousRequests = DISABLE; - hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV; - if ( HAL_ADC_Init(&hadc) != HAL_OK){ + hadc[adc_num].Instance = adc_instance; + + hadc[adc_num].Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; + hadc[adc_num].Init.Resolution = ADC_RESOLUTION_12B; + hadc[adc_num].Init.ScanConvMode = ENABLE; + hadc[adc_num].Init.ContinuousConvMode = ENABLE; + hadc[adc_num].Init.DiscontinuousConvMode = DISABLE; + hadc[adc_num].Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; + hadc[adc_num].Init.ExternalTrigConv = ADC_SOFTWARE_START; // for now + hadc[adc_num].Init.DataAlign = ADC_DATAALIGN_RIGHT; + hadc[adc_num].Init.NbrOfConversion = 1; + hadc[adc_num].Init.DMAContinuousRequests = DISABLE; + hadc[adc_num].Init.EOCSelection = ADC_EOC_SINGLE_CONV; + if ( HAL_ADC_Init(&hadc[adc_num]) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init ADC!"); #endif @@ -115,15 +119,15 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive if (!_isset(cs_params->pins[i])) continue; sConfigInjected.InjectedRank = _getADCInjectedRank(channel_no++); - sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc.Instance); - if (HAL_ADCEx_InjectedConfigChannel(&hadc, &sConfigInjected) != HAL_OK){ + sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc[adc_num].Instance); + if (HAL_ADCEx_InjectedConfigChannel(&hadc[adc_num], &sConfigInjected) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]) , hadc.Instance)); + SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]) , hadc[adc_num].Instance)); #endif return -1; } } - cs_params->adc_handle = &hadc; + cs_params->adc_handle = &hadc[adc_num]; return 0; } @@ -160,7 +164,10 @@ int _adc_gpio_init(Stm32CurrentSenseParams* cs_params, const int pinA, const int extern "C" { void ADC_IRQHandler(void) { - HAL_ADC_IRQHandler(&hadc); + for(int adc_num=0; adc_numpins); + auto adc_instance = _findBestADCForPins(3, cs_params->pins, hadc); - if(hadc.Instance == ADC1) __HAL_RCC_ADC1_CLK_ENABLE(); + if(adc_instance == ADC1) __HAL_RCC_ADC1_CLK_ENABLE(); #ifdef ADC2 // if defined ADC2 - else if(hadc.Instance == ADC2) __HAL_RCC_ADC2_CLK_ENABLE(); + else if(adc_instance == ADC2) __HAL_RCC_ADC2_CLK_ENABLE(); #endif #ifdef ADC3 // if defined ADC3 - else if(hadc.Instance == ADC3) __HAL_RCC_ADC3_CLK_ENABLE(); + else if(adc_instance == ADC3) __HAL_RCC_ADC3_CLK_ENABLE(); #endif else{ #ifdef SIMPLEFOC_STM32_DEBUG @@ -38,23 +38,26 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive #endif return -1; // error not a valid ADC instance } + + int adc_num = _adcToIndex(adc_instance); #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: Using ADC: ", _adcToIndex(&hadc)+1); + SIMPLEFOC_DEBUG("STM32-CS: Using ADC: ", adc_num+1); #endif - hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; - hadc.Init.Resolution = ADC_RESOLUTION_12B; - hadc.Init.ScanConvMode = ENABLE; - hadc.Init.ContinuousConvMode = DISABLE; - hadc.Init.DiscontinuousConvMode = DISABLE; - hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; - hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START; // for now - hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; - hadc.Init.NbrOfConversion = 1; - hadc.Init.DMAContinuousRequests = DISABLE; - hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV; - if ( HAL_ADC_Init(&hadc) != HAL_OK){ + hadc[adc_num].Instance = adc_instance; + hadc[adc_num].Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; + hadc[adc_num].Init.Resolution = ADC_RESOLUTION_12B; + hadc[adc_num].Init.ScanConvMode = ENABLE; + hadc[adc_num].Init.ContinuousConvMode = DISABLE; + hadc[adc_num].Init.DiscontinuousConvMode = DISABLE; + hadc[adc_num].Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; + hadc[adc_num].Init.ExternalTrigConv = ADC_SOFTWARE_START; // for now + hadc[adc_num].Init.DataAlign = ADC_DATAALIGN_RIGHT; + hadc[adc_num].Init.NbrOfConversion = 1; + hadc[adc_num].Init.DMAContinuousRequests = DISABLE; + hadc[adc_num].Init.EOCSelection = ADC_EOC_SINGLE_CONV; + if ( HAL_ADC_Init(&hadc[adc_num]) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init ADC!"); #endif @@ -123,16 +126,16 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive if (!_isset(cs_params->pins[i])) continue; sConfigInjected.InjectedRank = _getADCInjectedRank(channel_no++); - sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc.Instance); - if (HAL_ADCEx_InjectedConfigChannel(&hadc, &sConfigInjected) != HAL_OK){ + sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc[adc_num].Instance); + if (HAL_ADCEx_InjectedConfigChannel(&hadc[adc_num], &sConfigInjected) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]) , hadc.Instance)); + SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]) , hadc[adc_num].Instance)); #endif return -1; } } - cs_params->adc_handle = &hadc; + cs_params->adc_handle = &hadc[adc_num]; return 0; } @@ -172,7 +175,10 @@ int _adc_gpio_init(Stm32CurrentSenseParams* cs_params, const int pinA, const int extern "C" { void ADC_IRQHandler(void) { - HAL_ADC_IRQHandler(&hadc); + for(int adc_num=0; adc_numpins); + auto adc_instance = _findBestADCForPins(3, cs_params->pins, hadc); - if(hadc.Instance == ADC1) { + if(adc_instance == ADC1) { #ifdef __HAL_RCC_ADC1_CLK_ENABLE __HAL_RCC_ADC1_CLK_ENABLE(); #endif @@ -33,7 +35,7 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive #endif } #ifdef ADC2 - else if (hadc.Instance == ADC2) { + else if (adc_instance == ADC2) { #ifdef __HAL_RCC_ADC2_CLK_ENABLE __HAL_RCC_ADC2_CLK_ENABLE(); #endif @@ -43,7 +45,7 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive } #endif #ifdef ADC3 - else if (hadc.Instance == ADC3) { + else if (adc_instance == ADC3) { #ifdef __HAL_RCC_ADC3_CLK_ENABLE __HAL_RCC_ADC3_CLK_ENABLE(); #endif @@ -56,7 +58,7 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive } #endif #ifdef ADC4 - else if (hadc.Instance == ADC4) { + else if (adc_instance == ADC4) { #ifdef __HAL_RCC_ADC4_CLK_ENABLE __HAL_RCC_ADC4_CLK_ENABLE(); #endif @@ -69,7 +71,7 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive } #endif #ifdef ADC5 - else if (hadc.Instance == ADC5) { + else if (adc_instance == ADC5) { #if defined(ADC345_COMMON) __HAL_RCC_ADC345_CLK_ENABLE(); #endif @@ -82,26 +84,29 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive return -1; // error not a valid ADC instance } + int adc_num = _adcToIndex(adc_instance); + #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: Using ADC: ", _adcToIndex(&hadc)+1); -#endif - - - hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; - hadc.Init.Resolution = ADC_RESOLUTION_12B; - hadc.Init.ScanConvMode = ADC_SCAN_ENABLE; - hadc.Init.ContinuousConvMode = DISABLE; - hadc.Init.LowPowerAutoWait = DISABLE; - hadc.Init.GainCompensation = 0; - hadc.Init.DiscontinuousConvMode = DISABLE; - hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; - hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START; // for now - hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; - hadc.Init.NbrOfConversion = 1; - hadc.Init.DMAContinuousRequests = DISABLE; - hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV; - hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED; - if ( HAL_ADC_Init(&hadc) != HAL_OK){ + SIMPLEFOC_DEBUG("STM32-CS: Using ADC: ", adc_num+1); +#endif + + hadc[adc_num].Instance = adc_instance; + + hadc[adc_num].Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; + hadc[adc_num].Init.Resolution = ADC_RESOLUTION_12B; + hadc[adc_num].Init.ScanConvMode = ADC_SCAN_ENABLE; + hadc[adc_num].Init.ContinuousConvMode = DISABLE; + hadc[adc_num].Init.LowPowerAutoWait = DISABLE; + hadc[adc_num].Init.GainCompensation = 0; + hadc[adc_num].Init.DiscontinuousConvMode = DISABLE; + hadc[adc_num].Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; + hadc[adc_num].Init.ExternalTrigConv = ADC_SOFTWARE_START; // for now + hadc[adc_num].Init.DataAlign = ADC_DATAALIGN_RIGHT; + hadc[adc_num].Init.NbrOfConversion = 1; + hadc[adc_num].Init.DMAContinuousRequests = DISABLE; + hadc[adc_num].Init.EOCSelection = ADC_EOC_SINGLE_CONV; + hadc[adc_num].Init.Overrun = ADC_OVR_DATA_PRESERVED; + if ( HAL_ADC_Init(&hadc[adc_num]) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init ADC!"); #endif @@ -166,15 +171,15 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive if (!_isset(cs_params->pins[i])) continue; sConfigInjected.InjectedRank = _getADCInjectedRank(channel_no++); - sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc.Instance); - if (HAL_ADCEx_InjectedConfigChannel(&hadc, &sConfigInjected) != HAL_OK){ + sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc[adc_num].Instance); + if (HAL_ADCEx_InjectedConfigChannel(&hadc[adc_num], &sConfigInjected) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]) , hadc.Instance)); + SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]) , hadc[adc_num].Instance)); #endif return -1; } } - cs_params->adc_handle = &hadc; + cs_params->adc_handle = &hadc[adc_num]; return 0; } @@ -214,26 +219,32 @@ int _adc_gpio_init(Stm32CurrentSenseParams* cs_params, const int pinA, const int extern "C" { void ADC1_2_IRQHandler(void) { - HAL_ADC_IRQHandler(&hadc); + if (hadc[0].Instance != NP) + HAL_ADC_IRQHandler(&hadc[0]); + if (hadc[1].Instance != NP) + HAL_ADC_IRQHandler(&hadc[1]); } #ifdef ADC3 void ADC3_IRQHandler(void) { - HAL_ADC_IRQHandler(&hadc); + if (hadc[2].Instance != NP) + HAL_ADC_IRQHandler(&hadc[2]); } #endif #ifdef ADC4 void ADC4_IRQHandler(void) { - HAL_ADC_IRQHandler(&hadc); + if (hadc[3].Instance != NP) + HAL_ADC_IRQHandler(&hadc[3]); } #endif #ifdef ADC5 void ADC5_IRQHandler(void) { - HAL_ADC_IRQHandler(&hadc); + if (hadc[4].Instance != NP) + HAL_ADC_IRQHandler(&hadc[4]); } #endif } diff --git a/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_hal.cpp b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_hal.cpp index e1b5cfde..8259f960 100644 --- a/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_hal.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_hal.cpp @@ -6,7 +6,8 @@ #include "../../../../communication/SimpleFOCDebug.h" -ADC_HandleTypeDef hadc; +// pointer to the ADC handles used in the project +ADC_HandleTypeDef hadc[ADC_COUNT] = {0}; /** * Function initializing the ADC and the injected channels for the low-side current sensing @@ -23,14 +24,14 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */ - hadc.Instance = _findBestADCForPins(3, cs_params->pins); + auto adc_instance = _findBestADCForPins(3, cs_params->pins, hadc); - if(hadc.Instance == ADC1) __HAL_RCC_ADC12_CLK_ENABLE(); + if(adc_instance == ADC1) __HAL_RCC_ADC12_CLK_ENABLE(); #ifdef ADC2 // if defined ADC2 - else if(hadc.Instance == ADC2) __HAL_RCC_ADC12_CLK_ENABLE(); + else if(adc_instance == ADC2) __HAL_RCC_ADC12_CLK_ENABLE(); #endif #ifdef ADC3 // if defined ADC3 - else if(hadc.Instance == ADC3) __HAL_RCC_ADC3_CLK_ENABLE(); + else if(adc_instance == ADC3) __HAL_RCC_ADC3_CLK_ENABLE(); #endif else{ #ifdef SIMPLEFOC_STM32_DEBUG @@ -39,36 +40,39 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive return -1; // error not a valid ADC instance } + int adc_num = _adcToIndex(adc_instance); + #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: Using ADC: ", _adcToIndex(&hadc)+1); + SIMPLEFOC_DEBUG("STM32-CS: Using ADC: ", adc_num+1); #endif - hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; - hadc.Init.Resolution = ADC_RESOLUTION_12B; - hadc.Init.ScanConvMode = ENABLE; - hadc.Init.ContinuousConvMode = DISABLE; - hadc.Init.DiscontinuousConvMode = DISABLE; - hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; - hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START; // for now + hadc[adc_num].Instance = adc_instance; + hadc[adc_num].Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; + hadc[adc_num].Init.Resolution = ADC_RESOLUTION_12B; + hadc[adc_num].Init.ScanConvMode = ENABLE; + hadc[adc_num].Init.ContinuousConvMode = DISABLE; + hadc[adc_num].Init.DiscontinuousConvMode = DISABLE; + hadc[adc_num].Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; + hadc[adc_num].Init.ExternalTrigConv = ADC_SOFTWARE_START; // for now #if defined(ADC_VER_V5_V90) // only for ADC3 - if(hadc.Instance == ADC3){ - hadc.Init.DataAlign = ADC3_DATAALIGN_RIGHT; + if(hadc[adc_num].Instance == ADC3){ + hadc[adc_num].Init.DataAlign = ADC3_DATAALIGN_RIGHT; } // more info here // https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32H7xx_HAL_Driver/Inc/stm32h7xx_hal_adc.h#L170C13-L170C27 - hadc.Init.DMAContinuousRequests = DISABLE; + hadc[adc_num].Init.DMAContinuousRequests = DISABLE; // not sure about this one!!! maybe use: ADC_SAMPLING_MODE_NORMAL - hadc.Init.SamplingMode = ADC_SAMPLING_MODE_NORMAL; + hadc[adc_num].Init.SamplingMode = ADC_SAMPLING_MODE_NORMAL; #endif - hadc.Init.NbrOfConversion = 1; - hadc.Init.NbrOfDiscConversion = 0; - hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV; + hadc[adc_num].Init.NbrOfConversion = 1; + hadc[adc_num].Init.NbrOfDiscConversion = 0; + hadc[adc_num].Init.EOCSelection = ADC_EOC_SINGLE_CONV; - hadc.Init.LowPowerAutoWait = DISABLE; + hadc[adc_num].Init.LowPowerAutoWait = DISABLE; - if ( HAL_ADC_Init(&hadc) != HAL_OK){ + if ( HAL_ADC_Init(&hadc[adc_num]) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init ADC!"); #endif @@ -84,7 +88,7 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive } } // if ADC1 or ADC2 - if(hadc.Instance == ADC1 || hadc.Instance == ADC2){ + if(hadc[adc_num].Instance == ADC1 || hadc[adc_num].Instance == ADC2){ // more info here: https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32H7xx_HAL_Driver/Inc/stm32h7xx_hal_adc.h#L658 sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_2CYCLES_5; }else { @@ -144,16 +148,16 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive if (!_isset(cs_params->pins[i])) continue; sConfigInjected.InjectedRank = _getADCInjectedRank(channel_no++); - sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc.Instance); - if (HAL_ADCEx_InjectedConfigChannel(&hadc, &sConfigInjected) != HAL_OK){ + sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc[adc_num].Instance); + if (HAL_ADCEx_InjectedConfigChannel(&hadc[adc_num], &sConfigInjected) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]) , hadc.Instance)); + SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]) , hadc[adc_num].Instance)); #endif return -1; } } - cs_params->adc_handle = &hadc; + cs_params->adc_handle = &hadc[adc_num]; return 0; } @@ -194,14 +198,18 @@ int _adc_gpio_init(Stm32CurrentSenseParams* cs_params, const int pinA, const int extern "C" { void ADC_IRQHandler(void) { - HAL_ADC_IRQHandler(&hadc); + if (hadc[0].Instance != NP) + HAL_ADC_IRQHandler(&hadc[0]); + if (hadc[1].Instance != NP) + HAL_ADC_IRQHandler(&hadc[1]); } } #ifdef ADC3 extern "C" { void ADC3_IRQHandler(void) - { + { + if (hadc[2].Instance != NP) HAL_ADC_IRQHandler(&hadc); } } diff --git a/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_hal.cpp b/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_hal.cpp index b0b43062..48fa866f 100644 --- a/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_hal.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_hal.cpp @@ -6,7 +6,8 @@ #define SIMPLEFOC_STM32_DEBUG -ADC_HandleTypeDef hadc; +// pointer to the ADC handles used in the project +ADC_HandleTypeDef hadc[ADC_COUNT] = {0}; /** * Function initializing the ADC and the injected channels for the low-side current sensing @@ -22,9 +23,14 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */ - hadc.Instance = _findBestADCForPins(3, cs_params->pins); + auto adc_instance = _findBestADCForPins(3, cs_params->pins, hadc); + int adc_num = _adcToIndex(adc_instance); + if (hadc[adc_num].Instance != NP) { + SIMPLEFOC_DEBUG("STM32-CS: ERR: ADC already in use: ADC", adc_num + 1); + return -1; + } - if(hadc.Instance == ADC1) { + if(adc_instance == ADC1) { #ifdef __HAL_RCC_ADC1_CLK_ENABLE __HAL_RCC_ADC1_CLK_ENABLE(); #endif @@ -33,7 +39,7 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive #endif } #ifdef ADC2 - else if (hadc.Instance == ADC2) { + else if (adc_instance == ADC2) { #ifdef __HAL_RCC_ADC2_CLK_ENABLE __HAL_RCC_ADC2_CLK_ENABLE(); #endif @@ -43,7 +49,7 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive } #endif #ifdef ADC3 - else if (hadc.Instance == ADC3) { + else if (adc_instance == ADC3) { #ifdef __HAL_RCC_ADC3_CLK_ENABLE __HAL_RCC_ADC3_CLK_ENABLE(); #endif @@ -56,7 +62,7 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive } #endif #ifdef ADC4 - else if (hadc.Instance == ADC4) { + else if (adc_instance == ADC4) { #ifdef __HAL_RCC_ADC4_CLK_ENABLE __HAL_RCC_ADC4_CLK_ENABLE(); #endif @@ -69,7 +75,7 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive } #endif #ifdef ADC5 - else if (hadc.Instance == ADC5) { + else if (adc_instance == ADC5) { #if defined(ADC345_COMMON) __HAL_RCC_ADC345_CLK_ENABLE(); #endif @@ -83,23 +89,24 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive } #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: Using ADC: ", _adcToIndex(&hadc)+1); -#endif - - hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; - hadc.Init.Resolution = ADC_RESOLUTION_12B; - hadc.Init.ScanConvMode = ADC_SCAN_ENABLE; - hadc.Init.ContinuousConvMode = DISABLE; - hadc.Init.LowPowerAutoWait = DISABLE; - hadc.Init.DiscontinuousConvMode = DISABLE; - hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; - hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START; // for now - hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; - hadc.Init.NbrOfConversion = 1; - hadc.Init.DMAContinuousRequests = DISABLE; - hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV; - hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED; - if ( HAL_ADC_Init(&hadc) != HAL_OK){ + SIMPLEFOC_DEBUG("STM32-CS: Using ADC: ", adc_num+1); +#endif + + hadc[adc_num].Instance = adc_instance; + hadc[adc_num].Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; + hadc[adc_num].Init.Resolution = ADC_RESOLUTION_12B; + hadc[adc_num].Init.ScanConvMode = ADC_SCAN_ENABLE; + hadc[adc_num].Init.ContinuousConvMode = DISABLE; + hadc[adc_num].Init.LowPowerAutoWait = DISABLE; + hadc[adc_num].Init.DiscontinuousConvMode = DISABLE; + hadc[adc_num].Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; + hadc[adc_num].Init.ExternalTrigConv = ADC_SOFTWARE_START; // for now + hadc[adc_num].Init.DataAlign = ADC_DATAALIGN_RIGHT; + hadc[adc_num].Init.NbrOfConversion = 1; + hadc[adc_num].Init.DMAContinuousRequests = DISABLE; + hadc[adc_num].Init.EOCSelection = ADC_EOC_SINGLE_CONV; + hadc[adc_num].Init.Overrun = ADC_OVR_DATA_PRESERVED; + if ( HAL_ADC_Init(&hadc[adc_num]) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init ADC!"); #endif @@ -160,15 +167,15 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive if (!_isset(cs_params->pins[i])) continue; sConfigInjected.InjectedRank = _getADCInjectedRank(channel_no++); - sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc.Instance); - if (HAL_ADCEx_InjectedConfigChannel(&hadc, &sConfigInjected) != HAL_OK){ + sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc[adc_num].Instance); + if (HAL_ADCEx_InjectedConfigChannel(&hadc[adc_num], &sConfigInjected) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc.Instance)); + SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc[adc_num].Instance)); #endif return -1; } } - cs_params->adc_handle = &hadc; + cs_params->adc_handle = &hadc[adc_num]; return 0; } @@ -207,26 +214,32 @@ int _adc_gpio_init(Stm32CurrentSenseParams* cs_params, const int pinA, const int extern "C" { void ADC1_2_IRQHandler(void) { - HAL_ADC_IRQHandler(&hadc); + if (hadc[0].Instance != NP) + HAL_ADC_IRQHandler(&hadc[0]); + if (hadc[1].Instance != NP) + HAL_ADC_IRQHandler(&hadc[1]); } #ifdef ADC3 void ADC3_IRQHandler(void) { - HAL_ADC_IRQHandler(&hadc); + if (hadc[2].Instance != NP) + HAL_ADC_IRQHandler(&hadc[2]); } #endif #ifdef ADC4 void ADC4_IRQHandler(void) { - HAL_ADC_IRQHandler(&hadc); + if (hadc[3].Instance != NP) + HAL_ADC_IRQHandler(&hadc[3]); } #endif #ifdef ADC5 void ADC5_IRQHandler(void) { - HAL_ADC_IRQHandler(&hadc); + if (hadc[4].Instance != NP) + HAL_ADC_IRQHandler(&hadc[4]); } #endif } From 60701490dd73e1caace24548fe07fb7b83d4d328 Mon Sep 17 00:00:00 2001 From: gospar Date: Tue, 23 Dec 2025 14:51:49 +0100 Subject: [PATCH 2/2] typo --- .../hardware_specific/stm32/stm32f1/stm32f1_hal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_hal.cpp b/src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_hal.cpp index 7a265499..e65c99e5 100644 --- a/src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_hal.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_hal.cpp @@ -107,7 +107,7 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc[adc_num].Instance); if (HAL_ADCEx_InjectedConfigChannel(&hadc[adc_num], &sConfigInjected) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]) , hadc.Instance)); + SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]) , hadc[adc_num].Instance)); #endif return -1; }