From a42564b4b4aea300f88143d73452ee11a36ebb98 Mon Sep 17 00:00:00 2001 From: andygpz11 <111971637+andygpz11@users.noreply.github.com> Date: Tue, 21 Mar 2023 17:49:20 +0000 Subject: [PATCH] Allow support of crystals other than 12MHz (#1024) (#1272) * Allow pre-processor overrides for Clock/PLL setup * Use `_KHZ` rather than `_MHZ` for `XOSC_` `SYS_CLOCK_` etc definitions (`_MHZ` versions are provided for compatibility when `_KHZ` is a multiple of 1000) Co-authored-by: graham sanderson --- src/common/pico_stdlib/include/pico/stdlib.h | 2 +- .../include/hardware/platform_defs.h | 2 +- .../include/hardware/platform_defs.h | 35 +++++++++- src/rp2_common/hardware_clocks/clocks.c | 57 ++++++++--------- .../hardware_clocks/include/hardware/clocks.h | 64 +++++++++++++++++++ .../hardware_pll/include/hardware/pll.h | 12 +++- src/rp2_common/hardware_pll/pll.c | 10 +-- src/rp2_common/hardware_xosc/xosc.c | 10 +-- src/rp2_common/pico_stdlib/stdlib.c | 42 ++++++------ 9 files changed, 168 insertions(+), 66 deletions(-) diff --git a/src/common/pico_stdlib/include/pico/stdlib.h b/src/common/pico_stdlib/include/pico/stdlib.h index 255de7a2..bae744a9 100644 --- a/src/common/pico_stdlib/include/pico/stdlib.h +++ b/src/common/pico_stdlib/include/pico/stdlib.h @@ -105,7 +105,7 @@ void set_sys_clock_pll(uint32_t vco_freq, uint post_div1, uint post_div2); * \ingroup pico_stdlib * * \param freq_khz Requested frequency - * \param vco_freq_out On success, the voltage controller oscillator frequeucny to be used by the SYS PLL + * \param vco_freq_out On success, the voltage controlled oscillator frequency to be used by the SYS PLL * \param post_div1_out On success, The first post divider for the SYS PLL * \param post_div2_out On success, The second post divider for the SYS PLL. * @return true if the frequency is possible and the output parameters have been written. diff --git a/src/host/pico_platform/include/hardware/platform_defs.h b/src/host/pico_platform/include/hardware/platform_defs.h index 6d0aa841..95952ba0 100644 --- a/src/host/pico_platform/include/hardware/platform_defs.h +++ b/src/host/pico_platform/include/hardware/platform_defs.h @@ -17,7 +17,7 @@ #define NUM_SPIN_LOCKS 32u -#define XOSC_MHZ 12 +#define XOSC_KHZ 12000u #define NUM_SPIN_LOCKS 32u diff --git a/src/rp2040/hardware_regs/include/hardware/platform_defs.h b/src/rp2040/hardware_regs/include/hardware/platform_defs.h index c28bb901..5d635aed 100644 --- a/src/rp2040/hardware_regs/include/hardware/platform_defs.h +++ b/src/rp2040/hardware_regs/include/hardware/platform_defs.h @@ -37,9 +37,38 @@ #define PIO_INSTRUCTION_COUNT _u(32) -// PICO_CONFIG: XOSC_MHZ, The crystal oscillator frequency in Mhz, type=int, default=12, advanced=true, group=hardware_base -#ifndef XOSC_MHZ -#define XOSC_MHZ _u(12) +// PICO_CONFIG: XOSC_KHZ, The crystal oscillator frequency in kHz, type=int, default=12000, advanced=true, group=hardware_base +// NOTE: The system and USB clocks are generated from the frequency using two PLLs. +// If you override this define, or SYS_CLK_KHZ/USB_CLK_KHZ below, you will *also* need to add your own adjusted PLL set-up defines to +// override the defaults which live in src/rp2_common/hardware_clocks/include/hardware/clocks.h +// Please see the comments there about calculating the new PLL setting values. +#ifndef XOSC_KHZ +#define XOSC_KHZ _u(12000) +#endif + +// PICO_CONFIG: SYS_CLK_KHZ, The system operating frequency in kHz, type=int, default=125000, advanced=true, group=hardware_base +#ifndef SYS_CLK_KHZ +#define SYS_CLK_KHZ _u(125000) +#endif + +// PICO_CONFIG: USB_CLK_KHZ, USB clock frequency. Must be 48MHz for the USB interface to operate correctly, type=int, default=48000, advanced=true, group=hardware_base +#ifndef USB_CLK_KHZ +#define USB_CLK_KHZ _u(48000) +#endif + +// For backwards compatibility define XOSC_MHZ if the frequency is indeed an integer number of Mhz. +#if defined(XOSC_KHZ) && !defined(XOSC_MHZ) && (XOSC_KHZ % 1000 == 0) +#define XOSC_MHZ (XOSC_KHZ / 1000) +#endif + +// For backwards compatibility define SYS_CLK_MHZ if the frequency is indeed an integer number of Mhz. +#if defined(SYS_CLK_KHZ) && !defined(SYS_CLK_MHZ) && (SYS_CLK_KHZ % 1000 == 0) +#define SYS_CLK_MHZ (SYS_CLK_KHZ / 1000) +#endif + +// For backwards compatibility define USB_CLK_MHZ if the frequency is indeed an integer number of Mhz. +#if defined(USB_CLK_KHZ) && !defined(USB_CLK_MHZ) && (USB_CLK_KHZ % 1000 == 0) +#define USB_CLK_MHZ (USB_CLK_KHZ / 1000) #endif #define FIRST_USER_IRQ (NUM_IRQS - NUM_USER_IRQS) diff --git a/src/rp2_common/hardware_clocks/clocks.c b/src/rp2_common/hardware_clocks/clocks.c index 152a9641..ad1eaeb7 100644 --- a/src/rp2_common/hardware_clocks/clocks.c +++ b/src/rp2_common/hardware_clocks/clocks.c @@ -14,6 +14,12 @@ #include "hardware/irq.h" #include "hardware/gpio.h" +// The RTC clock frequency is 48MHz divided by power of 2 (to ensure an integer +// division ratio will be used in the clocks block). A divisor of 1024 generates +// an RTC clock tick of 46875Hz. This frequency is relatively close to the +// customary 32 or 32.768kHz 'slow clock' crystals and provides good timing resolution. +#define RTC_CLOCK_FREQ_HZ (USB_CLK_KHZ * KHZ / 1024) + check_hw_layout(clocks_hw_t, clk[clk_adc].selected, CLOCKS_CLK_ADC_SELECTED_OFFSET); check_hw_layout(clocks_hw_t, fc0.result, CLOCKS_FC0_RESULT_OFFSET); check_hw_layout(clocks_hw_t, ints, CLOCKS_INTS_OFFSET); @@ -113,15 +119,15 @@ bool clock_configure(enum clock_index clk_index, uint32_t src, uint32_t auxsrc, /// \end::clock_configure[] void clocks_init(void) { - // Start tick in watchdog - watchdog_start_tick(XOSC_MHZ); + // Start tick in watchdog, the argument is in 'cycles per microsecond' i.e. MHz + watchdog_start_tick(XOSC_KHZ / KHZ); // Everything is 48MHz on FPGA apart from RTC. Otherwise set to 0 and will be set in clock configure if (running_on_fpga()) { for (uint i = 0; i < CLK_COUNT; i++) { configured_freq[i] = 48 * MHZ; } - configured_freq[clk_rtc] = 46875; + configured_freq[clk_rtc] = RTC_CLOCK_FREQ_HZ; return; } @@ -139,63 +145,56 @@ void clocks_init(void) { while (clocks_hw->clk[clk_ref].selected != 0x1) tight_loop_contents(); - /// \tag::pll_settings[] - // Configure PLLs - // REF FBDIV VCO POSTDIV - // PLL SYS: 12 / 1 = 12MHz * 125 = 1500MHz / 6 / 2 = 125MHz - // PLL USB: 12 / 1 = 12MHz * 100 = 1200MHz / 5 / 5 = 48MHz - /// \end::pll_settings[] - /// \tag::pll_init[] - pll_init(pll_sys, 1, 1500 * MHZ, 6, 2); - pll_init(pll_usb, 1, 1200 * MHZ, 5, 5); + pll_init(pll_sys, PLL_COMMON_REFDIV, PLL_SYS_VCO_FREQ_KHZ * KHZ, PLL_SYS_POSTDIV1, PLL_SYS_POSTDIV2); + pll_init(pll_usb, PLL_COMMON_REFDIV, PLL_USB_VCO_FREQ_KHZ * KHZ, PLL_USB_POSTDIV1, PLL_USB_POSTDIV2); /// \end::pll_init[] // Configure clocks - // CLK_REF = XOSC (12MHz) / 1 = 12MHz + // CLK_REF = XOSC (usually) 12MHz / 1 = 12MHz clock_configure(clk_ref, CLOCKS_CLK_REF_CTRL_SRC_VALUE_XOSC_CLKSRC, 0, // No aux mux - 12 * MHZ, - 12 * MHZ); + XOSC_KHZ * KHZ, + XOSC_KHZ * KHZ); /// \tag::configure_clk_sys[] - // CLK SYS = PLL SYS (125MHz) / 1 = 125MHz + // CLK SYS = PLL SYS (usually) 125MHz / 1 = 125MHz clock_configure(clk_sys, CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX, CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS, - 125 * MHZ, - 125 * MHZ); + SYS_CLK_KHZ * KHZ, + SYS_CLK_KHZ * KHZ); /// \end::configure_clk_sys[] - // CLK USB = PLL USB (48MHz) / 1 = 48MHz + // CLK USB = PLL USB 48MHz / 1 = 48MHz clock_configure(clk_usb, 0, // No GLMUX CLOCKS_CLK_USB_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB, - 48 * MHZ, - 48 * MHZ); + USB_CLK_KHZ * KHZ, + USB_CLK_KHZ * KHZ); - // CLK ADC = PLL USB (48MHZ) / 1 = 48MHz + // CLK ADC = PLL USB 48MHZ / 1 = 48MHz clock_configure(clk_adc, 0, // No GLMUX CLOCKS_CLK_ADC_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB, - 48 * MHZ, - 48 * MHZ); + USB_CLK_KHZ * KHZ, + USB_CLK_KHZ * KHZ); - // CLK RTC = PLL USB (48MHz) / 1024 = 46875Hz + // CLK RTC = PLL USB 48MHz / 1024 = 46875Hz clock_configure(clk_rtc, 0, // No GLMUX CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB, - 48 * MHZ, - 46875); + USB_CLK_KHZ * KHZ, + RTC_CLOCK_FREQ_HZ); // CLK PERI = clk_sys. Used as reference clock for Peripherals. No dividers so just select and enable // Normally choose clk_sys or clk_usb clock_configure(clk_peri, 0, CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLK_SYS, - 125 * MHZ, - 125 * MHZ); + SYS_CLK_KHZ * KHZ, + SYS_CLK_KHZ * KHZ); } /// \tag::clock_get_hz[] diff --git a/src/rp2_common/hardware_clocks/include/hardware/clocks.h b/src/rp2_common/hardware_clocks/include/hardware/clocks.h index bc4d9ac1..66adefc6 100644 --- a/src/rp2_common/hardware_clocks/include/hardware/clocks.h +++ b/src/rp2_common/hardware_clocks/include/hardware/clocks.h @@ -89,6 +89,70 @@ extern "C" { #define KHZ 1000 #define MHZ 1000000 +/// \tag::pll_settings[] +// +// There are two PLLs in RP2040: +// 1. The 'SYS PLL' generates the 125MHz system clock, the frequency is defined by `SYS_CLK_KHZ`. +// 2. The 'USB PLL' generates the 48MHz USB clock, the frequency is defined by `USB_CLK_KHZ`. +// +// The two PLLs use the crystal oscillator output directly as their reference frequency input; the PLLs reference +// frequency cannot be reduced by the dividers present in the clocks block. The crystal frequency is defined by `XOSC_KHZ` or +// `XOSC_MHZ`. +// +// The system's default definitions are correct for the above frequencies with a 12MHz +// crystal frequency. If different frequencies are required, these must be defined in +// the board configuration file together with the revised PLL settings +// Use `vcocalc.py` to check and calculate new PLL settings if you change any of these frequencies. +// +// Default PLL configuration: +// REF FBDIV VCO POSTDIV +// PLL SYS: 12 / 1 = 12MHz * 125 = 1500MHz / 6 / 2 = 125MHz +// PLL USB: 12 / 1 = 12MHz * 100 = 1200MHz / 5 / 5 = 48MHz +/// \end::pll_settings[] + +// PICO_CONFIG: PLL_COMMON_REFDIV, PLL reference divider setting - used for both PLLs, type=int, default=1, advanced=true, group=hardware_clocks +#ifndef PLL_COMMON_REFDIV +#define PLL_COMMON_REFDIV 1 +#endif + +#if (SYS_CLK_KHZ == 125000) && (XOSC_KHZ == 12000) && (PLL_COMMON_REFDIV == 1) +// PLL settings for standard 125 MHz system clock. +// PICO_CONFIG: PLL_SYS_VCO_FREQ_KHZ, System clock PLL frequency, type=int, default=1500 * KHZ, advanced=true, group=hardware_clocks +#ifndef PLL_SYS_VCO_FREQ_KHZ +#define PLL_SYS_VCO_FREQ_KHZ (1500 * KHZ) +#endif +// PICO_CONFIG: PLL_SYS_POSTDIV1, System clock PLL post divider 1 setting, type=int, default=6, advanced=true, group=hardware_clocks +#ifndef PLL_SYS_POSTDIV1 +#define PLL_SYS_POSTDIV1 6 +#endif +// PICO_CONFIG: PLL_SYS_POSTDIV2, System clock PLL post divider 2 setting, type=int, default=2, advanced=true, group=hardware_clocks +#ifndef PLL_SYS_POSTDIV2 +#define PLL_SYS_POSTDIV2 2 +#endif +#endif // SYS_CLK_KHZ == 125000 && XOSC_KHZ == 12000 && PLL_COMMON_REFDIV == 1 +#if !defined(PLL_SYS_VCO_FREQ_KHZ) || !defined(PLL_SYS_POSTDIV1) || !defined(PLL_SYS_POSTDIV2) +#error PLL_SYS_VCO_FREQ_KHZ, PLL_SYS_POSTDIV1 and PLL_SYS_POSTDIV2 must all be specified when using custom clock setup +#endif + +#if (USB_CLK_KHZ == 48000) && (XOSC_KHZ == 12000) && (PLL_COMMON_REFDIV == 1) +// PLL settings for a USB clock of 48MHz. +// PICO_CONFIG: PLL_USB_VCO_FREQ_KHZ, USB clock PLL frequency, type=int, default=1200 * KHZ, advanced=true, group=hardware_clocks +#ifndef PLL_USB_VCO_FREQ_KHZ +#define PLL_USB_VCO_FREQ_KHZ (1200 * KHZ) +#endif +// PICO_CONFIG: PLL_USB_POSTDIV1, USB clock PLL post divider 1 setting, type=int, default=5, advanced=true, group=hardware_clocks +#ifndef PLL_USB_POSTDIV1 +#define PLL_USB_POSTDIV1 5 +#endif +// PICO_CONFIG: PLL_USB_POSTDIV2, USB clock PLL post divider 2 setting, type=int, default=5, advanced=true, group=hardware_clocks +#ifndef PLL_USB_POSTDIV2 +#define PLL_USB_POSTDIV2 5 +#endif +#endif // USB_CLK_KHZ == 48000 && XOSC_KHZ == 12000 && PLL_COMMON_REFDIV == 1 +#if !defined(PLL_USB_VCO_FREQ_KHZ) || !defined(PLL_USB_POSTDIV1) || !defined(PLL_USB_POSTDIV2) +#error PLL_USB_VCO_FREQ_KHZ, PLL_USB_POSTDIV1 and PLL_USB_POSTDIV2 must all be specified when using custom clock setup. +#endif + // PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_CLOCKS, Enable/disable assertions in the clocks module, type=bool, default=0, group=hardware_clocks #ifndef PARAM_ASSERTIONS_ENABLED_CLOCKS #define PARAM_ASSERTIONS_ENABLED_CLOCKS 0 diff --git a/src/rp2_common/hardware_pll/include/hardware/pll.h b/src/rp2_common/hardware_pll/include/hardware/pll.h index 59015f5e..001af6e0 100644 --- a/src/rp2_common/hardware_pll/include/hardware/pll.h +++ b/src/rp2_common/hardware_pll/include/hardware/pll.h @@ -31,12 +31,20 @@ typedef pll_hw_t *PLL; #define pll_sys pll_sys_hw #define pll_usb pll_usb_hw +#ifndef PICO_PLL_VCO_MIN_FREQ_KHZ #ifndef PICO_PLL_VCO_MIN_FREQ_MHZ -#define PICO_PLL_VCO_MIN_FREQ_MHZ 750 +#define PICO_PLL_VCO_MIN_FREQ_KHZ (750 * KHZ) +#else +#define PICO_PLL_VCO_MIN_FREQ_KHZ (PICO_PLL_VCO_MIN_FREQ_MHZ * KHZ) +#endif #endif +#ifndef PICO_PLL_VCO_MAX_FREQ_KHZ #ifndef PICO_PLL_VCO_MAX_FREQ_MHZ -#define PICO_PLL_VCO_MAX_FREQ_MHZ 1600 +#define PICO_PLL_VCO_MAX_FREQ_KHZ (1600 * KHZ) +#else +#define PICO_PLL_VCO_MAX_FREQ_KHZ (PICO_PLL_VCO_MAX_FREQ_MHZ * KHZ) +#endif #endif /*! \brief Initialise specified PLL. diff --git a/src/rp2_common/hardware_pll/pll.c b/src/rp2_common/hardware_pll/pll.c index 41d9fde9..48152b81 100644 --- a/src/rp2_common/hardware_pll/pll.c +++ b/src/rp2_common/hardware_pll/pll.c @@ -4,21 +4,21 @@ * SPDX-License-Identifier: BSD-3-Clause */ -// For MHZ definitions etc +// For frequency and PLL definitions etc. #include "hardware/clocks.h" #include "hardware/pll.h" #include "hardware/resets.h" /// \tag::pll_init_calculations[] void pll_init(PLL pll, uint refdiv, uint vco_freq, uint post_div1, uint post_div2) { - uint32_t ref_mhz = XOSC_MHZ / refdiv; + uint32_t ref_freq = XOSC_KHZ * KHZ / refdiv; // Check vco freq is in an acceptable range - assert(vco_freq >= (PICO_PLL_VCO_MIN_FREQ_MHZ * MHZ) && vco_freq <= (PICO_PLL_VCO_MAX_FREQ_MHZ * MHZ)); + assert(vco_freq >= (PICO_PLL_VCO_MIN_FREQ_KHZ * KHZ) && vco_freq <= (PICO_PLL_VCO_MAX_FREQ_KHZ * KHZ)); // What are we multiplying the reference clock by to get the vco freq // (The regs are called div, because you divide the vco output and compare it to the refclk) - uint32_t fbdiv = vco_freq / (ref_mhz * MHZ); + uint32_t fbdiv = vco_freq / ref_freq; /// \end::pll_init_calculations[] // fbdiv @@ -32,7 +32,7 @@ void pll_init(PLL pll, uint refdiv, uint vco_freq, uint post_div1, uint post_div // postdiv1 is designed to operate with a higher input frequency than postdiv2 // Check that reference frequency is no greater than vco / 16 - assert(ref_mhz <= (vco_freq / 16)); + assert(ref_freq <= (vco_freq / 16)); // div1 feeds into div2 so if div1 is 5 and div2 is 2 then you get a divide by 10 uint32_t pdiv = (post_div1 << PLL_PRIM_POSTDIV1_LSB) | diff --git a/src/rp2_common/hardware_xosc/xosc.c b/src/rp2_common/hardware_xosc/xosc.c index 7a7055cb..03e6785b 100644 --- a/src/rp2_common/hardware_xosc/xosc.c +++ b/src/rp2_common/hardware_xosc/xosc.c @@ -6,18 +6,20 @@ #include "pico.h" -// For MHZ definitions etc +// For frequency related definitions etc #include "hardware/clocks.h" #include "hardware/platform_defs.h" #include "hardware/regs/xosc.h" #include "hardware/xosc.h" -#if XOSC_MHZ < 1 || XOSC_MHZ > 50 -#error XOSC_MHZ must be in the range 1-50 +#if XOSC_KHZ < (1 * KHZ) || XOSC_KHZ > (50 * KHZ) +// Note: Although an external clock can be supplied up to 50 MHz, the maximum frequency the +// XOSC cell is specified to work with a crystal is less, please see the RP2040 Datasheet. +#error XOSC_KHZ must be in the range 1,000-50,000KHz i.e. 1-50MHz XOSC frequency #endif -#define STARTUP_DELAY (((((XOSC_MHZ * MHZ) / 1000) + 128) / 256) * PICO_XOSC_STARTUP_DELAY_MULTIPLIER) +#define STARTUP_DELAY (((XOSC_KHZ + 128) / 256) * PICO_XOSC_STARTUP_DELAY_MULTIPLIER) // The DELAY field in xosc_hw->startup is 14 bits wide. #if STARTUP_DELAY >= (1 << 13) diff --git a/src/rp2_common/pico_stdlib/stdlib.c b/src/rp2_common/pico_stdlib/stdlib.c index 159095ce..b0ffe645 100644 --- a/src/rp2_common/pico_stdlib/stdlib.c +++ b/src/rp2_common/pico_stdlib/stdlib.c @@ -21,8 +21,8 @@ void set_sys_clock_48mhz() { clock_configure(clk_sys, CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX, CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB, - 48 * MHZ, - 48 * MHZ); + USB_CLK_KHZ * KHZ, + USB_CLK_KHZ * KHZ); // Turn off PLL sys for good measure pll_deinit(pll_sys); @@ -31,8 +31,8 @@ void set_sys_clock_48mhz() { clock_configure(clk_peri, 0, CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLK_SYS, - 48 * MHZ, - 48 * MHZ); + USB_CLK_KHZ * KHZ, + USB_CLK_KHZ * KHZ); } } @@ -41,21 +41,21 @@ void set_sys_clock_pll(uint32_t vco_freq, uint post_div1, uint post_div2) { clock_configure(clk_sys, CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX, CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB, - 48 * MHZ, - 48 * MHZ); + USB_CLK_KHZ * KHZ, + USB_CLK_KHZ * KHZ); - pll_init(pll_sys, 1, vco_freq, post_div1, post_div2); + pll_init(pll_sys, PLL_COMMON_REFDIV, vco_freq, post_div1, post_div2); uint32_t freq = vco_freq / (post_div1 * post_div2); // Configure clocks - // CLK_REF = XOSC (12MHz) / 1 = 12MHz + // CLK_REF is the XOSC source clock_configure(clk_ref, CLOCKS_CLK_REF_CTRL_SRC_VALUE_XOSC_CLKSRC, 0, // No aux mux - 12 * MHZ, - 12 * MHZ); + XOSC_KHZ * KHZ, + XOSC_KHZ * KHZ); - // CLK SYS = PLL SYS (125MHz) / 1 = 125MHz + // CLK SYS = PLL SYS (usually) 125MHz / 1 = 125MHz clock_configure(clk_sys, CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX, CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS, @@ -64,23 +64,23 @@ void set_sys_clock_pll(uint32_t vco_freq, uint post_div1, uint post_div2) { clock_configure(clk_peri, 0, // Only AUX mux on ADC CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB, - 48 * MHZ, - 48 * MHZ); + USB_CLK_KHZ * KHZ, + USB_CLK_KHZ * KHZ); } } -bool check_sys_clock_khz(uint32_t freq_khz, uint *vco_out, uint *postdiv1_out, uint *postdiv_out) { - uint crystal_freq_khz = clock_get_hz(clk_ref) / 1000; +bool check_sys_clock_khz(uint32_t freq_khz, uint *vco_out, uint *postdiv1_out, uint *postdiv2_out) { + uint reference_freq_khz = XOSC_KHZ / PLL_COMMON_REFDIV; for (uint fbdiv = 320; fbdiv >= 16; fbdiv--) { - uint vco = fbdiv * crystal_freq_khz; - if (vco < PICO_PLL_VCO_MIN_FREQ_MHZ * 1000 || vco > PICO_PLL_VCO_MAX_FREQ_MHZ * 1000) continue; + uint vco_khz = fbdiv * reference_freq_khz; + if (vco_khz < PICO_PLL_VCO_MIN_FREQ_KHZ || vco_khz > PICO_PLL_VCO_MAX_FREQ_KHZ) continue; for (uint postdiv1 = 7; postdiv1 >= 1; postdiv1--) { for (uint postdiv2 = postdiv1; postdiv2 >= 1; postdiv2--) { - uint out = vco / (postdiv1 * postdiv2); - if (out == freq_khz && !(vco % (postdiv1 * postdiv2))) { - *vco_out = vco * 1000; + uint out = vco_khz / (postdiv1 * postdiv2); + if (out == freq_khz && !(vco_khz % (postdiv1 * postdiv2))) { + *vco_out = vco_khz * KHZ; *postdiv1_out = postdiv1; - *postdiv_out = postdiv2; + *postdiv2_out = postdiv2; return true; } }