SimpleFOClibrary 2.4.0
Loading...
Searching...
No Matches
stm32_searchtimers.cpp
Go to the documentation of this file.
1
4
5#if defined(_STM32_DEF_) || defined(TARGET_STM32H7)
6
7
8
9/*
10 timer combination scoring function
11 assigns a score, and also checks the combination is valid
12 returns <0 if combination is invalid, >=0 if combination is valid. lower (but positive) score is better
13 for 6 pwm, hardware 6-pwm is preferred over software 6-pwm
14 hardware 6-pwm is possible if each low channel is the inverted counterpart of its high channel
15 inverted channels are not allowed except when using hardware 6-pwm (in theory they could be but lets not complicate things)
16*/
17int _stm32_scoreCombination(int numPins, PinMap* pinTimers[]) {
18 // check already used - TODO move this to outer loop also...
19 for (int i=0; i<numPins; i++) {
20 if (stm32_isChannelUsed(pinTimers[i]))
21 return -2; // bad combination - timer channel already used
22 }
23
24 // TODO LPTIM and HRTIM are ignored for now, it would be cool to support them in the future
25
26 // TODO penalize combinations that re-use the same timers used by other motors
27
28 // check for inverted channels
29 if (numPins < 6) {
30 for (int i=0; i<numPins; i++) {
31 if (STM_PIN_INVERTED(pinTimers[i]->function))
32 return -3; // bad combination - inverted channel used in non-hardware 6pwm
33 }
34 }
35 // check for duplicated channels
36 for (int i=0; i<numPins-1; i++) {
37 for (int j=i+1; j<numPins; j++) {
38 if (pinTimers[i]->peripheral == pinTimers[j]->peripheral
39 && STM_PIN_CHANNEL(pinTimers[i]->function) == STM_PIN_CHANNEL(pinTimers[j]->function)
40 && STM_PIN_INVERTED(pinTimers[i]->function) == STM_PIN_INVERTED(pinTimers[j]->function))
41 return -4; // bad combination - duplicated channel
42 }
43 }
44 int score = 0;
45 for (int i=0; i<numPins; i++) {
46 // count distinct timers
47 bool found = false;
48 for (int j=i+1; j<numPins; j++) {
49 if (pinTimers[i]->peripheral == pinTimers[j]->peripheral)
50 found = true;
51 }
52 if (!found) score++;
53 }
54 if (numPins==6) {
55 // check for inverted channels - best: 1 timer, 3 channels, 3 matching inverted channels
56 // >1 timer, 3 channels, 3 matching inverted channels
57 // 1 timer, 6 channels (no inverted channels)
58 // >1 timer, 6 channels (no inverted channels)
59 // check for inverted high-side channels
60 if (STM_PIN_INVERTED(pinTimers[0]->function) || STM_PIN_INVERTED(pinTimers[2]->function) || STM_PIN_INVERTED(pinTimers[4]->function))
61 return -5; // bad combination - inverted channel used on high-side channel
62 if (pinTimers[0]->peripheral == pinTimers[1]->peripheral
63 && pinTimers[2]->peripheral == pinTimers[3]->peripheral
64 && pinTimers[4]->peripheral == pinTimers[5]->peripheral
65 && STM_PIN_CHANNEL(pinTimers[0]->function) == STM_PIN_CHANNEL(pinTimers[1]->function)
66 && STM_PIN_CHANNEL(pinTimers[2]->function) == STM_PIN_CHANNEL(pinTimers[3]->function)
67 && STM_PIN_CHANNEL(pinTimers[4]->function) == STM_PIN_CHANNEL(pinTimers[5]->function)
68 && STM_PIN_INVERTED(pinTimers[1]->function) && STM_PIN_INVERTED(pinTimers[3]->function) && STM_PIN_INVERTED(pinTimers[5]->function)) {
69 // hardware 6pwm, score <10
70
71 // TODO F37xxx doesn't support dead-time insertion, it has no TIM1/TIM8
72 // F301, F302 --> 6 channels, but only 1-3 have dead-time insertion
73 // TIM2/TIM3/TIM4/TIM5 don't do dead-time insertion
74 // TIM15/TIM16/TIM17 do dead-time insertion only on channel 1
75
76 // TODO check these defines
77 #if defined(STM32F4xx_HAL_TIM_H) || defined(STM32F3xx_HAL_TIM_H) || defined(STM32F2xx_HAL_TIM_H) || defined(STM32F1xx_HAL_TIM_H) || defined(STM32F100_HAL_TIM_H) || defined(STM32FG0x1_HAL_TIM_H) || defined(STM32G0x0_HAL_TIM_H)
78 if (STM_PIN_CHANNEL(pinTimers[0]->function)>3 || STM_PIN_CHANNEL(pinTimers[2]->function)>3 || STM_PIN_CHANNEL(pinTimers[4]->function)>3 )
79 return -8; // channel 4 does not have dead-time insertion
80 #endif
81 #ifdef STM32G4xx_HAL_TIM_H
82 if (STM_PIN_CHANNEL(pinTimers[0]->function)>4 || STM_PIN_CHANNEL(pinTimers[2]->function)>4 || STM_PIN_CHANNEL(pinTimers[4]->function)>4 )
83 return -8; // channels 5 & 6 do not have dead-time insertion
84 #endif
85 }
86 else {
87 // check for inverted low-side channels
88 if (STM_PIN_INVERTED(pinTimers[1]->function) || STM_PIN_INVERTED(pinTimers[3]->function) || STM_PIN_INVERTED(pinTimers[5]->function))
89 return -6; // bad combination - inverted channel used on low-side channel in software 6-pwm
90 if (pinTimers[0]->peripheral != pinTimers[1]->peripheral
91 || pinTimers[2]->peripheral != pinTimers[3]->peripheral
92 || pinTimers[4]->peripheral != pinTimers[5]->peripheral)
93 return -7; // bad combination - non-matching timers for H/L side in software 6-pwm
94 score += 10; // software 6pwm, score >10
95 }
96 }
97 return score;
98}
99
100
101
102
103int _stm32_findIndexOfFirstPinMapEntry(int pin) {
104 PinName pinName = digitalPinToPinName(pin);
105 int i = 0;
106 while (PinMap_TIM[i].pin!=NC) {
107 if (pinName == PinMap_TIM[i].pin)
108 return i;
109 i++;
110 }
111 return -1;
112}
113
114
115int _stm32_findIndexOfLastPinMapEntry(int pin) {
116 PinName pinName = digitalPinToPinName(pin);
117 int i = 0;
118 while (PinMap_TIM[i].pin!=NC) {
119 if ( pinName == (PinMap_TIM[i].pin & ~ALTX_MASK)
120 && pinName != (PinMap_TIM[i+1].pin & ~ALTX_MASK))
121 return i;
122 i++;
123 }
124 return -1;
125}
126
127
128
129
130
131
132#define NOT_FOUND 1000
133
134int _stm32_findBestTimerCombination(int numPins, int index, int pins[], PinMap* pinTimers[]) {
135 PinMap* searchArray[6] = { NULL, NULL, NULL, NULL, NULL, NULL };
136 for (int j=0;j<numPins;j++)
137 searchArray[j] = pinTimers[j];
138 int bestScore = NOT_FOUND;
139 int startIndex = _stm32_findIndexOfFirstPinMapEntry(pins[index]);
140 int endIndex = _stm32_findIndexOfLastPinMapEntry(pins[index]);
141 if (startIndex == -1 || endIndex == -1) {
142 SIMPLEFOC_DEBUG("STM32-DRV: ERR: no timer on pin ", pins[index]);
143 return -1; // pin is not connected to any timer
144 }
145 for (int i=startIndex;i<=endIndex;i++) {
146 searchArray[index] = (PinMap*)&PinMap_TIM[i];
147 int score = NOT_FOUND;
148 if (index<numPins-1)
149 score = _stm32_findBestTimerCombination(numPins, index+1, pins, searchArray);
150 else {
151 score = _stm32_scoreCombination(numPins, searchArray);
152 #if defined(SIMPLEFOC_STM32_DEBUG) && !defined(SIMPLEFOC_DISABLE_DEBUG)
153 stm32_printTimerCombination(numPins, searchArray, score);
154 #endif
155 }
156 if (score==-1)
157 return -1; // pin not connected to any timer, propagate driectly
158 if (score>=0 && score<bestScore) {
159 bestScore = score;
160 for (int j=index;j<numPins;j++)
161 pinTimers[j] = searchArray[j];
162 }
163 }
164 return bestScore;
165}
166
167
168
169
170
171int stm32_findBestTimerCombination(int numPins, int pins[], PinMap* pinTimers[]) {
172 int bestScore = _stm32_findBestTimerCombination(numPins, 0, pins, pinTimers);
173 if (bestScore == NOT_FOUND) {
174 #if defined(SIMPLEFOC_STM32_DEBUG) && !defined(SIMPLEFOC_DISABLE_DEBUG)
175 SimpleFOCDebug::println("STM32-DRV: no workable combination found on these pins");
176 #endif
177 return -10; // no workable combination found
178 }
179 else if (bestScore >= 0) {
180 #if defined(SIMPLEFOC_STM32_DEBUG) && !defined(SIMPLEFOC_DISABLE_DEBUG)
181 SimpleFOCDebug::print("STM32-DRV: best: ");
182 stm32_printTimerCombination(numPins, pinTimers, bestScore);
183 #endif
184 }
185 return bestScore;
186};
187
188
189
190
191
192#endif
193
#define SIMPLEFOC_DEBUG(msg,...)
static void print(const char *msg)
static void println()