SimpleFOClibrary 2.4.0
Loading...
Searching...
No Matches
stm32_timerutils.cpp
Go to the documentation of this file.
1
3#include <Arduino.h>
4
5#if defined(_STM32_DEF_) || defined(TARGET_STM32H7) // if stm32duino or portenta
6
7
8void stm32_pauseTimer(TIM_HandleTypeDef* handle){
9 /* Disable timer unconditionally. Required to guarantee timer is stopped,
10 * even if some channels are still running */
11 LL_TIM_DisableCounter(handle->Instance);
12// handle->State = HAL_TIM_STATE_READY;
13 // on advanced control timers there is also the option of using the brake or the MOE?
14 // TIM1->EGR |= TIM_EGR_BG; // break generation
15}
16
17
18void stm32_resumeTimer(TIM_HandleTypeDef* handle){
19 LL_TIM_EnableCounter(handle->Instance);
20}
21
22
23void stm32_refreshTimer(TIM_HandleTypeDef* handle){
24 handle->Instance->EGR = TIM_EVENTSOURCE_UPDATE;
25}
26
27
28void stm32_pauseChannel(TIM_HandleTypeDef* handle, uint32_t llchannels){
29 LL_TIM_CC_DisableChannel(handle->Instance, llchannels);
30}
31
32
33void stm32_resumeChannel(TIM_HandleTypeDef* handle, uint32_t llchannels){
34 LL_TIM_CC_EnableChannel(handle->Instance, llchannels);
35}
36
37
38
39
40
41
42
43
44uint32_t stm32_setClockAndARR(TIM_HandleTypeDef* handle, uint32_t PWM_freq) {
45 // set the clock
46 uint32_t arr_value = 0;
47 uint32_t cycles = stm32_getTimerClockFreq(handle) / PWM_freq / 2;
48 uint32_t prescaler = (cycles / 0x10000) + 1; // TODO consider 32 bit timers
49 LL_TIM_SetPrescaler(handle->Instance, prescaler - 1);
50 uint32_t ticks = cycles / prescaler;
51 if (ticks > 0) {
52 arr_value = ticks - 1;
53 }
54 __HAL_TIM_SET_AUTORELOAD(handle, arr_value);
55 stm32_refreshTimer(handle);
56 // #ifdef SIMPLEFOC_STM32_DEBUG
57 // SIMPLEFOC_DEBUG("STM32-DRV: Timer clock: ", (int)stm32_getTimerClockFreq(handle));
58 // SIMPLEFOC_DEBUG("STM32-DRV: Timer prescaler: ", (int)prescaler);
59 // SIMPLEFOC_DEBUG("STM32-DRV: Timer ARR: ", (int)arr_value);
60 // #endif
61 return arr_value;
62}
63
64
65
66
67
68// setting pwm to hardware pin - instead analogWrite()
69void stm32_setPwm(TIM_HandleTypeDef *timer, uint32_t channel, uint32_t value) {
70 // value assumed to be in correct range
71 switch (channel) {
72 case 1: timer->Instance->CCR1 = value; break;
73 case 2: timer->Instance->CCR2 = value; break;
74 case 3: timer->Instance->CCR3 = value; break;
75 case 4: timer->Instance->CCR4 = value; break;
76 #ifdef LL_TIM_CHANNEL_CH5
77 case 5: timer->Instance->CCR5 = value; break;
78 #endif
79 #ifdef LL_TIM_CHANNEL_CH6
80 case 6: timer->Instance->CCR6 = value; break;
81 #endif
82 default: break;
83 }
84}
85
86
87uint32_t stm32_getHALChannel(uint32_t channel) {
88 uint32_t return_value;
89 switch (channel) {
90 case 1:
91 return_value = TIM_CHANNEL_1;
92 break;
93 case 2:
94 return_value = TIM_CHANNEL_2;
95 break;
96 case 3:
97 return_value = TIM_CHANNEL_3;
98 break;
99 case 4:
100 return_value = TIM_CHANNEL_4;
101 break;
102 #ifdef TIM_CHANNEL_5
103 case 5:
104 return_value = TIM_CHANNEL_5;
105 break;
106 #endif
107 #ifdef TIM_CHANNEL_6
108 case 6:
109 return_value = TIM_CHANNEL_6;
110 break;
111 #endif
112 default:
113 return_value = -1;
114 }
115 return return_value;
116}
117
118
119
120uint32_t stm32_getLLChannel(PinMap* timer) {
121#if defined(TIM_CCER_CC1NE)
122 if (STM_PIN_INVERTED(timer->function)) {
123 switch (STM_PIN_CHANNEL(timer->function)) {
124 case 1: return LL_TIM_CHANNEL_CH1N;
125 case 2: return LL_TIM_CHANNEL_CH2N;
126 case 3: return LL_TIM_CHANNEL_CH3N;
127#if defined(LL_TIM_CHANNEL_CH4N)
128 case 4: return LL_TIM_CHANNEL_CH4N;
129#endif
130 default: return -1;
131 }
132 } else
133#endif
134 {
135 switch (STM_PIN_CHANNEL(timer->function)) {
136 case 1: return LL_TIM_CHANNEL_CH1;
137 case 2: return LL_TIM_CHANNEL_CH2;
138 case 3: return LL_TIM_CHANNEL_CH3;
139 case 4: return LL_TIM_CHANNEL_CH4;
140 #ifdef LL_TIM_CHANNEL_CH5
141 case 5: return LL_TIM_CHANNEL_CH5;
142 #endif
143 #ifdef LL_TIM_CHANNEL_CH6
144 case 6: return LL_TIM_CHANNEL_CH6;
145 #endif
146 default: return -1;
147 }
148 }
149 return -1;
150}
151
152
153
154uint8_t stm32_countTimers(TIM_HandleTypeDef *timers[], uint8_t num_timers) {
155 uint8_t count = 1;
156 for (int i=1; i<num_timers; i++) {
157 if (timers[i] != NULL) break;
158 bool found = false;
159 for (int j=0; j<i; j++) {
160 if (timers[i] == timers[j]) {
161 found = true;
162 break;
163 }
164 }
165 if (found==false)
166 count++;
167 }
168 return count;
169}
170
171uint8_t stm32_distinctTimers(TIM_HandleTypeDef* timers_in[], uint8_t num_timers, TIM_HandleTypeDef* timers_out[]) {
172 uint8_t count = 0;
173 for (int i=0; i<num_timers; i++) {
174 if (timers_in[i] == NULL) continue;
175 bool found = false;
176 for (int j=0; j<count; j++) {
177 if (timers_in[i] == timers_out[j]) {
178 found = true;
179 break;
180 }
181 }
182 if (found==false)
183 timers_out[count++] = timers_in[i];
184 }
185 return count;
186}
187
188
189
190#if defined(STM32G4xx)
191// function finds the appropriate timer source trigger for the master/slave timer combination
192// returns -1 if no trigger source is found
193// currently supports the master timers to be from TIM1 to TIM4 and TIM8
194int stm32_getInternalSourceTrigger(TIM_HandleTypeDef* master, TIM_HandleTypeDef* slave) { // put master and slave in temp variables to avoid arrows
195 TIM_TypeDef *TIM_master = master->Instance;
196 #if defined(TIM1) && defined(LL_TIM_TS_ITR0)
197 if (TIM_master == TIM1) return LL_TIM_TS_ITR0;// return TIM_TS_ITR0;
198 #endif
199 #if defined(TIM2) && defined(LL_TIM_TS_ITR1)
200 else if (TIM_master == TIM2) return LL_TIM_TS_ITR1;//return TIM_TS_ITR1;
201 #endif
202 #if defined(TIM3) && defined(LL_TIM_TS_ITR2)
203 else if (TIM_master == TIM3) return LL_TIM_TS_ITR2;//return TIM_TS_ITR2;
204 #endif
205 #if defined(TIM4) && defined(LL_TIM_TS_ITR3)
206 else if (TIM_master == TIM4) return LL_TIM_TS_ITR3;//return TIM_TS_ITR3;
207 #endif
208 #if defined(TIM5) && defined(LL_TIM_TS_ITR4)
209 else if (TIM_master == TIM5) return LL_TIM_TS_ITR4;//return TIM_TS_ITR4;
210 #endif
211 #if defined(TIM8) && defined(LL_TIM_TS_ITR5)
212 else if (TIM_master == TIM8) return LL_TIM_TS_ITR5;//return TIM_TS_ITR5;
213 #endif
214 return -1;
215}
216#elif defined(STM32F4xx) || defined(STM32F1xx) || defined(STM32L4xx) || defined(STM32F7xx) || defined(STM32H7xx) || defined(TARGET_STM32H7)
217
218// function finds the appropriate timer source trigger for the master/slave timer combination
219// returns -1 if no trigger source is found
220// currently supports the master timers to be from
221//
222// fammilies | timers
223// --------------| --------------------------------
224// f1,f4,f7 | TIM1 to TIM4 and TIM8
225// l4 | TIM1 to TIM4, TIM8 and TIM15
226// h7 | TIM1 to TIM5, TIM8, TIM15, TIM23 and TIM24
227int stm32_getInternalSourceTrigger(TIM_HandleTypeDef* master, TIM_HandleTypeDef* slave) {
228 // put master and slave in temp variables to avoid arrows
229 TIM_TypeDef *TIM_master = master->Instance;
230 TIM_TypeDef *TIM_slave = slave->Instance;
231 #if defined(TIM1) && defined(LL_TIM_TS_ITR0)
232 if (TIM_master == TIM1){
233 #if defined(TIM2)
234 if(TIM_slave == TIM2) return LL_TIM_TS_ITR0;
235 #endif
236 #if defined(TIM3)
237 else if(TIM_slave == TIM3) return LL_TIM_TS_ITR0;
238 #endif
239 #if defined(TIM4)
240 else if(TIM_slave == TIM4) return LL_TIM_TS_ITR0;
241 #endif
242 #if defined(TIM8)
243 else if(TIM_slave == TIM8) return LL_TIM_TS_ITR0;
244 #endif
245 #if defined(STM32H7xx) || defined(TARGET_STM32H7)
246 #if defined(TIM23)
247 else if(TIM_slave == TIM23) return LL_TIM_TS_ITR0;
248 #endif
249 #if defined(TIM24)
250 else if(TIM_slave == TIM24) return LL_TIM_TS_ITR0;
251 #endif
252 #endif
253 }
254 #endif
255 #if defined(TIM2) && defined(LL_TIM_TS_ITR1)
256 else if (TIM_master == TIM2){
257 #if defined(TIM1)
258 if(TIM_slave == TIM1) return LL_TIM_TS_ITR1;
259 #endif
260 #if defined(TIM3)
261 else if(TIM_slave == TIM3) return LL_TIM_TS_ITR1;
262 #endif
263 #if defined(TIM4)
264 else if(TIM_slave == TIM4) return LL_TIM_TS_ITR1;
265 #endif
266 #if defined(TIM8)
267 else if(TIM_slave == TIM8) return LL_TIM_TS_ITR1;
268 #endif
269 #if defined(STM32H7xx) || defined(TARGET_STM32H7)
270 #if defined(TIM23)
271 else if(TIM_slave == TIM23) return LL_TIM_TS_ITR1;
272 #endif
273 #if defined(TIM24)
274 else if(TIM_slave == TIM24) return LL_TIM_TS_ITR1;
275 #endif
276 #else
277 #if defined(TIM5)
278 else if(TIM_slave == TIM5) return LL_TIM_TS_ITR0;
279 #endif
280 #endif
281 }
282 #endif
283 #if defined(TIM3) && defined(LL_TIM_TS_ITR2)
284 else if (TIM_master == TIM3){
285 #if defined(TIM1)
286 if(TIM_slave == TIM1) return LL_TIM_TS_ITR2;
287 #endif
288 #if defined(TIM2)
289 else if(TIM_slave == TIM2) return LL_TIM_TS_ITR2;
290 #endif
291 #if defined(TIM4)
292 else if(TIM_slave == TIM4) return LL_TIM_TS_ITR2;
293 #endif
294 #if defined(STM32H7xx) || defined(TARGET_STM32H7)
295 #if defined(TIM5)
296 else if(TIM_slave == TIM5) return LL_TIM_TS_ITR2;
297 #endif
298 #if defined(TIM23)
299 else if(TIM_slave == TIM23) return LL_TIM_TS_ITR2;
300 #endif
301 #if defined(TIM24)
302 else if(TIM_slave == TIM24) return LL_TIM_TS_ITR2;
303 #endif
304 #else
305 #if defined(TIM5)
306 else if(TIM_slave == TIM5) return LL_TIM_TS_ITR1;
307 #endif
308 #endif
309 }
310 #endif
311 #if defined(TIM4) && defined(LL_TIM_TS_ITR3)
312 else if (TIM_master == TIM4){
313 #if defined(TIM1)
314 if(TIM_slave == TIM1) return LL_TIM_TS_ITR3;
315 #endif
316 #if defined(TIM2)
317 else if(TIM_slave == TIM2) return LL_TIM_TS_ITR3;
318 #endif
319 #if defined(TIM3)
320 else if(TIM_slave == TIM3) return LL_TIM_TS_ITR3;
321 #endif
322 #if defined(TIM8)
323 else if(TIM_slave == TIM8) return LL_TIM_TS_ITR2;
324 #endif
325
326 #if defined(STM32H7xx) || defined(TARGET_STM32H7)
327 #if defined(TIM5)
328 else if(TIM_slave == TIM5) return LL_TIM_TS_ITR3;
329 #endif
330 #if defined(TIM23)
331 else if(TIM_slave == TIM23) return LL_TIM_TS_ITR3;
332 #endif
333 #if defined(TIM24)
334 else if(TIM_slave == TIM24) return LL_TIM_TS_ITR3;
335 #endif
336 #else
337 #if defined(TIM5)
338 else if(TIM_slave == TIM5) return LL_TIM_TS_ITR2;
339 #endif
340 #endif
341 }
342 #endif
343 #if defined(TIM5)
344 else if (TIM_master == TIM5){
345 #if defined(STM32F4xx) || defined(STM32F1xx) || defined(STM32F7xx) // f1, f4 adn f7 have tim5 sycned with tim1 and tim3 while others (l4, h7) have tim15
346 #if defined(TIM1)
347 if(TIM_slave == TIM1) return LL_TIM_TS_ITR0;
348 #endif
349 #if defined(TIM3)
350 else if(TIM_slave == TIM3) return LL_TIM_TS_ITR2;
351 #endif
352 #endif
353 #if defined(TIM8)
354 if(TIM_slave == TIM8) return LL_TIM_TS_ITR3;
355 #endif
356
357 #if defined(STM32H7xx) || defined(TARGET_STM32H7)
358 #if defined(TIM23)
359 else if(TIM_slave == TIM23) return LL_TIM_TS_ITR4;
360 #endif
361 #if defined(TIM24)
362 else if(TIM_slave == TIM24) return LL_TIM_TS_ITR4;
363 #endif
364 #endif
365 }
366 #endif
367 #if defined(TIM8)
368 else if (TIM_master == TIM8){
369 #if defined(TIM2)
370 if(TIM_slave==TIM2) return LL_TIM_TS_ITR1;
371 #endif
372 #if defined(TIM4)
373 else if(TIM_slave == TIM4) return LL_TIM_TS_ITR3;
374 #endif
375
376 #if defined(STM32H7xx) || defined(TARGET_STM32H7)
377 #if defined(TIM5)
378 else if(TIM_slave == TIM5) return LL_TIM_TS_ITR1;
379 #endif
380 #if defined(TIM23)
381 else if(TIM_slave == TIM23) return LL_TIM_TS_ITR5;
382 #endif
383 #if defined(TIM24)
384 else if(TIM_slave == TIM24) return LL_TIM_TS_ITR5;
385 #endif
386 #else
387 #if defined(TIM5)
388 else if(TIM_slave == TIM5) return LL_TIM_TS_ITR3;
389 #endif
390 #endif
391 }
392 #endif
393 #if defined(TIM15) && (defined(STM32L4xx) || defined(STM32H7xx) || defined(TARGET_STM32H7) )
394 else if (TIM_master == TIM15){
395 #if defined(TIM1)
396 if(TIM_slave == TIM1) return LL_TIM_TS_ITR0;
397 #endif
398 #if defined(TIM3)
399 if(TIM_slave == TIM3) return LL_TIM_TS_ITR2;
400 #endif
401 }
402 #endif
403 #if defined(TIM23) && (defined(STM32H7xx) || defined(TARGET_STM32H7))
404 else if (TIM_master == TIM23){
405 #if defined(TIM1)
406 if(TIM_slave == TIM1) return LL_TIM_TS_ITR12;
407 #endif
408 #if defined(TIM2)
409 if(TIM_slave == TIM2) return LL_TIM_TS_ITR12;
410 #endif
411 #if defined(TIM3)
412 if(TIM_slave == TIM3) return LL_TIM_TS_ITR12;
413 #endif
414 #if defined(TIM4)
415 if(TIM_slave == TIM4) return LL_TIM_TS_ITR12;
416 #endif
417 #if defined(TIM5)
418 if(TIM_slave == TIM5) return LL_TIM_TS_ITR12;
419 #endif
420 #if defined(TIM8)
421 if(TIM_slave == TIM8) return LL_TIM_TS_ITR12;
422 #endif
423 #if defined(TIM24)
424 if(TIM_slave == TIM24) return LL_TIM_TS_ITR12;
425 #endif
426 }
427 #endif
428 #if defined(TIM24) && (defined(STM32H7xx) || defined(TARGET_STM32H7))
429 else if (TIM_master == TIM24){
430 #if defined(TIM1)
431 if(TIM_slave == TIM1) return LL_TIM_TS_ITR13;
432 #endif
433 #if defined(TIM2)
434 if(TIM_slave == TIM2) return LL_TIM_TS_ITR13;
435 #endif
436 #if defined(TIM3)
437 if(TIM_slave == TIM3) return LL_TIM_TS_ITR13;
438 #endif
439 #if defined(TIM4)
440 if(TIM_slave == TIM4) return LL_TIM_TS_ITR13;
441 #endif
442 #if defined(TIM5)
443 if(TIM_slave == TIM5) return LL_TIM_TS_ITR13;
444 #endif
445 #if defined(TIM8)
446 if(TIM_slave == TIM8) return LL_TIM_TS_ITR13;
447 #endif
448 #if defined(TIM23)
449 if(TIM_slave == TIM23) return LL_TIM_TS_ITR13;
450 #endif
451 }
452 #endif
453 return -1; // combination not supported
454}
455#else
456// Alignment not supported for this architecture
457int stm32_getInternalSourceTrigger(TIM_HandleTypeDef* master, TIM_HandleTypeDef* slave) {
458 return -1;
459}
460#endif
461
462
463
464
465
466// call with the timers used for a motor. The function will align the timers and
467// start them at the same time (if possible). Results of this function can be:
468// - success, no changes needed
469// - success, different timers aligned and started concurrently
470// - failure, cannot align timers
471// in each case, the timers are started.
472//
473// TODO: this topic is quite complex if we allow multiple motors and multiple timers per motor.
474// that's because the motors could potentially share the same timer. In this case aligning
475// the timers is problematic.
476// Even more problematic is stopping and resetting the timers. Even with a single motor,
477// this would cause problems and mis-align the PWM signals.
478// We can handle three cases:
479// - only one timer needed, no need to align
480// - master timer can be found, and timers used by only this motor: alignment possible
481// - TODO all timers for all motors can be aligned to one master: alignment possible
482// - otherwise, alignment not possible
483// frequency alignment is based on checking their pwm frequencies match.
484// pwm alignment is based on linking timers to start them at the same time, and making sure they are reset in sync.
485// On newer chips supporting it (STM32G4) we use gated + reset mode to start/stop only the master timer. Slaves
486// are started/stopped automatically with the master. TODO probably just using gated mode is better
487// On older chips (STM32F1) we used gated mode to start/stop the slave timers with the master, but have to take
488// care of the reset manually. TODO is it really needed to reset the timers?
489TIM_HandleTypeDef* stm32_alignTimers(TIM_HandleTypeDef *timers_in[], uint8_t num_timers_in) {
490 // find the timers used
491 TIM_HandleTypeDef *timers[6];
492 int numTimers = stm32_distinctTimers(timers_in, num_timers_in, timers);
493
494 // compare with the existing timers used for other motors...
495 for (int i=0; i<numTimers; i++) {
496 for (int j=0; j<stm32_getNumMotorsUsed(); j++) {
497 STM32DriverParams* params = stm32_getMotorUsed(j);
498 for (int k=0; k<6; k++) {
499 if (params->timers_handle[k] == NULL) break;
500 if (params->timers_handle[k] == timers[i]) {
501 #ifdef SIMPLEFOC_STM32_DEBUG
502 SIMPLEFOC_DEBUG("STM32-DRV: ERR: Timer already used by another motor: TIM", stm32_getTimerNumber(timers[i]->Instance));
503 #endif
504 // TODO handle this case, and make it a warning
505 // two sub-cases we could handle at the moment:
506 // - the other motor does not have a master timer, so we can initialize this motor without a master also
507 }
508 }
509 }
510 }
511
512
513 #if defined(SIMPLEFOC_STM32_DEBUG) && !defined(SIMPLEFOC_DISABLE_DEBUG)
514 SimpleFOCDebug::print("STM32-DRV: Synchronising ");
515 SimpleFOCDebug::print(numTimers);
516 SimpleFOCDebug::println(" timers");
517 #endif
518
519 // see if there is more then 1 timers used for the pwm
520 // if yes, try to align timers
521 if(numTimers > 1){
522 // find the master timer
523 int16_t master_index = -1;
524 int triggerEvent = -1;
525 for (int i=0; i<numTimers; i++) {
526 // check if timer can be master
527 if(IS_TIM_MASTER_INSTANCE(timers[i]->Instance)) {
528 // check if timer already configured in TRGO update mode (used for ADC triggering)
529 // in that case we should not change its TRGO configuration
530 if(timers[i]->Instance->CR2 & LL_TIM_TRGO_UPDATE) continue;
531 // check if the timer has the supported internal trigger for other timers
532 for (int slave_i=0; slave_i<numTimers; slave_i++) {
533 if (i==slave_i) continue; // skip self
534 // check if it has the supported internal trigger
535 triggerEvent = stm32_getInternalSourceTrigger(timers[i],timers[slave_i]);
536 if(triggerEvent == -1) break; // not supported keep searching
537 }
538 if(triggerEvent == -1) continue; // cannot be master, keep searching
539 // otherwise the master has been found, remember the index
540 master_index = i; // found the master timer
541 break;
542 }
543 }
544
545
546 // if no master timer found do not perform alignment
547 if (master_index == -1) {
548 #ifdef SIMPLEFOC_STM32_DEBUG
549 SIMPLEFOC_DEBUG("STM32-DRV: WARN: No master timer found, cannot align timers!");
550 #endif
551 }else{
552 #ifdef SIMPLEFOC_STM32_DEBUG
553 SIMPLEFOC_DEBUG("STM32-DRV: master timer: TIM", stm32_getTimerNumber(timers[master_index]->Instance));
554 #endif
555 // make the master timer generate ITRGx event
556 // if it was already configured in slave mode, disable the slave mode on the master
557 LL_TIM_SetSlaveMode(timers[master_index]->Instance, LL_TIM_SLAVEMODE_DISABLED );
558 // Configure the master timer to send a trigger signal on enable
559 LL_TIM_SetTriggerOutput(timers[master_index]->Instance, LL_TIM_TRGO_ENABLE);
560 //LL_TIM_EnableMasterSlaveMode(timers[master_index]->Instance);
561
562 // configure other timers to get the input trigger from the master timer
563 for (int slave_index=0; slave_index < numTimers; slave_index++) {
564 if (slave_index == master_index)
565 continue;
566 #ifdef SIMPLEFOC_STM32_DEBUG
567 SIMPLEFOC_DEBUG("STM32-DRV: slave timer: TIM", stm32_getTimerNumber(timers[slave_index]->Instance));
568 #endif
569 // Configure the slave timer to be triggered by the master enable signal
570 uint32_t trigger = stm32_getInternalSourceTrigger(timers[master_index], timers[slave_index]);
571 // #ifdef SIMPLEFOC_STM32_DEBUG
572 // SIMPLEFOC_DEBUG("STM32-DRV: slave trigger ITR ", (int)trigger);
573 // #endif
574 LL_TIM_SetTriggerInput(timers[slave_index]->Instance, trigger);
575 // #if defined(STM32G4xx)
576 // LL_TIM_SetSlaveMode(timers[slave_index]->Instance, LL_TIM_SLAVEMODE_COMBINED_GATEDRESET);
577 // #else
578 LL_TIM_SetSlaveMode(timers[slave_index]->Instance, LL_TIM_SLAVEMODE_GATED);
579 // #endif
580 }
581 for (int i=0; i<numTimers; i++) { // resume the timers TODO at the moment the first PWM cycle is not well-aligned
582 stm32_refreshTimer(timers[i]);
583 if (i != master_index)
584 stm32_resumeTimer(timers[i]);
585 SIMPLEFOC_DEBUG("STM32-DRV: slave counter: ", (int)timers[i]->Instance->CNT);
586 }
587 stm32_resumeTimer(timers[master_index]);
588 return timers[master_index];
589 }
590 }
591
592 // if we had only one timer, or there was no master timer found
593 for (int i=0; i<numTimers; i++) // resume the timers individually
594 stm32_resumeTimer(timers[i]);
595 return NULL;
596
597}
598
599
600
601
602
603uint32_t stm32_getTimerClockFreq(TIM_HandleTypeDef *handle) {
604#if defined(STM32MP1xx)
605 uint8_t timerClkSrc = getTimerClkSrc(handle->Instance);
606 uint64_t clkSelection = timerClkSrc == 1 ? RCC_PERIPHCLK_TIMG1 : RCC_PERIPHCLK_TIMG2;
607 return HAL_RCCEx_GetPeriphCLKFreq(clkSelection);
608#else
609 RCC_ClkInitTypeDef clkconfig = {};
610 uint32_t pFLatency = 0U;
611 uint32_t uwTimclock = 0U, uwAPBxPrescaler = 0U;
612
613 /* Get clock configuration */
614 HAL_RCC_GetClockConfig(&clkconfig, &pFLatency);
615 switch (getTimerClkSrc(handle->Instance)) {
616 case 1:
617 uwAPBxPrescaler = clkconfig.APB1CLKDivider;
618 uwTimclock = HAL_RCC_GetPCLK1Freq();
619 break;
620#if !defined(STM32C0xx) && !defined(STM32F0xx) && !defined(STM32G0xx)
621 case 2:
622 uwAPBxPrescaler = clkconfig.APB2CLKDivider;
623 uwTimclock = HAL_RCC_GetPCLK2Freq();
624 break;
625#endif
626 default:
627 case 0: // Unknown timer clock source
628 return 0;
629 }
630
631#if defined(STM32H7xx) || defined(TARGET_STM32H7)
632 /* When TIMPRE bit of the RCC_CFGR register is reset,
633 * if APBx prescaler is 1 or 2 then TIMxCLK = HCLK,
634 * otherwise TIMxCLK = 2x PCLKx.
635 * When TIMPRE bit in the RCC_CFGR register is set,
636 * if APBx prescaler is 1,2 or 4, then TIMxCLK = HCLK,
637 * otherwise TIMxCLK = 4x PCLKx
638 */
639 RCC_PeriphCLKInitTypeDef PeriphClkConfig = {};
640 HAL_RCCEx_GetPeriphCLKConfig(&PeriphClkConfig);
641
642 if (PeriphClkConfig.TIMPresSelection == RCC_TIMPRES_ACTIVATED) {
643 switch (uwAPBxPrescaler) {
644 default:
645 case RCC_APB1_DIV1:
646 case RCC_APB1_DIV2:
647 case RCC_APB1_DIV4:
648 /* case RCC_APB2_DIV1: */
649 case RCC_APB2_DIV2:
650 case RCC_APB2_DIV4:
651 /* Note: in such cases, HCLK = (APBCLK * DIVx) */
652 uwTimclock = HAL_RCC_GetHCLKFreq();
653 break;
654 case RCC_APB1_DIV8:
655 case RCC_APB1_DIV16:
656 case RCC_APB2_DIV8:
657 case RCC_APB2_DIV16:
658 uwTimclock *= 4;
659 break;
660 }
661 } else {
662 switch (uwAPBxPrescaler) {
663 default:
664 case RCC_APB1_DIV1:
665 case RCC_APB1_DIV2:
666 /* case RCC_APB2_DIV1: */
667 case RCC_APB2_DIV2:
668 /* Note: in such cases, HCLK = (APBCLK * DIVx) */
669 uwTimclock = HAL_RCC_GetHCLKFreq();
670 break;
671 case RCC_APB1_DIV4:
672 case RCC_APB1_DIV8:
673 case RCC_APB1_DIV16:
674 case RCC_APB2_DIV4:
675 case RCC_APB2_DIV8:
676 case RCC_APB2_DIV16:
677 uwTimclock *= 2;
678 break;
679 }
680 }
681#else
682 /* When TIMPRE bit of the RCC_DCKCFGR register is reset,
683 * if APBx prescaler is 1, then TIMxCLK = PCLKx,
684 * otherwise TIMxCLK = 2x PCLKx.
685 * When TIMPRE bit in the RCC_DCKCFGR register is set,
686 * if APBx prescaler is 1,2 or 4, then TIMxCLK = HCLK,
687 * otherwise TIMxCLK = 4x PCLKx
688 */
689#if defined(STM32F4xx) || defined(STM32F7xx)
690#if !defined(STM32F405xx) && !defined(STM32F415xx) &&\
691 !defined(STM32F407xx) && !defined(STM32F417xx)
692 RCC_PeriphCLKInitTypeDef PeriphClkConfig = {};
693 HAL_RCCEx_GetPeriphCLKConfig(&PeriphClkConfig);
694
695 if (PeriphClkConfig.TIMPresSelection == RCC_TIMPRES_ACTIVATED)
696 switch (uwAPBxPrescaler) {
697 default:
698 case RCC_HCLK_DIV1:
699 case RCC_HCLK_DIV2:
700 case RCC_HCLK_DIV4:
701 /* Note: in such cases, HCLK = (APBCLK * DIVx) */
702 uwTimclock = HAL_RCC_GetHCLKFreq();
703 break;
704 case RCC_HCLK_DIV8:
705 case RCC_HCLK_DIV16:
706 uwTimclock *= 4;
707 break;
708 } else
709#endif
710#endif
711 switch (uwAPBxPrescaler) {
712 default:
713 case RCC_HCLK_DIV1:
714 // uwTimclock*=1;
715 break;
716 case RCC_HCLK_DIV2:
717 case RCC_HCLK_DIV4:
718 case RCC_HCLK_DIV8:
719 case RCC_HCLK_DIV16:
720 uwTimclock *= 2;
721 break;
722 }
723#endif /* STM32H7xx */
724 return uwTimclock;
725#endif /* STM32MP1xx */
726}
727
728
729
730
731
732
733
734#if defined(__MBED__)
735
736void enableTimerClock(TIM_HandleTypeDef *htim) {
737 // Enable TIM clock
738#if defined(TIM1_BASE)
739 if (htim->Instance == TIM1) {
740 __HAL_RCC_TIM1_CLK_ENABLE();
741 }
742#endif
743#if defined(TIM2_BASE)
744 if (htim->Instance == TIM2) {
745 __HAL_RCC_TIM2_CLK_ENABLE();
746 }
747#endif
748#if defined(TIM3_BASE)
749 if (htim->Instance == TIM3) {
750 __HAL_RCC_TIM3_CLK_ENABLE();
751 }
752#endif
753#if defined(TIM4_BASE)
754 if (htim->Instance == TIM4) {
755 __HAL_RCC_TIM4_CLK_ENABLE();
756 }
757#endif
758#if defined(TIM5_BASE)
759 if (htim->Instance == TIM5) {
760 __HAL_RCC_TIM5_CLK_ENABLE();
761 }
762#endif
763#if defined(TIM6_BASE)
764 if (htim->Instance == TIM6) {
765 __HAL_RCC_TIM6_CLK_ENABLE();
766 }
767#endif
768#if defined(TIM7_BASE)
769 if (htim->Instance == TIM7) {
770 __HAL_RCC_TIM7_CLK_ENABLE();
771 }
772#endif
773#if defined(TIM8_BASE)
774 if (htim->Instance == TIM8) {
775 __HAL_RCC_TIM8_CLK_ENABLE();
776 }
777#endif
778#if defined(TIM9_BASE)
779 if (htim->Instance == TIM9) {
780 __HAL_RCC_TIM9_CLK_ENABLE();
781 }
782#endif
783#if defined(TIM10_BASE)
784 if (htim->Instance == TIM10) {
785 __HAL_RCC_TIM10_CLK_ENABLE();
786 }
787#endif
788#if defined(TIM11_BASE)
789 if (htim->Instance == TIM11) {
790 __HAL_RCC_TIM11_CLK_ENABLE();
791 }
792#endif
793#if defined(TIM12_BASE)
794 if (htim->Instance == TIM12) {
795 __HAL_RCC_TIM12_CLK_ENABLE();
796 }
797#endif
798#if defined(TIM13_BASE)
799 if (htim->Instance == TIM13) {
800 __HAL_RCC_TIM13_CLK_ENABLE();
801 }
802#endif
803#if defined(TIM14_BASE)
804 if (htim->Instance == TIM14) {
805 __HAL_RCC_TIM14_CLK_ENABLE();
806 }
807#endif
808#if defined(TIM15_BASE)
809 if (htim->Instance == TIM15) {
810 __HAL_RCC_TIM15_CLK_ENABLE();
811 }
812#endif
813#if defined(TIM16_BASE)
814 if (htim->Instance == TIM16) {
815 __HAL_RCC_TIM16_CLK_ENABLE();
816 }
817#endif
818#if defined(TIM17_BASE)
819 if (htim->Instance == TIM17) {
820 __HAL_RCC_TIM17_CLK_ENABLE();
821 }
822#endif
823#if defined(TIM18_BASE)
824 if (htim->Instance == TIM18) {
825 __HAL_RCC_TIM18_CLK_ENABLE();
826 }
827#endif
828#if defined(TIM19_BASE)
829 if (htim->Instance == TIM19) {
830 __HAL_RCC_TIM19_CLK_ENABLE();
831 }
832#endif
833#if defined(TIM20_BASE)
834 if (htim->Instance == TIM20) {
835 __HAL_RCC_TIM20_CLK_ENABLE();
836 }
837#endif
838#if defined(TIM21_BASE)
839 if (htim->Instance == TIM21) {
840 __HAL_RCC_TIM21_CLK_ENABLE();
841 }
842#endif
843#if defined(TIM22_BASE)
844 if (htim->Instance == TIM22) {
845 __HAL_RCC_TIM22_CLK_ENABLE();
846 }
847#endif
848}
849
850
851uint8_t getTimerClkSrc(TIM_TypeDef *tim) {
852 uint8_t clkSrc = 0;
853
854 if (tim != (TIM_TypeDef *)NC)
855#if defined(STM32C0xx) || defined(STM32F0xx) || defined(STM32G0xx)
856 /* TIMx source CLK is PCKL1 */
857 clkSrc = 1;
858#else
859 {
860 if (
861 #if defined(TIM2_BASE)
862 tim == TIM2 ||
863 #endif
864 #if defined(TIM3_BASE)
865 tim == TIM3 ||
866 #endif
867 #if defined(TIM4_BASE)
868 tim == TIM4 ||
869 #endif
870 #if defined(TIM5_BASE)
871 tim == TIM5 ||
872 #endif
873 #if defined(TIM6_BASE)
874 tim == TIM6 ||
875 #endif
876 #if defined(TIM7_BASE)
877 tim == TIM7 ||
878 #endif
879 #if defined(TIM12_BASE)
880 tim == TIM12 ||
881 #endif
882 #if defined(TIM13_BASE)
883 tim == TIM13 ||
884 #endif
885 #if defined(TIM14_BASE)
886 tim == TIM14 ||
887 #endif
888 #if defined(TIM18_BASE)
889 tim == TIM18 ||
890 #endif
891 false)
892 clkSrc = 1;
893 else
894 if (
895 #if defined(TIM1_BASE)
896 tim == TIM1 ||
897 #endif
898 #if defined(TIM8_BASE)
899 tim == TIM8 ||
900 #endif
901 #if defined(TIM9_BASE)
902 tim == TIM9 ||
903 #endif
904 #if defined(TIM10_BASE)
905 tim == TIM10 ||
906 #endif
907 #if defined(TIM11_BASE)
908 tim == TIM11 ||
909 #endif
910 #if defined(TIM15_BASE)
911 tim == TIM15 ||
912 #endif
913 #if defined(TIM16_BASE)
914 tim == TIM16 ||
915 #endif
916 #if defined(TIM17_BASE)
917 tim == TIM17 ||
918 #endif
919 #if defined(TIM19_BASE)
920 tim == TIM19 ||
921 #endif
922 #if defined(TIM20_BASE)
923 tim == TIM20 ||
924 #endif
925 #if defined(TIM21_BASE)
926 tim == TIM21 ||
927 #endif
928 #if defined(TIM22_BASE)
929 tim == TIM22 ||
930 #endif
931 false )
932 clkSrc = 2;
933 else
934 return 0;
935 }
936#endif
937 return clkSrc;
938}
939
940#endif
941
942
943
944
945
946
947
948
949#if defined(SIMPLEFOC_STM32_DEBUG) && !defined(SIMPLEFOC_DISABLE_DEBUG)
950
951/*
952 some utility functions to print out the timer combinations
953*/
954
955int stm32_getTimerNumber(TIM_TypeDef *instance) {
956 #if defined(TIM1_BASE)
957 if (instance==TIM1) return 1;
958 #endif
959 #if defined(TIM2_BASE)
960 if (instance==TIM2) return 2;
961 #endif
962 #if defined(TIM3_BASE)
963 if (instance==TIM3) return 3;
964 #endif
965 #if defined(TIM4_BASE)
966 if (instance==TIM4) return 4;
967 #endif
968 #if defined(TIM5_BASE)
969 if (instance==TIM5) return 5;
970 #endif
971 #if defined(TIM6_BASE)
972 if (instance==TIM6) return 6;
973 #endif
974 #if defined(TIM7_BASE)
975 if (instance==TIM7) return 7;
976 #endif
977 #if defined(TIM8_BASE)
978 if (instance==TIM8) return 8;
979 #endif
980 #if defined(TIM9_BASE)
981 if (instance==TIM9) return 9;
982 #endif
983 #if defined(TIM10_BASE)
984 if (instance==TIM10) return 10;
985 #endif
986 #if defined(TIM11_BASE)
987 if (instance==TIM11) return 11;
988 #endif
989 #if defined(TIM12_BASE)
990 if (instance==TIM12) return 12;
991 #endif
992 #if defined(TIM13_BASE)
993 if (instance==TIM13) return 13;
994 #endif
995 #if defined(TIM14_BASE)
996 if (instance==TIM14) return 14;
997 #endif
998 #if defined(TIM15_BASE)
999 if (instance==TIM15) return 15;
1000 #endif
1001 #if defined(TIM16_BASE)
1002 if (instance==TIM16) return 16;
1003 #endif
1004 #if defined(TIM17_BASE)
1005 if (instance==TIM17) return 17;
1006 #endif
1007 #if defined(TIM18_BASE)
1008 if (instance==TIM18) return 18;
1009 #endif
1010 #if defined(TIM19_BASE)
1011 if (instance==TIM19) return 19;
1012 #endif
1013 #if defined(TIM20_BASE)
1014 if (instance==TIM20) return 20;
1015 #endif
1016 #if defined(TIM21_BASE)
1017 if (instance==TIM21) return 21;
1018 #endif
1019 #if defined(TIM22_BASE)
1020 if (instance==TIM22) return 22;
1021 #endif
1022 return -1;
1023}
1024
1025
1026void stm32_printTimerCombination(int numPins, PinMap* timers[], int score) {
1027 for (int i=0; i<numPins; i++) {
1028 if (timers[i] == NULL)
1030 else {
1031 SimpleFOCDebug::print("TIM");
1032 SimpleFOCDebug::print(stm32_getTimerNumber((TIM_TypeDef*)timers[i]->peripheral));
1033 SimpleFOCDebug::print("-CH");
1034 SimpleFOCDebug::print(STM_PIN_CHANNEL(timers[i]->function));
1035 if (STM_PIN_INVERTED(timers[i]->function))
1037 }
1039 }
1040 SimpleFOCDebug::println("score: ", score);
1041}
1042
1043#endif
1044
1045
1046#endif
#define SIMPLEFOC_DEBUG(msg,...)
static void print(const char *msg)
static void println()
GenericCurrentSenseParams * params