Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/rp2040/hardware_regs/include/hardware/platform_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,6 @@
#define FIRST_USER_IRQ (NUM_IRQS - NUM_USER_IRQS)
#define VTABLE_FIRST_IRQ 16

#define REG_FIELD_WIDTH(f) (f ## _MSB + 1 - f ## _LSB)

#endif
5 changes: 5 additions & 0 deletions src/rp2040/pico_platform/include/pico/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@
#define PICO_RAM_VECTOR_TABLE_SIZE (VTABLE_FIRST_IRQ + NUM_IRQS)
#endif

// PICO_CONFIG: PICO_CLKDIV_ROUND_NEAREST, True if floating point clock divisors should be rounded to the nearest possible clock divisor by default rather than rounding down, type=bool, default=1, group=pico_platform
#ifndef PICO_CLKDIV_ROUND_NEAREST
#define PICO_CLKDIV_ROUND_NEAREST 1
#endif

#ifndef __ASSEMBLER__

/*! \brief No-op function for the body of tight loops
Expand Down
2 changes: 2 additions & 0 deletions src/rp2350/hardware_regs/include/hardware/platform_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,4 +160,6 @@
#endif
#define FIRST_USER_IRQ (NUM_IRQS - NUM_USER_IRQS)

#define REG_FIELD_WIDTH(f) (f ## _MSB + 1 - f ## _LSB)

#endif
5 changes: 5 additions & 0 deletions src/rp2350/pico_platform/include/pico/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@
#define PICO_USE_STACK_GUARDS 0
#endif

// PICO_CONFIG: PICO_CLKDIV_ROUND_NEAREST, True if floating point clock divisors should be rounded to the nearest possible clock divisor by default rather than rounding down, type=bool, default=1, group=pico_platform
#ifndef PICO_CLKDIV_ROUND_NEAREST
#define PICO_CLKDIV_ROUND_NEAREST 1
#endif

#ifndef __ASSEMBLER__

/*! \brief No-op function for the body of tight loops
Expand Down
13 changes: 11 additions & 2 deletions src/rp2_common/hardware_adc/include/hardware/adc.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@
#define ADC_TEMPERATURE_CHANNEL_NUM (NUM_ADC_CHANNELS - 1)
#endif

// PICO_CONFIG: PICO_ADC_CLKDIV_ROUND_NEAREST, True if floating point ADC clock divisors should be rounded to the nearest possible clock divisor rather than rounding down, type=bool, default=PICO_CLKDIV_ROUND_NEAREST, group=hardware_adc
#ifndef PICO_ADC_CLKDIV_ROUND_NEAREST
#define PICO_ADC_CLKDIV_ROUND_NEAREST PICO_CLKDIV_ROUND_NEAREST
#endif

#ifdef __cplusplus
extern "C" {
#endif
Expand Down Expand Up @@ -197,8 +202,12 @@ static inline void adc_run(bool run) {
* \param clkdiv If non-zero, conversion will be started at intervals rather than back to back.
*/
static inline void adc_set_clkdiv(float clkdiv) {
invalid_params_if(HARDWARE_ADC, clkdiv >= 1 << (ADC_DIV_INT_MSB - ADC_DIV_INT_LSB + 1));
adc_hw->div = (uint32_t)(clkdiv * (float) (1 << ADC_DIV_INT_LSB));
invalid_params_if(HARDWARE_ADC, clkdiv >= 1 << REG_FIELD_WIDTH(ADC_DIV_INT));
const int frac_bit_count = REG_FIELD_WIDTH(ADC_DIV_FRAC);
#if PICO_ADC_CLKDIV_ROUND_NEAREST
clkdiv += 0.5f / (1 << frac_bit_count); // round to the nearest fraction
#endif
adc_hw->div = (uint32_t)(clkdiv * (float) (1 << frac_bit_count));
}

