From b8240262287a6f82dc92b924180b5163d708db06 Mon Sep 17 00:00:00 2001 From: gospar Date: Thu, 13 Mar 2025 12:07:57 +0100 Subject: [PATCH 01/15] inital support for h7 low-side current sensing - compiless --- .../stm32/stm32h7/stm32h7_hal.cpp | 207 +++++++++++++++ .../stm32/stm32h7/stm32h7_hal.h | 13 + .../stm32/stm32h7/stm32h7_mcu.cpp | 116 +++++++++ .../stm32/stm32h7/stm32h7_utils.cpp | 240 ++++++++++++++++++ .../stm32/stm32h7/stm32h7_utils.h | 30 +++ 5 files changed, 606 insertions(+) create mode 100644 src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_hal.cpp create mode 100644 src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_hal.h create mode 100644 src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_mcu.cpp create mode 100644 src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_utils.cpp create mode 100644 src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_utils.h diff --git a/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_hal.cpp b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_hal.cpp new file mode 100644 index 00000000..d8ed8652 --- /dev/null +++ b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_hal.cpp @@ -0,0 +1,207 @@ +#include "stm32h7_hal.h" + +#if defined(STM32H7xx) + +//#define SIMPLEFOC_STM32_DEBUG + +#include "../../../../communication/SimpleFOCDebug.h" +#define _TRGO_NOT_AVAILABLE 12345 + +ADC_HandleTypeDef hadc; + +/** + * Function initializing the ADC and the injected channels for the low-side current sensing + * + * @param cs_params - current sense parameters + * @param driver_params - driver parameters + * + * @return int - 0 if success + */ +int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* driver_params) +{ + ADC_InjectionConfTypeDef sConfigInjected; + + // check if all pins belong to the same ADC + ADC_TypeDef* adc_pin1 = _isset(cs_params->pins[0]) ? (ADC_TypeDef*)pinmap_peripheral(analogInputToPinName(cs_params->pins[0]), PinMap_ADC) : nullptr; + ADC_TypeDef* adc_pin2 = _isset(cs_params->pins[1]) ? (ADC_TypeDef*)pinmap_peripheral(analogInputToPinName(cs_params->pins[1]), PinMap_ADC) : nullptr; + ADC_TypeDef* adc_pin3 = _isset(cs_params->pins[2]) ? (ADC_TypeDef*)pinmap_peripheral(analogInputToPinName(cs_params->pins[2]), PinMap_ADC) : nullptr; + if ( ((adc_pin1 != adc_pin2) && (adc_pin1 && adc_pin2)) || + ((adc_pin2 != adc_pin3) && (adc_pin2 && adc_pin3)) || + ((adc_pin1 != adc_pin3) && (adc_pin1 && adc_pin3)) + ){ +#ifdef SIMPLEFOC_STM32_DEBUG + SIMPLEFOC_DEBUG("STM32-CS: ERR: Analog pins dont belong to the same ADC!"); +#endif + return -1; + } + + + /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) + */ + hadc.Instance = (ADC_TypeDef *)pinmap_peripheral(analogInputToPinName(cs_params->pins[0]), PinMap_ADC); + + if(hadc.Instance == ADC1) __HAL_RCC_ADC12_CLK_ENABLE(); +#ifdef ADC2 // if defined ADC2 + else if(hadc.Instance == ADC2) __HAL_RCC_ADC12_CLK_ENABLE(); +#endif +#ifdef ADC3 // if defined ADC3 + else if(hadc.Instance == ADC3) __HAL_RCC_ADC3_CLK_ENABLE(); +#endif + else{ +#ifdef SIMPLEFOC_STM32_DEBUG + SIMPLEFOC_DEBUG("STM32-CS: ERR: Pin does not belong to any ADC!"); +#endif + return -1; // error not a valid ADC instance + } + +#ifdef SIMPLEFOC_STM32_DEBUG + SIMPLEFOC_DEBUG("STM32-CS: Using ADC: ", _adcToIndex(&hadc)+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 +#if defined(ADC_VER_V5_V90) + // only for ADC3 + if(hadc.Instance == ADC3){ + hadc.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; + // not sure about this one!!! maybe use: ADC_SAMPLING_MODE_NORMAL + hadc.Init.SamplingMode = ADC_SAMPLING_MODE_TRIGGER_CONTROLED; +#endif + hadc.Init.NbrOfConversion = 1; + hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV; + if ( HAL_ADC_Init(&hadc) != HAL_OK){ +#ifdef SIMPLEFOC_STM32_DEBUG + SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init ADC!"); +#endif + return -1; + } + + /**Configures for the selected ADC injected channel its corresponding rank in the sequencer and its sample time + */ + sConfigInjected.InjectedNbrOfConversion = _isset(cs_params->pins[2]) ? 3 : 2; + // if ADC1 or ADC2 + if(hadc.Instance == ADC1 || hadc.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.InjectedNbrOfConversion = ADC_SAMPLETIME_2CYCLE_5; + }else { + // adc3 + // https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32H7xx_HAL_Driver/Inc/stm32h7xx_hal_adc.h#L673 + sConfigInjected.InjectedNbrOfConversion = ADC3_SAMPLETIME_2CYCLES_5; + } + sConfigInjected.ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONV_EDGE_RISINGFALLING; + sConfigInjected.AutoInjectedConv = DISABLE; + sConfigInjected.InjectedDiscontinuousConvMode = DISABLE; + sConfigInjected.InjectedOffset = 0; + + // automating TRGO flag finding - hardware specific + uint8_t tim_num = 0; + for (size_t i=0; i<6; i++) { + TIM_HandleTypeDef *timer_to_check = driver_params->timers_handle[tim_num++]; + TIM_TypeDef *instance_to_check = timer_to_check->Instance; + + uint32_t trigger_flag = _timerToInjectedTRGO(timer_to_check); + if(trigger_flag == _TRGO_NOT_AVAILABLE) continue; // timer does not have valid trgo for injected channels + + // check if TRGO used already - if yes use the next timer + if((timer_to_check->Instance->CR2 & LL_TIM_TRGO_ENABLE) || // if used for timer sync + (timer_to_check->Instance->CR2 & LL_TIM_TRGO_UPDATE)) // if used for ADC sync + { + continue; + } + + // if the code comes here, it has found the timer available + // timer does have trgo flag for injected channels + sConfigInjected.ExternalTrigInjecConv = trigger_flag; + + // this will be the timer with which the ADC will sync + cs_params->timer_handle = timer_to_check; + // done + break; + } + if( cs_params->timer_handle == NP ){ + // not possible to use these timers for low-side current sense + #ifdef SIMPLEFOC_STM32_DEBUG + SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot sync any timer to injected channels!"); + #endif + return -1; + }else{ +#ifdef SIMPLEFOC_STM32_DEBUG + SIMPLEFOC_DEBUG("STM32-CS: Using timer: ", stm32_getTimerNumber(cs_params->timer_handle->Instance)); +#endif + } + + for(int i=0; i<3; i++){ + // skip if not set + if (!_isset(cs_params->pins[i])) continue; + + sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1 + i; + sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i])); + if (HAL_ADCEx_InjectedConfigChannel(&hadc, &sConfigInjected) != HAL_OK){ + #ifdef SIMPLEFOC_STM32_DEBUG + SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i])) ); + #endif + return -1; + } + } + + #ifdef SIMPLEFOC_STM32_ADC_INTERRUPT + // enable interrupt + HAL_NVIC_SetPriority(ADC_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(ADC_IRQn); + #endif + + cs_params->adc_handle = &hadc; + return 0; +} + + +/** + * Function to initialize the ADC GPIO pins + * + * @param cs_params current sense parameters + * @param pinA pin number for phase A + * @param pinB pin number for phase B + * @param pinC pin number for phase C + * @return int 0 if success, -1 if error + */ +int _adc_gpio_init(Stm32CurrentSenseParams* cs_params, const int pinA, const int pinB, const int pinC) +{ + int pins[3] = {pinA, pinB, pinC}; + const char* port_names[3] = {"A", "B", "C"}; + for(int i=0; i<3; i++){ + if(_isset(pins[i])){ + // check if pin is an analog pin + if(pinmap_peripheral(analogInputToPinName(pins[i]), PinMap_ADC) == NP){ +#ifdef SIMPLEFOC_STM32_DEBUG + SimpleFOCDebug::print("STM32-CS: ERR: Pin "); + SimpleFOCDebug::print(port_names[i]); + SimpleFOCDebug::println(" does not belong to any ADC!"); +#endif + return -1; + } + pinmap_pinout(analogInputToPinName(pins[i]), PinMap_ADC); + cs_params->pins[i] = pins[i]; + } + } + return 0; +} + +#ifdef SIMPLEFOC_STM32_ADC_INTERRUPT +extern "C" { + void ADC_IRQHandler(void) + { + HAL_ADC_IRQHandler(&hadc); + } +} +#endif + +#endif \ No newline at end of file diff --git a/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_hal.h b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_hal.h new file mode 100644 index 00000000..623f2b85 --- /dev/null +++ b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_hal.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Arduino.h" + +#if defined(STM32H7xx) +#include "stm32h7xx_hal.h" +#include "../stm32_mcu.h" +#include "stm32h7_utils.h" + +int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* driver_params); +int _adc_gpio_init(Stm32CurrentSenseParams* cs_params, const int pinA, const int pinB, const int pinC); + +#endif diff --git a/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_mcu.cpp b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_mcu.cpp new file mode 100644 index 00000000..f07a8ad8 --- /dev/null +++ b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_mcu.cpp @@ -0,0 +1,116 @@ +#include "../../../hardware_api.h" + +#if defined(STM32H7xx) +#include "../../../../common/foc_utils.h" +#include "../../../../drivers/hardware_api.h" +#include "../../../../drivers/hardware_specific/stm32/stm32_mcu.h" +#include "../../../hardware_api.h" +#include "../stm32_mcu.h" +#include "stm32h7_hal.h" +#include "stm32h7_utils.h" +#include "Arduino.h" + + +#define _ADC_VOLTAGE 3.3f +#define _ADC_RESOLUTION 4096.0f + + +// array of values of 4 injected channels per adc instance (3) +uint32_t adc_val[3][4]={0}; +// does adc interrupt need a downsample - per adc (3) +bool needs_downsample[3] = {1}; +// downsampling variable - per adc (3) +uint8_t tim_downsample[3] = {1}; + +void* _configureADCLowSide(const void* driver_params, const int pinA, const int pinB, const int pinC){ + + Stm32CurrentSenseParams* cs_params= new Stm32CurrentSenseParams { + .pins={(int)NOT_SET,(int)NOT_SET,(int)NOT_SET}, + .adc_voltage_conv = (_ADC_VOLTAGE) / (_ADC_RESOLUTION) + }; + if(_adc_gpio_init(cs_params, pinA,pinB,pinC) != 0) return SIMPLEFOC_CURRENT_SENSE_INIT_FAILED; + if(_adc_init(cs_params, (STM32DriverParams*)driver_params) != 0) return SIMPLEFOC_CURRENT_SENSE_INIT_FAILED; + return cs_params; +} + + +void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ + STM32DriverParams* driver_params = (STM32DriverParams*)_driver_params; + Stm32CurrentSenseParams* cs_params = (Stm32CurrentSenseParams*)_cs_params; + + // if compatible timer has not been found + if (cs_params->timer_handle == NULL) return SIMPLEFOC_CURRENT_SENSE_INIT_FAILED; + + // stop all the timers for the driver + stm32_pause(driver_params); + + // if timer has repetition counter - it will downsample using it + // and it does not need the software downsample + if( IS_TIM_REPETITION_COUNTER_INSTANCE(cs_params->timer_handle->Instance) ){ + // adjust the initial timer state such that the trigger + // - for DMA transfer aligns with the pwm peaks instead of throughs. + // - for interrupt based ADC transfer + // - only necessary for the timers that have repetition counters + + cs_params->timer_handle->Instance->CR1 |= TIM_CR1_DIR; + cs_params->timer_handle->Instance->CNT = cs_params->timer_handle->Instance->ARR; + // remember that this timer has repetition counter - no need to downasmple + needs_downsample[_adcToIndex(cs_params->adc_handle)] = 0; + } + // set the trigger output event + LL_TIM_SetTriggerOutput(cs_params->timer_handle->Instance, LL_TIM_TRGO_UPDATE); + + // start the adc + #ifdef SIMPLEFOC_STM32_ADC_INTERRUPT + HAL_ADCEx_InjectedStart_IT(cs_params->adc_handle); + #else + HAL_ADCEx_InjectedStart(cs_params->adc_handle); + #endif + + // restart all the timers of the driver + stm32_resume(driver_params); + + // return the cs parameters + // successfully initialized + // TODO verify if success in future + return _cs_params; +} + + +// function reading an ADC value and returning the read voltage +float _readADCVoltageLowSide(const int pin, const void* cs_params){ + for(int i=0; i < 3; i++){ + if( pin == ((Stm32CurrentSenseParams*)cs_params)->pins[i]){ // found in the buffer + #ifdef SIMPLEFOC_STM32_ADC_INTERRUPT + return adc_val[_adcToIndex(((Stm32CurrentSenseParams*)cs_params)->adc_handle)][i] * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; + #else + // an optimized way to go from i to the channel i=0 -> channel 1, i=1 -> channel 2, i=2 -> channel 3 + uint32_t channel = (i == 0) ? ADC_INJECTED_RANK_1 : (i == 1) ? ADC_INJECTED_RANK_2 : ADC_INJECTED_RANK_3; + return HAL_ADCEx_InjectedGetValue(((Stm32CurrentSenseParams*)cs_params)->adc_handle, channel) * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; + #endif + } + } + return 0; +} + +#ifdef SIMPLEFOC_STM32_ADC_INTERRUPT +extern "C" { + void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *AdcHandle){ + + // calculate the instance + int adc_index = _adcToIndex(AdcHandle); + + // if the timer han't repetition counter - downsample two times + if( needs_downsample[adc_index] && tim_downsample[adc_index]++ > 0) { + tim_downsample[adc_index] = 0; + return; + } + + adc_val[adc_index][0]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_1); + adc_val[adc_index][1]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_2); + adc_val[adc_index][2]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_3); + } +} +#endif + +#endif \ No newline at end of file diff --git a/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_utils.cpp b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_utils.cpp new file mode 100644 index 00000000..41db1d9a --- /dev/null +++ b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_utils.cpp @@ -0,0 +1,240 @@ +#include "stm32h7_utils.h" + +#if defined(STM32H7xx) + +/* Exported Functions */ + + +PinName analog_to_pin(uint32_t pin) { + PinName pin_name = analogInputToPinName(pin); + if (pin_name == NC) { + return (PinName) pin; + } + return pin_name; +} + + +/** + * @brief Return ADC HAL channel linked to a PinName + * @param pin: PinName + * @retval Valid HAL channel + */ +uint32_t _getADCChannel(PinName pin) +{ + uint32_t function = pinmap_function(pin, PinMap_ADC); + uint32_t channel = 0; + switch (STM_PIN_CHANNEL(function)) { +#ifdef ADC_CHANNEL_0 + case 0: + channel = ADC_CHANNEL_0; + break; +#endif + case 1: + channel = ADC_CHANNEL_1; + break; + case 2: + channel = ADC_CHANNEL_2; + break; + case 3: + channel = ADC_CHANNEL_3; + break; + case 4: + channel = ADC_CHANNEL_4; + break; + case 5: + channel = ADC_CHANNEL_5; + break; + case 6: + channel = ADC_CHANNEL_6; + break; + case 7: + channel = ADC_CHANNEL_7; + break; + case 8: + channel = ADC_CHANNEL_8; + break; + case 9: + channel = ADC_CHANNEL_9; + break; + case 10: + channel = ADC_CHANNEL_10; + break; + case 11: + channel = ADC_CHANNEL_11; + break; + case 12: + channel = ADC_CHANNEL_12; + break; + case 13: + channel = ADC_CHANNEL_13; + break; + case 14: + channel = ADC_CHANNEL_14; + break; + case 15: + channel = ADC_CHANNEL_15; + break; +#ifdef ADC_CHANNEL_16 + case 16: + channel = ADC_CHANNEL_16; + break; +#endif + case 17: + channel = ADC_CHANNEL_17; + break; +#ifdef ADC_CHANNEL_18 + case 18: + channel = ADC_CHANNEL_18; + break; +#endif +#ifdef ADC_CHANNEL_19 + case 19: + channel = ADC_CHANNEL_19; + break; +#endif +#ifdef ADC_CHANNEL_20 + case 20: + channel = ADC_CHANNEL_20; + break; + case 21: + channel = ADC_CHANNEL_21; + break; + case 22: + channel = ADC_CHANNEL_22; + break; + case 23: + channel = ADC_CHANNEL_23; + break; +#ifdef ADC_CHANNEL_24 + case 24: + channel = ADC_CHANNEL_24; + break; + case 25: + channel = ADC_CHANNEL_25; + break; + case 26: + channel = ADC_CHANNEL_26; + break; +#ifdef ADC_CHANNEL_27 + case 27: + channel = ADC_CHANNEL_27; + break; + case 28: + channel = ADC_CHANNEL_28; + break; + case 29: + channel = ADC_CHANNEL_29; + break; + case 30: + channel = ADC_CHANNEL_30; + break; + case 31: + channel = ADC_CHANNEL_31; + break; +#endif +#endif +#endif + default: + _Error_Handler("ADC: Unknown adc channel", (int)(STM_PIN_CHANNEL(function))); + break; + } + return channel; +} + +// timer to injected TRGO +// https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32H7xx_HAL_Driver/Inc/stm32h7xx_hal_adc_ex.h#L235 +uint32_t _timerToInjectedTRGO(TIM_HandleTypeDef* timer){ + + if(timer->Instance == TIM1) + return ADC_EXTERNALTRIGINJEC_T1_TRGO; +#ifdef TIM2 // if defined timer 2 + else if(timer->Instance == TIM2) + return ADC_EXTERNALTRIGINJEC_T2_TRGO; +#endif +#ifdef TIM4 // if defined timer 4 + else if(timer->Instance == TIM4) + return ADC_EXTERNALTRIGINJEC_T4_TRGO; +#endif +#ifdef TIM3 // if defined timer 3 + else if(timer->Instance == TIM3) + return ADC_EXTERNALTRIGINJEC_T3_TRGO; +#endif +#ifdef TIM6 // if defined timer 6 + else if(timer->Instance == TIM6) + return ADC_EXTERNALTRIGINJEC_T6_TRGO; +#endif +#ifdef TIM8 // if defined timer 8 + else if(timer->Instance == TIM8) + return ADC_EXTERNALTRIGINJEC_T8_TRGO; +#endif +#ifdef TIM15 // if defined timer 15 + else if(timer->Instance == TIM15) + return ADC_EXTERNALTRIGINJEC_T15_TRGO; +#endif + else + return _TRGO_NOT_AVAILABLE; +} + +// timer to regular TRGO +// https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32H7xx_HAL_Driver/Inc/stm32h7xx_hal_adc.h#L554 +uint32_t _timerToRegularTRGO(TIM_HandleTypeDef* timer){ + if(timer->Instance == TIM1) + return ADC_EXTERNALTRIG_T1_TRGO; +#ifdef TIM2 // if defined timer 2 + else if(timer->Instance == TIM2) + return ADC_EXTERNALTRIG_T2_TRGO; +#endif +#ifdef TIM3 // if defined timer 3 + else if(timer->Instance == TIM3) + return ADC_EXTERNALTRIG_T3_TRGO; +#endif +#ifdef TIM4 // if defined timer 4 + else if(timer->Instance == TIM4) + return ADC_EXTERNALTRIG_T4_TRGO; +#endif +#ifdef TIM6 // if defined timer 6 + else if(timer->Instance == TIM6) + return ADC_EXTERNALTRIG_T6_TRGO; +#endif +#ifdef TIM8 // if defined timer 8 + else if(timer->Instance == TIM8) + return ADC_EXTERNALTRIG_T8_TRGO; +#endif +#ifdef TIM15 // if defined timer 15 + else if(timer->Instance == TIM15) + return ADC_EXTERNALTRIG_T15_TRGO; +#endif +#ifdef TIM23 // if defined timer 23 + else if(timer->Instance == TIM23) + return ADC_EXTERNALTRIG_T23_TRGO; +#endif +#ifdef TIM24 // if defined timer 24 + else if(timer->Instance == TIM24) + return ADC_EXTERNALTRIG_T24_TRGO; +#endif + else + return _TRGO_NOT_AVAILABLE; +} + + +int _adcToIndex(ADC_TypeDef *AdcHandle){ + if(AdcHandle == ADC1) return 0; +#ifdef ADC2 // if ADC2 exists + else if(AdcHandle == ADC2) return 1; +#endif +#ifdef ADC3 // if ADC3 exists + else if(AdcHandle == ADC3) return 2; +#endif +#ifdef ADC4 // if ADC4 exists + else if(AdcHandle == ADC4) return 3; +#endif +#ifdef ADC5 // if ADC5 exists + else if(AdcHandle == ADC5) return 4; +#endif + return 0; +} +int _adcToIndex(ADC_HandleTypeDef *AdcHandle){ + return _adcToIndex(AdcHandle->Instance); +} + +#endif \ No newline at end of file diff --git a/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_utils.h b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_utils.h new file mode 100644 index 00000000..22dfbed1 --- /dev/null +++ b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_utils.h @@ -0,0 +1,30 @@ +#pragma once + +#include "Arduino.h" + +#if defined(STM32H7xx) + +#define _TRGO_NOT_AVAILABLE 12345 + + +/* Exported Functions */ +/** + * @brief Return ADC HAL channel linked to a PinName + * @param pin: PinName + * @retval Valid HAL channel + */ +uint32_t _getADCChannel(PinName pin); + +// timer to injected TRGO +// https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc_ex.h#L179 +uint32_t _timerToInjectedTRGO(TIM_HandleTypeDef* timer); + +// timer to regular TRGO +// https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc.h#L331 +uint32_t _timerToRegularTRGO(TIM_HandleTypeDef* timer); + +// function returning index of the ADC instance +int _adcToIndex(ADC_HandleTypeDef *AdcHandle); +int _adcToIndex(ADC_TypeDef *AdcHandle); + +#endif \ No newline at end of file From 412c47ab68032256a4df7d1b12d3bf05bc01ecc5 Mon Sep 17 00:00:00 2001 From: gospar Date: Fri, 14 Mar 2025 09:31:09 +0100 Subject: [PATCH 02/15] use default dir only if sensor not connected --- src/BLDCMotor.cpp | 11 +++++++---- src/HybridStepperMotor.cpp | 12 ++++++++---- src/StepperMotor.cpp | 11 +++++++---- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/BLDCMotor.cpp b/src/BLDCMotor.cpp index 5ad8a93f..74c3ce2f 100644 --- a/src/BLDCMotor.cpp +++ b/src/BLDCMotor.cpp @@ -93,10 +93,13 @@ int BLDCMotor::init() { P_angle.limit = velocity_limit; // if using open loop control, set a CW as the default direction if not already set - if ((controller==MotionControlType::angle_openloop - ||controller==MotionControlType::velocity_openloop) - && (sensor_direction == Direction::UNKNOWN)) { - sensor_direction = Direction::CW; + // only if no sensor is used + if(!sensor){ + if ((controller==MotionControlType::angle_openloop + ||controller==MotionControlType::velocity_openloop) + && (sensor_direction == Direction::UNKNOWN)) { + sensor_direction = Direction::CW; + } } _delay(500); diff --git a/src/HybridStepperMotor.cpp b/src/HybridStepperMotor.cpp index 2e70965f..618985d9 100644 --- a/src/HybridStepperMotor.cpp +++ b/src/HybridStepperMotor.cpp @@ -30,6 +30,7 @@ HybridStepperMotor::HybridStepperMotor(int pp, float _R, float _KV, float _induc void HybridStepperMotor::linkDriver(BLDCDriver *_driver) { driver = _driver; + SIMPLEFOC_DEBUG("MOT: BLDCDriver linked, using pin C as the mid-phase"); } // init hardware pins @@ -64,10 +65,13 @@ int HybridStepperMotor::init() P_angle.limit = velocity_limit; // if using open loop control, set a CW as the default direction if not already set - if ((controller==MotionControlType::angle_openloop - ||controller==MotionControlType::velocity_openloop) - && (sensor_direction == Direction::UNKNOWN)) { - sensor_direction = Direction::CW; + // only if no sensor is used + if(!sensor){ + if ((controller==MotionControlType::angle_openloop + ||controller==MotionControlType::velocity_openloop) + && (sensor_direction == Direction::UNKNOWN)) { + sensor_direction = Direction::CW; + } } _delay(500); diff --git a/src/StepperMotor.cpp b/src/StepperMotor.cpp index 1d8f3147..ec805914 100644 --- a/src/StepperMotor.cpp +++ b/src/StepperMotor.cpp @@ -57,10 +57,13 @@ int StepperMotor::init() { P_angle.limit = velocity_limit; // if using open loop control, set a CW as the default direction if not already set - if ((controller==MotionControlType::angle_openloop - ||controller==MotionControlType::velocity_openloop) - && (sensor_direction == Direction::UNKNOWN)) { - sensor_direction = Direction::CW; + // only if no sensor is used + if(!sensor){ + if ((controller==MotionControlType::angle_openloop + ||controller==MotionControlType::velocity_openloop) + && (sensor_direction == Direction::UNKNOWN)) { + sensor_direction = Direction::CW; + } } _delay(500); From 5f9c23b9db8aa1f40e3bfcd2b50c06d2061017db Mon Sep 17 00:00:00 2001 From: gospar Date: Tue, 18 Mar 2025 12:09:45 +0100 Subject: [PATCH 03/15] inital testing for h7 --- .../stm32/stm32h7/stm32h7_hal.cpp | 26 +++++++++++++------ .../stm32/stm32h7/stm32h7_mcu.cpp | 4 +++ 2 files changed, 22 insertions(+), 8 deletions(-) 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 d8ed8652..b572a5aa 100644 --- a/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_hal.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_hal.cpp @@ -35,7 +35,6 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive return -1; } - /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */ hadc.Instance = (ADC_TypeDef *)pinmap_peripheral(analogInputToPinName(cs_params->pins[0]), PinMap_ADC); @@ -74,10 +73,15 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive // 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; // not sure about this one!!! maybe use: ADC_SAMPLING_MODE_NORMAL - hadc.Init.SamplingMode = ADC_SAMPLING_MODE_TRIGGER_CONTROLED; + hadc.Init.SamplingMode = ADC_SAMPLING_MODE_BULB; #endif hadc.Init.NbrOfConversion = 1; + hadc.Init.NbrOfDiscConversion = 0; hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV; + + hadc.Init.LowPowerAutoWait = DISABLE; + + if ( HAL_ADC_Init(&hadc) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init ADC!"); @@ -91,16 +95,20 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive // if ADC1 or ADC2 if(hadc.Instance == ADC1 || hadc.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.InjectedNbrOfConversion = ADC_SAMPLETIME_2CYCLE_5; + sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_2CYCLE_5; }else { // adc3 // https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32H7xx_HAL_Driver/Inc/stm32h7xx_hal_adc.h#L673 - sConfigInjected.InjectedNbrOfConversion = ADC3_SAMPLETIME_2CYCLES_5; + sConfigInjected.InjectedSamplingTime = ADC3_SAMPLETIME_2CYCLES_5; } sConfigInjected.ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONV_EDGE_RISINGFALLING; sConfigInjected.AutoInjectedConv = DISABLE; sConfigInjected.InjectedDiscontinuousConvMode = DISABLE; sConfigInjected.InjectedOffset = 0; + sConfigInjected.InjectedSingleDiff = ADC_SINGLE_ENDED; + sConfigInjected.InjectedOffsetNumber = ADC_OFFSET_NONE; + sConfigInjected.QueueInjectedContext = DISABLE; + sConfigInjected.InjecOversamplingMode = DISABLE; // automating TRGO flag finding - hardware specific uint8_t tim_num = 0; @@ -139,11 +147,11 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive #endif } + uint32_t ranks[4] = {ADC_INJECTED_RANK_1, ADC_INJECTED_RANK_2, ADC_INJECTED_RANK_3, ADC_INJECTED_RANK_4}; for(int i=0; i<3; i++){ // skip if not set - if (!_isset(cs_params->pins[i])) continue; - - sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1 + i; + if (!_isset(cs_params->pins[i])) continue; + sConfigInjected.InjectedRank = ranks[i]; sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i])); if (HAL_ADCEx_InjectedConfigChannel(&hadc, &sConfigInjected) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG @@ -152,7 +160,9 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive return -1; } } - + + + delay(1000); #ifdef SIMPLEFOC_STM32_ADC_INTERRUPT // enable interrupt HAL_NVIC_SetPriority(ADC_IRQn, 0, 0); diff --git a/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_mcu.cpp b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_mcu.cpp index f07a8ad8..fe7f16ed 100644 --- a/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_mcu.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_mcu.cpp @@ -60,6 +60,9 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ // set the trigger output event LL_TIM_SetTriggerOutput(cs_params->timer_handle->Instance, LL_TIM_TRGO_UPDATE); + // Start the adc calibration + HAL_ADCEx_Calibration_Start(cs_params->adc_handle, ADC_CALIB_OFFSET_LINEARITY, ADC_SINGLE_ENDED); + // start the adc #ifdef SIMPLEFOC_STM32_ADC_INTERRUPT HAL_ADCEx_InjectedStart_IT(cs_params->adc_handle); @@ -67,6 +70,7 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ HAL_ADCEx_InjectedStart(cs_params->adc_handle); #endif + // restart all the timers of the driver stm32_resume(driver_params); From f1823852eea549f7a0850114084cfa9d3458a384 Mon Sep 17 00:00:00 2001 From: gospar Date: Tue, 18 Mar 2025 12:10:02 +0100 Subject: [PATCH 04/15] target_h7 to stm32h7 --- .../stm32/stm32_timerutils.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/drivers/hardware_specific/stm32/stm32_timerutils.cpp b/src/drivers/hardware_specific/stm32/stm32_timerutils.cpp index 3eef0849..73ddba86 100644 --- a/src/drivers/hardware_specific/stm32/stm32_timerutils.cpp +++ b/src/drivers/hardware_specific/stm32/stm32_timerutils.cpp @@ -2,7 +2,7 @@ #include "./stm32_timerutils.h" #include -#if defined(_STM32_DEF_) || defined(TARGET_STM32H7) +#if defined(_STM32_DEF_) || defined(STM32H7xx) void stm32_pauseTimer(TIM_HandleTypeDef* handle){ @@ -213,7 +213,7 @@ int stm32_getInternalSourceTrigger(TIM_HandleTypeDef* master, TIM_HandleTypeDef* #endif return -1; } -#elif defined(STM32F4xx) || defined(STM32F1xx) || defined(STM32L4xx) || defined(STM32F7xx) || defined(TARGET_STM32H7) +#elif defined(STM32F4xx) || defined(STM32F1xx) || defined(STM32L4xx) || defined(STM32F7xx) || defined(STM32H7xx) // function finds the appropriate timer source trigger for the master/slave timer combination // returns -1 if no trigger source is found @@ -252,7 +252,7 @@ int stm32_getInternalSourceTrigger(TIM_HandleTypeDef* master, TIM_HandleTypeDef* #if defined(TIM8) else if(TIM_slave == TIM8) return LL_TIM_TS_ITR1; #endif - #if defined(TIM5) && !defined(TARGET_STM32H7) + #if defined(TIM5) && !defined(STM32H7xx) else if(TIM_slave == TIM5) return LL_TIM_TS_ITR0; #endif } @@ -268,10 +268,10 @@ int stm32_getInternalSourceTrigger(TIM_HandleTypeDef* master, TIM_HandleTypeDef* #if defined(TIM4) else if(TIM_slave == TIM4) return LL_TIM_TS_ITR2; #endif - #if defined(TIM5) && !defined(TARGET_STM32H7) + #if defined(TIM5) && !defined(STM32H7xx) else if(TIM_slave == TIM5) return LL_TIM_TS_ITR1; #endif - #if defined(TIM5) && defined(TARGET_STM32H7) + #if defined(TIM5) && defined(STM32H7xx) else if(TIM_slave == TIM5) return LL_TIM_TS_ITR2; #endif } @@ -290,10 +290,10 @@ int stm32_getInternalSourceTrigger(TIM_HandleTypeDef* master, TIM_HandleTypeDef* #if defined(TIM8) else if(TIM_slave == TIM8) return LL_TIM_TS_ITR2; #endif - #if defined(TIM5) && !defined(TARGET_STM32H7) + #if defined(TIM5) && !defined(STM32H7xx) else if(TIM_slave == TIM5) return LL_TIM_TS_ITR1; #endif - #if defined(TIM5) && defined(TARGET_STM32H7) + #if defined(TIM5) && defined(STM32H7xx) else if(TIM_slave == TIM5) return LL_TIM_TS_ITR3; #endif } @@ -326,7 +326,7 @@ int stm32_getInternalSourceTrigger(TIM_HandleTypeDef* master, TIM_HandleTypeDef* #endif } #endif - #if defined(TIM15) && defined(TARGET_STM32H7) + #if defined(TIM15) && defined(STM32H7xx) else if (TIM_master == TIM15){ #if defined(TIM1) if(TIM_slave == TIM1) return LL_TIM_TS_ITR0; @@ -514,7 +514,7 @@ uint32_t stm32_getTimerClockFreq(TIM_HandleTypeDef *handle) { return 0; } -#if defined(STM32H7xx) || defined(TARGET_STM32H7) +#if defined(STM32H7xx) || defined(STM32H7xx) /* When TIMPRE bit of the RCC_CFGR register is reset, * if APBx prescaler is 1 or 2 then TIMxCLK = HCLK, * otherwise TIMxCLK = 2x PCLKx. From b7c663844f756d158a04a54914e44902d3eaf1ed Mon Sep 17 00:00:00 2001 From: gospar Date: Wed, 19 Mar 2025 08:41:46 +0100 Subject: [PATCH 05/15] add the compile for portenta and giga --- .github/workflows/arduino_mbed.yml | 47 ++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 .github/workflows/arduino_mbed.yml diff --git a/.github/workflows/arduino_mbed.yml b/.github/workflows/arduino_mbed.yml new file mode 100644 index 00000000..62de3080 --- /dev/null +++ b/.github/workflows/arduino_mbed.yml @@ -0,0 +1,47 @@ +name: AVR +on: [push, pull_request] +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: arduino/arduino-lint-action@v1 + with: + library-manager: update + project-type: library + build: + name: Test compiling + runs-on: ubuntu-latest + + strategy: + matrix: + arduino-boards-fqbn: + - arduino:mbed:giga # arudino giga + - arduino:mbed:nanorp2040connect # arduino nano rp2040 connect + - arduino:mbed:portenta # arduino portenta + + include: + - arduino-boards-fqbn: arduino:mbed:nanorp2040connect + sketch-names: open_loop_position_example.ino + + - arduino-boards-fqbn: arduino:mbed:portenta + sketch-names: open_loop_position_example.ino + + - arduino-boards-fqbn: arduino:mbed:giga + sketch-names: single_full_control_example.ino + + + # Do not cancel all jobs / architectures if one job fails + fail-fast: false + steps: + - name: Checkout + uses: actions/checkout@master + - name: Compile all examples + uses: ArminJo/arduino-test-compile@master + with: + arduino-board-fqbn: ${{ matrix.arduino-boards-fqbn }} + required-libraries: ${{ matrix.required-libraries }} + platform-url: ${{ matrix.platform-url }} + sketch-names: ${{ matrix.sketch-names }} + sketches-exclude: ${{ matrix.sketches-exclude }} + build-properties: ${{ toJson(matrix.build-properties) }} From 9e81c2ccb5c148fb93bf63bae08a317636f50144 Mon Sep 17 00:00:00 2001 From: gospar Date: Wed, 19 Mar 2025 08:52:27 +0100 Subject: [PATCH 06/15] issues with compile CI --- .github/workflows/arduino_mbed.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/arduino_mbed.yml b/.github/workflows/arduino_mbed.yml index 62de3080..abffacb2 100644 --- a/.github/workflows/arduino_mbed.yml +++ b/.github/workflows/arduino_mbed.yml @@ -18,13 +18,17 @@ jobs: arduino-boards-fqbn: - arduino:mbed:giga # arudino giga - arduino:mbed:nanorp2040connect # arduino nano rp2040 connect + - arduino:mbed:nano33ble # arduino nano 33 ble - arduino:mbed:portenta # arduino portenta include: - arduino-boards-fqbn: arduino:mbed:nanorp2040connect sketch-names: open_loop_position_example.ino + + - arduino-boards-fqbn: arduino:mbed:nano33ble + sketch-names: open_loop_position_example.ino - - arduino-boards-fqbn: arduino:mbed:portenta + - arduino-boards-fqbn: arduino:mbed:envie_m7 sketch-names: open_loop_position_example.ino - arduino-boards-fqbn: arduino:mbed:giga From d6b83cbcb61459f0c3ce137b424be572784ba1ee Mon Sep 17 00:00:00 2001 From: gospar Date: Wed, 19 Mar 2025 08:56:55 +0100 Subject: [PATCH 07/15] remove giga from CI --- .github/workflows/arduino_mbed.yml | 10 +++++----- README.md | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/arduino_mbed.yml b/.github/workflows/arduino_mbed.yml index abffacb2..8d1b47e5 100644 --- a/.github/workflows/arduino_mbed.yml +++ b/.github/workflows/arduino_mbed.yml @@ -1,4 +1,4 @@ -name: AVR +name: MDED on: [push, pull_request] jobs: lint: @@ -16,10 +16,10 @@ jobs: strategy: matrix: arduino-boards-fqbn: - - arduino:mbed:giga # arudino giga + #- arduino:mbed:giga # arudino giga - arduino:mbed:nanorp2040connect # arduino nano rp2040 connect - arduino:mbed:nano33ble # arduino nano 33 ble - - arduino:mbed:portenta # arduino portenta + - arduino:mbed:envie_m7 # arduino portenta include: - arduino-boards-fqbn: arduino:mbed:nanorp2040connect @@ -31,8 +31,8 @@ jobs: - arduino-boards-fqbn: arduino:mbed:envie_m7 sketch-names: open_loop_position_example.ino - - arduino-boards-fqbn: arduino:mbed:giga - sketch-names: single_full_control_example.ino + # - arduino-boards-fqbn: arduino:mbed:giga + # sketch-names: single_full_control_example.ino # Do not cancel all jobs / architectures if one job fails diff --git a/README.md b/README.md index 3dcc7385..19bdd96c 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ [![RP2040 build](https://github.com/simplefoc/Arduino-FOC/actions/workflows/rpi.yml/badge.svg)](https://github.com/simplefoc/Arduino-FOC/actions/workflows/rpi.yml) [![SAMD build](https://github.com/simplefoc/Arduino-FOC/actions/workflows/samd.yml/badge.svg)](https://github.com/simplefoc/Arduino-FOC/actions/workflows/samd.yml) [![Teensy build](https://github.com/simplefoc/Arduino-FOC/actions/workflows/teensy.yml/badge.svg)](https://github.com/simplefoc/Arduino-FOC/actions/workflows/teensy.yml) +[![MBED build](https://github.com/simplefoc/Arduino-FOC/actions/workflows/arduino_mbed.yml/badge.svg)](https://github.com/simplefoc/Arduino-FOC/actions/workflows/arduino_mbed.yml) ![GitHub release (latest by date)](https://img.shields.io/github/v/release/simplefoc/arduino-foc) ![GitHub Release Date](https://img.shields.io/github/release-date/simplefoc/arduino-foc?color=blue) From 74face78552c1024422d7a1e1b7304a1d68355ff Mon Sep 17 00:00:00 2001 From: gospar Date: Wed, 19 Mar 2025 10:49:48 +0100 Subject: [PATCH 08/15] a rewrite for portenta + bugfixes --- .../hardware_specific/stm32/stm32_mcu.cpp | 2 +- .../stm32/stm32_timerutils.cpp | 154 +++++++++++++++--- 2 files changed, 135 insertions(+), 21 deletions(-) diff --git a/src/drivers/hardware_specific/stm32/stm32_mcu.cpp b/src/drivers/hardware_specific/stm32/stm32_mcu.cpp index ed9da6be..1a9c833e 100644 --- a/src/drivers/hardware_specific/stm32/stm32_mcu.cpp +++ b/src/drivers/hardware_specific/stm32/stm32_mcu.cpp @@ -4,7 +4,7 @@ #include "./stm32_timerutils.h" #include "./stm32_searchtimers.h" -#if defined(_STM32_DEF_) || defined(TARGET_STM32H7) +#if defined(_STM32_DEF_) || defined(TARGET_STM32H7) // if stm32duino or portenta #pragma message("") #pragma message("SimpleFOC: compiling for STM32") diff --git a/src/drivers/hardware_specific/stm32/stm32_timerutils.cpp b/src/drivers/hardware_specific/stm32/stm32_timerutils.cpp index 73ddba86..b4a4fbf2 100644 --- a/src/drivers/hardware_specific/stm32/stm32_timerutils.cpp +++ b/src/drivers/hardware_specific/stm32/stm32_timerutils.cpp @@ -2,7 +2,7 @@ #include "./stm32_timerutils.h" #include -#if defined(_STM32_DEF_) || defined(STM32H7xx) +#if defined(_STM32_DEF_) || defined(TARGET_STM32H7) // if stm32duino or portenta void stm32_pauseTimer(TIM_HandleTypeDef* handle){ @@ -213,11 +213,17 @@ int stm32_getInternalSourceTrigger(TIM_HandleTypeDef* master, TIM_HandleTypeDef* #endif return -1; } -#elif defined(STM32F4xx) || defined(STM32F1xx) || defined(STM32L4xx) || defined(STM32F7xx) || defined(STM32H7xx) +#elif defined(STM32F4xx) || defined(STM32F1xx) || defined(STM32L4xx) || defined(STM32F7xx) || defined(STM32H7xx) || defined(TARGET_STM32H7) // function finds the appropriate timer source trigger for the master/slave timer combination // returns -1 if no trigger source is found -// currently supports the master timers to be from TIM1 to TIM4 and TIM8 +// currently supports the master timers to be from +// +// fammilies | timers +// --------------| -------------------------------- +// f1,f4,f7 | TIM1 to TIM4 and TIM8 +// l4 | TIM1 to TIM4, TIM8 and TIM15 +// h7 | TIM1 to TIM5, TIM8, TIM15, TIM23 and TIM24 int stm32_getInternalSourceTrigger(TIM_HandleTypeDef* master, TIM_HandleTypeDef* slave) { // put master and slave in temp variables to avoid arrows TIM_TypeDef *TIM_master = master->Instance; @@ -236,6 +242,14 @@ int stm32_getInternalSourceTrigger(TIM_HandleTypeDef* master, TIM_HandleTypeDef* #if defined(TIM8) else if(TIM_slave == TIM8) return LL_TIM_TS_ITR0; #endif + #if defined(STM32H7xx) || defined(TARGET_STM32H7) + #if defined(TIM23) + else if(TIM_slave == TIM23) return LL_TIM_TS_ITR0; + #endif + #if defined(TIM24) + else if(TIM_slave == TIM24) return LL_TIM_TS_ITR0; + #endif + #endif } #endif #if defined(TIM2) && defined(LL_TIM_TS_ITR1) @@ -252,8 +266,17 @@ int stm32_getInternalSourceTrigger(TIM_HandleTypeDef* master, TIM_HandleTypeDef* #if defined(TIM8) else if(TIM_slave == TIM8) return LL_TIM_TS_ITR1; #endif - #if defined(TIM5) && !defined(STM32H7xx) - else if(TIM_slave == TIM5) return LL_TIM_TS_ITR0; + #if defined(STM32H7xx) || defined(TARGET_STM32H7) + #if defined(TIM23) + else if(TIM_slave == TIM23) return LL_TIM_TS_ITR1; + #endif + #if defined(TIM24) + else if(TIM_slave == TIM24) return LL_TIM_TS_ITR1; + #endif + #else + #if defined(TIM5) + else if(TIM_slave == TIM5) return LL_TIM_TS_ITR0; + #endif #endif } #endif @@ -268,11 +291,20 @@ int stm32_getInternalSourceTrigger(TIM_HandleTypeDef* master, TIM_HandleTypeDef* #if defined(TIM4) else if(TIM_slave == TIM4) return LL_TIM_TS_ITR2; #endif - #if defined(TIM5) && !defined(STM32H7xx) - else if(TIM_slave == TIM5) return LL_TIM_TS_ITR1; - #endif - #if defined(TIM5) && defined(STM32H7xx) - else if(TIM_slave == TIM5) return LL_TIM_TS_ITR2; + #if defined(STM32H7xx) || defined(TARGET_STM32H7) + #if defined(TIM5) + else if(TIM_slave == TIM5) return LL_TIM_TS_ITR2; + #endif + #if defined(TIM23) + else if(TIM_slave == TIM23) return LL_TIM_TS_ITR2; + #endif + #if defined(TIM24) + else if(TIM_slave == TIM24) return LL_TIM_TS_ITR2; + #endif + #else + #if defined(TIM5) + else if(TIM_slave == TIM5) return LL_TIM_TS_ITR1; + #endif #endif } #endif @@ -290,17 +322,27 @@ int stm32_getInternalSourceTrigger(TIM_HandleTypeDef* master, TIM_HandleTypeDef* #if defined(TIM8) else if(TIM_slave == TIM8) return LL_TIM_TS_ITR2; #endif - #if defined(TIM5) && !defined(STM32H7xx) - else if(TIM_slave == TIM5) return LL_TIM_TS_ITR1; - #endif - #if defined(TIM5) && defined(STM32H7xx) - else if(TIM_slave == TIM5) return LL_TIM_TS_ITR3; + + #if defined(STM32H7xx) || defined(TARGET_STM32H7) + #if defined(TIM5) + else if(TIM_slave == TIM5) return LL_TIM_TS_ITR3; + #endif + #if defined(TIM23) + else if(TIM_slave == TIM23) return LL_TIM_TS_ITR3; + #endif + #if defined(TIM24) + else if(TIM_slave == TIM24) return LL_TIM_TS_ITR3; + #endif + #else + #if defined(TIM5) + else if(TIM_slave == TIM5) return LL_TIM_TS_ITR2; + #endif #endif } #endif #if defined(TIM5) else if (TIM_master == TIM5){ - #if !defined(STM32L4xx) // only difference between F4,F1 and L4 + #if defined(STM32F4xx) || defined(STM32F1xx) || defined(STM32F7xx) // f1, f4 adn f7 have tim5 sycned with tim1 and tim3 while others (l4, h7) have tim15 #if defined(TIM1) if(TIM_slave == TIM1) return LL_TIM_TS_ITR0; #endif @@ -311,6 +353,15 @@ int stm32_getInternalSourceTrigger(TIM_HandleTypeDef* master, TIM_HandleTypeDef* #if defined(TIM8) if(TIM_slave == TIM8) return LL_TIM_TS_ITR3; #endif + + #if defined(STM32H7xx) || defined(TARGET_STM32H7) + #if defined(TIM23) + else if(TIM_slave == TIM23) return LL_TIM_TS_ITR4; + #endif + #if defined(TIM24) + else if(TIM_slave == TIM24) return LL_TIM_TS_ITR4; + #endif + #endif } #endif #if defined(TIM8) @@ -321,12 +372,25 @@ int stm32_getInternalSourceTrigger(TIM_HandleTypeDef* master, TIM_HandleTypeDef* #if defined(TIM4) else if(TIM_slave == TIM4) return LL_TIM_TS_ITR3; #endif - #if defined(TIM5) - else if(TIM_slave == TIM5) return LL_TIM_TS_ITR3; + + #if defined(STM32H7xx) || defined(TARGET_STM32H7) + #if defined(TIM5) + else if(TIM_slave == TIM5) return LL_TIM_TS_ITR1; + #endif + #if defined(TIM23) + else if(TIM_slave == TIM23) return LL_TIM_TS_ITR5; + #endif + #if defined(TIM24) + else if(TIM_slave == TIM24) return LL_TIM_TS_ITR5; + #endif + #else + #if defined(TIM5) + else if(TIM_slave == TIM5) return LL_TIM_TS_ITR3; + #endif #endif } #endif - #if defined(TIM15) && defined(STM32H7xx) + #if defined(TIM15) && (defined(STM32L4xx) || defined(STM32H7xx) || defined(TARGET_STM32H7) ) else if (TIM_master == TIM15){ #if defined(TIM1) if(TIM_slave == TIM1) return LL_TIM_TS_ITR0; @@ -336,6 +400,56 @@ int stm32_getInternalSourceTrigger(TIM_HandleTypeDef* master, TIM_HandleTypeDef* #endif } #endif + #if defined(TIM23) && (defined(STM32H7xx) || defined(TARGET_STM32H7)) + else if (TIM_master == TIM23){ + #if defined(TIM1) + if(TIM_slave == TIM1) return LL_TIM_TS_ITR12; + #endif + #if defined(TIM2) + if(TIM_slave == TIM2) return LL_TIM_TS_ITR12; + #endif + #if defined(TIM3) + if(TIM_slave == TIM3) return LL_TIM_TS_ITR12; + #endif + #if defined(TIM4) + if(TIM_slave == TIM4) return LL_TIM_TS_ITR12; + #endif + #if defined(TIM5) + if(TIM_slave == TIM5) return LL_TIM_TS_ITR12; + #endif + #if defined(TIM8) + if(TIM_slave == TIM8) return LL_TIM_TS_ITR12; + #endif + #if defined(TIM24) + if(TIM_slave == TIM24) return LL_TIM_TS_ITR12; + #endif + } + #endif + #if defined(TIM24) && (defined(STM32H7xx) || defined(TARGET_STM32H7)) + else if (TIM_master == TIM24){ + #if defined(TIM1) + if(TIM_slave == TIM1) return LL_TIM_TS_ITR13; + #endif + #if defined(TIM2) + if(TIM_slave == TIM2) return LL_TIM_TS_ITR13; + #endif + #if defined(TIM3) + if(TIM_slave == TIM3) return LL_TIM_TS_ITR13; + #endif + #if defined(TIM4) + if(TIM_slave == TIM4) return LL_TIM_TS_ITR13; + #endif + #if defined(TIM5) + if(TIM_slave == TIM5) return LL_TIM_TS_ITR13; + #endif + #if defined(TIM8) + if(TIM_slave == TIM8) return LL_TIM_TS_ITR13; + #endif + #if defined(TIM23) + if(TIM_slave == TIM23) return LL_TIM_TS_ITR13; + #endif + } + #endif return -1; // combination not supported } #else @@ -514,7 +628,7 @@ uint32_t stm32_getTimerClockFreq(TIM_HandleTypeDef *handle) { return 0; } -#if defined(STM32H7xx) || defined(STM32H7xx) +#if defined(STM32H7xx) || defined(TARGET_STM32H7) /* When TIMPRE bit of the RCC_CFGR register is reset, * if APBx prescaler is 1 or 2 then TIMxCLK = HCLK, * otherwise TIMxCLK = 2x PCLKx. From 36e078c0ae5ae5a95e602127e7d36e13c5df5792 Mon Sep 17 00:00:00 2001 From: gospar Date: Fri, 21 Mar 2025 10:26:51 +0100 Subject: [PATCH 09/15] inital update of the cs for stm32 --- .../stm32/stm32_adc_utils.cpp | 268 ++++++++++++++++++ .../stm32f4_utils.h => stm32_adc_utils.h} | 25 +- .../hardware_specific/stm32/stm32_mcu.cpp | 1 + .../hardware_specific/stm32/stm32_mcu.h | 1 + .../stm32/stm32f4/stm32f4_hal.h | 2 +- .../stm32/stm32f4/stm32f4_mcu.cpp | 2 +- .../stm32/stm32f4/stm32f4_utils.cpp | 152 +--------- .../stm32/stm32f7/stm32f7_hal.h | 8 +- .../stm32/stm32f7/stm32f7_mcu.cpp | 2 +- .../stm32/stm32f7/stm32f7_utils.cpp | 161 +---------- .../stm32/stm32f7/stm32f7_utils.h | 30 -- .../stm32/stm32g4/stm32g4_hal.cpp | 11 +- .../stm32/stm32g4/stm32g4_hal.h | 2 +- .../stm32/stm32g4/stm32g4_mcu.cpp | 4 +- .../stm32/stm32g4/stm32g4_utils.cpp | 152 +--------- .../stm32/stm32g4/stm32g4_utils.h | 34 --- .../stm32/stm32l4/stm32l4_hal.h | 2 +- .../stm32/stm32l4/stm32l4_mcu.cpp | 2 +- .../stm32/stm32l4/stm32l4_utils.cpp | 151 +--------- .../stm32/stm32l4/stm32l4_utils.h | 34 --- 20 files changed, 311 insertions(+), 733 deletions(-) create mode 100644 src/current_sense/hardware_specific/stm32/stm32_adc_utils.cpp rename src/current_sense/hardware_specific/stm32/{stm32f4/stm32f4_utils.h => stm32_adc_utils.h} (51%) delete mode 100644 src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_utils.h delete mode 100644 src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_utils.h delete mode 100644 src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_utils.h diff --git a/src/current_sense/hardware_specific/stm32/stm32_adc_utils.cpp b/src/current_sense/hardware_specific/stm32/stm32_adc_utils.cpp new file mode 100644 index 00000000..fac4a377 --- /dev/null +++ b/src/current_sense/hardware_specific/stm32/stm32_adc_utils.cpp @@ -0,0 +1,268 @@ +#include "stm32_adc_utils.h" + +#if defined(_STM32_DEF_) + +// for searching the best ADCs, we need to know the number of ADCs +// it might be better to use some HAL variable for example ADC_COUNT +// here I've assumed the maximum number of ADCs is 5 +#define ADC_COUNT 5 + +/** + * @brief Return ADC HAL channel linked to a PinName + * @param pin: PinName + * @retval Valid HAL channel + */ +uint32_t _getADCChannel(PinName pin) +{ + uint32_t function = pinmap_function(pin, PinMap_ADC); + uint32_t channel = 0; + switch (STM_PIN_CHANNEL(function)) { +#ifdef ADC_CHANNEL_0 + case 0: + channel = ADC_CHANNEL_0; + break; +#endif + case 1: + channel = ADC_CHANNEL_1; + break; + case 2: + channel = ADC_CHANNEL_2; + break; + case 3: + channel = ADC_CHANNEL_3; + break; + case 4: + channel = ADC_CHANNEL_4; + break; + case 5: + channel = ADC_CHANNEL_5; + break; + case 6: + channel = ADC_CHANNEL_6; + break; + case 7: + channel = ADC_CHANNEL_7; + break; + case 8: + channel = ADC_CHANNEL_8; + break; + case 9: + channel = ADC_CHANNEL_9; + break; + case 10: + channel = ADC_CHANNEL_10; + break; + case 11: + channel = ADC_CHANNEL_11; + break; + case 12: + channel = ADC_CHANNEL_12; + break; + case 13: + channel = ADC_CHANNEL_13; + break; + case 14: + channel = ADC_CHANNEL_14; + break; + case 15: + channel = ADC_CHANNEL_15; + break; +#ifdef ADC_CHANNEL_16 + case 16: + channel = ADC_CHANNEL_16; + break; +#endif + case 17: + channel = ADC_CHANNEL_17; + break; +#ifdef ADC_CHANNEL_18 + case 18: + channel = ADC_CHANNEL_18; + break; +#endif +#ifdef ADC_CHANNEL_19 + case 19: + channel = ADC_CHANNEL_19; + break; +#endif +#ifdef ADC_CHANNEL_20 + case 20: + channel = ADC_CHANNEL_20; + break; + case 21: + channel = ADC_CHANNEL_21; + break; + case 22: + channel = ADC_CHANNEL_22; + break; + case 23: + channel = ADC_CHANNEL_23; + break; +#ifdef ADC_CHANNEL_24 + case 24: + channel = ADC_CHANNEL_24; + break; + case 25: + channel = ADC_CHANNEL_25; + break; + case 26: + channel = ADC_CHANNEL_26; + break; +#ifdef ADC_CHANNEL_27 + case 27: + channel = ADC_CHANNEL_27; + break; + case 28: + channel = ADC_CHANNEL_28; + break; + case 29: + channel = ADC_CHANNEL_29; + break; + case 30: + channel = ADC_CHANNEL_30; + break; + case 31: + channel = ADC_CHANNEL_31; + break; +#endif +#endif +#endif + default: + _Error_Handler("ADC: Unknown adc channel", (int)(STM_PIN_CHANNEL(function))); + break; + } + return channel; +} + + +int _adcToIndex(ADC_TypeDef *AdcHandle){ + if(AdcHandle == ADC1) return 0; +#ifdef ADC2 // if ADC2 exists + else if(AdcHandle == ADC2) return 1; +#endif +#ifdef ADC3 // if ADC3 exists + else if(AdcHandle == ADC3) return 2; +#endif +#ifdef ADC4 // if ADC4 exists + else if(AdcHandle == ADC4) return 3; +#endif +#ifdef ADC5 // if ADC5 exists + else if(AdcHandle == ADC5) return 4; +#endif + return 0; +} +int _adcToIndex(ADC_HandleTypeDef *AdcHandle){ + return _adcToIndex(AdcHandle->Instance); +} + + +ADC_TypeDef* _indexToADC(uint8_t index){ + switch (index) { + case 0: + return ADC1; + break; +#ifdef ADC2 // if ADC2 exists + case 1: + return ADC2; + break; +#endif +#ifdef ADC3 // if ADC3 exists + case 2: + return ADC3; + break; +#endif +#ifdef ADC4 // if ADC4 exists + case 3: + return ADC4; + break; +#endif +#ifdef ADC5 // if ADC5 exists + case 4: + return ADC5; + break; +#endif + } + return nullptr; +} + + +// functions finding the index of the first pin entry in the PinMap_ADC +// returns -1 if not found +int _findIndexOfFirstPinMapADCEntry(int pin) { + PinName pinName = digitalPinToPinName(pin); + int i = 0; + while ((PinMap_ADC[i].pin & ~ALTX_MASK) !=NC) { + if (pinName == (PinMap_ADC[i].pin & ~ALTX_MASK)) + return i; + i++; + } + return -1; +} + +// functions finding the index of the last pin entry in the PinMap_ADC +// returns -1 if not found +int _findIndexOfLastPinMapADCEntry(int pin) { + PinName pinName = digitalPinToPinName(pin); + int i = 0; + while (PinMap_ADC[i].pin!=NC) { + if ( pinName == (PinMap_ADC[i].pin & ~ALTX_MASK) + && pinName != (PinMap_ADC[i+1].pin & ~ALTX_MASK)) + return i; + i++; + } + return -1; +} + +// find the best ADC combination for the given pins +// returns the index of the best ADC +// 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[]) { + + // assuning that there is less than 8 ADCs + uint8_t pins_at_adc[ADC_COUNT] = {0}; + + // check how many pins are there and are not set + int no_pins = 0; + for (int i = 0; i < numPins; i++) { + if(_isset(pins[i])) no_pins++; + } + + // loop over all elements and count the pins connected to each ADC + for (int i = 0; i < numPins; i++) { + int pin = pins[i]; + if(!_isset(pin)) continue; + + int index = _findIndexOfFirstPinMapADCEntry(pin); + int last_index = _findIndexOfLastPinMapADCEntry(pin); + if (index == -1) { + return nullptr; + } + for (int j = index; j <= last_index; j++) { + if (PinMap_ADC[j].pin == NC) { + break; + } + int adcIndex = _adcToIndex((ADC_TypeDef*)PinMap_ADC[j].peripheral); + pins_at_adc[adcIndex]++; + } + } + + for (int i = 0; i < ADC_COUNT; i++) { + if(!pins_at_adc[i]) continue; + SimpleFOCDebug::print("STM32-CS: ADC"); + SimpleFOCDebug::print(i+1); + SimpleFOCDebug::print(" pins: "); + SimpleFOCDebug::println(pins_at_adc[i]); + } + + // now take the first ADC that has all pins connected + for (int i = 0; i < ADC_COUNT; i++) { + if (pins_at_adc[i] == no_pins) { + return _indexToADC(i); + } + } + return nullptr; +} + +#endif \ No newline at end of file diff --git a/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_utils.h b/src/current_sense/hardware_specific/stm32/stm32_adc_utils.h similarity index 51% rename from src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_utils.h rename to src/current_sense/hardware_specific/stm32/stm32_adc_utils.h index 05303965..0dd2a2a2 100644 --- a/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_utils.h +++ b/src/current_sense/hardware_specific/stm32/stm32_adc_utils.h @@ -1,13 +1,14 @@ - -#ifndef STM32F4_UTILS_HAL -#define STM32F4_UTILS_HAL +#ifndef STM32_ADC_UTILS_HAL +#define STM32_ADC_UTILS_HAL #include "Arduino.h" -#if defined(STM32F4xx) +#if defined(_STM32_DEF_) #define _TRGO_NOT_AVAILABLE 12345 +#include "../../../common/foc_utils.h" +#include "../../../communication/SimpleFOCDebug.h" /* Exported Functions */ /** @@ -17,18 +18,22 @@ */ uint32_t _getADCChannel(PinName pin); -// timer to injected TRGO -// https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc_ex.h#L179 +// timer to injected TRGO - architecure specific uint32_t _timerToInjectedTRGO(TIM_HandleTypeDef* timer); -// timer to regular TRGO -// https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc.h#L331 +// timer to regular TRGO - architecure specific uint32_t _timerToRegularTRGO(TIM_HandleTypeDef* timer); // function returning index of the ADC instance int _adcToIndex(ADC_HandleTypeDef *AdcHandle); int _adcToIndex(ADC_TypeDef *AdcHandle); -#endif -#endif \ No newline at end of file + + +// functions helping to find the best ADC channel +int _findIndexOfFirstPinMapADCEntry(int pin); +int _findIndexOfLastPinMapADCEntry(int pin); +ADC_TypeDef* _findBestADCForPins(int num_pins, int pins[]); +#endif +#endif diff --git a/src/current_sense/hardware_specific/stm32/stm32_mcu.cpp b/src/current_sense/hardware_specific/stm32/stm32_mcu.cpp index 94253d74..efc55733 100644 --- a/src/current_sense/hardware_specific/stm32/stm32_mcu.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32_mcu.cpp @@ -30,4 +30,5 @@ __attribute__((weak)) float _readADCVoltageInline(const int pinA, const void* c return raw_adc * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; } + #endif \ No newline at end of file diff --git a/src/current_sense/hardware_specific/stm32/stm32_mcu.h b/src/current_sense/hardware_specific/stm32/stm32_mcu.h index 5c7b1a28..564598d3 100644 --- a/src/current_sense/hardware_specific/stm32/stm32_mcu.h +++ b/src/current_sense/hardware_specific/stm32/stm32_mcu.h @@ -19,5 +19,6 @@ typedef struct Stm32CurrentSenseParams { TIM_HandleTypeDef* timer_handle = NP; } Stm32CurrentSenseParams; + #endif #endif \ No newline at end of file diff --git a/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_hal.h b/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_hal.h index ca73f181..f0f9a03d 100644 --- a/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_hal.h +++ b/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_hal.h @@ -6,7 +6,7 @@ #if defined(STM32F4xx) #include "stm32f4xx_hal.h" #include "../stm32_mcu.h" -#include "stm32f4_utils.h" +#include "../stm32_adc_utils.h" int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* driver_params); int _adc_gpio_init(Stm32CurrentSenseParams* cs_params, const int pinA, const int pinB, const int pinC); diff --git a/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_mcu.cpp b/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_mcu.cpp index 85d142bc..ed58e8cb 100644 --- a/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_mcu.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_mcu.cpp @@ -6,8 +6,8 @@ #include "../../../../drivers/hardware_specific/stm32/stm32_mcu.h" #include "../../../hardware_api.h" #include "../stm32_mcu.h" +#include "../stm32_adc_utils.h" #include "stm32f4_hal.h" -#include "stm32f4_utils.h" #include "Arduino.h" diff --git a/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_utils.cpp b/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_utils.cpp index 8a636c84..23d4b0d3 100644 --- a/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_utils.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_utils.cpp @@ -1,136 +1,7 @@ -#include "stm32f4_utils.h" +#include "../stm32_adc_utils.h" #if defined(STM32F4xx) -/* Exported Functions */ -/** - * @brief Return ADC HAL channel linked to a PinName - * @param pin: PinName - * @retval Valid HAL channel - */ -uint32_t _getADCChannel(PinName pin) -{ - uint32_t function = pinmap_function(pin, PinMap_ADC); - uint32_t channel = 0; - switch (STM_PIN_CHANNEL(function)) { -#ifdef ADC_CHANNEL_0 - case 0: - channel = ADC_CHANNEL_0; - break; -#endif - case 1: - channel = ADC_CHANNEL_1; - break; - case 2: - channel = ADC_CHANNEL_2; - break; - case 3: - channel = ADC_CHANNEL_3; - break; - case 4: - channel = ADC_CHANNEL_4; - break; - case 5: - channel = ADC_CHANNEL_5; - break; - case 6: - channel = ADC_CHANNEL_6; - break; - case 7: - channel = ADC_CHANNEL_7; - break; - case 8: - channel = ADC_CHANNEL_8; - break; - case 9: - channel = ADC_CHANNEL_9; - break; - case 10: - channel = ADC_CHANNEL_10; - break; - case 11: - channel = ADC_CHANNEL_11; - break; - case 12: - channel = ADC_CHANNEL_12; - break; - case 13: - channel = ADC_CHANNEL_13; - break; - case 14: - channel = ADC_CHANNEL_14; - break; - case 15: - channel = ADC_CHANNEL_15; - break; -#ifdef ADC_CHANNEL_16 - case 16: - channel = ADC_CHANNEL_16; - break; -#endif - case 17: - channel = ADC_CHANNEL_17; - break; -#ifdef ADC_CHANNEL_18 - case 18: - channel = ADC_CHANNEL_18; - break; -#endif -#ifdef ADC_CHANNEL_19 - case 19: - channel = ADC_CHANNEL_19; - break; -#endif -#ifdef ADC_CHANNEL_20 - case 20: - channel = ADC_CHANNEL_20; - break; - case 21: - channel = ADC_CHANNEL_21; - break; - case 22: - channel = ADC_CHANNEL_22; - break; - case 23: - channel = ADC_CHANNEL_23; - break; -#ifdef ADC_CHANNEL_24 - case 24: - channel = ADC_CHANNEL_24; - break; - case 25: - channel = ADC_CHANNEL_25; - break; - case 26: - channel = ADC_CHANNEL_26; - break; -#ifdef ADC_CHANNEL_27 - case 27: - channel = ADC_CHANNEL_27; - break; - case 28: - channel = ADC_CHANNEL_28; - break; - case 29: - channel = ADC_CHANNEL_29; - break; - case 30: - channel = ADC_CHANNEL_30; - break; - case 31: - channel = ADC_CHANNEL_31; - break; -#endif -#endif -#endif - default: - _Error_Handler("ADC: Unknown adc channel", (int)(STM_PIN_CHANNEL(function))); - break; - } - return channel; -} - - // timer to injected TRGO // https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc_ex.h#L179 uint32_t _timerToInjectedTRGO(TIM_HandleTypeDef* timer){ @@ -169,25 +40,4 @@ uint32_t _timerToRegularTRGO(TIM_HandleTypeDef* timer){ return _TRGO_NOT_AVAILABLE; } - -int _adcToIndex(ADC_TypeDef *AdcHandle){ - if(AdcHandle == ADC1) return 0; -#ifdef ADC2 // if ADC2 exists - else if(AdcHandle == ADC2) return 1; -#endif -#ifdef ADC3 // if ADC3 exists - else if(AdcHandle == ADC3) return 2; -#endif -#ifdef ADC4 // if ADC4 exists - else if(AdcHandle == ADC4) return 3; -#endif -#ifdef ADC5 // if ADC5 exists - else if(AdcHandle == ADC5) return 4; -#endif - return 0; -} -int _adcToIndex(ADC_HandleTypeDef *AdcHandle){ - return _adcToIndex(AdcHandle->Instance); -} - #endif \ No newline at end of file diff --git a/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_hal.h b/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_hal.h index ebd9e75e..391b3fb5 100644 --- a/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_hal.h +++ b/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_hal.h @@ -1,13 +1,17 @@ -#pragma once +#ifndef STM32F7_LOWSIDE_HAL +#define STM32F7_LOWSIDE_HAL #include "Arduino.h" #if defined(STM32F7xx) + #include "stm32f7xx_hal.h" #include "../stm32_mcu.h" -#include "stm32f7_utils.h" +#include "../stm32_adc_utils.h" int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* driver_params); int _adc_gpio_init(Stm32CurrentSenseParams* cs_params, const int pinA, const int pinB, const int pinC); #endif + +#endif \ No newline at end of file diff --git a/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_mcu.cpp b/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_mcu.cpp index 868aafd0..7ff5bede 100644 --- a/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_mcu.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_mcu.cpp @@ -6,8 +6,8 @@ #include "../../../../drivers/hardware_specific/stm32/stm32_mcu.h" #include "../../../hardware_api.h" #include "../stm32_mcu.h" +#include "../stm32_adc_utils.h" #include "stm32f7_hal.h" -#include "stm32f7_utils.h" #include "Arduino.h" diff --git a/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_utils.cpp b/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_utils.cpp index 2321c5da..fbd20d40 100644 --- a/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_utils.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_utils.cpp @@ -1,145 +1,7 @@ -#include "stm32f7_utils.h" +#include "../stm32_adc_utils.h" #if defined(STM32F7xx) -/* Exported Functions */ - - -PinName analog_to_pin(uint32_t pin) { - PinName pin_name = analogInputToPinName(pin); - if (pin_name == NC) { - return (PinName) pin; - } - return pin_name; -} - - -/** - * @brief Return ADC HAL channel linked to a PinName - * @param pin: PinName - * @retval Valid HAL channel - */ -uint32_t _getADCChannel(PinName pin) -{ - uint32_t function = pinmap_function(pin, PinMap_ADC); - uint32_t channel = 0; - switch (STM_PIN_CHANNEL(function)) { -#ifdef ADC_CHANNEL_0 - case 0: - channel = ADC_CHANNEL_0; - break; -#endif - case 1: - channel = ADC_CHANNEL_1; - break; - case 2: - channel = ADC_CHANNEL_2; - break; - case 3: - channel = ADC_CHANNEL_3; - break; - case 4: - channel = ADC_CHANNEL_4; - break; - case 5: - channel = ADC_CHANNEL_5; - break; - case 6: - channel = ADC_CHANNEL_6; - break; - case 7: - channel = ADC_CHANNEL_7; - break; - case 8: - channel = ADC_CHANNEL_8; - break; - case 9: - channel = ADC_CHANNEL_9; - break; - case 10: - channel = ADC_CHANNEL_10; - break; - case 11: - channel = ADC_CHANNEL_11; - break; - case 12: - channel = ADC_CHANNEL_12; - break; - case 13: - channel = ADC_CHANNEL_13; - break; - case 14: - channel = ADC_CHANNEL_14; - break; - case 15: - channel = ADC_CHANNEL_15; - break; -#ifdef ADC_CHANNEL_16 - case 16: - channel = ADC_CHANNEL_16; - break; -#endif - case 17: - channel = ADC_CHANNEL_17; - break; -#ifdef ADC_CHANNEL_18 - case 18: - channel = ADC_CHANNEL_18; - break; -#endif -#ifdef ADC_CHANNEL_19 - case 19: - channel = ADC_CHANNEL_19; - break; -#endif -#ifdef ADC_CHANNEL_20 - case 20: - channel = ADC_CHANNEL_20; - break; - case 21: - channel = ADC_CHANNEL_21; - break; - case 22: - channel = ADC_CHANNEL_22; - break; - case 23: - channel = ADC_CHANNEL_23; - break; -#ifdef ADC_CHANNEL_24 - case 24: - channel = ADC_CHANNEL_24; - break; - case 25: - channel = ADC_CHANNEL_25; - break; - case 26: - channel = ADC_CHANNEL_26; - break; -#ifdef ADC_CHANNEL_27 - case 27: - channel = ADC_CHANNEL_27; - break; - case 28: - channel = ADC_CHANNEL_28; - break; - case 29: - channel = ADC_CHANNEL_29; - break; - case 30: - channel = ADC_CHANNEL_30; - break; - case 31: - channel = ADC_CHANNEL_31; - break; -#endif -#endif -#endif - default: - _Error_Handler("ADC: Unknown adc channel", (int)(STM_PIN_CHANNEL(function))); - break; - } - return channel; -} /* TIM1 TIM2 @@ -231,25 +93,4 @@ uint32_t _timerToRegularTRGO(TIM_HandleTypeDef* timer){ return _TRGO_NOT_AVAILABLE; } - -int _adcToIndex(ADC_TypeDef *AdcHandle){ - if(AdcHandle == ADC1) return 0; -#ifdef ADC2 // if ADC2 exists - else if(AdcHandle == ADC2) return 1; -#endif -#ifdef ADC3 // if ADC3 exists - else if(AdcHandle == ADC3) return 2; -#endif -#ifdef ADC4 // if ADC4 exists - else if(AdcHandle == ADC4) return 3; -#endif -#ifdef ADC5 // if ADC5 exists - else if(AdcHandle == ADC5) return 4; -#endif - return 0; -} -int _adcToIndex(ADC_HandleTypeDef *AdcHandle){ - return _adcToIndex(AdcHandle->Instance); -} - #endif \ No newline at end of file diff --git a/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_utils.h b/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_utils.h deleted file mode 100644 index 2e125d35..00000000 --- a/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_utils.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include "Arduino.h" - -#if defined(STM32F7xx) - -#define _TRGO_NOT_AVAILABLE 12345 - - -/* Exported Functions */ -/** - * @brief Return ADC HAL channel linked to a PinName - * @param pin: PinName - * @retval Valid HAL channel - */ -uint32_t _getADCChannel(PinName pin); - -// timer to injected TRGO -// https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_adc_ex.h#L178 -uint32_t _timerToInjectedTRGO(TIM_HandleTypeDef* timer); - -// timer to regular TRGO -// https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_adc.h#L331 -uint32_t _timerToRegularTRGO(TIM_HandleTypeDef* timer); - -// function returning index of the ADC instance -int _adcToIndex(ADC_HandleTypeDef *AdcHandle); -int _adcToIndex(ADC_TypeDef *AdcHandle); - -#endif \ No newline at end of file diff --git a/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_hal.cpp b/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_hal.cpp index 0ac50c80..c437ae51 100644 --- a/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_hal.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_hal.cpp @@ -19,7 +19,11 @@ ADC_HandleTypeDef hadc; int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* driver_params) { ADC_InjectionConfTypeDef sConfigInjected; - + + /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) + */ + // hadc.Instance = _findBestADCForPins(3, cs_params->pins); + // check if all pins belong to the same ADC ADC_TypeDef* adc_pin1 = _isset(cs_params->pins[0]) ? (ADC_TypeDef*)pinmap_peripheral(analogInputToPinName(cs_params->pins[0]), PinMap_ADC) : nullptr; ADC_TypeDef* adc_pin2 = _isset(cs_params->pins[1]) ? (ADC_TypeDef*)pinmap_peripheral(analogInputToPinName(cs_params->pins[1]), PinMap_ADC) : nullptr; @@ -35,7 +39,7 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive } - /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) + /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */ hadc.Instance = (ADC_TypeDef *)pinmap_peripheral(analogInputToPinName(cs_params->pins[0]), PinMap_ADC); @@ -92,7 +96,7 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive #endif else{ #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: ERR: Pin does not belong to any ADC!"); + SIMPLEFOC_DEBUG("STM32-CS: ERR: Cannot find a common ADC for the pins!"); #endif return -1; // error not a valid ADC instance } @@ -101,6 +105,7 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive 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; diff --git a/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_hal.h b/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_hal.h index 34fb947e..81faf26b 100644 --- a/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_hal.h +++ b/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_hal.h @@ -7,7 +7,7 @@ #include "stm32g4xx_hal.h" #include "../stm32_mcu.h" -#include "stm32g4_utils.h" +#include "../stm32_adc_utils.h" int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* driver_params); int _adc_gpio_init(Stm32CurrentSenseParams* cs_params, const int pinA, const int pinB, const int pinC); diff --git a/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_mcu.cpp b/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_mcu.cpp index a4d66b60..67585edc 100644 --- a/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_mcu.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_mcu.cpp @@ -7,8 +7,8 @@ #include "../../../../drivers/hardware_specific/stm32/stm32_mcu.h" #include "../../../hardware_api.h" #include "../stm32_mcu.h" +#include "../stm32_adc_utils.h" #include "stm32g4_hal.h" -#include "stm32g4_utils.h" #include "Arduino.h" // #define SIMPLEFOC_STM32_ADC_INTERRUPT @@ -77,7 +77,7 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ LL_TIM_SetTriggerOutput(cs_params->timer_handle->Instance, LL_TIM_TRGO_UPDATE); // Start the adc calibration - HAL_ADCEx_Calibration_Start(cs_params->adc_handle,ADC_SINGLE_ENDED); + HAL_ADCEx_Calibration_Start(cs_params->adc_handle, ADC_SINGLE_ENDED); // start the adc if (use_adc_interrupt){ diff --git a/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_utils.cpp b/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_utils.cpp index 2f9e7e4d..3622c928 100644 --- a/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_utils.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_utils.cpp @@ -1,136 +1,7 @@ -#include "stm32g4_utils.h" +#include "../stm32_adc_utils.h" #if defined(STM32G4xx) && !defined(ARDUINO_B_G431B_ESC1) -/* Exported Functions */ -/** - * @brief Return ADC HAL channel linked to a PinName - * @param pin: PinName - * @retval Valid HAL channel - */ -uint32_t _getADCChannel(PinName pin) -{ - uint32_t function = pinmap_function(pin, PinMap_ADC); - uint32_t channel = 0; - switch (STM_PIN_CHANNEL(function)) { -#ifdef ADC_CHANNEL_0 - case 0: - channel = ADC_CHANNEL_0; - break; -#endif - case 1: - channel = ADC_CHANNEL_1; - break; - case 2: - channel = ADC_CHANNEL_2; - break; - case 3: - channel = ADC_CHANNEL_3; - break; - case 4: - channel = ADC_CHANNEL_4; - break; - case 5: - channel = ADC_CHANNEL_5; - break; - case 6: - channel = ADC_CHANNEL_6; - break; - case 7: - channel = ADC_CHANNEL_7; - break; - case 8: - channel = ADC_CHANNEL_8; - break; - case 9: - channel = ADC_CHANNEL_9; - break; - case 10: - channel = ADC_CHANNEL_10; - break; - case 11: - channel = ADC_CHANNEL_11; - break; - case 12: - channel = ADC_CHANNEL_12; - break; - case 13: - channel = ADC_CHANNEL_13; - break; - case 14: - channel = ADC_CHANNEL_14; - break; - case 15: - channel = ADC_CHANNEL_15; - break; -#ifdef ADC_CHANNEL_16 - case 16: - channel = ADC_CHANNEL_16; - break; -#endif - case 17: - channel = ADC_CHANNEL_17; - break; -#ifdef ADC_CHANNEL_18 - case 18: - channel = ADC_CHANNEL_18; - break; -#endif -#ifdef ADC_CHANNEL_19 - case 19: - channel = ADC_CHANNEL_19; - break; -#endif -#ifdef ADC_CHANNEL_20 - case 20: - channel = ADC_CHANNEL_20; - break; - case 21: - channel = ADC_CHANNEL_21; - break; - case 22: - channel = ADC_CHANNEL_22; - break; - case 23: - channel = ADC_CHANNEL_23; - break; -#ifdef ADC_CHANNEL_24 - case 24: - channel = ADC_CHANNEL_24; - break; - case 25: - channel = ADC_CHANNEL_25; - break; - case 26: - channel = ADC_CHANNEL_26; - break; -#ifdef ADC_CHANNEL_27 - case 27: - channel = ADC_CHANNEL_27; - break; - case 28: - channel = ADC_CHANNEL_28; - break; - case 29: - channel = ADC_CHANNEL_29; - break; - case 30: - channel = ADC_CHANNEL_30; - break; - case 31: - channel = ADC_CHANNEL_31; - break; -#endif -#endif -#endif - default: - _Error_Handler("ADC: Unknown adc channel", (int)(STM_PIN_CHANNEL(function))); - break; - } - return channel; -} - - // timer to injected TRGO // https://github.com/stm32duino/Arduino_Core_STM32/blob/6588dee03382e73ed42c4a5e473900ab3b79d6e4/system/Drivers/STM32G4xx_HAL_Driver/Inc/stm32g4xx_hal_adc_ex.h#L217 uint32_t _timerToInjectedTRGO(TIM_HandleTypeDef* timer){ @@ -213,25 +84,4 @@ uint32_t _timerToRegularTRGO(TIM_HandleTypeDef* timer){ return _TRGO_NOT_AVAILABLE; } - -int _adcToIndex(ADC_TypeDef *AdcHandle){ - if(AdcHandle == ADC1) return 0; -#ifdef ADC2 // if ADC2 exists - else if(AdcHandle == ADC2) return 1; -#endif -#ifdef ADC3 // if ADC3 exists - else if(AdcHandle == ADC3) return 2; -#endif -#ifdef ADC4 // if ADC4 exists - else if(AdcHandle == ADC4) return 3; -#endif -#ifdef ADC5 // if ADC5 exists - else if(AdcHandle == ADC5) return 4; -#endif - return 0; -} -int _adcToIndex(ADC_HandleTypeDef *AdcHandle){ - return _adcToIndex(AdcHandle->Instance); -} - #endif \ No newline at end of file diff --git a/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_utils.h b/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_utils.h deleted file mode 100644 index 5a3aca29..00000000 --- a/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_utils.h +++ /dev/null @@ -1,34 +0,0 @@ - -#ifndef STM32G4_UTILS_HAL -#define STM32G4_UTILS_HAL - -#include "Arduino.h" - -#if defined(STM32G4xx) && !defined(ARDUINO_B_G431B_ESC1) - -#define _TRGO_NOT_AVAILABLE 12345 - - -/* Exported Functions */ -/** - * @brief Return ADC HAL channel linked to a PinName - * @param pin: PinName - * @retval Valid HAL channel - */ -uint32_t _getADCChannel(PinName pin); - -// timer to injected TRGO -// https://github.com/stm32duino/Arduino_Core_STM32/blob/6588dee03382e73ed42c4a5e473900ab3b79d6e4/system/Drivers/STM32G4xx_HAL_Driver/Inc/stm32g4xx_hal_adc_ex.h#L217 -uint32_t _timerToInjectedTRGO(TIM_HandleTypeDef* timer); - -// timer to regular TRGO -// https://github.com/stm32duino/Arduino_Core_STM32/blob/6588dee03382e73ed42c4a5e473900ab3b79d6e4/system/Drivers/STM32G4xx_HAL_Driver/Inc/stm32g4xx_hal_adc.h#L519 -uint32_t _timerToRegularTRGO(TIM_HandleTypeDef* timer); - -// function returning index of the ADC instance -int _adcToIndex(ADC_HandleTypeDef *AdcHandle); -int _adcToIndex(ADC_TypeDef *AdcHandle); - -#endif - -#endif \ No newline at end of file diff --git a/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_hal.h b/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_hal.h index 2004ff69..fa49d593 100644 --- a/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_hal.h +++ b/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_hal.h @@ -7,7 +7,7 @@ #include "stm32l4xx_hal.h" #include "../stm32_mcu.h" -#include "stm32l4_utils.h" +#include "../stm32_adc_utils.h" int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* driver_params); int _adc_gpio_init(Stm32CurrentSenseParams* cs_params, const int pinA, const int pinB, const int pinC); diff --git a/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_mcu.cpp b/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_mcu.cpp index 4ddc5484..b2b9a264 100644 --- a/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_mcu.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_mcu.cpp @@ -7,8 +7,8 @@ #include "../../../../drivers/hardware_specific/stm32/stm32_mcu.h" #include "../../../hardware_api.h" #include "../stm32_mcu.h" +#include "../stm32_adc_utils.h" #include "stm32l4_hal.h" -#include "stm32l4_utils.h" #include "Arduino.h" diff --git a/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_utils.cpp b/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_utils.cpp index f93e63a4..64229b8a 100644 --- a/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_utils.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_utils.cpp @@ -1,135 +1,7 @@ -#include "stm32l4_utils.h" +#include "../stm32_adc_utils.h" #if defined(STM32L4xx) -/* Exported Functions */ -/** - * @brief Return ADC HAL channel linked to a PinName - * @param pin: PinName - * @retval Valid HAL channel - */ -uint32_t _getADCChannel(PinName pin) -{ - uint32_t function = pinmap_function(pin, PinMap_ADC); - uint32_t channel = 0; - switch (STM_PIN_CHANNEL(function)) { -#ifdef ADC_CHANNEL_0 - case 0: - channel = ADC_CHANNEL_0; - break; -#endif - case 1: - channel = ADC_CHANNEL_1; - break; - case 2: - channel = ADC_CHANNEL_2; - break; - case 3: - channel = ADC_CHANNEL_3; - break; - case 4: - channel = ADC_CHANNEL_4; - break; - case 5: - channel = ADC_CHANNEL_5; - break; - case 6: - channel = ADC_CHANNEL_6; - break; - case 7: - channel = ADC_CHANNEL_7; - break; - case 8: - channel = ADC_CHANNEL_8; - break; - case 9: - channel = ADC_CHANNEL_9; - break; - case 10: - channel = ADC_CHANNEL_10; - break; - case 11: - channel = ADC_CHANNEL_11; - break; - case 12: - channel = ADC_CHANNEL_12; - break; - case 13: - channel = ADC_CHANNEL_13; - break; - case 14: - channel = ADC_CHANNEL_14; - break; - case 15: - channel = ADC_CHANNEL_15; - break; -#ifdef ADC_CHANNEL_16 - case 16: - channel = ADC_CHANNEL_16; - break; -#endif - case 17: - channel = ADC_CHANNEL_17; - break; -#ifdef ADC_CHANNEL_18 - case 18: - channel = ADC_CHANNEL_18; - break; -#endif -#ifdef ADC_CHANNEL_19 - case 19: - channel = ADC_CHANNEL_19; - break; -#endif -#ifdef ADC_CHANNEL_20 - case 20: - channel = ADC_CHANNEL_20; - break; - case 21: - channel = ADC_CHANNEL_21; - break; - case 22: - channel = ADC_CHANNEL_22; - break; - case 23: - channel = ADC_CHANNEL_23; - break; -#ifdef ADC_CHANNEL_24 - case 24: - channel = ADC_CHANNEL_24; - break; - case 25: - channel = ADC_CHANNEL_25; - break; - case 26: - channel = ADC_CHANNEL_26; - break; -#ifdef ADC_CHANNEL_27 - case 27: - channel = ADC_CHANNEL_27; - break; - case 28: - channel = ADC_CHANNEL_28; - break; - case 29: - channel = ADC_CHANNEL_29; - break; - case 30: - channel = ADC_CHANNEL_30; - break; - case 31: - channel = ADC_CHANNEL_31; - break; -#endif -#endif -#endif - default: - _Error_Handler("ADC: Unknown adc channel", (int)(STM_PIN_CHANNEL(function))); - break; - } - return channel; -} - // timer to injected TRGO // https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_adc_ex.h#L210 @@ -197,25 +69,4 @@ uint32_t _timerToRegularTRGO(TIM_HandleTypeDef* timer){ return _TRGO_NOT_AVAILABLE; } - -int _adcToIndex(ADC_TypeDef *AdcHandle){ - if(AdcHandle == ADC1) return 0; -#ifdef ADC2 // if ADC2 exists - else if(AdcHandle == ADC2) return 1; -#endif -#ifdef ADC3 // if ADC3 exists - else if(AdcHandle == ADC3) return 2; -#endif -#ifdef ADC4 // if ADC4 exists - else if(AdcHandle == ADC4) return 3; -#endif -#ifdef ADC5 // if ADC5 exists - else if(AdcHandle == ADC5) return 4; -#endif - return 0; -} -int _adcToIndex(ADC_HandleTypeDef *AdcHandle){ - return _adcToIndex(AdcHandle->Instance); -} - #endif \ No newline at end of file diff --git a/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_utils.h b/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_utils.h deleted file mode 100644 index e30bf0ce..00000000 --- a/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_utils.h +++ /dev/null @@ -1,34 +0,0 @@ - -#ifndef STM32L4_UTILS_HAL -#define STM32L4_UTILS_HAL - -#include "Arduino.h" - -#if defined(STM32L4xx) - -#define _TRGO_NOT_AVAILABLE 12345 - - -/* Exported Functions */ -/** - * @brief Return ADC HAL channel linked to a PinName - * @param pin: PinName - * @retval Valid HAL channel - */ -uint32_t _getADCChannel(PinName pin); - -// timer to injected TRGO -// https://github.com/stm32duino/Arduino_Core_STM32/blob/6588dee03382e73ed42c4a5e473900ab3b79d6e4/system/Drivers/STM32G4xx_HAL_Driver/Inc/stm32g4xx_hal_adc_ex.h#L217 -uint32_t _timerToInjectedTRGO(TIM_HandleTypeDef* timer); - -// timer to regular TRGO -// https://github.com/stm32duino/Arduino_Core_STM32/blob/6588dee03382e73ed42c4a5e473900ab3b79d6e4/system/Drivers/STM32G4xx_HAL_Driver/Inc/stm32g4xx_hal_adc.h#L519 -uint32_t _timerToRegularTRGO(TIM_HandleTypeDef* timer); - -// function returning index of the ADC instance -int _adcToIndex(ADC_HandleTypeDef *AdcHandle); -int _adcToIndex(ADC_TypeDef *AdcHandle); - -#endif - -#endif \ No newline at end of file From 49e34e8e5a68a4c433fde1ec144206c76541be47 Mon Sep 17 00:00:00 2001 From: gospar Date: Fri, 21 Mar 2025 11:53:03 +0100 Subject: [PATCH 10/15] automatic adc selsction --- .../stm32/stm32_adc_utils.cpp | 320 +++++++++++------- .../hardware_specific/stm32/stm32_adc_utils.h | 7 +- .../stm32/stm32f4/stm32f4_hal.cpp | 32 +- .../stm32/stm32f4/stm32f4_mcu.cpp | 6 +- .../stm32/stm32f7/stm32f7_hal.cpp | 32 +- .../stm32/stm32f7/stm32f7_mcu.cpp | 6 +- .../stm32/stm32g4/stm32g4_hal.cpp | 36 +- .../stm32/stm32g4/stm32g4_mcu.cpp | 7 +- .../stm32/stm32l4/stm32l4_hal.cpp | 26 +- .../stm32/stm32l4/stm32l4_mcu.cpp | 6 +- 10 files changed, 262 insertions(+), 216 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 fac4a377..95eb3e8f 100644 --- a/src/current_sense/hardware_specific/stm32/stm32_adc_utils.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32_adc_utils.cpp @@ -7,12 +7,173 @@ // here I've assumed the maximum number of ADCs is 5 #define ADC_COUNT 5 + + +int _adcToIndex(ADC_TypeDef *AdcHandle){ + if(AdcHandle == ADC1) return 0; +#ifdef ADC2 // if ADC2 exists + else if(AdcHandle == ADC2) return 1; +#endif +#ifdef ADC3 // if ADC3 exists + else if(AdcHandle == ADC3) return 2; +#endif +#ifdef ADC4 // if ADC4 exists + else if(AdcHandle == ADC4) return 3; +#endif +#ifdef ADC5 // if ADC5 exists + else if(AdcHandle == ADC5) return 4; +#endif + return 0; +} +int _adcToIndex(ADC_HandleTypeDef *AdcHandle){ + return _adcToIndex(AdcHandle->Instance); +} + + +ADC_TypeDef* _indexToADC(uint8_t index){ + switch (index) { + case 0: + return ADC1; + break; +#ifdef ADC2 // if ADC2 exists + case 1: + return ADC2; + break; +#endif +#ifdef ADC3 // if ADC3 exists + case 2: + return ADC3; + break; +#endif +#ifdef ADC4 // if ADC4 exists + case 3: + return ADC4; + break; +#endif +#ifdef ADC5 // if ADC5 exists + case 4: + return ADC5; + break; +#endif + } + return nullptr; +} + +int _findIndexOfEntry(PinName pin) { + // remove the ALT if it is there + PinName pinName = (PinName)(pinName & ~ALTX_MASK); + int i = 0; + SIMPLEFOC_DEBUG("STM32-CS: Looking for pin "); + while (PinMap_ADC[i].pin !=NC) { + if (pinName == PinMap_ADC[i].pin ) + return i; + i++; + SIMPLEFOC_DEBUG("STM32-CS: Looking for pin ", i); + } + return -1; +} + +int _findIndexOfLastEntry(PinName pin) { + // remove the ALT if it is there + PinName pinName = (PinName)(pin & ~ALTX_MASK); + + int i = 0; + while (PinMap_ADC[i].pin!=NC) { + if ( pinName == (PinMap_ADC[i].pin & ~ALTX_MASK) + && pinName != (PinMap_ADC[i+1].pin & ~ALTX_MASK)) + return i; + i++; + } + return -1; +} +int _findIndexOfFirstEntry(PinName pin) { + // remove the ALT if it is there + PinName pinName = (PinName)(pin & ~ALTX_MASK); + int i = 0; + while (PinMap_ADC[i].pin !=NC) { + if (pinName == PinMap_ADC[i].pin ) + return i; + i++; + } + return -1; +} + +// functions finding the index of the first pin entry in the PinMap_ADC +// returns -1 if not found +int _findIndexOfFirstPinMapADCEntry(int pin) { + PinName pinName = digitalPinToPinName(pin); + // remove the ALT if it is there + return _findIndexOfFirstEntry(pinName); +} + +// functions finding the index of the last pin entry in the PinMap_ADC +// returns -1 if not found +int _findIndexOfLastPinMapADCEntry(int pin) { + PinName pinName = digitalPinToPinName(pin); + // remove the ALT if it is there + return _findIndexOfLastEntry(pinName); +} + +// find the best ADC combination for the given pins +// returns the index of the best ADC +// 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[]) { + + // assuning that there is less than 8 ADCs + uint8_t pins_at_adc[ADC_COUNT] = {0}; + + // check how many pins are there and are not set + int no_pins = 0; + for (int i = 0; i < numPins; i++) { + if(_isset(pins[i])) no_pins++; + } + + // loop over all elements and count the pins connected to each ADC + for (int i = 0; i < numPins; i++) { + int pin = pins[i]; + if(!_isset(pin)) continue; + + int index = _findIndexOfFirstPinMapADCEntry(pin); + int last_index = _findIndexOfLastPinMapADCEntry(pin); + if (index == -1) { + return nullptr; + } + for (int j = index; j <= last_index; j++) { + if (PinMap_ADC[j].pin == NC) { + break; + } + int adcIndex = _adcToIndex((ADC_TypeDef*)PinMap_ADC[j].peripheral); + pins_at_adc[adcIndex]++; + } + } + + for (int i = 0; i < ADC_COUNT; i++) { + if(!pins_at_adc[i]) continue; + SimpleFOCDebug::print("STM32-CS: ADC"); + SimpleFOCDebug::print(i+1); + SimpleFOCDebug::print(" pins: "); + SimpleFOCDebug::println(pins_at_adc[i]); + } + + // now take the first ADC that has all pins connected + for (int i = 0; i < ADC_COUNT; i++) { + if (pins_at_adc[i] == no_pins) { + return _indexToADC(i); + } + } + return nullptr; +} + + + /** * @brief Return ADC HAL channel linked to a PinName * @param pin: PinName * @retval Valid HAL channel */ -uint32_t _getADCChannel(PinName pin) +uint32_t _getADCChannelFromPinMap(PinName pin) { uint32_t function = pinmap_function(pin, PinMap_ADC); uint32_t channel = 0; @@ -134,135 +295,60 @@ uint32_t _getADCChannel(PinName pin) return channel; } +/** + * @brief Return ADC HAL channel linked to a PinName and the ADC handle + * @param pin: PinName + * @param AdcHandle: ADC_HandleTypeDef a pointer to the ADC handle + * @retval Valid HAL channel + */ +uint32_t _getADCChannel(PinName pin, ADC_TypeDef *AdcHandle ) +{ + if (AdcHandle == NP) { + return _getADCChannelFromPinMap(pin); + } + // find the PinName that corresponds to the ADC + int first_ind = _findIndexOfFirstEntry(pin); + int last_ind = _findIndexOfLastEntry(pin); + if (first_ind == -1 || last_ind == -1) { + _Error_Handler("ADC: Pin not found in PinMap_ADC", (int)pin); + } + // find the channel + uint32_t channel = 0; + for (int i = first_ind; i <= last_ind; i++) { + if (PinMap_ADC[i].peripheral == AdcHandle) { + channel =_getADCChannelFromPinMap(PinMap_ADC[i].pin); -int _adcToIndex(ADC_TypeDef *AdcHandle){ - if(AdcHandle == ADC1) return 0; -#ifdef ADC2 // if ADC2 exists - else if(AdcHandle == ADC2) return 1; -#endif -#ifdef ADC3 // if ADC3 exists - else if(AdcHandle == ADC3) return 2; -#endif -#ifdef ADC4 // if ADC4 exists - else if(AdcHandle == ADC4) return 3; -#endif -#ifdef ADC5 // if ADC5 exists - else if(AdcHandle == ADC5) return 4; -#endif - return 0; -} -int _adcToIndex(ADC_HandleTypeDef *AdcHandle){ - return _adcToIndex(AdcHandle->Instance); -} +// #ifdef SIMPLEFOC_STM32_DEBUG + SimpleFOCDebug::print("STM32-CS: Configuring ADC"); + SimpleFOCDebug::print(_adcToIndex(AdcHandle)+1); + SimpleFOCDebug::print(" channel: "); + SimpleFOCDebug::println((int)STM_PIN_CHANNEL(pinmap_function(PinMap_ADC[i].pin, PinMap_ADC))); +// #endif + break; + } + } + return channel; +} -ADC_TypeDef* _indexToADC(uint8_t index){ - switch (index) { +uint32_t _getADCInjectedRank(uint8_t ind){ + switch (ind) { case 0: - return ADC1; + return ADC_INJECTED_RANK_1; break; -#ifdef ADC2 // if ADC2 exists case 1: - return ADC2; + return ADC_INJECTED_RANK_2; break; -#endif -#ifdef ADC3 // if ADC3 exists case 2: - return ADC3; + return ADC_INJECTED_RANK_3; break; -#endif -#ifdef ADC4 // if ADC4 exists case 3: - return ADC4; + return ADC_INJECTED_RANK_4; break; -#endif -#ifdef ADC5 // if ADC5 exists - case 4: - return ADC5; + default: + return 0; break; -#endif - } - return nullptr; -} - - -// functions finding the index of the first pin entry in the PinMap_ADC -// returns -1 if not found -int _findIndexOfFirstPinMapADCEntry(int pin) { - PinName pinName = digitalPinToPinName(pin); - int i = 0; - while ((PinMap_ADC[i].pin & ~ALTX_MASK) !=NC) { - if (pinName == (PinMap_ADC[i].pin & ~ALTX_MASK)) - return i; - i++; } - return -1; -} - -// functions finding the index of the last pin entry in the PinMap_ADC -// returns -1 if not found -int _findIndexOfLastPinMapADCEntry(int pin) { - PinName pinName = digitalPinToPinName(pin); - int i = 0; - while (PinMap_ADC[i].pin!=NC) { - if ( pinName == (PinMap_ADC[i].pin & ~ALTX_MASK) - && pinName != (PinMap_ADC[i+1].pin & ~ALTX_MASK)) - return i; - i++; - } - return -1; -} - -// find the best ADC combination for the given pins -// returns the index of the best ADC -// 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[]) { - - // assuning that there is less than 8 ADCs - uint8_t pins_at_adc[ADC_COUNT] = {0}; - - // check how many pins are there and are not set - int no_pins = 0; - for (int i = 0; i < numPins; i++) { - if(_isset(pins[i])) no_pins++; - } - - // loop over all elements and count the pins connected to each ADC - for (int i = 0; i < numPins; i++) { - int pin = pins[i]; - if(!_isset(pin)) continue; - - int index = _findIndexOfFirstPinMapADCEntry(pin); - int last_index = _findIndexOfLastPinMapADCEntry(pin); - if (index == -1) { - return nullptr; - } - for (int j = index; j <= last_index; j++) { - if (PinMap_ADC[j].pin == NC) { - break; - } - int adcIndex = _adcToIndex((ADC_TypeDef*)PinMap_ADC[j].peripheral); - pins_at_adc[adcIndex]++; - } - } - - for (int i = 0; i < ADC_COUNT; i++) { - if(!pins_at_adc[i]) continue; - SimpleFOCDebug::print("STM32-CS: ADC"); - SimpleFOCDebug::print(i+1); - SimpleFOCDebug::print(" pins: "); - SimpleFOCDebug::println(pins_at_adc[i]); - } - - // now take the first ADC that has all pins connected - for (int i = 0; i < ADC_COUNT; i++) { - if (pins_at_adc[i] == no_pins) { - return _indexToADC(i); - } - } - return nullptr; } #endif \ No newline at end of file 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 0dd2a2a2..7e74a96f 100644 --- a/src/current_sense/hardware_specific/stm32/stm32_adc_utils.h +++ b/src/current_sense/hardware_specific/stm32/stm32_adc_utils.h @@ -14,9 +14,11 @@ /** * @brief Return ADC HAL channel linked to a PinName * @param pin: PinName + * @param adc: ADC_TypeDef a pointer to the ADC handle * @retval Valid HAL channel */ -uint32_t _getADCChannel(PinName pin); +uint32_t _getADCChannel(PinName pin, ADC_TypeDef* adc = NP); +uint32_t _getADCInjectedRank(uint8_t ind); // timer to injected TRGO - architecure specific uint32_t _timerToInjectedTRGO(TIM_HandleTypeDef* timer); @@ -28,9 +30,6 @@ uint32_t _timerToRegularTRGO(TIM_HandleTypeDef* timer); int _adcToIndex(ADC_HandleTypeDef *AdcHandle); int _adcToIndex(ADC_TypeDef *AdcHandle); - - - // functions helping to find the best ADC channel int _findIndexOfFirstPinMapADCEntry(int pin); int _findIndexOfLastPinMapADCEntry(int pin); 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 1c85d1fa..e6ee1cbc 100644 --- a/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_hal.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_hal.cpp @@ -21,24 +21,9 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive { ADC_InjectionConfTypeDef sConfigInjected; - // check if all pins belong to the same ADC - ADC_TypeDef* adc_pin1 = _isset(cs_params->pins[0]) ? (ADC_TypeDef*)pinmap_peripheral(analogInputToPinName(cs_params->pins[0]), PinMap_ADC) : nullptr; - ADC_TypeDef* adc_pin2 = _isset(cs_params->pins[1]) ? (ADC_TypeDef*)pinmap_peripheral(analogInputToPinName(cs_params->pins[1]), PinMap_ADC) : nullptr; - ADC_TypeDef* adc_pin3 = _isset(cs_params->pins[2]) ? (ADC_TypeDef*)pinmap_peripheral(analogInputToPinName(cs_params->pins[2]), PinMap_ADC) : nullptr; - if ( ((adc_pin1 != adc_pin2) && (adc_pin1 && adc_pin2)) || - ((adc_pin2 != adc_pin3) && (adc_pin2 && adc_pin3)) || - ((adc_pin1 != adc_pin3) && (adc_pin1 && adc_pin3)) - ){ -#ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: ERR: Analog pins dont belong to the same ADC!"); -#endif - return -1; - } - - /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */ - hadc.Instance = (ADC_TypeDef *)pinmap_peripheral(analogInputToPinName(cs_params->pins[0]), PinMap_ADC); + hadc.Instance = _findBestADCForPins(3, cs_params->pins); if(hadc.Instance == ADC1) __HAL_RCC_ADC1_CLK_ENABLE(); #ifdef ADC2 // if defined ADC2 @@ -78,7 +63,12 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive /**Configures for the selected ADC injected channel its corresponding rank in the sequencer and its sample time */ - sConfigInjected.InjectedNbrOfConversion = _isset(cs_params->pins[2]) ? 3 : 2; + sConfigInjected.InjectedNbrOfConversion = 0; + for(int pin_no=0; pin_no<3; pin_no++){ + if(_isset(cs_params->pins[pin_no])){ + sConfigInjected.InjectedNbrOfConversion++; + } + } sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_3CYCLES; sConfigInjected.ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONVEDGE_RISING; sConfigInjected.AutoInjectedConv = DISABLE; @@ -119,16 +109,16 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive #endif } - uint32_t ranks[4]= {ADC_INJECTED_RANK_1, ADC_INJECTED_RANK_2, ADC_INJECTED_RANK_3, ADC_INJECTED_RANK_4}; + uint8_t channel_no = 0; for(int i=0; i<3; i++){ // skip if not set if (!_isset(cs_params->pins[i])) continue; - sConfigInjected.InjectedRank = ranks[i]; - sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i])); + sConfigInjected.InjectedRank = _getADCInjectedRank(channel_no++); + sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc.Instance); if (HAL_ADCEx_InjectedConfigChannel(&hadc, &sConfigInjected) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i])) ); + SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]) , hadc.Instance)); #endif return -1; } diff --git a/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_mcu.cpp b/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_mcu.cpp index ed58e8cb..be49adfe 100644 --- a/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_mcu.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_mcu.cpp @@ -96,16 +96,18 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ // function reading an ADC value and returning the read voltage float _readADCVoltageLowSide(const int pin, const void* cs_params){ + uint8_t channel_no = 0; for(int i=0; i < 3; i++){ if( pin == ((Stm32CurrentSenseParams*)cs_params)->pins[i]){ // found in the buffer if (use_adc_interrupt){ - return adc_val[_adcToIndex(((Stm32CurrentSenseParams*)cs_params)->adc_handle)][i] * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; + return adc_val[_adcToIndex(((Stm32CurrentSenseParams*)cs_params)->adc_handle)][channel_no] * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; }else{ // an optimized way to go from i to the channel i=0 -> channel 1, i=1 -> channel 2, i=2 -> channel 3 - uint32_t channel = (i == 0) ? ADC_INJECTED_RANK_1 : (i == 1) ? ADC_INJECTED_RANK_2 : ADC_INJECTED_RANK_3; + uint32_t channel = _getADCInjectedRank(channel_no); return HAL_ADCEx_InjectedGetValue(((Stm32CurrentSenseParams*)cs_params)->adc_handle, channel) * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; } } + if(_isset(((Stm32CurrentSenseParams*)cs_params)->pins[i])) channel_no++; } return 0; } diff --git a/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_hal.cpp b/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_hal.cpp index 5f905633..ec5ccb64 100644 --- a/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_hal.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_hal.cpp @@ -21,24 +21,9 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive { ADC_InjectionConfTypeDef sConfigInjected; - // check if all pins belong to the same ADC - ADC_TypeDef* adc_pin1 = _isset(cs_params->pins[0]) ? (ADC_TypeDef*)pinmap_peripheral(analogInputToPinName(cs_params->pins[0]), PinMap_ADC) : nullptr; - ADC_TypeDef* adc_pin2 = _isset(cs_params->pins[1]) ? (ADC_TypeDef*)pinmap_peripheral(analogInputToPinName(cs_params->pins[1]), PinMap_ADC) : nullptr; - ADC_TypeDef* adc_pin3 = _isset(cs_params->pins[2]) ? (ADC_TypeDef*)pinmap_peripheral(analogInputToPinName(cs_params->pins[2]), PinMap_ADC) : nullptr; - if ( ((adc_pin1 != adc_pin2) && (adc_pin1 && adc_pin2)) || - ((adc_pin2 != adc_pin3) && (adc_pin2 && adc_pin3)) || - ((adc_pin1 != adc_pin3) && (adc_pin1 && adc_pin3)) - ){ -#ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: ERR: Analog pins dont belong to the same ADC!"); -#endif - return -1; - } - - /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */ - hadc.Instance = (ADC_TypeDef *)pinmap_peripheral(analogInputToPinName(cs_params->pins[0]), PinMap_ADC); + hadc.Instance = _findBestADCForPins(3, cs_params->pins); if(hadc.Instance == ADC1) __HAL_RCC_ADC1_CLK_ENABLE(); #ifdef ADC2 // if defined ADC2 @@ -78,7 +63,12 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive /**Configures for the selected ADC injected channel its corresponding rank in the sequencer and its sample time */ - sConfigInjected.InjectedNbrOfConversion = _isset(cs_params->pins[2]) ? 3 : 2; + sConfigInjected.InjectedNbrOfConversion = 0; + for(int pin_no=0; pin_no<3; pin_no++){ + if(_isset(cs_params->pins[pin_no])){ + sConfigInjected.InjectedNbrOfConversion++; + } + } sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_3CYCLES; sConfigInjected.ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONVEDGE_RISINGFALLING; sConfigInjected.AutoInjectedConv = DISABLE; @@ -127,16 +117,16 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive #endif } - uint32_t ranks[4]= {ADC_INJECTED_RANK_1, ADC_INJECTED_RANK_2, ADC_INJECTED_RANK_3, ADC_INJECTED_RANK_4}; + uint8_t channel_no = 0; for(int i=0; i<3; i++){ // skip if not set if (!_isset(cs_params->pins[i])) continue; - sConfigInjected.InjectedRank = ranks[i]; - sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i])); + sConfigInjected.InjectedRank = _getADCInjectedRank(channel_no++); + sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc.Instance); if (HAL_ADCEx_InjectedConfigChannel(&hadc, &sConfigInjected) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i])) ); + SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]) , hadc.Instance)); #endif return -1; } diff --git a/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_mcu.cpp b/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_mcu.cpp index 7ff5bede..664262dc 100644 --- a/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_mcu.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_mcu.cpp @@ -79,16 +79,18 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ // function reading an ADC value and returning the read voltage float _readADCVoltageLowSide(const int pin, const void* cs_params){ + uint8_t channel_no = 0; for(int i=0; i < 3; i++){ if( pin == ((Stm32CurrentSenseParams*)cs_params)->pins[i]){ // found in the buffer #ifdef SIMPLEFOC_STM32_ADC_INTERRUPT - return adc_val[_adcToIndex(((Stm32CurrentSenseParams*)cs_params)->adc_handle)][i] * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; + return adc_val[_adcToIndex(((Stm32CurrentSenseParams*)cs_params)->adc_handle)][channel_no] * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; #else // an optimized way to go from i to the channel i=0 -> channel 1, i=1 -> channel 2, i=2 -> channel 3 - uint32_t channel = (i == 0) ? ADC_INJECTED_RANK_1 : (i == 1) ? ADC_INJECTED_RANK_2 : ADC_INJECTED_RANK_3; + uint32_t channel = _getADCInjectedRank(channel_no); return HAL_ADCEx_InjectedGetValue(((Stm32CurrentSenseParams*)cs_params)->adc_handle, channel) * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; #endif } + if(_isset(((Stm32CurrentSenseParams*)cs_params)->pins[i])) channel_no++; } return 0; } diff --git a/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_hal.cpp b/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_hal.cpp index a4c72680..df639932 100644 --- a/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_hal.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_hal.cpp @@ -22,26 +22,7 @@ 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); - - // check if all pins belong to the same ADC - ADC_TypeDef* adc_pin1 = _isset(cs_params->pins[0]) ? (ADC_TypeDef*)pinmap_peripheral(analogInputToPinName(cs_params->pins[0]), PinMap_ADC) : nullptr; - ADC_TypeDef* adc_pin2 = _isset(cs_params->pins[1]) ? (ADC_TypeDef*)pinmap_peripheral(analogInputToPinName(cs_params->pins[1]), PinMap_ADC) : nullptr; - ADC_TypeDef* adc_pin3 = _isset(cs_params->pins[2]) ? (ADC_TypeDef*)pinmap_peripheral(analogInputToPinName(cs_params->pins[2]), PinMap_ADC) : nullptr; - if ( ((adc_pin1 != adc_pin2) && (adc_pin1 && adc_pin2)) || - ((adc_pin2 != adc_pin3) && (adc_pin2 && adc_pin3)) || - ((adc_pin1 != adc_pin3) && (adc_pin1 && adc_pin3)) - ){ -#ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: ERR: Analog pins dont belong to the same ADC!"); -#endif - return -1; - } - - - /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) - */ - hadc.Instance = (ADC_TypeDef *)pinmap_peripheral(analogInputToPinName(cs_params->pins[0]), PinMap_ADC); + hadc.Instance = _findBestADCForPins(3, cs_params->pins); if(hadc.Instance == ADC1) { #ifdef __HAL_RCC_ADC1_CLK_ENABLE @@ -129,7 +110,12 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive /**Configures for the selected ADC injected channel its corresponding rank in the sequencer and its sample time */ - sConfigInjected.InjectedNbrOfConversion = _isset(cs_params->pins[2]) ? 3 : 2; + sConfigInjected.InjectedNbrOfConversion = 0; + for(int pin_no=0; pin_no<3; pin_no++){ + if(_isset(cs_params->pins[pin_no])){ + sConfigInjected.InjectedNbrOfConversion++; + } + } sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_2CYCLES_5; sConfigInjected.ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONV_EDGE_RISING; sConfigInjected.AutoInjectedConv = DISABLE; @@ -174,16 +160,16 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive #endif } - uint32_t ranks[4]= {ADC_INJECTED_RANK_1, ADC_INJECTED_RANK_2, ADC_INJECTED_RANK_3, ADC_INJECTED_RANK_4}; + uint8_t channel_no = 0; for(int i=0; i<3; i++){ // skip if not set if (!_isset(cs_params->pins[i])) continue; - sConfigInjected.InjectedRank = ranks[i]; - sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i])); + sConfigInjected.InjectedRank = _getADCInjectedRank(channel_no++); + sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc.Instance); if (HAL_ADCEx_InjectedConfigChannel(&hadc, &sConfigInjected) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i])) ); + SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]) , hadc.Instance)); #endif return -1; } diff --git a/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_mcu.cpp b/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_mcu.cpp index 67585edc..5db5cea7 100644 --- a/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_mcu.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_mcu.cpp @@ -133,16 +133,18 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ // function reading an ADC value and returning the read voltage float _readADCVoltageLowSide(const int pin, const void* cs_params){ + uint8_t channel_no = 0; for(int i=0; i < 3; i++){ if( pin == ((Stm32CurrentSenseParams*)cs_params)->pins[i]){ // found in the buffer if (use_adc_interrupt){ - return adc_val[_adcToIndex(((Stm32CurrentSenseParams*)cs_params)->adc_handle)][i] * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; + return adc_val[_adcToIndex(((Stm32CurrentSenseParams*)cs_params)->adc_handle)][channel_no] * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; }else{ // an optimized way to go from i to the channel i=0 -> channel 1, i=1 -> channel 2, i=2 -> channel 3 - uint32_t channel = (i == 0) ? ADC_INJECTED_RANK_1 : (i == 1) ? ADC_INJECTED_RANK_2 : ADC_INJECTED_RANK_3; + uint32_t channel = _getADCInjectedRank(channel_no); return HAL_ADCEx_InjectedGetValue(((Stm32CurrentSenseParams*)cs_params)->adc_handle, channel) * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; } } + if(_isset(((Stm32CurrentSenseParams*)cs_params)->pins[i])) channel_no++; } return 0; } @@ -161,6 +163,7 @@ extern "C" { adc_val[adc_index][0]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_1); adc_val[adc_index][1]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_2); adc_val[adc_index][2]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_3); + adc_val[adc_index][3]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_4); } } 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 7d8923fd..3d1352b9 100644 --- a/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_hal.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_hal.cpp @@ -20,23 +20,9 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive { ADC_InjectionConfTypeDef sConfigInjected; - // check if all pins belong to the same ADC - ADC_TypeDef* adc_pin1 = _isset(cs_params->pins[0]) ? (ADC_TypeDef*)pinmap_peripheral(analogInputToPinName(cs_params->pins[0]), PinMap_ADC) : nullptr; - ADC_TypeDef* adc_pin2 = _isset(cs_params->pins[1]) ? (ADC_TypeDef*)pinmap_peripheral(analogInputToPinName(cs_params->pins[1]), PinMap_ADC) : nullptr; - ADC_TypeDef* adc_pin3 = _isset(cs_params->pins[2]) ? (ADC_TypeDef*)pinmap_peripheral(analogInputToPinName(cs_params->pins[2]), PinMap_ADC) : nullptr; - if ( ((adc_pin1 != adc_pin2) && (adc_pin1 && adc_pin2)) || - ((adc_pin2 != adc_pin3) && (adc_pin2 && adc_pin3)) || - ((adc_pin1 != adc_pin3) && (adc_pin1 && adc_pin3)) - ){ -#ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: ERR: Analog pins dont belong to the same ADC!"); -#endif - return -1; - } - /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */ - hadc.Instance = (ADC_TypeDef *)pinmap_peripheral(analogInputToPinName(cs_params->pins[0]), PinMap_ADC); + hadc.Instance = _findBestADCForPins(3, cs_params->pins); if(hadc.Instance == ADC1) { #ifdef __HAL_RCC_ADC1_CLK_ENABLE @@ -91,7 +77,7 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive #endif else{ #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: ERR: Pin does not belong to any ADC!"); + SIMPLEFOC_DEBUG("STM32-CS: ERR: Cannot find a common ADC for the pins!"); #endif return -1; // error not a valid ADC instance } @@ -168,16 +154,16 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive } - uint32_t ranks[4]= {ADC_INJECTED_RANK_1, ADC_INJECTED_RANK_2, ADC_INJECTED_RANK_3, ADC_INJECTED_RANK_4}; + uint8_t channel_no = 0; for(int i=0; i<3; i++){ // skip if not set if (!_isset(cs_params->pins[i])) continue; - sConfigInjected.InjectedRank = ranks[i]; - sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i])); + sConfigInjected.InjectedRank = _getADCInjectedRank(channel_no++); + sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc.Instance); if (HAL_ADCEx_InjectedConfigChannel(&hadc, &sConfigInjected) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i])) ); + SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc.Instance)); #endif return -1; } diff --git a/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_mcu.cpp b/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_mcu.cpp index b2b9a264..4a6e529c 100644 --- a/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_mcu.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_mcu.cpp @@ -129,16 +129,18 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ // function reading an ADC value and returning the read voltage float _readADCVoltageLowSide(const int pin, const void* cs_params){ + uint8_t channel_no = 0; for(int i=0; i < 3; i++){ if( pin == ((Stm32CurrentSenseParams*)cs_params)->pins[i]){ // found in the buffer if (use_adc_interrupt){ - return adc_val[_adcToIndex(((Stm32CurrentSenseParams*)cs_params)->adc_handle)][i] * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; + return adc_val[_adcToIndex(((Stm32CurrentSenseParams*)cs_params)->adc_handle)][channel_no] * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; }else{ // an optimized way to go from i to the channel i=0 -> channel 1, i=1 -> channel 2, i=2 -> channel 3 - uint32_t channel = (i == 0) ? ADC_INJECTED_RANK_1 : (i == 1) ? ADC_INJECTED_RANK_2 : ADC_INJECTED_RANK_3; + uint32_t channel = _getADCInjectedRank(channel_no); return HAL_ADCEx_InjectedGetValue(((Stm32CurrentSenseParams*)cs_params)->adc_handle,channel) * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; } } + if(_isset(((Stm32CurrentSenseParams*)cs_params)->pins[i])) channel_no++; } return 0; } From 9bb6cfb19827895c7bd1d6dc1bf4ba151f9b3e17 Mon Sep 17 00:00:00 2001 From: gospar Date: Fri, 21 Mar 2025 11:57:31 +0100 Subject: [PATCH 11/15] remove some debugging --- .../hardware_specific/stm32/stm32_adc_utils.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 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 95eb3e8f..19e31cc1 100644 --- a/src/current_sense/hardware_specific/stm32/stm32_adc_utils.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32_adc_utils.cpp @@ -317,14 +317,7 @@ uint32_t _getADCChannel(PinName pin, ADC_TypeDef *AdcHandle ) for (int i = first_ind; i <= last_ind; i++) { if (PinMap_ADC[i].peripheral == AdcHandle) { channel =_getADCChannelFromPinMap(PinMap_ADC[i].pin); - -// #ifdef SIMPLEFOC_STM32_DEBUG - SimpleFOCDebug::print("STM32-CS: Configuring ADC"); - SimpleFOCDebug::print(_adcToIndex(AdcHandle)+1); - SimpleFOCDebug::print(" channel: "); - SimpleFOCDebug::println((int)STM_PIN_CHANNEL(pinmap_function(PinMap_ADC[i].pin, PinMap_ADC))); -// #endif - + SIMPLEFOC_DEBUG("STM32-CS: ADC channel: ", (int)STM_PIN_CHANNEL(pinmap_function(PinMap_ADC[i].pin, PinMap_ADC))); break; } } From 2857d3ea67e36323694d801b78490df9984bdc29 Mon Sep 17 00:00:00 2001 From: gospar Date: Fri, 21 Mar 2025 12:11:41 +0100 Subject: [PATCH 12/15] h7 update for auto-search --- .../stm32/stm32h7/stm32h7_hal.cpp | 37 ++-- .../stm32/stm32h7/stm32h7_hal.h | 2 +- .../stm32/stm32h7/stm32h7_mcu.cpp | 8 +- .../stm32/stm32h7/stm32h7_utils.cpp | 159 +----------------- .../stm32/stm32h7/stm32h7_utils.h | 30 ---- 5 files changed, 21 insertions(+), 215 deletions(-) delete mode 100644 src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_utils.h 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 b572a5aa..33d20c67 100644 --- a/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_hal.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_hal.cpp @@ -5,7 +5,6 @@ //#define SIMPLEFOC_STM32_DEBUG #include "../../../../communication/SimpleFOCDebug.h" -#define _TRGO_NOT_AVAILABLE 12345 ADC_HandleTypeDef hadc; @@ -21,23 +20,10 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive { ADC_InjectionConfTypeDef sConfigInjected; - // check if all pins belong to the same ADC - ADC_TypeDef* adc_pin1 = _isset(cs_params->pins[0]) ? (ADC_TypeDef*)pinmap_peripheral(analogInputToPinName(cs_params->pins[0]), PinMap_ADC) : nullptr; - ADC_TypeDef* adc_pin2 = _isset(cs_params->pins[1]) ? (ADC_TypeDef*)pinmap_peripheral(analogInputToPinName(cs_params->pins[1]), PinMap_ADC) : nullptr; - ADC_TypeDef* adc_pin3 = _isset(cs_params->pins[2]) ? (ADC_TypeDef*)pinmap_peripheral(analogInputToPinName(cs_params->pins[2]), PinMap_ADC) : nullptr; - if ( ((adc_pin1 != adc_pin2) && (adc_pin1 && adc_pin2)) || - ((adc_pin2 != adc_pin3) && (adc_pin2 && adc_pin3)) || - ((adc_pin1 != adc_pin3) && (adc_pin1 && adc_pin3)) - ){ -#ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: ERR: Analog pins dont belong to the same ADC!"); -#endif - return -1; - } /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */ - hadc.Instance = (ADC_TypeDef *)pinmap_peripheral(analogInputToPinName(cs_params->pins[0]), PinMap_ADC); + hadc.Instance = _findBestADCForPins(3, cs_params->pins); if(hadc.Instance == ADC1) __HAL_RCC_ADC12_CLK_ENABLE(); #ifdef ADC2 // if defined ADC2 @@ -48,7 +34,7 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive #endif else{ #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: ERR: Pin does not belong to any ADC!"); + SIMPLEFOC_DEBUG("STM32-CS: ERR: Cannot find a common ADC for the pins!"); #endif return -1; // error not a valid ADC instance } @@ -91,7 +77,12 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive /**Configures for the selected ADC injected channel its corresponding rank in the sequencer and its sample time */ - sConfigInjected.InjectedNbrOfConversion = _isset(cs_params->pins[2]) ? 3 : 2; + sConfigInjected.InjectedNbrOfConversion = 0; + for(int pin_no=0; pin_no<3; pin_no++){ + if(_isset(cs_params->pins[pin_no])){ + sConfigInjected.InjectedNbrOfConversion++; + } + } // if ADC1 or ADC2 if(hadc.Instance == ADC1 || hadc.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 @@ -147,21 +138,21 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive #endif } - uint32_t ranks[4] = {ADC_INJECTED_RANK_1, ADC_INJECTED_RANK_2, ADC_INJECTED_RANK_3, ADC_INJECTED_RANK_4}; + uint8_t channel_no = 0; for(int i=0; i<3; i++){ // skip if not set - if (!_isset(cs_params->pins[i])) continue; - sConfigInjected.InjectedRank = ranks[i]; - sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i])); + 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){ #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i])) ); + SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]) , hadc.Instance)); #endif return -1; } } - delay(1000); #ifdef SIMPLEFOC_STM32_ADC_INTERRUPT // enable interrupt diff --git a/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_hal.h b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_hal.h index 623f2b85..70a4b762 100644 --- a/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_hal.h +++ b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_hal.h @@ -4,8 +4,8 @@ #if defined(STM32H7xx) #include "stm32h7xx_hal.h" +#include "../stm32_adc_utils.h" #include "../stm32_mcu.h" -#include "stm32h7_utils.h" int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* driver_params); int _adc_gpio_init(Stm32CurrentSenseParams* cs_params, const int pinA, const int pinB, const int pinC); diff --git a/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_mcu.cpp b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_mcu.cpp index fe7f16ed..94869c54 100644 --- a/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_mcu.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_mcu.cpp @@ -6,8 +6,8 @@ #include "../../../../drivers/hardware_specific/stm32/stm32_mcu.h" #include "../../../hardware_api.h" #include "../stm32_mcu.h" +#include "../stm32_adc_utils.h" #include "stm32h7_hal.h" -#include "stm32h7_utils.h" #include "Arduino.h" @@ -83,16 +83,18 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ // function reading an ADC value and returning the read voltage float _readADCVoltageLowSide(const int pin, const void* cs_params){ + uint8_t channel_no = 0; for(int i=0; i < 3; i++){ if( pin == ((Stm32CurrentSenseParams*)cs_params)->pins[i]){ // found in the buffer #ifdef SIMPLEFOC_STM32_ADC_INTERRUPT - return adc_val[_adcToIndex(((Stm32CurrentSenseParams*)cs_params)->adc_handle)][i] * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; + return adc_val[_adcToIndex(((Stm32CurrentSenseParams*)cs_params)->adc_handle)][channel_no] * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; #else // an optimized way to go from i to the channel i=0 -> channel 1, i=1 -> channel 2, i=2 -> channel 3 - uint32_t channel = (i == 0) ? ADC_INJECTED_RANK_1 : (i == 1) ? ADC_INJECTED_RANK_2 : ADC_INJECTED_RANK_3; + uint32_t channel = _getADCInjectedRank(channel_no); return HAL_ADCEx_InjectedGetValue(((Stm32CurrentSenseParams*)cs_params)->adc_handle, channel) * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; #endif } + if(_isset(((Stm32CurrentSenseParams*)cs_params)->pins[i])) channel_no++; } return 0; } diff --git a/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_utils.cpp b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_utils.cpp index 41db1d9a..9b16263f 100644 --- a/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_utils.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_utils.cpp @@ -1,146 +1,10 @@ -#include "stm32h7_utils.h" +#include "../stm32_adc_utils.h" #if defined(STM32H7xx) /* Exported Functions */ -PinName analog_to_pin(uint32_t pin) { - PinName pin_name = analogInputToPinName(pin); - if (pin_name == NC) { - return (PinName) pin; - } - return pin_name; -} - - -/** - * @brief Return ADC HAL channel linked to a PinName - * @param pin: PinName - * @retval Valid HAL channel - */ -uint32_t _getADCChannel(PinName pin) -{ - uint32_t function = pinmap_function(pin, PinMap_ADC); - uint32_t channel = 0; - switch (STM_PIN_CHANNEL(function)) { -#ifdef ADC_CHANNEL_0 - case 0: - channel = ADC_CHANNEL_0; - break; -#endif - case 1: - channel = ADC_CHANNEL_1; - break; - case 2: - channel = ADC_CHANNEL_2; - break; - case 3: - channel = ADC_CHANNEL_3; - break; - case 4: - channel = ADC_CHANNEL_4; - break; - case 5: - channel = ADC_CHANNEL_5; - break; - case 6: - channel = ADC_CHANNEL_6; - break; - case 7: - channel = ADC_CHANNEL_7; - break; - case 8: - channel = ADC_CHANNEL_8; - break; - case 9: - channel = ADC_CHANNEL_9; - break; - case 10: - channel = ADC_CHANNEL_10; - break; - case 11: - channel = ADC_CHANNEL_11; - break; - case 12: - channel = ADC_CHANNEL_12; - break; - case 13: - channel = ADC_CHANNEL_13; - break; - case 14: - channel = ADC_CHANNEL_14; - break; - case 15: - channel = ADC_CHANNEL_15; - break; -#ifdef ADC_CHANNEL_16 - case 16: - channel = ADC_CHANNEL_16; - break; -#endif - case 17: - channel = ADC_CHANNEL_17; - break; -#ifdef ADC_CHANNEL_18 - case 18: - channel = ADC_CHANNEL_18; - break; -#endif -#ifdef ADC_CHANNEL_19 - case 19: - channel = ADC_CHANNEL_19; - break; -#endif -#ifdef ADC_CHANNEL_20 - case 20: - channel = ADC_CHANNEL_20; - break; - case 21: - channel = ADC_CHANNEL_21; - break; - case 22: - channel = ADC_CHANNEL_22; - break; - case 23: - channel = ADC_CHANNEL_23; - break; -#ifdef ADC_CHANNEL_24 - case 24: - channel = ADC_CHANNEL_24; - break; - case 25: - channel = ADC_CHANNEL_25; - break; - case 26: - channel = ADC_CHANNEL_26; - break; -#ifdef ADC_CHANNEL_27 - case 27: - channel = ADC_CHANNEL_27; - break; - case 28: - channel = ADC_CHANNEL_28; - break; - case 29: - channel = ADC_CHANNEL_29; - break; - case 30: - channel = ADC_CHANNEL_30; - break; - case 31: - channel = ADC_CHANNEL_31; - break; -#endif -#endif -#endif - default: - _Error_Handler("ADC: Unknown adc channel", (int)(STM_PIN_CHANNEL(function))); - break; - } - return channel; -} - // timer to injected TRGO // https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32H7xx_HAL_Driver/Inc/stm32h7xx_hal_adc_ex.h#L235 uint32_t _timerToInjectedTRGO(TIM_HandleTypeDef* timer){ @@ -216,25 +80,4 @@ uint32_t _timerToRegularTRGO(TIM_HandleTypeDef* timer){ return _TRGO_NOT_AVAILABLE; } - -int _adcToIndex(ADC_TypeDef *AdcHandle){ - if(AdcHandle == ADC1) return 0; -#ifdef ADC2 // if ADC2 exists - else if(AdcHandle == ADC2) return 1; -#endif -#ifdef ADC3 // if ADC3 exists - else if(AdcHandle == ADC3) return 2; -#endif -#ifdef ADC4 // if ADC4 exists - else if(AdcHandle == ADC4) return 3; -#endif -#ifdef ADC5 // if ADC5 exists - else if(AdcHandle == ADC5) return 4; -#endif - return 0; -} -int _adcToIndex(ADC_HandleTypeDef *AdcHandle){ - return _adcToIndex(AdcHandle->Instance); -} - #endif \ No newline at end of file diff --git a/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_utils.h b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_utils.h deleted file mode 100644 index 22dfbed1..00000000 --- a/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_utils.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include "Arduino.h" - -#if defined(STM32H7xx) - -#define _TRGO_NOT_AVAILABLE 12345 - - -/* Exported Functions */ -/** - * @brief Return ADC HAL channel linked to a PinName - * @param pin: PinName - * @retval Valid HAL channel - */ -uint32_t _getADCChannel(PinName pin); - -// timer to injected TRGO -// https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc_ex.h#L179 -uint32_t _timerToInjectedTRGO(TIM_HandleTypeDef* timer); - -// timer to regular TRGO -// https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc.h#L331 -uint32_t _timerToRegularTRGO(TIM_HandleTypeDef* timer); - -// function returning index of the ADC instance -int _adcToIndex(ADC_HandleTypeDef *AdcHandle); -int _adcToIndex(ADC_TypeDef *AdcHandle); - -#endif \ No newline at end of file From d8fac13074314e063ec4528a84cba2e0a040571c Mon Sep 17 00:00:00 2001 From: gospar Date: Fri, 21 Mar 2025 12:18:27 +0100 Subject: [PATCH 13/15] f1 update --- .../stm32/stm32_adc_utils.cpp | 2 +- .../stm32/stm32f1/stm32f1_hal.cpp | 35 +--------------- .../stm32/stm32f1/stm32f1_utils.cpp | 40 +++++++++++++++++++ 3 files changed, 42 insertions(+), 35 deletions(-) create mode 100644 src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_utils.cpp 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 19e31cc1..33774a55 100644 --- a/src/current_sense/hardware_specific/stm32/stm32_adc_utils.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32_adc_utils.cpp @@ -1,6 +1,6 @@ #include "stm32_adc_utils.h" -#if defined(_STM32_DEF_) +#if defined(_STM32_DEF_) // for searching the best ADCs, we need to know the number of ADCs // it might be better to use some HAL variable for example ADC_COUNT 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 d9e88ca0..5cd94a6a 100644 --- a/src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_hal.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_hal.cpp @@ -3,42 +3,9 @@ #if defined(STM32F1xx) #include "../../../../communication/SimpleFOCDebug.h" +#include "../stm32_adc_utils.h" #define _TRGO_NOT_AVAILABLE 12345 -// timer to injected TRGO -// https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_adc_ex.h#L215 -uint32_t _timerToInjectedTRGO(TIM_HandleTypeDef* timer){ - if(timer->Instance == TIM1) - return ADC_EXTERNALTRIGINJECCONV_T1_TRGO; -#ifdef TIM2 // if defined timer 2 - else if(timer->Instance == TIM2) - return ADC_EXTERNALTRIGINJECCONV_T2_TRGO; -#endif -#ifdef TIM4 // if defined timer 4 - else if(timer->Instance == TIM4) - return ADC_EXTERNALTRIGINJECCONV_T4_TRGO; -#endif -#ifdef TIM5 // if defined timer 5 - else if(timer->Instance == TIM5) - return ADC_EXTERNALTRIGINJECCONV_T5_TRGO; -#endif - else - return _TRGO_NOT_AVAILABLE; -} - -// timer to regular TRGO -// https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_adc_ex.h#L215 -uint32_t _timerToRegularTRGO(TIM_HandleTypeDef* timer){ - if(timer->Instance == TIM3) - return ADC_EXTERNALTRIGCONV_T3_TRGO; -#ifdef TIM8 // if defined timer 8 - else if(timer->Instance == TIM8) - return ADC_EXTERNALTRIGCONV_T8_TRGO; -#endif - else - return _TRGO_NOT_AVAILABLE; -} - ADC_HandleTypeDef hadc; /** diff --git a/src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_utils.cpp b/src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_utils.cpp new file mode 100644 index 00000000..8cd6eb96 --- /dev/null +++ b/src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_utils.cpp @@ -0,0 +1,40 @@ +#include "../stm32_adc_utils.h" + +#if defined(STM32F1xx) + + +// timer to injected TRGO +// https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_adc_ex.h#L215 +uint32_t _timerToInjectedTRGO(TIM_HandleTypeDef* timer){ + if(timer->Instance == TIM1) + return ADC_EXTERNALTRIGINJECCONV_T1_TRGO; +#ifdef TIM2 // if defined timer 2 + else if(timer->Instance == TIM2) + return ADC_EXTERNALTRIGINJECCONV_T2_TRGO; +#endif +#ifdef TIM4 // if defined timer 4 + else if(timer->Instance == TIM4) + return ADC_EXTERNALTRIGINJECCONV_T4_TRGO; +#endif +#ifdef TIM5 // if defined timer 5 + else if(timer->Instance == TIM5) + return ADC_EXTERNALTRIGINJECCONV_T5_TRGO; +#endif + else + return _TRGO_NOT_AVAILABLE; +} + +// timer to regular TRGO +// https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_adc_ex.h#L215 +uint32_t _timerToRegularTRGO(TIM_HandleTypeDef* timer){ + if(timer->Instance == TIM3) + return ADC_EXTERNALTRIGCONV_T3_TRGO; +#ifdef TIM8 // if defined timer 8 + else if(timer->Instance == TIM8) + return ADC_EXTERNALTRIGCONV_T8_TRGO; +#endif + else + return _TRGO_NOT_AVAILABLE; +} + +#endif \ No newline at end of file From b9b9cf3758fd238c22c9524e0ace3af206505f53 Mon Sep 17 00:00:00 2001 From: gospar Date: Fri, 21 Mar 2025 12:21:01 +0100 Subject: [PATCH 14/15] restructuring for f1 --- .../stm32/stm32f1/stm32f1_hal.cpp | 18 ++++++++++++------ .../stm32/stm32f1/stm32f1_mcu.cpp | 18 +++++------------- 2 files changed, 17 insertions(+), 19 deletions(-) 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 5cd94a6a..5378fb1a 100644 --- a/src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_hal.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_hal.cpp @@ -22,7 +22,8 @@ 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 = (ADC_TypeDef *)pinmap_peripheral(analogInputToPinName(cs_params->pins[0]), PinMap_ADC); + hadc.Instance = _findBestADCForPins(3, cs_params->pins); + if(hadc.Instance == ADC1) __HAL_RCC_ADC1_CLK_ENABLE(); #ifdef ADC2 // if defined ADC2 else if(hadc.Instance == ADC2) __HAL_RCC_ADC2_CLK_ENABLE(); @@ -49,7 +50,12 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive /**Configures for the selected ADC injected channel its corresponding rank in the sequencer and its sample time */ - sConfigInjected.InjectedNbrOfConversion = _isset(cs_params->pins[2]) ? 3 : 2; + sConfigInjected.InjectedNbrOfConversion = 0; + for(int pin_no=0; pin_no<3; pin_no++){ + if(_isset(cs_params->pins[pin_no])){ + sConfigInjected.InjectedNbrOfConversion++; + } + } sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_1CYCLE_5; sConfigInjected.AutoInjectedConv = DISABLE; sConfigInjected.InjectedDiscontinuousConvMode = DISABLE; @@ -90,16 +96,16 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive } - uint32_t ranks[4]= {ADC_INJECTED_RANK_1, ADC_INJECTED_RANK_2, ADC_INJECTED_RANK_3, ADC_INJECTED_RANK_4}; + uint8_t channel_no = 0; for(int i=0; i<3; i++){ // skip if not set if (!_isset(cs_params->pins[i])) continue; - sConfigInjected.InjectedRank = ranks[i]; - sConfigInjected.InjectedChannel = STM_PIN_CHANNEL(pinmap_function(analogInputToPinName(cs_params->pins[i]), PinMap_ADC)); + sConfigInjected.InjectedRank = _getADCInjectedRank(channel_no++); + sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc.Instance); if (HAL_ADCEx_InjectedConfigChannel(&hadc, &sConfigInjected) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)STM_PIN_CHANNEL(pinmap_function(analogInputToPinName(cs_params->pins[i]), PinMap_ADC))); + SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]) , hadc.Instance)); #endif return -1; } diff --git a/src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_mcu.cpp b/src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_mcu.cpp index b52b48bd..6d69dc89 100644 --- a/src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_mcu.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_mcu.cpp @@ -5,6 +5,7 @@ #include "../../../../drivers/hardware_api.h" #include "../../../../drivers/hardware_specific/stm32/stm32_mcu.h" #include "../../../hardware_api.h" +#include "../stm32_adc_utils.h" #include "../stm32_mcu.h" #include "stm32f1_hal.h" #include "Arduino.h" @@ -25,17 +26,6 @@ uint8_t use_adc_interrupt = 1; uint8_t use_adc_interrupt = 0; #endif -int _adcToIndex(ADC_HandleTypeDef *AdcHandle){ - if(AdcHandle->Instance == ADC1) return 0; -#ifdef ADC2 // if ADC2 exists - else if(AdcHandle->Instance == ADC2) return 1; -#endif -#ifdef ADC3 // if ADC3 exists - else if(AdcHandle->Instance == ADC3) return 2; -#endif - return 0; -} - void* _configureADCLowSide(const void* driver_params, const int pinA, const int pinB, const int pinC){ Stm32CurrentSenseParams* cs_params= new Stm32CurrentSenseParams { @@ -107,16 +97,18 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ // function reading an ADC value and returning the read voltage float _readADCVoltageLowSide(const int pin, const void* cs_params){ + uint8_t channel_no = 0; for(int i=0; i < 3; i++){ if( pin == ((Stm32CurrentSenseParams*)cs_params)->pins[i]){ // found in the buffer if (use_adc_interrupt){ - return adc_val[_adcToIndex(((Stm32CurrentSenseParams*)cs_params)->adc_handle)][i] * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; + return adc_val[_adcToIndex(((Stm32CurrentSenseParams*)cs_params)->adc_handle)][channel_no] * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; }else{ // an optimized way to go from i to the channel i=0 -> channel 1, i=1 -> channel 2, i=2 -> channel 3 - uint32_t channel = (i == 0) ? ADC_INJECTED_RANK_1 : (i == 1) ? ADC_INJECTED_RANK_2 : ADC_INJECTED_RANK_3;; + uint32_t channel = _getADCInjectedRank(channel_no); return HAL_ADCEx_InjectedGetValue(((Stm32CurrentSenseParams*)cs_params)->adc_handle, channel) * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; } } + if(_isset(((Stm32CurrentSenseParams*)cs_params)->pins[i])) channel_no++; } return 0; } From 302719c14102e286158472d4de04b98f3efabc97 Mon Sep 17 00:00:00 2001 From: gospar Date: Tue, 29 Apr 2025 17:12:23 +0200 Subject: [PATCH 15/15] tested h7 low-side, added repetition counterhandling --- .../stm32/stm32f4/stm32f4_utils.cpp | 9 +-- .../stm32/stm32h7/stm32h7_hal.cpp | 5 +- .../stm32/stm32h7/stm32h7_mcu.cpp | 61 +++++++++++++++---- 3 files changed, 55 insertions(+), 20 deletions(-) diff --git a/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_utils.cpp b/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_utils.cpp index 23d4b0d3..22a54f85 100644 --- a/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_utils.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_utils.cpp @@ -26,18 +26,19 @@ uint32_t _timerToInjectedTRGO(TIM_HandleTypeDef* timer){ // timer to regular TRGO // https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc.h#L331 uint32_t _timerToRegularTRGO(TIM_HandleTypeDef* timer){ +#ifdef TIM2 // if defined timer 2 if(timer->Instance == TIM2) return ADC_EXTERNALTRIGCONV_T2_TRGO; +#endif #ifdef TIM3 // if defined timer 3 - else if(timer->Instance == TIM3) + if(timer->Instance == TIM3) return ADC_EXTERNALTRIGCONV_T3_TRGO; #endif #ifdef TIM8 // if defined timer 8 - else if(timer->Instance == TIM8) + if(timer->Instance == TIM8) return ADC_EXTERNALTRIGCONV_T8_TRGO; #endif - else - return _TRGO_NOT_AVAILABLE; + return _TRGO_NOT_AVAILABLE; } #endif \ No newline at end of file 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 33d20c67..61ae2de3 100644 --- a/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_hal.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_hal.cpp @@ -86,7 +86,7 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive // if ADC1 or ADC2 if(hadc.Instance == ADC1 || hadc.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_2CYCLE_5; + sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_1CYCLE_5; }else { // adc3 // https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32H7xx_HAL_Driver/Inc/stm32h7xx_hal_adc.h#L673 @@ -196,13 +196,12 @@ int _adc_gpio_init(Stm32CurrentSenseParams* cs_params, const int pinA, const int return 0; } -#ifdef SIMPLEFOC_STM32_ADC_INTERRUPT + extern "C" { void ADC_IRQHandler(void) { HAL_ADC_IRQHandler(&hadc); } } -#endif #endif \ No newline at end of file diff --git a/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_mcu.cpp b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_mcu.cpp index 94869c54..f826e69d 100644 --- a/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_mcu.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_mcu.cpp @@ -22,6 +22,12 @@ bool needs_downsample[3] = {1}; // downsampling variable - per adc (3) uint8_t tim_downsample[3] = {1}; +#ifdef SIMPLEFOC_STM32_ADC_INTERRUPT +uint8_t use_adc_interrupt = 1; +#else +uint8_t use_adc_interrupt = 0; +#endif + void* _configureADCLowSide(const void* driver_params, const int pinA, const int pinB, const int pinC){ Stm32CurrentSenseParams* cs_params= new Stm32CurrentSenseParams { @@ -56,19 +62,47 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ cs_params->timer_handle->Instance->CNT = cs_params->timer_handle->Instance->ARR; // remember that this timer has repetition counter - no need to downasmple needs_downsample[_adcToIndex(cs_params->adc_handle)] = 0; + }else{ + if(!use_adc_interrupt){ + // If the timer has no repetition counter, it needs to use the interrupt to downsample for low side sensing + use_adc_interrupt = 1; + #ifdef SIMPLEFOC_STM32_DEBUG + SIMPLEFOC_DEBUG("STM32-CS: timer has no repetition counter, ADC interrupt has to be used"); + #endif + } } + // set the trigger output event LL_TIM_SetTriggerOutput(cs_params->timer_handle->Instance, LL_TIM_TRGO_UPDATE); // Start the adc calibration - HAL_ADCEx_Calibration_Start(cs_params->adc_handle, ADC_CALIB_OFFSET_LINEARITY, ADC_SINGLE_ENDED); + if(HAL_ADCEx_Calibration_Start(cs_params->adc_handle, ADC_CALIB_OFFSET_LINEARITY, ADC_SINGLE_ENDED) != HAL_OK){ + #ifdef SIMPLEFOC_STM32_DEBUG + SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot calibrate ADC!"); + #endif + return SIMPLEFOC_CURRENT_SENSE_INIT_FAILED; + } // start the adc - #ifdef SIMPLEFOC_STM32_ADC_INTERRUPT - HAL_ADCEx_InjectedStart_IT(cs_params->adc_handle); - #else - HAL_ADCEx_InjectedStart(cs_params->adc_handle); - #endif + if(use_adc_interrupt){ + // enable interrupt + HAL_NVIC_SetPriority(ADC_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(ADC_IRQn); + + if(HAL_ADCEx_InjectedStart_IT(cs_params->adc_handle) != HAL_OK){ + #ifdef SIMPLEFOC_STM32_DEBUG + SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot start injected channels in interrupt mode!"); + #endif + return SIMPLEFOC_CURRENT_SENSE_INIT_FAILED; + } + }else{ + if(HAL_ADCEx_InjectedStart(cs_params->adc_handle) != HAL_OK){ + #ifdef SIMPLEFOC_STM32_DEBUG + SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot start injected channels!"); + #endif + return SIMPLEFOC_CURRENT_SENSE_INIT_FAILED; + } + } // restart all the timers of the driver @@ -83,23 +117,25 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ // function reading an ADC value and returning the read voltage float _readADCVoltageLowSide(const int pin, const void* cs_params){ + // print all values in the buffer + // SIMPLEFOC_DEBUG("adc_a:", (int)HAL_ADCEx_InjectedGetValue(((Stm32CurrentSenseParams*)cs_params)->adc_handle, _getADCInjectedRank(0))); + // SIMPLEFOC_DEBUG("adc_b:", (int)HAL_ADCEx_InjectedGetValue(((Stm32CurrentSenseParams*)cs_params)->adc_handle, _getADCInjectedRank(1))); uint8_t channel_no = 0; for(int i=0; i < 3; i++){ if( pin == ((Stm32CurrentSenseParams*)cs_params)->pins[i]){ // found in the buffer - #ifdef SIMPLEFOC_STM32_ADC_INTERRUPT + if (use_adc_interrupt){ return adc_val[_adcToIndex(((Stm32CurrentSenseParams*)cs_params)->adc_handle)][channel_no] * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; - #else + }else{ // an optimized way to go from i to the channel i=0 -> channel 1, i=1 -> channel 2, i=2 -> channel 3 uint32_t channel = _getADCInjectedRank(channel_no); return HAL_ADCEx_InjectedGetValue(((Stm32CurrentSenseParams*)cs_params)->adc_handle, channel) * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; - #endif + } } if(_isset(((Stm32CurrentSenseParams*)cs_params)->pins[i])) channel_no++; } return 0; } -#ifdef SIMPLEFOC_STM32_ADC_INTERRUPT extern "C" { void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *AdcHandle){ @@ -107,8 +143,8 @@ extern "C" { int adc_index = _adcToIndex(AdcHandle); // if the timer han't repetition counter - downsample two times - if( needs_downsample[adc_index] && tim_downsample[adc_index]++ > 0) { - tim_downsample[adc_index] = 0; + if( needs_downsample[adc_index] && tim_downsample[adc_index]++ > 1) { + tim_downsample[adc_index] = 1; return; } @@ -117,6 +153,5 @@ extern "C" { adc_val[adc_index][2]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_3); } } -#endif #endif \ No newline at end of file