Skip to content

Commit b2ec4bd

Browse files
authored
Merge upstream changes
Upstream sync
2 parents 49b41d1 + 594ec7e commit b2ec4bd

4 files changed

Lines changed: 36 additions & 34 deletions

File tree

src/rp2040/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ config RPXXXX_SELECT
1414
select HAVE_GPIO_HARD_PWM
1515
select HAVE_STEPPER_OPTIMIZED_BOTH_EDGE
1616
select HAVE_BOOTLOADER_REQUEST
17-
# Software divide needed on rp2040 in spi rate, i2c rate, hard_pwm rate
17+
# Software divide needed on rp2040 for rate calculation in i2c.c
1818
select HAVE_SOFTWARE_DIVIDE_REQUIRED if MACH_RP2040
1919

2020
config BOARD_DIRECTORY

src/rp2040/gpio.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,9 @@ uint8_t gpio_in_read(struct gpio_in g);
2323

2424
struct gpio_pwm {
2525
void *reg;
26-
uint8_t shift;
27-
uint32_t mask;
26+
uint32_t hwpwm_ticks, shift, mask;
2827
};
29-
struct gpio_pwm gpio_pwm_setup(uint8_t pin, uint32_t cycle_time, uint8_t val);
28+
struct gpio_pwm gpio_pwm_setup(uint8_t pin, uint32_t cycle_time, uint32_t val);
3029
void gpio_pwm_write(struct gpio_pwm g, uint32_t val);
3130

