SimpleFOClibrary 2.4.0
Loading...
Searching...
No Matches
stm32h7_hal.cpp
Go to the documentation of this file.
1#include "stm32h7_hal.h"
2
3#if defined(STM32H7xx)
4
5//#define SIMPLEFOC_STM32_DEBUG
6
7#include "../../../../communication/SimpleFOCDebug.h"
8
9// pointer to the ADC handles used in the project
10ADC_HandleTypeDef hadc[ADC_COUNT] = {0};
11
12ADC_HandleTypeDef* _get_adc_handles(){
13 return hadc;
14}
15
16
17/**
18 * Function initializing the ADC for the regular channels for the low-side current sensing
19 *
20 * @param adc_instance - ADC instance to initialize
21 *
22 * @return int - 0 if success
23 */
24int _adc_init_regular(ADC_TypeDef* adc_instance)
25{
26
27
28 /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
29 */
30 if(adc_instance == ADC1) __HAL_RCC_ADC12_CLK_ENABLE();
31#ifdef ADC2 // if defined ADC2
32 else if(adc_instance == ADC2) __HAL_RCC_ADC12_CLK_ENABLE();
33#endif
34#ifdef ADC3 // if defined ADC3
35 else if(adc_instance == ADC3) __HAL_RCC_ADC3_CLK_ENABLE();
36#endif
37 else{
38#ifdef SIMPLEFOC_STM32_DEBUG
39 SIMPLEFOC_DEBUG("STM32-CS: ERR: Cannot find a common ADC for the pins!");
40#endif
41 return -1; // error not a valid ADC instance
42 }
43
44 int adc_num = _adcToIndex(adc_instance);
45
46#ifdef SIMPLEFOC_STM32_DEBUG
47 SIMPLEFOC_DEBUG("STM32-CS: Using ADC: ", adc_num+1);
48#endif
49
50 hadc[adc_num].Instance = adc_instance;
51 hadc[adc_num].Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
52 hadc[adc_num].Init.Resolution = ADC_RESOLUTION_12B;
53 hadc[adc_num].Init.ScanConvMode = ENABLE;
54 hadc[adc_num].Init.ContinuousConvMode = DISABLE;
55 hadc[adc_num].Init.DiscontinuousConvMode = DISABLE;
56 hadc[adc_num].Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
57 hadc[adc_num].Init.ExternalTrigConv = ADC_SOFTWARE_START; // for now
58#if defined(ADC_VER_V5_V90)
59 // only for ADC3
60 if(hadc[adc_num].Instance == ADC3){
61 hadc[adc_num].Init.DataAlign = ADC3_DATAALIGN_RIGHT;
62 }
63 // more info here
64 // https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32H7xx_HAL_Driver/Inc/stm32h7xx_hal_adc.h#L170C13-L170C27
65 hadc[adc_num].Init.DMAContinuousRequests = DISABLE;
66 // not sure about this one!!! maybe use: ADC_SAMPLING_MODE_NORMAL
67 hadc[adc_num].Init.SamplingMode = ADC_SAMPLING_MODE_NORMAL;
68#endif
69 hadc[adc_num].Init.NbrOfConversion = 1;
70 hadc[adc_num].Init.NbrOfDiscConversion = 0;
71 hadc[adc_num].Init.EOCSelection = ADC_EOC_SINGLE_CONV;
72
73 hadc[adc_num].Init.LowPowerAutoWait = DISABLE;
74
75
76 if ( HAL_ADC_Init(&hadc[adc_num]) != HAL_OK){
77#ifdef SIMPLEFOC_STM32_DEBUG
78 SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init ADC!");
79#endif
80 return -1;
81 }
82 return 0;
83}
84
85/**
86 * Function initializing the ADC and the injected channels for the low-side current sensing
87 *
88 * @param cs_params - current sense parameters
89 * @param driver_params - driver parameters
90 *
91 * @return int - 0 if success
92 */
93int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* driver_params)
94{
95
96
97 /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
98 */
99 auto adc_instance = _findBestADCForInjectedPins(3, cs_params->pins, hadc);
100 if(adc_instance == NP){
101#ifdef SIMPLEFOC_STM32_DEBUG
102 SIMPLEFOC_DEBUG("STM32-CS: ERR: Pin does not belong to any ADC!");
103#endif
104 return -1; // error not a valid ADC instance
105 }
106 if( _adc_init_regular(adc_instance) != 0){
107 return -1;
108 }
109 int adc_num = _adcToIndex(adc_instance);
110
111 /**Configures for the selected ADC injected channel its corresponding rank in the sequencer and its sample time
112 */
113 ADC_InjectionConfTypeDef sConfigInjected;
114 sConfigInjected.InjectedNbrOfConversion = 0;
115 for(int pin_no=0; pin_no<3; pin_no++){
116 if(_isset(cs_params->pins[pin_no])){
117 sConfigInjected.InjectedNbrOfConversion++;
118 }
119 }
120 // if ADC1 or ADC2
121 if(hadc[adc_num].Instance == ADC1 || hadc[adc_num].Instance == ADC2){
122 // more info here: https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32H7xx_HAL_Driver/Inc/stm32h7xx_hal_adc.h#L658
123 sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_2CYCLES_5;
124 }else {
125 // adc3
126 // https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32H7xx_HAL_Driver/Inc/stm32h7xx_hal_adc.h#L673
127 sConfigInjected.InjectedSamplingTime = ADC3_SAMPLETIME_2CYCLES_5;
128 }
129 sConfigInjected.ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONV_EDGE_RISINGFALLING;
130 sConfigInjected.AutoInjectedConv = DISABLE;
131 sConfigInjected.InjectedDiscontinuousConvMode = DISABLE;
132 sConfigInjected.InjectedOffset = 0;
133 sConfigInjected.InjectedSingleDiff = ADC_SINGLE_ENDED;
134 sConfigInjected.InjectedOffsetNumber = ADC_OFFSET_NONE;
135 sConfigInjected.QueueInjectedContext = DISABLE;
136 sConfigInjected.InjecOversamplingMode = DISABLE;
137
138 // automating TRGO flag finding - hardware specific
139 uint8_t tim_num = 0;
140 for (size_t i=0; i<6; i++) {
141 TIM_HandleTypeDef *timer_to_check = driver_params->timers_handle[tim_num++];
142 TIM_TypeDef *instance_to_check = timer_to_check->Instance;
143
144 uint32_t trigger_flag = _timerToInjectedTRGO(timer_to_check);
145 if(trigger_flag == _TRGO_NOT_AVAILABLE) continue; // timer does not have valid trgo for injected channels
146
147 // check if TRGO used already - if yes use the next timer
148 if((timer_to_check->Instance->CR2 & LL_TIM_TRGO_ENABLE) || // if used for timer sync
149 (timer_to_check->Instance->CR2 & LL_TIM_TRGO_UPDATE)) // if used for ADC sync
150 {
151 continue;
152 }
153
154 // if the code comes here, it has found the timer available
155 // timer does have trgo flag for injected channels
156 sConfigInjected.ExternalTrigInjecConv = trigger_flag;
157
158 // this will be the timer with which the ADC will sync
159 cs_params->timer_handle = timer_to_check;
160 // done
161 break;
162 }
163 if( cs_params->timer_handle == NP ){
164 // not possible to use these timers for low-side current sense
165 #ifdef SIMPLEFOC_STM32_DEBUG
166 SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot sync any timer to injected channels!");
167 #endif
168 return -1;
169 }else{
170#ifdef SIMPLEFOC_STM32_DEBUG
171 SIMPLEFOC_DEBUG("STM32-CS: Using timer: ", stm32_getTimerNumber(cs_params->timer_handle->Instance));
172#endif
173 }
174
175 uint8_t channel_no = 0;
176 for(int i=0; i<3; i++){
177 // skip if not set
178 if (!_isset(cs_params->pins[i])) continue;
179
180 sConfigInjected.InjectedRank = _getADCInjectedRank(channel_no++);
181 sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc[adc_num].Instance);
182#ifdef SIMPLEFOC_STM32_DEBUG
183 SIMPLEFOC_DEBUG("STM32-CS: ADC channel: ", (int)STM_PIN_CHANNEL(pinmap_function(PinMap_ADC[i].pin, PinMap_ADC)));
184#endif
185 if (HAL_ADCEx_InjectedConfigChannel(&hadc[adc_num], &sConfigInjected) != HAL_OK){
186 #ifdef SIMPLEFOC_STM32_DEBUG
187 SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]) , hadc[adc_num].Instance));
188 #endif
189 return -1;
190 }
191 }
192
193 cs_params->adc_handle = &hadc[adc_num];
194 return 0;
195}
196
197
198/**
199 * Function to initialize the ADC GPIO pins
200 *
201 * @param cs_params current sense parameters
202 * @param pinA pin number for phase A
203 * @param pinB pin number for phase B
204 * @param pinC pin number for phase C
205 * @return int 0 if success, -1 if error
206 */
207int _adc_gpio_init(Stm32CurrentSenseParams* cs_params, const int pinA, const int pinB, const int pinC)
208{
209 int pins[3] = {pinA, pinB, pinC};
210 const char* port_names[3] = {"A", "B", "C"};
211 for(int i=0; i<3; i++){
212 if(_isset(pins[i])){
213 // check if pin is an analog pin
214 if(pinmap_peripheral(analogInputToPinName(pins[i]), PinMap_ADC) == NP){
215
216#if defined(SIMPLEFOC_STM32_DEBUG) && !defined(SIMPLEFOC_DISABLE_DEBUG)
217 SimpleFOCDebug::print("STM32-CS: ERR: Pin ");
218 SimpleFOCDebug::print(port_names[i]);
219 SimpleFOCDebug::println(" does not belong to any ADC!");
220#endif
221 return -1;
222 }
223 pinmap_pinout(analogInputToPinName(pins[i]), PinMap_ADC);
224 cs_params->pins[i] = pins[i];
225 }
226 }
227 return 0;
228}
229
230
231extern "C" {
232 void ADC_IRQHandler(void)
233 {
234 if (hadc[0].Instance != NP)
235 HAL_ADC_IRQHandler(&hadc[0]);
236 if (hadc[1].Instance != NP)
237 HAL_ADC_IRQHandler(&hadc[1]);
238 }
239}
240
241#ifdef ADC3
242extern "C" {
243 void ADC3_IRQHandler(void)
244 {
245 if (hadc[2].Instance != NP)
246 HAL_ADC_IRQHandler(&hadc[2]);
247 }
248}
249#endif
250
251#endif
#define SIMPLEFOC_DEBUG(msg,...)
static void print(const char *msg)
static void println()
const int const int const int pinC
#define _isset(a)
Definition foc_utils.h:13