SimpleFOClibrary 2.4.0
Loading...
Searching...
No Matches
drivers/hardware_specific/rp2040/rp2040_mcu.cpp
Go to the documentation of this file.
1
2/**
3 * Support for the RP2040 MCU, as found on the Raspberry Pi Pico.
4 */
5
6#include "./rp2040_mcu.h"
7
8
9#if defined(TARGET_RP2040) || defined(TARGET_RP2350)
10
11
12#pragma message("")
13#pragma message("SimpleFOC: compiling for RP2040/RP2350")
14#pragma message("")
15
16#if !defined(SIMPLEFOC_DEBUG_RP2040)
17#define SIMPLEFOC_DEBUG_RP2040
18#endif
19
20#include "../../hardware_api.h"
21#include "hardware/pwm.h"
22#include "hardware/clocks.h"
23#if defined(USE_ARDUINO_PINOUT)
24#include <pinDefinitions.h>
25#endif
26
27#define _PWM_FREQUENCY 24000
28#define _PWM_FREQUENCY_MAX 66000
29#define _PWM_FREQUENCY_MIN 1
30
31
32
33// until I can figure out if this can be quickly read from some register, keep it here.
34// it also serves as a marker for what slices are already used.
35uint16_t wrapvalues[NUM_PWM_SLICES];
36
37
38// TODO add checks which channels are already used...
39
40void setupPWM(int pin_nr, long pwm_frequency, bool invert, RP2040DriverParams* params, uint8_t index) {
41 #if defined(USE_ARDUINO_PINOUT)
42 uint pin = (uint)digitalPinToPinName(pin_nr); // we could check for -DBOARD_HAS_PIN_REMAP ?
43 #else
44 uint pin = (uint)pin_nr;
45 #endif
46 gpio_set_function(pin, GPIO_FUNC_PWM);
47 uint slice = pwm_gpio_to_slice_num(pin);
48 uint chan = pwm_gpio_to_channel(pin);
49 params->pins[index] = pin;
50 params->slice[index] = slice;
51 params->chan[index] = chan;
52 uint32_t sysclock_hz = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_SYS) * 1000;
53 uint32_t factor = 4096 * 2 * pwm_frequency;
54 uint32_t div = sysclock_hz / factor;
55 if (sysclock_hz % factor !=0) div+=1;
56 if (div < 16) div = 16;
57 uint32_t wrapvalue = (sysclock_hz * 8) / div / pwm_frequency - 1;
58#if defined(SIMPLEFOC_DEBUG_RP2040) && !defined(SIMPLEFOC_DISABLE_DEBUG)
59 SimpleFOCDebug::print("Configuring pin ");
60 SimpleFOCDebug::print((int)pin);
61 SimpleFOCDebug::print(" slice ");
62 SimpleFOCDebug::print((int)slice);
63 SimpleFOCDebug::print(" channel ");
64 SimpleFOCDebug::print((int)chan);
65 SimpleFOCDebug::print(" frequency ");
66 SimpleFOCDebug::print((int)pwm_frequency);
67 SimpleFOCDebug::print(" divisor ");
68 SimpleFOCDebug::print((int)(div>>4));
70 SimpleFOCDebug::print((int)(div&0xF));
71 SimpleFOCDebug::print(" top value ");
72 SimpleFOCDebug::println((int)wrapvalue);
73 if (wrapvalue < 999)
74 SimpleFOCDebug::println("Warning: PWM resolution is low.");
75#endif
76 pwm_set_clkdiv_int_frac(slice, div>>4, div&0xF);
77 pwm_set_phase_correct(slice, true);
78 pwm_set_wrap(slice, wrapvalue);
79 wrapvalues[slice] = wrapvalue;
80 if (invert) {
81 if (chan==0)
82 hw_write_masked(&pwm_hw->slice[slice].csr, 0x1 << PWM_CH0_CSR_A_INV_LSB, PWM_CH0_CSR_A_INV_BITS);
83 else
84 hw_write_masked(&pwm_hw->slice[slice].csr, 0x1 << PWM_CH0_CSR_B_INV_LSB, PWM_CH0_CSR_B_INV_BITS);
85 }
86 pwm_set_chan_level(slice, chan, 0); // switch off initially
87}
88
89
90void syncSlices() {
91 for (uint i=0;i<NUM_PWM_SLICES;i++) {
92 pwm_set_enabled(i, false);
93 pwm_set_counter(i, 0);
94 }
95 // enable all slices
96 pwm_set_mask_enabled(0xFFF);
97}
98
99
100
101void* _configure1PWM(long pwm_frequency, const int pinA) {
102 RP2040DriverParams* params = new RP2040DriverParams();
103 if( !pwm_frequency || !_isset(pwm_frequency) ) pwm_frequency = _PWM_FREQUENCY;
104 else pwm_frequency = _constrain(pwm_frequency, _PWM_FREQUENCY_MIN, _PWM_FREQUENCY_MAX);
105 params->pwm_frequency = pwm_frequency;
106 setupPWM(pinA, pwm_frequency, !SIMPLEFOC_PWM_ACTIVE_HIGH, params, 0);
107 syncSlices();
108 return params;
109}
110
111
112
113void* _configure2PWM(long pwm_frequency, const int pinA, const int pinB) {
114 RP2040DriverParams* params = new RP2040DriverParams();
115 if( !pwm_frequency || !_isset(pwm_frequency) ) pwm_frequency = _PWM_FREQUENCY;
116 else pwm_frequency = _constrain(pwm_frequency, _PWM_FREQUENCY_MIN, _PWM_FREQUENCY_MAX);
117 params->pwm_frequency = pwm_frequency;
118 setupPWM(pinA, pwm_frequency, !SIMPLEFOC_PWM_ACTIVE_HIGH, params, 0);
119 setupPWM(pinB, pwm_frequency, !SIMPLEFOC_PWM_ACTIVE_HIGH, params, 1);
120 syncSlices();
121 return params;
122}
123
124
125
126void* _configure3PWM(long pwm_frequency, const int pinA, const int pinB, const int pinC) {
127 RP2040DriverParams* params = new RP2040DriverParams();
128 if( !pwm_frequency || !_isset(pwm_frequency) ) pwm_frequency = _PWM_FREQUENCY;
129 else pwm_frequency = _constrain(pwm_frequency, _PWM_FREQUENCY_MIN, _PWM_FREQUENCY_MAX);
130 params->pwm_frequency = pwm_frequency;
131 setupPWM(pinA, pwm_frequency, !SIMPLEFOC_PWM_ACTIVE_HIGH, params, 0);
132 setupPWM(pinB, pwm_frequency, !SIMPLEFOC_PWM_ACTIVE_HIGH, params, 1);
133 setupPWM(pinC, pwm_frequency, !SIMPLEFOC_PWM_ACTIVE_HIGH, params, 2);
134 syncSlices();
135 return params;
136}
137
138
139
140
141void* _configure4PWM(long pwm_frequency, const int pin1A, const int pin1B, const int pin2A, const int pin2B) {
142 RP2040DriverParams* params = new RP2040DriverParams();
143 if( !pwm_frequency || !_isset(pwm_frequency) ) pwm_frequency = _PWM_FREQUENCY;
144 else pwm_frequency = _constrain(pwm_frequency, _PWM_FREQUENCY_MIN, _PWM_FREQUENCY_MAX);
145 params->pwm_frequency = pwm_frequency;
146 setupPWM(pin1A, pwm_frequency, !SIMPLEFOC_PWM_ACTIVE_HIGH, params, 0);
147 setupPWM(pin1B, pwm_frequency, !SIMPLEFOC_PWM_ACTIVE_HIGH, params, 1);
148 setupPWM(pin2A, pwm_frequency, !SIMPLEFOC_PWM_ACTIVE_HIGH, params, 2);
149 setupPWM(pin2B, pwm_frequency, !SIMPLEFOC_PWM_ACTIVE_HIGH, params, 3);
150 syncSlices();
151 return params;
152}
153
154
155void* _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) {
156 // non-PIO solution...
157 RP2040DriverParams* params = new RP2040DriverParams();
158 if( !pwm_frequency || !_isset(pwm_frequency) ) pwm_frequency = _PWM_FREQUENCY;
159 else pwm_frequency = _constrain(pwm_frequency, _PWM_FREQUENCY_MIN, _PWM_FREQUENCY_MAX);
160 params->pwm_frequency = pwm_frequency;
161 params->dead_zone = dead_zone;
162 setupPWM(pinA_h, pwm_frequency, !SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH, params, 0);
163 setupPWM(pinB_h, pwm_frequency, !SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH, params, 2);
164 setupPWM(pinC_h, pwm_frequency, !SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH, params, 4);
165 setupPWM(pinA_l, pwm_frequency, SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH, params, 1);
166 setupPWM(pinB_l, pwm_frequency, SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH, params, 3);
167 setupPWM(pinC_l, pwm_frequency, SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH, params, 5);
168 syncSlices();
169 return params;
170}
171
172
173
174
175
176void writeDutyCycle(float val, uint slice, uint chan) {
177 pwm_set_chan_level(slice, chan, (wrapvalues[slice]+1) * val);
178}
179
180
181
182
183void _writeDutyCycle1PWM(float dc_a, void* params) {
184 writeDutyCycle(dc_a, ((RP2040DriverParams*)params)->slice[0], ((RP2040DriverParams*)params)->chan[0]);
185}
186
187
188
189
190void _writeDutyCycle2PWM(float dc_a, float dc_b, void* params) {
191 writeDutyCycle(dc_a, ((RP2040DriverParams*)params)->slice[0], ((RP2040DriverParams*)params)->chan[0]);
192 writeDutyCycle(dc_b, ((RP2040DriverParams*)params)->slice[1], ((RP2040DriverParams*)params)->chan[1]);
193}
194
195
196
197void _writeDutyCycle3PWM(float dc_a, float dc_b, float dc_c, void* params) {
198 writeDutyCycle(dc_a, ((RP2040DriverParams*)params)->slice[0], ((RP2040DriverParams*)params)->chan[0]);
199 writeDutyCycle(dc_b, ((RP2040DriverParams*)params)->slice[1], ((RP2040DriverParams*)params)->chan[1]);
200 writeDutyCycle(dc_c, ((RP2040DriverParams*)params)->slice[2], ((RP2040DriverParams*)params)->chan[2]);
201}
202
203
204
205void _writeDutyCycle4PWM(float dc_1a, float dc_1b, float dc_2a, float dc_2b, void* params) {
206 writeDutyCycle(dc_1a, ((RP2040DriverParams*)params)->slice[0], ((RP2040DriverParams*)params)->chan[0]);
207 writeDutyCycle(dc_1b, ((RP2040DriverParams*)params)->slice[1], ((RP2040DriverParams*)params)->chan[1]);
208 writeDutyCycle(dc_2a, ((RP2040DriverParams*)params)->slice[2], ((RP2040DriverParams*)params)->chan[2]);
209 writeDutyCycle(dc_2b, ((RP2040DriverParams*)params)->slice[3], ((RP2040DriverParams*)params)->chan[3]);
210}
211
212inline float swDti(float val, float dt) {
213 float ret = dt+val;
214 if (ret>1.0) ret = 1.0f;
215 return ret;
216}
217
218void _writeDutyCycle6PWM(float dc_a, float dc_b, float dc_c, PhaseState *phase_state, void* params) {
220 writeDutyCycle(dc_a, ((RP2040DriverParams*)params)->slice[0], ((RP2040DriverParams*)params)->chan[0]);
221 else
222 writeDutyCycle(0.0f, ((RP2040DriverParams*)params)->slice[0], ((RP2040DriverParams*)params)->chan[0]);
224 writeDutyCycle(swDti(dc_a, ((RP2040DriverParams*)params)->dead_zone), ((RP2040DriverParams*)params)->slice[1], ((RP2040DriverParams*)params)->chan[1]);
225 else
226 writeDutyCycle(0.0f, ((RP2040DriverParams*)params)->slice[1], ((RP2040DriverParams*)params)->chan[1]);
227
229 writeDutyCycle(dc_b, ((RP2040DriverParams*)params)->slice[2], ((RP2040DriverParams*)params)->chan[2]);
230 else
231 writeDutyCycle(0.0f, ((RP2040DriverParams*)params)->slice[2], ((RP2040DriverParams*)params)->chan[2]);
233 writeDutyCycle(swDti(dc_b, ((RP2040DriverParams*)params)->dead_zone), ((RP2040DriverParams*)params)->slice[3], ((RP2040DriverParams*)params)->chan[3]);
234 else
235 writeDutyCycle(0.0f, ((RP2040DriverParams*)params)->slice[3], ((RP2040DriverParams*)params)->chan[3]);
236
238 writeDutyCycle(dc_c, ((RP2040DriverParams*)params)->slice[4], ((RP2040DriverParams*)params)->chan[4]);
239 else
240 writeDutyCycle(0.0f, ((RP2040DriverParams*)params)->slice[4], ((RP2040DriverParams*)params)->chan[4]);
242 writeDutyCycle(swDti(dc_c, ((RP2040DriverParams*)params)->dead_zone), ((RP2040DriverParams*)params)->slice[5], ((RP2040DriverParams*)params)->chan[5]);
243 else
244 writeDutyCycle(0.0f, ((RP2040DriverParams*)params)->slice[5], ((RP2040DriverParams*)params)->chan[5]);
245
247}
248
249#endif
PhaseState
Definition FOCDriver.h:7
@ PHASE_HI
Definition FOCDriver.h:10
@ PHASE_ON
Definition FOCDriver.h:9
@ PHASE_LO
Definition FOCDriver.h:11
static void print(const char *msg)
static void println()
const int const int const int pinC
GenericCurrentSenseParams * params
#define SIMPLEFOC_PWM_ACTIVE_HIGH
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)
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)
#define SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH
void _writeDutyCycle6PWM(float dc_a, float dc_b, float dc_c, PhaseState *phase_state, void *params)
void * _configure1PWM(long pwm_frequency, const int pinA)
#define SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH
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 _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