SimpleFOClibrary 2.4.0
Loading...
Searching...
No Matches
drivers/hardware_specific/silabs/efr32_mcu.cpp
Go to the documentation of this file.
1// File: efr32_mcu.cpp
2
3#if defined(ARDUINO_ARCH_SILABS)
4
5#include <em_device.h>
6#include <em_prs.h>
7#include "efr32_pwm.h"
8#include "efr32_mcu.h"
9
10void _getPrsSourceAndUnderflowSignal(
11 TIMER_TypeDef *timer,
12 uint32_t *source,
13 uint32_t *signal
14) {
15 if (!timer || !source || !signal) return;
16
17 switch ((uint32_t) timer) {
18 case TIMER0_BASE:
19 *source = PRS_ASYNC_CH_CTRL_SOURCESEL_TIMER0;
20 *signal = PRS_ASYNC_CH_CTRL_SIGSEL_TIMER0UF;
21 break;
22
23 case TIMER1_BASE:
24 *source = PRS_ASYNC_CH_CTRL_SOURCESEL_TIMER1;
25 *signal = PRS_ASYNC_CH_CTRL_SIGSEL_TIMER1UF;
26 break;
27
28 case TIMER2_BASE:
29 *source = PRS_ASYNC_CH_CTRL_SOURCESEL_TIMER2;
30 *signal = PRS_ASYNC_CH_CTRL_SIGSEL_TIMER2UF;
31 break;
32
33 default:
34 break;
35 }
36}
37
38// Callbacks
39static void _alignPWMTimers(
40 TIMER_InitCC_TypeDef *initCC,
41 void *params
42) {
43 EFR32PwmInstance *p = (EFR32PwmInstance*)params;
44 if (!p || !initCC) return;
45
46 CMU_ClockEnable(cmuClock_PRS, true);
47
48 uint32_t prsSource, prsSignal;
49
50 initCC->prsInputType = timerPrsInputAsyncPulse;
51 initCC->prsInput = true;
52 initCC->prsSel = SILABS_PWM_PRS_CHANNEL;
53
54 _getPrsSourceAndUnderflowSignal(p->h.timer, &prsSource, &prsSignal);
55 PRS_SourceAsyncSignalSet(SILABS_PWM_PRS_CHANNEL, prsSource, prsSignal);
56}
57
58static void _configPWMMode(
59 TIMER_Init_TypeDef *init,
60 void *params
61) {
62 if (!init) return;
64 init->mode = timerModeUpDown;
65}
66
67static void _alignPWMStart(
68 TIMER_Init_TypeDef *init,
69 void *params
70) {
71 if (!init) return;
73 init->mode = timerModeUpDown;
74 init->riseAction = timerInputActionReloadStart;
75}
76
77static void _setSinglePhaseState(EFR32PwmInstance *inst, PhaseState state) {
78 if (!inst) return;
79
80 switch (state) {
82 pwmOff(inst);
83 break;
84
85 default:
86 pwmOn(inst);
87 break;
88 }
89}
90
91void *_configure1PWM(long pwm_frequency, const int pinA) {
92 EFR32DriverParams* params = new EFR32DriverParams;
94
95 if (!pwm_frequency || !_isset(pwm_frequency)) pwm_frequency = SILABS_DEFAULT_PWM_FREQUENCY;
96 else pwm_frequency = _constrain(pwm_frequency, 0, SILABS_DEFAULT_PWM_FREQUENCY);
97
98 params->pwm_frequency = pwm_frequency;
99 params->noPwmChannel = 1;
100
101 // Ensure all PWMs use the same TIMER instance
102 pwmHiConfig(&params->inst[0], SILABS_DEFAULT_PWM_PERPHERAL, pinA, 0);
103
104 // Initialize PWM
105 EFR32PwmConfig pwmConfig;
106 pwmConfig.frequency = pwm_frequency;
107 pwmConfig.polarity = PWM_P_ACTIVE_LOW;
108 pwmConfig.outInvert = true;
109
110 pwmHiInit(&params->inst[0], &pwmConfig, NULL, NULL);
111
112 // PWM On
113 pwmHiOn(&params->inst[0]);
114
115 // Start PWM
116 pwmStart(&params->inst[0], _configPWMMode, NULL);
117
118 return params;
119}
120
121void* _configure2PWM(long pwm_frequency, const int pinA, const int pinB) {
122 EFR32DriverParams *params = new EFR32DriverParams;
124
125 if (!pwm_frequency || !_isset(pwm_frequency)) pwm_frequency = SILABS_DEFAULT_PWM_FREQUENCY;
126 else pwm_frequency = _constrain(pwm_frequency, 0, SILABS_DEFAULT_PWM_FREQUENCY);
127
128 params->pwm_frequency = pwm_frequency;
129 params->noPwmChannel = 2;
130
131 // Ensure all PWMs use the same TIMER instance
132 pwmHiConfig(&params->inst[0], SILABS_DEFAULT_PWM_PERPHERAL, pinA, 0);
133 pwmHiConfig(&params->inst[1], SILABS_DEFAULT_PWM_PERPHERAL, pinB, 1);
134
135 // Initialize PWM
136 EFR32PwmConfig pwmConfig;
137 pwmConfig.frequency = pwm_frequency << 1;
138 pwmConfig.polarity = PWM_P_ACTIVE_LOW;
139 pwmConfig.outInvert = true;
140
141 pwmHiInit(&params->inst[0], &pwmConfig, NULL, NULL);
142 pwmHiInit(&params->inst[1], &pwmConfig, NULL, NULL);
143
144 // PWM On
145 pwmHiOn(&params->inst[0]);
146 pwmHiOn(&params->inst[1]);
147
148 // Start PWM
149 pwmStart(&params->inst[0], _configPWMMode, NULL);
150
151 return params;
152}
153
154void* _configure3PWM(
155 long pwm_frequency,
156 const int pinA,
157 const int pinB,
158 const int pinC
159) {
160 EFR32DriverParams *params = new EFR32DriverParams;
162
163 if (!pwm_frequency || !_isset(pwm_frequency)) pwm_frequency = SILABS_DEFAULT_PWM_FREQUENCY;
164 else pwm_frequency = _constrain(pwm_frequency, 0, SILABS_DEFAULT_PWM_FREQUENCY);
165
166 params->pwm_frequency = pwm_frequency;
167 params->noPwmChannel = 3;
168
169 // Ensure all PWMs use the same TIMER instance
170 pwmHiConfig(&params->inst[0], SILABS_DEFAULT_PWM_PERPHERAL, pinA, 0);
171 pwmHiConfig(&params->inst[1], SILABS_DEFAULT_PWM_PERPHERAL, pinB, 1);
172 pwmHiConfig(&params->inst[2], SILABS_DEFAULT_PWM_PERPHERAL, pinC, 2);
173
174 // Initialize PWM
175 EFR32PwmConfig pwmConfig;
176 pwmConfig.frequency = pwm_frequency << 1;
177 pwmConfig.polarity = PWM_P_ACTIVE_LOW;
178 pwmConfig.outInvert = true;
179
180 pwmHiInit(&params->inst[0], &pwmConfig, NULL, NULL);
181 pwmHiInit(&params->inst[1], &pwmConfig, NULL, NULL);
182 pwmHiInit(&params->inst[2], &pwmConfig, NULL, NULL);
183
184 // PWM On
185 pwmHiOn(&params->inst[0]);
186 pwmHiOn(&params->inst[1]);
187 pwmHiOn(&params->inst[2]);
188
189 // Start PWM
190 pwmStart(&params->inst[0], _configPWMMode, NULL);
191
192 return params;
193}
194
195void* _configure4PWM(
196 long pwm_frequency,
197 const int pin1A,
198 const int pin1B,
199 const int pin2A,
200 const int pin2B
201) {
202 EFR32DriverParams *params = new EFR32DriverParams;
204
205 if (!pwm_frequency || !_isset(pwm_frequency)) pwm_frequency = SILABS_DEFAULT_PWM_FREQUENCY;
206 else pwm_frequency = _constrain(pwm_frequency, 0, SILABS_DEFAULT_PWM_FREQUENCY);
207
208 params->pwm_frequency = pwm_frequency;
209 params->noPwmChannel = 4;
210
211 // Ensure all PWMs use the same TIMER instance
212 pwmHiConfig(&params->inst[0], SILABS_DEFAULT_PWM_PERPHERAL, pin1A, 0);
213 pwmHiConfig(&params->inst[1], SILABS_DEFAULT_PWM_PERPHERAL, pin1B, 1);
214 pwmHiConfig(&params->inst[2], SILABS_DEFAULT_PWM_PERPHERAL, pin2A, 2);
215 pwmHiConfig(&params->inst[3], SILABS_SECOND_PWM_PERPHERAL , pin2B, 0);
216
217 // Initialize PWM
218 EFR32PwmConfig pwmConfig;
219 pwmConfig.frequency = pwm_frequency << 1;
220 pwmConfig.polarity = PWM_P_ACTIVE_LOW;
221 pwmConfig.outInvert = true;
222
223 pwmHiInit(&params->inst[0], &pwmConfig, NULL, NULL);
224 pwmHiInit(&params->inst[1], &pwmConfig, NULL, NULL);
225 pwmHiInit(&params->inst[2], &pwmConfig, NULL, NULL);
226 pwmHiInit(&params->inst[3], &pwmConfig, _alignPWMTimers, &params->inst[0]);
227
228 // PWM On
229 pwmHiOn(&params->inst[0]);
230 pwmHiOn(&params->inst[1]);
231 pwmHiOn(&params->inst[2]);
232 pwmHiOn(&params->inst[3]);
233
234 // Start PWM
235 pwmStart(&params->inst[0], _configPWMMode, NULL);
236 pwmStart(&params->inst[3], _alignPWMStart, NULL);
237
238 return params;
239}
240
241void* _configure6PWM(
242 long pwm_frequency,
243 float dead_zone,
244 const int pinA_h,
245 const int pinA_l,
246 const int pinB_h,
247 const int pinB_l,
248 const int pinC_h,
249 const int pinC_l
250) {
251 EFR32DriverParams *params = new EFR32DriverParams;
253
254 if (!pwm_frequency || !_isset(pwm_frequency)) pwm_frequency = SILABS_DEFAULT_PWM_FREQUENCY;
255 else pwm_frequency = _constrain(pwm_frequency, 0, SILABS_DEFAULT_PWM_FREQUENCY);
256
257 params->pwm_frequency = pwm_frequency;
258 params->dead_zone = (dead_zone == NOT_SET) ? SILABS_DEFAULT_DEAD_ZONE : dead_zone;
259 params->lowside = true;
260 params->noPwmChannel = 3;
261
262 // Ensure all PWMs use the same TIMER instance
263 pwmHiConfig(&params->inst[0], SILABS_DEFAULT_PWM_PERPHERAL, pinA_h, 0);
264 pwmLoConfig(&params->inst[0], pinA_l);
265
266 pwmHiConfig(&params->inst[1], SILABS_DEFAULT_PWM_PERPHERAL, pinB_h, 1);
267 pwmLoConfig(&params->inst[1], pinB_l);
268
269 pwmHiConfig(&params->inst[2], SILABS_DEFAULT_PWM_PERPHERAL, pinC_h, 2);
270 pwmLoConfig(&params->inst[2], pinC_l);
271
272 // Initialize PWM
273 EFR32PwmConfig pwmConfig;
274 pwmConfig.frequency = pwm_frequency << 1;
275 pwmConfig.polarity = PWM_P_ACTIVE_LOW;
276 pwmConfig.outInvert = true;
277
278 pwmInit(&params->inst[0], &pwmConfig, NULL, NULL);
279 pwmInit(&params->inst[1], &pwmConfig, NULL, NULL);
280 pwmInit(&params->inst[2], &pwmConfig, NULL, NULL);
281
282 // Dead Time PWM
283 uint32_t deadTimeNs = (float) (1e9f / pwm_frequency) * dead_zone;
284 EFR32PwmDeadTimeConfig deadTimeConfig;
285 deadTimeConfig.deadTimeNs = deadTimeNs >> 1;
286 deadTimeConfig.outputMask = TIMER_DTOGEN_DTOGCC0EN
287 | TIMER_DTOGEN_DTOGCC1EN
288 | TIMER_DTOGEN_DTOGCC2EN
289 | TIMER_DTOGEN_DTOGCDTI0EN
290 | TIMER_DTOGEN_DTOGCDTI1EN
291 | TIMER_DTOGEN_DTOGCDTI2EN;
292 pwmDeadTimeInit(&params->inst[0], &deadTimeConfig);
293
294 // PWM On
295 pwmOn(&params->inst[0]);
296 pwmOn(&params->inst[1]);
297 pwmOn(&params->inst[2]);
298
299 // Start PWM
300 pwmStart(&params->inst[0], _configPWMMode, NULL);
301
302 return params;
303}
304
305void _writeDutyCycle1PWM(float dc_a, void* params) {
306 EFR32DriverParams *p = (EFR32DriverParams*) params;
307 if (!p) return;
308
309 pwmHiSetDutyCycle(&p->inst[0], dc_a * 100.0f);
310}
311
312void _writeDutyCycle2PWM(float dc_a, float dc_b, void* params) {
313 EFR32DriverParams *p = (EFR32DriverParams*) params;
314 if (!p) return;
315
316 pwmHiSetDutyCycle(&p->inst[0], dc_a * 100.0f);
317 pwmHiSetDutyCycle(&p->inst[1], dc_b * 100.0f);
318}
319
320void _writeDutyCycle3PWM(float dc_a, float dc_b, float dc_c, void* params) {
321 EFR32DriverParams *p = (EFR32DriverParams*) params;
322 if (!p) return;
323
324 pwmHiSetDutyCycle(&p->inst[0], dc_a * 100.0f);
325 pwmHiSetDutyCycle(&p->inst[1], dc_b * 100.0f);
326 pwmHiSetDutyCycle(&p->inst[2], dc_c * 100.0f);
327}
328
330 float dc_1a,
331 float dc_1b,
332 float dc_2a,
333 float dc_2b,
334 void* params
335) {
336 EFR32DriverParams *p = (EFR32DriverParams*) params;
337 if (!p) return;
338
339 pwmHiSetDutyCycle(&p->inst[0], dc_1a * 100.0f);
340 pwmHiSetDutyCycle(&p->inst[1], dc_1b * 100.0f);
341 pwmHiSetDutyCycle(&p->inst[2], dc_2a * 100.0f);
342 pwmHiSetDutyCycle(&p->inst[3], dc_2b * 100.0f);
343}
344
346 float dc_a,
347 float dc_b,
348 float dc_c,
350 void* params
351) {
352 EFR32DriverParams *p = (EFR32DriverParams*) params;
353 if (!p || !phase_state) return;
354
355 _setSinglePhaseState(&p->inst[0], phase_state[0]);
356 if (phase_state[0] == PhaseState::PHASE_OFF) dc_a = 0.0f;
357 pwmHiSetDutyCycle(&p->inst[0], dc_a * 100);
358
359 _setSinglePhaseState(&p->inst[1], phase_state[1]);
360 if (phase_state[1] == PhaseState::PHASE_OFF) dc_b = 0.0f;
361 pwmHiSetDutyCycle(&p->inst[1], dc_b * 100.0f);
362
363 _setSinglePhaseState(&p->inst[2], phase_state[2]);
364 if (phase_state[2] == PhaseState::PHASE_OFF) dc_c = 0.0f;
365 pwmHiSetDutyCycle(&p->inst[2], dc_c * 100.0f);
366}
367
368#endif
PhaseState
Definition FOCDriver.h:7
@ PHASE_OFF
Definition FOCDriver.h:8
const int const int const int pinC
GenericCurrentSenseParams * params
void * _configure4PWM(long pwm_frequency, const int pin1A, const int pin1B, const int pin2A, const int pin2B)
void * _configure6PWM(long pwm_frequency, float dead_zone, const int pinA_h, const int pinA_l, const int pinB_h, const int pinB_l, const int pinC_h, const int pinC_l)
void * _configure2PWM(long pwm_frequency, const int pinA, const int pinB)
void _writeDutyCycle2PWM(float dc_a, float dc_b, void *params)
void _writeDutyCycle1PWM(float dc_a, void *params)
#define SIMPLEFOC_DRIVER_INIT_FAILED
void _writeDutyCycle4PWM(float dc_1a, float dc_1b, float dc_2a, float dc_2b, void *params)
void * _configure3PWM(long pwm_frequency, const int pinA, const int pinB, const int pinC)
void _writeDutyCycle6PWM(float dc_a, float dc_b, float dc_c, PhaseState *phase_state, void *params)
void * _configure1PWM(long pwm_frequency, const int pinA)
void _writeDutyCycle3PWM(float dc_a, float dc_b, float dc_c, void *params)
float const int const int const int pinB_h
float const int const int const int const int pinB_l
const int const int pin1B
const int const int const int pin2A
float const int const int const int const int const int pinC_h
float float float dc_2b
float float PhaseState * phase_state
float const int const int const int const int const int const int pinC_l
float const int const int pinA_l
const int const int const int const int pin2B
#define NOT_SET
Definition foc_utils.h:34
#define _UNUSED(v)
Definition foc_utils.h:14
#define _isset(a)
Definition foc_utils.h:13
#define _constrain(amt, low, high)
Definition foc_utils.h:11