3231
struct gpio_adc {

src/rp2040/hard_pwm.c

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@
1313
#include "hardware/structs/iobank0.h" // iobank0_hw
1414
#include "hardware/regs/resets.h" // RESETS_RESET_PWM_BITS
1515

16-
#define MAX_PWM 255
16+
#define MAX_PWM (1<<15)
1717
DECL_CONSTANT("PWM_MAX", MAX_PWM);
1818

1919
struct gpio_pwm
20-
gpio_pwm_setup(uint8_t pin, uint32_t cycle_time, uint8_t val) {
20+
gpio_pwm_setup(uint8_t pin, uint32_t cycle_time, uint32_t val)
21+
{
2122
if(pin >= 30)
2223
shutdown("invalid gpio pin");
2324

@@ -26,33 +27,32 @@ gpio_pwm_setup(uint8_t pin, uint32_t cycle_time, uint8_t val) {
2627
pwm_slice_hw_t * slice = &pwm_hw->slice[(pin >> 1) & 0x7];
2728
uint8_t channel = pin & 1;
2829

29-
// Map cycle_time to clock divider
3030
// The rp2040 has an 8.4 fractional divider, so we'll map the requested
3131
// cycle time into that. The cycle_time we receive from Klippy is in
3232
// relation to the crystal frequency and so we need to scale it up to match
3333
// the PWM clock.
34-
// For better precision, we introduce a scale factor such that pclk * scale
35-
// doesn't overflow. We then multiply by this scale factor at the beginning
36-
// and divide by it at the end.
3734
uint32_t pclk = get_pclock_frequency(RESETS_RESET_PWM_BITS);
38-
uint32_t scale = 1 << __builtin_clz(pclk);
39-
uint32_t clock_mult = (scale * get_pclock_frequency(RESETS_RESET_PWM_BITS))
40-
/ CONFIG_CLOCK_FREQ;
41-
uint32_t cycle_clocks = clock_mult * cycle_time;
42-
uint32_t div_int = cycle_clocks / MAX_PWM / scale;
43-
uint32_t div_frac = (cycle_clocks - div_int * MAX_PWM * scale) * 16
44-
/ MAX_PWM / scale;
35+
uint32_t mult_16ticks = 16ULL * pclk / CONFIG_CLOCK_FREQ;
36+
uint64_t cycle_16ticks_64 = (uint64_t)cycle_time * mult_16ticks;
37+
if (cycle_16ticks_64 > 0x80000000)
38+
// Host never sends large cycle_time, so no need for elaborate handling
39+
cycle_16ticks_64 = 0x80000000;
40+
uint32_t cycle_16ticks = cycle_16ticks_64;
4541

46-
// Clamp range of the divider
47-
if(div_int > 255) {
48-
div_int = 255;
49-
div_frac = 15;
50-
} else if(div_int < 1) {
51-
div_int = 1;
52-
div_frac = 0;
42+
// Convert requested cycle time (cycle_time/CLOCK_FREQ) to actual
43+
// cycle time (hwpwm_ticks*(pwm_div/16)/FREQ_SYS).
44+
uint32_t hwpwm_ticks, pwm_div, shift = 4;
45+
for (;;) {
46+
hwpwm_ticks = (cycle_16ticks + (1 << (shift-1))) >> shift;
47+
pwm_div = 1 << shift;
48+
if (hwpwm_ticks <= UINT16_MAX)
49+
break;
50+
shift += 1;
5351
}
54-
55-
uint32_t pwm_div = div_int << 4 | div_frac;
52+
if (pwm_div > 0xfff)
53+
pwm_div = 0xfff;
54+
if (hwpwm_ticks < 2)
55+
hwpwm_ticks = 2;
5656

5757
// Enable clock
5858
if (!is_enabled_pclock(RESETS_RESET_PWM_BITS))
@@ -65,12 +65,12 @@ gpio_pwm_setup(uint8_t pin, uint32_t cycle_time, uint8_t val) {
6565
// as long as their cycle times are the same.
6666
if(!(slice->csr & PWM_CH0_CSR_EN_BITS)) {
6767
slice->div = pwm_div;
68-
slice->top = MAX_PWM - 1;
68+
slice->top = hwpwm_ticks - 1;
6969
slice->ctr = PWM_CH0_CTR_RESET;
7070
slice->cc = PWM_CH0_CC_RESET;
7171
slice->csr = PWM_CH0_CSR_EN_BITS;
7272
} else {
73-
if (slice->div != pwm_div)
73+
if (slice->div != pwm_div || slice->top != hwpwm_ticks - 1)
7474
shutdown("PWM pin has different cycle time from another in "
7575
"the same slice");
7676

@@ -86,6 +86,7 @@ gpio_pwm_setup(uint8_t pin, uint32_t cycle_time, uint8_t val) {
8686

8787
struct gpio_pwm out;
8888
out.reg = (void*)&slice->cc;
89+
out.hwpwm_ticks = hwpwm_ticks;
8990
out.shift = channel ? PWM_CH0_CC_B_LSB : PWM_CH0_CC_A_LSB;
9091
out.mask = channel ? PWM_CH0_CC_B_BITS : PWM_CH0_CC_A_BITS;
9192

@@ -96,6 +97,8 @@ gpio_pwm_setup(uint8_t pin, uint32_t cycle_time, uint8_t val) {
9697
}
9798

9899
void
99-
gpio_pwm_write(struct gpio_pwm g, uint32_t val) {
100-
hw_write_masked((uint32_t*)g.reg, val << g.shift, g.mask);
100+
gpio_pwm_write(struct gpio_pwm g, uint32_t val)
101+
{
102+
uint32_t r = DIV_ROUND_CLOSEST(val * g.hwpwm_ticks, MAX_PWM);
103+
hw_write_masked((uint32_t*)g.reg, r << g.shift, g.mask);
101104
}

src/rp2040/spi.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,15 +86,15 @@ spi_setup(uint32_t bus, uint8_t mode, uint32_t rate)
8686

8787
struct spi_config res = {spi_bus[bus].spi, 0, 0};
8888

89-
uint8_t prescale;
89+
uint32_t prescale;
9090
for (prescale = 2; prescale <= 254; prescale += 2) {
91-
if (pclk < (prescale + 2) * 256 * rate)
91+
if ((prescale + 2) * 256 * rate > pclk)
9292
break;
9393
}
9494

95-
uint8_t postdiv;
95+
uint32_t postdiv;
9696
for (postdiv = 255; postdiv > 0; --postdiv) {
97-
if ((pclk / (prescale * postdiv)) > rate)
97+
if (prescale * postdiv * rate < pclk)
9898
break;
9999
}
100100

0 commit comments

Comments
 (0)