Skip to content

Commit 3fc05d2

Browse files
committed
rp2040 (aka Raspberry Pi Pico) support
1 parent 8da3507 commit 3fc05d2

File tree

2 files changed

+165
-0
lines changed

2 files changed

+165
-0
lines changed

src/drivers/hardware_specific/generic_mcu.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
#elif defined(__SAME51J19A__) || defined(__ATSAME51J19A__) // samd51
2020

21+
#elif defined(TARGET_RP2040)
22+
2123
#else
2224

2325
// function setting the high pwm frequency to the supplied pins
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
2+
/**
3+
* Support for the RP2040 MCU, as found on the Raspberry Pi Pico.
4+
*/
5+
#if defined(TARGET_RP2040)
6+
7+
#define SIMPLEFOC_DEBUG_RP2040
8+
9+
10+
#ifdef SIMPLEFOC_DEBUG_RP2040
11+
12+
#ifndef SIMPLEFOC_RP2040_DEBUG_SERIAL
13+
#define SIMPLEFOC_RP2040_DEBUG_SERIAL Serial
14+
#endif
15+
16+
#endif
17+
18+
#include "Arduino.h"
19+
20+
21+
22+
23+
// until I can figure out if this can be quickly read from some register, keep it here.
24+
// it also serves as a marker for what slices are already used.
25+
uint16_t wrapvalues[NUM_PWM_SLICES];
26+
27+
28+
// TODO add checks which channels are already used...
29+
30+
void setupPWM(int pin, long pwm_frequency, bool invert = false) {
31+
gpio_set_function(pin, GPIO_FUNC_PWM);
32+
uint slice = pwm_gpio_to_slice_num(pin);
33+
uint chan = pwm_gpio_to_channel(pin);
34+
pwm_set_clkdiv_int_frac(slice, 1, 0); // fastest pwm we can get
35+
pwm_set_phase_correct(slice, true);
36+
uint16_t wrapvalue = ((125L * 1000L * 1000L) / pwm_frequency) / 2L - 1L;
37+
if (wrapvalue < 999) wrapvalue = 999; // 66kHz, resolution 1000
38+
if (wrapvalue > 3299) wrapvalue = 3299; // 20kHz, resolution 3300
39+
#ifdef SIMPLEFOC_DEBUG_RP2040
40+
SIMPLEFOC_RP2040_DEBUG_SERIAL.print("Configuring pin ");
41+
SIMPLEFOC_RP2040_DEBUG_SERIAL.print(pin);
42+
SIMPLEFOC_RP2040_DEBUG_SERIAL.print(" slice ");
43+
SIMPLEFOC_RP2040_DEBUG_SERIAL.print(slice);
44+
SIMPLEFOC_RP2040_DEBUG_SERIAL.print(" channel ");
45+
SIMPLEFOC_RP2040_DEBUG_SERIAL.print(chan);
46+
SIMPLEFOC_RP2040_DEBUG_SERIAL.print(" frequency ");
47+
SIMPLEFOC_RP2040_DEBUG_SERIAL.print(pwm_frequency);
48+
SIMPLEFOC_RP2040_DEBUG_SERIAL.print(" top value ");
49+
SIMPLEFOC_RP2040_DEBUG_SERIAL.println(wrapvalue);
50+
#endif
51+
pwm_set_wrap(slice, wrapvalue);
52+
wrapvalues[slice] = wrapvalue;
53+
if (invert) {
54+
if (chan==0)
55+
hw_write_masked(&pwm_hw->slice[slice].csr, 0x1 << PWM_CH0_CSR_A_INV_LSB, PWM_CH0_CSR_A_INV_BITS);
56+
else
57+
hw_write_masked(&pwm_hw->slice[slice].csr, 0x1 << PWM_CH0_CSR_B_INV_LSB, PWM_CH0_CSR_B_INV_BITS);
58+
}
59+
pwm_set_chan_level(slice, chan, 0); // switch off initially
60+
}
61+
62+
63+
void syncSlices() {
64+
for (int i=0;i<NUM_PWM_SLICES;i++) {
65+
pwm_set_enabled(i, false);
66+
pwm_set_counter(i, 0);
67+
}
68+
// enable all slices
69+
pwm_set_mask_enabled(0x7F);
70+
}
71+
72+
73+
void _configure2PWM(long pwm_frequency, const int pinA, const int pinB) {
74+
setupPWM(pinA, pwm_frequency);
75+
setupPWM(pinB, pwm_frequency);
76+
syncSlices();
77+
}
78+
79+
80+
81+
void _configure3PWM(long pwm_frequency, const int pinA, const int pinB, const int pinC) {
82+
setupPWM(pinA, pwm_frequency);
83+
setupPWM(pinB, pwm_frequency);
84+
setupPWM(pinC, pwm_frequency);
85+
syncSlices();
86+
}
87+
88+
89+
90+
91+
void _configure4PWM(long pwm_frequency, const int pin1A, const int pin1B, const int pin2A, const int pin2B) {
92+
setupPWM(pin1A, pwm_frequency);
93+
setupPWM(pin1B, pwm_frequency);
94+
setupPWM(pin2A, pwm_frequency);
95+
setupPWM(pin2B, pwm_frequency);
96+
syncSlices();
97+
}
98+
99+
100+
int _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) {
101+
// non-PIO solution...
102+
setupPWM(pinA_h, pwm_frequency);
103+
setupPWM(pinB_h, pwm_frequency);
104+
setupPWM(pinC_h, pwm_frequency);
105+
setupPWM(pinA_l, pwm_frequency, true);
106+
setupPWM(pinB_l, pwm_frequency, true);
107+
setupPWM(pinC_l, pwm_frequency, true);
108+
syncSlices();
109+
return 0;
110+
}
111+
112+
113+
114+
115+
116+
void writeDutyCycle(float val, int pin) {
117+
uint slice = pwm_gpio_to_slice_num(pin);
118+
uint chan = pwm_gpio_to_channel(pin);
119+
pwm_set_chan_level(slice, chan, (wrapvalues[slice]+1) * val);
120+
}
121+
122+
123+
124+
125+
126+
void _writeDutyCycle2PWM(float dc_a, float dc_b, int pinA, int pinB) {
127+
writeDutyCycle(dc_a, pinA);
128+
writeDutyCycle(dc_b, pinB);
129+
}
130+
131+
132+
133+
void _writeDutyCycle3PWM(float dc_a, float dc_b, float dc_c, int pinA, int pinB, int pinC) {
134+
writeDutyCycle(dc_a, pinA);
135+
writeDutyCycle(dc_b, pinB);
136+
writeDutyCycle(dc_c, pinC);
137+
}
138+
139+
140+
141+
void _writeDutyCycle4PWM(float dc_1a, float dc_1b, float dc_2a, float dc_2b, int pin1A, int pin1B, int pin2A, int pin2B) {
142+
writeDutyCycle(dc_1a, pin1A);
143+
writeDutyCycle(dc_1b, pin1B);
144+
writeDutyCycle(dc_2a, pin2A);
145+
writeDutyCycle(dc_2b, pin2B);
146+
}
147+
148+
inline float swDti(float val, float dt) {
149+
float ret = dt+val;
150+
if (ret>1.0) ret = 1.0;
151+
return ret;
152+
}
153+
154+
void _writeDutyCycle6PWM(float dc_a, float dc_b, float dc_c, float dead_zone, int pinA_h, int pinA_l, int pinB_h, int pinB_l, int pinC_h, int pinC_l) {
155+
writeDutyCycle(dc_a, pinA_h);
156+
writeDutyCycle(swDti(dc_a, dead_zone), pinA_l);
157+
writeDutyCycle(dc_b, pinB_h);
158+
writeDutyCycle(swDti(dc_b,dead_zone), pinB_l);
159+
writeDutyCycle(dc_c, pinC_h);
160+
writeDutyCycle(swDti(dc_c,dead_zone), pinC_l);
161+
}
162+
163+
#endif

0 commit comments

Comments
 (0)