From 4b8488031c917d20dda88fd419dedfc79c2b92a6 Mon Sep 17 00:00:00 2001 From: Andrew Scheller Date: Wed, 20 Nov 2024 18:43:35 +0000 Subject: [PATCH] Add a new REG_FIELD_WIDTH macro, and make the calculation of the clock-dividers more consistent --- .../include/hardware/platform_defs.h | 2 ++ .../include/hardware/platform_defs.h | 2 ++ .../hardware_adc/include/hardware/adc.h | 7 ++++--- src/rp2_common/hardware_clocks/clocks.c | 8 ++++---- .../hardware_clocks/include/hardware/clocks.h | 11 ++++++----- .../hardware_pio/include/hardware/pio.h | 15 ++++++++------- .../hardware_pwm/include/hardware/pwm.h | 11 ++++++----- 7 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/rp2040/hardware_regs/include/hardware/platform_defs.h b/src/rp2040/hardware_regs/include/hardware/platform_defs.h index 54d9344c8..1d23b9d12 100644 --- a/src/rp2040/hardware_regs/include/hardware/platform_defs.h +++ b/src/rp2040/hardware_regs/include/hardware/platform_defs.h @@ -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 diff --git a/src/rp2350/hardware_regs/include/hardware/platform_defs.h b/src/rp2350/hardware_regs/include/hardware/platform_defs.h index 6e5eba2f7..bd8b68a9f 100644 --- a/src/rp2350/hardware_regs/include/hardware/platform_defs.h +++ b/src/rp2350/hardware_regs/include/hardware/platform_defs.h @@ -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 diff --git a/src/rp2_common/hardware_adc/include/hardware/adc.h b/src/rp2_common/hardware_adc/include/hardware/adc.h index 66fdeecc3..40bdb3260 100644 --- a/src/rp2_common/hardware_adc/include/hardware/adc.h +++ b/src/rp2_common/hardware_adc/include/hardware/adc.h @@ -202,11 +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)); + 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 << (ADC_DIV_FRAC_MSB + 1 - ADC_DIV_FRAC_LSB)); // round to the nearest fraction + clkdiv += 0.5f / (1 << frac_bit_count); // round to the nearest fraction #endif - adc_hw->div = (uint32_t)(clkdiv * (float) (1 << ADC_DIV_INT_LSB)); + adc_hw->div = (uint32_t)(clkdiv * (float) (1 << frac_bit_count)); } /*! \brief Setup the ADC FIFO diff --git a/src/rp2_common/hardware_clocks/clocks.c b/src/rp2_common/hardware_clocks/clocks.c index 1800164f0..cd76c1354 100644 --- a/src/rp2_common/hardware_clocks/clocks.c +++ b/src/rp2_common/hardware_clocks/clocks.c @@ -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 @@ -439,4 +439,4 @@ bool check_sys_clock_khz(uint32_t freq_khz, uint *vco_out, uint *postdiv1_out, u } } return false; -} \ No newline at end of file +} diff --git a/src/rp2_common/hardware_clocks/include/hardware/clocks.h b/src/rp2_common/hardware_clocks/include/hardware/clocks.h index 43fb08e2b..8fd50a20e 100644 --- a/src/rp2_common/hardware_clocks/include/hardware/clocks.h +++ b/src/rp2_common/hardware_clocks/include/hardware/clocks.h @@ -392,14 +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; + const int frac_bit_count = REG_FIELD_WIDTH(CLOCKS_CLK_GPOUT0_DIV_FRAC); #if PICO_CLOCK_GPIO_CLKDIV_ROUND_NEAREST - div += 0.5f / (1 << (CLOCKS_CLK_GPOUT0_DIV_FRAC_MSB + 1 - CLOCKS_CLK_GPOUT0_DIV_FRAC_LSB)); // round to the nearest fraction + div += 0.5f / (1 << frac_bit_count); // round to the nearest fraction #endif -#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)); +#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 diff --git a/src/rp2_common/hardware_pio/include/hardware/pio.h b/src/rp2_common/hardware_pio/include/hardware/pio.h index 5fc354814..30c919b36 100644 --- a/src/rp2_common/hardware_pio/include/hardware/pio.h +++ b/src/rp2_common/hardware_pio/include/hardware/pio.h @@ -478,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); @@ -494,17 +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 << (PIO_SM0_CLKDIV_FRAC_MSB + 1 - PIO_SM0_CLKDIV_FRAC_LSB)); // round to the nearest 1/256 + 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)); } } @@ -1675,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); diff --git a/src/rp2_common/hardware_pwm/include/hardware/pwm.h b/src/rp2_common/hardware_pwm/include/hardware/pwm.h index 48c2673df..2dd6da8f7 100644 --- a/src/rp2_common/hardware_pwm/include/hardware/pwm.h +++ b/src/rp2_common/hardware_pwm/include/hardware/pwm.h @@ -160,10 +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); + const int frac_bit_count = REG_FIELD_WIDTH(PWM_CH0_DIV_FRAC); #if PICO_PWM_CLKDIV_ROUND_NEAREST - div += 0.5f / (1 << (PWM_CH0_DIV_FRAC_MSB + 1 - PWM_CH0_DIV_FRAC_LSB)); // round to the nearest fraction + div += 0.5f / (1 << frac_bit_count); // round to the nearest fraction #endif - c->div = (uint32_t)(div * (float)(1u << PWM_CH0_DIV_INT_LSB)); + 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 @@ -178,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); } @@ -447,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); }