/*! \brief Setup the ADC FIFO
Expand Down
8 changes: 4 additions & 4 deletions src/rp2_common/hardware_clocks/clocks.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,13 +245,13 @@ void clock_gpio_init_int_frac16(uint gpio, uint src, uint32_t div_int, uint16_t
invalid_params_if(HARDWARE_CLOCKS, true);
}

invalid_params_if(HARDWARE_CLOCKS, div_int >> (CLOCKS_CLK_GPOUT0_DIV_INT_MSB - CLOCKS_CLK_GPOUT0_DIV_INT_LSB + 1));
invalid_params_if(HARDWARE_CLOCKS, div_int >> REG_FIELD_WIDTH(CLOCKS_CLK_GPOUT0_DIV_INT));
// Set up the gpclk generator
clocks_hw->clk[gpclk].ctrl = (src << CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_LSB) |
CLOCKS_CLK_GPOUT0_CTRL_ENABLE_BITS;
#if CLOCKS_CLK_GPOUT0_DIV_FRAC_MSB - CLOCKS_CLK_GPOUT0_DIV_FRAC_LSB == 15
#if REG_FIELD_WIDTH(CLOCKS_CLK_GPOUT0_DIV_FRAC) == 16
clocks_hw->clk[gpclk].div = (div_int << CLOCKS_CLK_GPOUT0_DIV_INT_LSB) | (div_frac16 << CLOCKS_CLK_GPOUT0_DIV_FRAC_LSB);
#elif CLOCKS_CLK_GPOUT0_DIV_FRAC_MSB - CLOCKS_CLK_GPOUT0_DIV_FRAC_LSB == 7
#elif REG_FIELD_WIDTH(CLOCKS_CLK_GPOUT0_DIV_FRAC) == 8
clocks_hw->clk[gpclk].div = (div_int << CLOCKS_CLK_GPOUT0_DIV_INT_LSB) | ((div_frac16>>8u) << CLOCKS_CLK_GPOUT0_DIV_FRAC_LSB);
#else
#error unsupported number of fractional bits
Expand Down Expand Up @@ -439,4 +439,4 @@ bool check_sys_clock_khz(uint32_t freq_khz, uint *vco_out, uint *postdiv1_out, u
}
}
return false;
}
}
17 changes: 13 additions & 4 deletions src/rp2_common/hardware_clocks/include/hardware/clocks.h
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,11 @@ extern "C" {
#else
#define PARAM_ASSERTIONS_ENABLED_HARDWARE_CLOCKS 0
#endif
#endif

// PICO_CONFIG: PICO_CLOCK_GPIO_CLKDIV_ROUND_NEAREST, True if floating point GPIO clock divisors should be rounded to the nearest possible clock divisor rather than rounding down, type=bool, default=PICO_CLKDIV_ROUND_NEAREST, group=hardware_clocks
#ifndef PICO_CLOCK_GPIO_CLKDIV_ROUND_NEAREST
#define PICO_CLOCK_GPIO_CLKDIV_ROUND_NEAREST PICO_CLKDIV_ROUND_NEAREST
#endif

typedef clock_num_t clock_handle_t;
Expand Down Expand Up @@ -387,11 +392,15 @@ static inline void clock_gpio_init_int_frac(uint gpio, uint src, uint32_t div_in
static inline void clock_gpio_init(uint gpio, uint src, float div)
{
uint div_int = (uint)div;
#if CLOCKS_CLK_GPOUT0_DIV_FRAC_MSB - CLOCKS_CLK_GPOUT0_DIV_FRAC_LSB == 15
uint16_t frac = (uint16_t)((div - (float)div_int) * (1u << 16));
const int frac_bit_count = REG_FIELD_WIDTH(CLOCKS_CLK_GPOUT0_DIV_FRAC);
#if PICO_CLOCK_GPIO_CLKDIV_ROUND_NEAREST
div += 0.5f / (1 << frac_bit_count); // round to the nearest fraction
#endif
#if REG_FIELD_WIDTH(CLOCKS_CLK_GPOUT0_DIV_FRAC) == 16
uint16_t frac = (uint16_t)((div - (float)div_int) * (1u << frac_bit_count));
clock_gpio_init_int_frac16(gpio, src, div_int, frac);
#elif CLOCKS_CLK_GPOUT0_DIV_FRAC_MSB - CLOCKS_CLK_GPOUT0_DIV_FRAC_LSB == 7
uint8_t frac = (uint8_t)((div - (float)div_int) * (1u << 8));
#elif REG_FIELD_WIDTH(CLOCKS_CLK_GPOUT0_DIV_FRAC) == 8
uint8_t frac = (uint8_t)((div - (float)div_int) * (1u << frac_bit_count));
clock_gpio_init_int_frac8(gpio, src, div_int, frac);
#else
#error unsupported number of fractional bits
Expand Down
22 changes: 16 additions & 6 deletions src/rp2_common/hardware_pio/include/hardware/pio.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@
#define PICO_PIO_VERSION 0
#endif
#endif

// PICO_CONFIG: PICO_PIO_CLKDIV_ROUND_NEAREST, True if floating point PIO clock divisors should be rounded to the nearest possible clock divisor rather than rounding down, type=bool, default=PICO_CLKDIV_ROUND_NEAREST, group=hardware_pio
#ifndef PICO_PIO_CLKDIV_ROUND_NEAREST
#define PICO_PIO_CLKDIV_ROUND_NEAREST PICO_CLKDIV_ROUND_NEAREST
#endif

/** \file hardware/pio.h
* \defgroup hardware_pio hardware_pio
*
Expand Down Expand Up @@ -472,10 +478,10 @@ static inline void sm_config_set_sideset(pio_sm_config *c, uint bit_count, bool
* \sa sm_config_set_clkdiv()
*/
static inline void sm_config_set_clkdiv_int_frac8(pio_sm_config *c, uint32_t div_int, uint8_t div_frac8) {
static_assert(PIO_SM0_CLKDIV_INT_MSB - PIO_SM0_CLKDIV_INT_LSB == 15, "");
static_assert(REG_FIELD_WIDTH(PIO_SM0_CLKDIV_INT) == 16, "");
invalid_params_if(HARDWARE_PIO, div_int >> 16);
invalid_params_if(HARDWARE_PIO, div_int == 0 && div_frac8 != 0);
static_assert(PIO_SM0_CLKDIV_FRAC_MSB - PIO_SM0_CLKDIV_FRAC_LSB == 7, "");
static_assert(REG_FIELD_WIDTH(PIO_SM0_CLKDIV_FRAC) == 8, "");
c->clkdiv =
(((uint)div_frac8) << PIO_SM0_CLKDIV_FRAC_LSB) |
(((uint)div_int) << PIO_SM0_CLKDIV_INT_LSB);
Expand All @@ -488,14 +494,18 @@ static inline void sm_config_set_clkdiv_int_frac(pio_sm_config *c, uint16_t div_

static inline void pio_calculate_clkdiv8_from_float(float div, uint32_t *div_int, uint8_t *div_frac8) {
valid_params_if(HARDWARE_PIO, div >= 1 && div <= 65536);
const int frac_bit_count = REG_FIELD_WIDTH(PIO_SM0_CLKDIV_FRAC);
#if PICO_PIO_CLKDIV_ROUND_NEAREST
div += 0.5f / (1 << frac_bit_count); // round to the nearest 1/256
#endif
*div_int = (uint16_t)div;
// not a strictly necessary check, but if this changes, then this method should
// probably no longer be used in favor of one with a larger fraction
static_assert(PIO_SM0_CLKDIV_FRAC_MSB - PIO_SM0_CLKDIV_FRAC_LSB == 7, "");
static_assert(REG_FIELD_WIDTH(PIO_SM0_CLKDIV_FRAC) == 8, "");
if (*div_int == 0) {
*div_frac8 = 0;
} else {
*div_frac8 = (uint8_t)((div - (float)*div_int) * (1u << 8u));
*div_frac8 = (uint8_t)((div - (float)*div_int) * (1u << frac_bit_count));
}
}

Expand Down Expand Up @@ -1666,10 +1676,10 @@ void pio_sm_drain_tx_fifo(PIO pio, uint sm);
static inline void pio_sm_set_clkdiv_int_frac8(PIO pio, uint sm, uint32_t div_int, uint8_t div_frac8) {
check_pio_param(pio);
check_sm_param(sm);
static_assert(PIO_SM0_CLKDIV_INT_MSB - PIO_SM0_CLKDIV_INT_LSB == 15, "");
static_assert(REG_FIELD_WIDTH(PIO_SM0_CLKDIV_INT) == 16, "");
invalid_params_if(HARDWARE_PIO, div_int >> 16);
invalid_params_if(HARDWARE_PIO, div_int == 0 && div_frac8 != 0);
static_assert(PIO_SM0_CLKDIV_FRAC_MSB - PIO_SM0_CLKDIV_FRAC_LSB == 7, "");
static_assert(REG_FIELD_WIDTH(PIO_SM0_CLKDIV_FRAC) == 8, "");
pio->sm[sm].clkdiv =
(((uint)div_frac8) << PIO_SM0_CLKDIV_FRAC_LSB) |
(((uint)div_int) << PIO_SM0_CLKDIV_INT_LSB);
Expand Down
17 changes: 13 additions & 4 deletions src/rp2_common/hardware_pwm/include/hardware/pwm.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@ static_assert(DREQ_PWM_WRAP7 == DREQ_PWM_WRAP0 + 7, "");
})
#endif

// PICO_CONFIG: PICO_PWM_CLKDIV_ROUND_NEAREST, True if floating point PWM clock divisors should be rounded to the nearest possible clock divisor rather than rounding down, type=bool, default=PICO_CLKDIV_ROUND_NEAREST, group=hardware_pwm
#ifndef PICO_PWM_CLKDIV_ROUND_NEAREST
#define PICO_PWM_CLKDIV_ROUND_NEAREST PICO_CLKDIV_ROUND_NEAREST
#endif

static inline void check_slice_num_param(__unused uint slice_num) {
valid_params_if(HARDWARE_PWM, slice_num < NUM_PWM_SLICES);
}
Expand Down Expand Up @@ -155,7 +160,11 @@ static inline void pwm_config_set_phase_correct(pwm_config *c, bool phase_correc
*/
static inline void pwm_config_set_clkdiv(pwm_config *c, float div) {
valid_params_if(HARDWARE_PWM, div >= 1.f && div < 256.f);
c->div = (uint32_t)(div * (float)(1u << PWM_CH0_DIV_INT_LSB));
const int frac_bit_count = REG_FIELD_WIDTH(PWM_CH0_DIV_FRAC);
#if PICO_PWM_CLKDIV_ROUND_NEAREST
div += 0.5f / (1 << frac_bit_count); // round to the nearest fraction
#endif
c->div = (uint32_t)(div * (float)(1u << frac_bit_count));
}

/** \brief Set PWM clock divider in a PWM configuration using an 8:4 fractional value
Expand All @@ -170,9 +179,9 @@ static inline void pwm_config_set_clkdiv(pwm_config *c, float div) {
* before passing them on to the PWM counter.
*/
static inline void pwm_config_set_clkdiv_int_frac4(pwm_config *c, uint32_t div_int, uint8_t div_frac4) {
static_assert(PWM_CH0_DIV_INT_MSB - PWM_CH0_DIV_INT_LSB == 7, "");
static_assert(REG_FIELD_WIDTH(PWM_CH0_DIV_INT) == 8, "");
valid_params_if(HARDWARE_PWM, div_int >= 1 && div_int < 256);
static_assert(PWM_CH0_DIV_FRAC_MSB - PWM_CH0_DIV_FRAC_LSB == 3, "");
static_assert(REG_FIELD_WIDTH(PWM_CH0_DIV_FRAC) == 4, "");
valid_params_if(HARDWARE_PWM, div_frac4 < 16);
c->div = (((uint)div_int) << PWM_CH0_DIV_INT_LSB) | (((uint)div_frac4) << PWM_CH0_DIV_FRAC_LSB);
}
Expand Down Expand Up @@ -439,7 +448,7 @@ static inline void pwm_retard_count(uint slice_num) {
static inline void pwm_set_clkdiv_int_frac4(uint slice_num, uint8_t div_int, uint8_t div_frac4) {
check_slice_num_param(slice_num);
valid_params_if(HARDWARE_PWM, div_int >= 1);
static_assert(PWM_CH0_DIV_FRAC_MSB - PWM_CH0_DIV_FRAC_LSB == 3, "");
static_assert(REG_FIELD_WIDTH(PWM_CH0_DIV_FRAC) == 4, "");
valid_params_if(HARDWARE_PWM, div_frac4 < 16);
pwm_hw->slice[slice_num].div = (((uint)div_int) << PWM_CH0_DIV_INT_LSB) | (((uint)div_frac4) << PWM_CH0_DIV_FRAC_LSB);
}
Expand Down
Loading