Loading...
Searching...
No Matches
clocks.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#ifndef _HARDWARE_CLOCKS_H
8#define _HARDWARE_CLOCKS_H
9
10#include "pico.h"
11#include "hardware/structs/clocks.h"
13
14#ifdef __cplusplus
15extern "C" {
16#endif
17
139
140#define KHZ 1000
141#define MHZ 1000000
142
143// \tag::pll_settings[]
144// There are two PLLs in RP-series microcontrollers:
145// 1. The 'SYS PLL' generates the system clock, the frequency is defined by `SYS_CLK_KHZ`.
146// 2. The 'USB PLL' generates the USB clock, the frequency is defined by `USB_CLK_KHZ`.
147//
148// The two PLLs use the crystal oscillator output directly as their reference frequency input; the PLLs reference
149// frequency cannot be reduced by the dividers present in the clocks block. The crystal frequency is defined by `XOSC_HZ` (or
150// `XOSC_KHZ` or `XOSC_MHZ`).
151//
152// The system's default definitions are correct for the above frequencies with a 12MHz
153// crystal frequency. If different frequencies are required, these must be defined in
154// the board configuration file together with the revised PLL settings
155// Use `vcocalc.py` to check and calculate new PLL settings if you change any of these frequencies.
156//
157// Default PLL configuration RP2040:
158// REF FBDIV VCO POSTDIV
159// PLL SYS: 12 / 1 = 12MHz * 125 = 1500MHz / 6 / 2 = 125MHz
160// PLL USB: 12 / 1 = 12MHz * 100 = 1200MHz / 5 / 5 = 48MHz
161//
162// Default PLL configuration RP2350:
163// REF FBDIV VCO POSTDIV
164// PLL SYS: 12 / 1 = 12MHz * 125 = 1500MHz / 5 / 2 = 150MHz
165// PLL USB: 12 / 1 = 12MHz * 100 = 1200MHz / 5 / 5 = 48MHz
166// \end::pll_settings[]
167
168#ifndef PLL_COMMON_REFDIV
169// backwards compatibility, but now deprecated
170#define PLL_COMMON_REFDIV 1
171#endif
172
173// PICO_CONFIG: PLL_SYS_REFDIV, PLL reference divider setting for PLL_SYS, type=int, default=1, advanced=true, group=hardware_clocks
174#ifndef PLL_SYS_REFDIV
175// backwards compatibility with deprecated PLL_COMMON_REFDIV
176#ifdef PLL_COMMON_REFDIV
177#define PLL_SYS_REFDIV PLL_COMMON_REFDIV
178#else
179#define PLL_SYS_REFDIV 1
180#endif
181#endif
182
183#ifndef PLL_SYS_VCO_FREQ_HZ
184// For backwards compatibility define PLL_SYS_VCO_FREQ_HZ if PLL_SYS_VCO_FREQ_KHZ is defined
185#ifdef PLL_SYS_VCO_FREQ_KHZ
186#define PLL_SYS_VCO_FREQ_HZ (PLL_SYS_VCO_FREQ_KHZ * KHZ)
187#endif
188#endif
189
190#if (SYS_CLK_HZ == 125 * MHZ || SYS_CLK_HZ == 150 * MHZ) && (XOSC_HZ == 12 * MHZ) && (PLL_SYS_REFDIV == 1)
191// PLL settings for standard 125/150 MHz system clock.
192// PICO_CONFIG: PLL_SYS_VCO_FREQ_HZ, System clock PLL frequency, type=int, default=(1500 * MHZ), advanced=true, group=hardware_clocks
193#ifndef PLL_SYS_VCO_FREQ_HZ
194#define PLL_SYS_VCO_FREQ_HZ (1500 * MHZ)
195#endif
196// PICO_CONFIG: PLL_SYS_POSTDIV1, System clock PLL post divider 1 setting, type=int, default=6 on RP2040 or 5 on RP2350, advanced=true, group=hardware_clocks
197#ifndef PLL_SYS_POSTDIV1
198#if SYS_CLK_HZ == 125 * MHZ
199#define PLL_SYS_POSTDIV1 6
200#else
201#define PLL_SYS_POSTDIV1 5
202#endif
203#endif
204// PICO_CONFIG: PLL_SYS_POSTDIV2, System clock PLL post divider 2 setting, type=int, default=2, advanced=true, group=hardware_clocks
205#ifndef PLL_SYS_POSTDIV2
206#define PLL_SYS_POSTDIV2 2
207#endif
208#endif // SYS_CLK_KHZ == 125000 && XOSC_KHZ == 12000 && PLL_COMMON_REFDIV == 1
209
210#if PICO_RP2040 && (SYS_CLK_HZ == 200 * MHZ) && (XOSC_HZ == 12 * MHZ) && (PLL_SYS_REFDIV == 1)
211// PICO_CONFIG: SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST, Should the regulator voltage be adjusted above SYS_CLK_VREG_VOLTAGE_MIN when initializing the clocks, type=bool, default=0, advanced=true, group=hardware_clocks
212#ifndef SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST
213#define SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST 1
214#endif
215// PICO_CONFIG: SYS_CLK_VREG_VOLTAGE_MIN, minimum voltage (see VREG_VOLTAGE_x_xx) for the voltage regulator to be ensured during clock initialization if SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST is 1, type=int, advanced=true, group=hardware_clocks
216#if SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST && !defined(SYS_CLK_VREG_VOLTAGE_MIN)
217#define SYS_CLK_VREG_VOLTAGE_MIN VREG_VOLTAGE_1_15
218#endif
219// PLL settings for fast 200 MHz system clock on RP2040
220#ifndef PLL_SYS_VCO_FREQ_HZ
221#define PLL_SYS_VCO_FREQ_HZ (1200 * MHZ)
222#endif
223#ifndef PLL_SYS_POSTDIV1
224#define PLL_SYS_POSTDIV1 6
225#endif
226#ifndef PLL_SYS_POSTDIV2
227#define PLL_SYS_POSTDIV2 1
228#endif
229#else
230#ifndef SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST
231#define SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST 0
232#endif
233#endif // PICO_RP2040 && SYS_CLK_KHZ == 200000 && XOSC_KHZ == 12000 && PLL_COMMON_REFDIV == 1
234
235// PICO_CONFIG: SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST_DELAY_US, Number of microseconds to wait after updating regulator voltage due to SYS_CLK_VREG_VOLTAGE_MIN to allow voltage to settle, type=int, default=1000, advanced=true, group=hardware_clocks
236#ifndef SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST_DELAY_US
237#define SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST_DELAY_US 1000
238#endif
239
240#if !defined(PLL_SYS_VCO_FREQ_HZ) || !defined(PLL_SYS_POSTDIV1) || !defined(PLL_SYS_POSTDIV2)
241#error PLL_SYS_VCO_FREQ_HZ, PLL_SYS_POSTDIV1 and PLL_SYS_POSTDIV2 must all be specified when using custom clock setup
242#endif
243
244// PICO_CONFIG: PLL_USB_REFDIV, PLL reference divider setting for PLL_USB, type=int, default=1, advanced=true, group=hardware_clocks
245#ifndef PLL_USB_REFDIV
246// backwards compatibility with deprecated PLL_COMMON_REFDIV
247#ifdef PLL_COMMON_REFDIV
248#define PLL_USB_REFDIV PLL_COMMON_REFDIV
249#else
250#define PLL_USB_REFDIV 1
251#endif
252#endif
253
254#ifndef PLL_USB_VCO_FREQ_HZ
255// For backwards compatibility define PLL_USB_VCO_FREQ_HZ if PLL_USB_VCO_FREQ_KHZ is defined
256#ifdef PLL_USB_VCO_FREQ_KHZ
257#define PLL_USB_VCO_FREQ_HZ (PLL_USB_VCO_FREQ_KHZ * KHZ)
258#endif
259#endif
260
261#if (USB_CLK_HZ == 48 * MHZ) && (XOSC_HZ == 12 * MHZ) && (PLL_USB_REFDIV == 1)
262// PLL settings for a USB clock of 48MHz.
263// PICO_CONFIG: PLL_USB_VCO_FREQ_HZ, USB clock PLL frequency, type=int, default=(1200 * MHZ), advanced=true, group=hardware_clocks
264#ifndef PLL_USB_VCO_FREQ_HZ
265#define PLL_USB_VCO_FREQ_HZ (1200 * MHZ)
266#endif
267// PICO_CONFIG: PLL_USB_POSTDIV1, USB clock PLL post divider 1 setting, type=int, default=5, advanced=true, group=hardware_clocks
268#ifndef PLL_USB_POSTDIV1
269#define PLL_USB_POSTDIV1 5
270#endif
271// PICO_CONFIG: PLL_USB_POSTDIV2, USB clock PLL post divider 2 setting, type=int, default=5, advanced=true, group=hardware_clocks
272#ifndef PLL_USB_POSTDIV2
273#define PLL_USB_POSTDIV2 5
274#endif
275#endif // USB_CLK_HZ == 48000000 && XOSC_HZ == 12000000 && PLL_COMMON_REFDIV == 1
276#if !defined(PLL_USB_VCO_FREQ_HZ) || !defined(PLL_USB_POSTDIV1) || !defined(PLL_USB_POSTDIV2)
277#error PLL_USB_VCO_FREQ_HZ, PLL_USB_POSTDIV1 and PLL_USB_POSTDIV2 must all be specified when using custom clock setup.
278#endif
279
280// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_HARDWARE_CLOCKS, Enable/disable assertions in the hardware_clocks module, type=bool, default=0, group=hardware_clocks
281#ifndef PARAM_ASSERTIONS_ENABLED_HARDWARE_CLOCKS
282#ifdef PARAM_ASSERTIONS_ENABLED_CLOCKS // backwards compatibility with SDK < 2.0.0
283#define PARAM_ASSERTIONS_ENABLED_HARDWARE_CLOCKS PARAM_ASSERTIONS_ENABLED_CLOCKS
284#else
285#define PARAM_ASSERTIONS_ENABLED_HARDWARE_CLOCKS 0
286#endif
287#endif
288
289 // 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
290#ifndef PICO_CLOCK_GPIO_CLKDIV_ROUND_NEAREST
291#define PICO_CLOCK_GPIO_CLKDIV_ROUND_NEAREST PICO_CLKDIV_ROUND_NEAREST
292#endif
293
294typedef clock_num_t clock_handle_t;
295
320bool clock_configure(clock_handle_t clock, uint32_t src, uint32_t auxsrc, uint32_t src_freq, uint32_t freq);
321
346bool clock_configure_mhz(clock_handle_t clock, uint32_t src, uint32_t auxsrc, uint32_t src_freq_mhz, uint32_t freq_mhz);
347
358void clock_configure_undivided(clock_handle_t clock, uint32_t src, uint32_t auxsrc, uint32_t src_freq);
359
371void clock_configure_int_divider(clock_handle_t clock, uint32_t src, uint32_t auxsrc, uint32_t src_freq, uint32_t int_divider);
372
378void clock_stop(clock_handle_t clock);
379
386uint32_t clock_get_hz(clock_handle_t clock);
387
397uint32_t frequency_count_khz(uint src);
398
404void clock_set_reported_hz(clock_handle_t clock, uint hz);
405
416static inline float frequency_count_mhz(uint src) {
417 return ((float) (frequency_count_khz(src))) / KHZ;
418}
419
420
426typedef void (*resus_callback_t)(void);
427
436void clocks_enable_resus(resus_callback_t resus_callback);
437
458void clock_gpio_init_int_frac16(uint gpio, uint src, uint32_t div_int, uint16_t div_frac16);
459
480static inline void clock_gpio_init_int_frac8(uint gpio, uint src, uint32_t div_int, uint8_t div_frac8) {
481 return clock_gpio_init_int_frac16(gpio, src, div_int, (uint16_t)(div_frac8 << 8u));
482}
483
484// backwards compatibility
485static inline void clock_gpio_init_int_frac(uint gpio, uint src, uint32_t div_int, uint8_t div_frac8) {
486 return clock_gpio_init_int_frac8(gpio, src, div_int, div_frac8);
487}
488
507static inline void clock_gpio_init(uint gpio, uint src, float div)
508{
509 uint div_int = (uint)div;
510 const int frac_bit_count = REG_FIELD_WIDTH(CLOCKS_CLK_GPOUT0_DIV_FRAC);
511#if PICO_CLOCK_GPIO_CLKDIV_ROUND_NEAREST
512 div += 0.5f / (1 << frac_bit_count); // round to the nearest fraction
513#endif
514#if REG_FIELD_WIDTH(CLOCKS_CLK_GPOUT0_DIV_FRAC) == 16
515 uint16_t frac = (uint16_t)((div - (float)div_int) * (1u << frac_bit_count));
516 clock_gpio_init_int_frac16(gpio, src, div_int, frac);
517#elif REG_FIELD_WIDTH(CLOCKS_CLK_GPOUT0_DIV_FRAC) == 8
518 uint8_t frac = (uint8_t)((div - (float)div_int) * (1u << frac_bit_count));
519 clock_gpio_init_int_frac8(gpio, src, div_int, frac);
520#else
521#error unsupported number of fractional bits
522#endif
523}
524
534bool clock_configure_gpin(clock_handle_t clock, uint gpio, uint32_t src_freq, uint32_t freq);
535
541void set_sys_clock_48mhz(void);
542
552void set_sys_clock_pll(uint32_t vco_freq, uint post_div1, uint post_div2);
553
563bool check_sys_clock_hz(uint32_t freq_hz, uint *vco_freq_out, uint *post_div1_out, uint *post_div2_out);
564
574bool check_sys_clock_khz(uint32_t freq_khz, uint *vco_freq_out, uint *post_div1_out, uint *post_div2_out);
575
587static inline bool set_sys_clock_hz(uint32_t freq_hz, bool required) {
588 uint vco, postdiv1, postdiv2;
589 if (check_sys_clock_hz(freq_hz, &vco, &postdiv1, &postdiv2)) {
590 set_sys_clock_pll(vco, postdiv1, postdiv2);
591 return true;
592 } else if (required) {
593 panic("System clock of %u Hz cannot be exactly achieved", freq_hz);
594 }
595 return false;
596}
597
609static inline bool set_sys_clock_khz(uint32_t freq_khz, bool required) {
610 uint vco, postdiv1, postdiv2;
611 if (check_sys_clock_khz(freq_khz, &vco, &postdiv1, &postdiv2)) {
612 set_sys_clock_pll(vco, postdiv1, postdiv2);
613 return true;
614 } else if (required) {
615 panic("System clock of %u kHz cannot be exactly achieved", freq_khz);
616 }
617 return false;
618}
619
620typedef fixed_bitset_type(NUM_CLOCK_DESTINATIONS) clock_dest_bitset_t;
621#define clock_dest_bitset_none() fixed_bitset_with_fill(clock_dest_bitset_t, NUM_CLOCK_DESTINATIONS, 0)
622#define clock_dest_bitset_all() fixed_bitset_with_fill(clock_dest_bitset_t, NUM_CLOCK_DESTINATIONS, 1)
623
624static inline clock_dest_bitset_t *clock_dest_bitset_clear(clock_dest_bitset_t *dests) {
625 fixed_bitset_clear_all(&dests->bitset);
626 return dests;
627}
628
629static inline clock_dest_bitset_t *clock_dest_bitset_add_all(clock_dest_bitset_t *dests) {
630 fixed_bitset_set_all(&dests->bitset);
631 return dests;
632}
633
634static inline clock_dest_bitset_t *clock_dest_bitset_add(clock_dest_bitset_t *dests, clock_dest_num_t dest) {
635 fixed_bitset_set(&dests->bitset, dest);
636 return dests;
637}
638
639static inline clock_dest_bitset_t *clock_dest_bitset_remove(clock_dest_bitset_t *dests, clock_dest_num_t dest) {
640 fixed_bitset_clear(&dests->bitset, dest);
641 return dests;
642}
643
644void clock_get_sleep_en_gate(clock_dest_bitset_t *clocks);
645void clock_gate_sleep_en(const clock_dest_bitset_t *clocks);
646
647#define GPIO_TO_GPOUT_CLOCK_HANDLE_RP2040(gpio, default_clk_handle) \
648 ((gpio) == 21 ? clk_gpout0 : \
649 ((gpio) == 23 ? clk_gpout1 : \
650 ((gpio) == 24 ? clk_gpout2 : \
651 ((gpio) == 25 ? clk_gpout3 : \
652 (default_clk_handle)))))
653
654#define GPIO_TO_GPOUT_CLOCK_HANDLE_RP2350(gpio, default_clk_handle) \
655 ((gpio) == 13 ? clk_gpout0 : \
656 ((gpio) == 15 ? clk_gpout1 : \
657 (GPIO_TO_GPOUT_CLOCK_HANDLE_RP2040(gpio, default_clk_handle))))
658
667#ifndef GPIO_TO_GPOUT_CLOCK_HANDLE
668#if PICO_RP2040
669#define GPIO_TO_GPOUT_CLOCK_HANDLE GPIO_TO_GPOUT_CLOCK_HANDLE_RP2040
670#else
671#define GPIO_TO_GPOUT_CLOCK_HANDLE GPIO_TO_GPOUT_CLOCK_HANDLE_RP2350
672#endif
673#endif
674
680static inline clock_handle_t gpio_to_gpout_clock_handle(uint gpio, clock_handle_t default_clk_handle) {
681 return GPIO_TO_GPOUT_CLOCK_HANDLE(gpio, ({invalid_params_if(HARDWARE_CLOCKS, true); default_clk_handle;}));
682}
683#ifdef __cplusplus
684}
685#endif
686
687#endif
static fixed_bitset_t * fixed_bitset_clear(fixed_bitset_t *bitset, uint bit_index)
Clear a single bit in the bitset.
Definition fixed_bitset.h:202
static fixed_bitset_t * fixed_bitset_set(fixed_bitset_t *bitset, uint bit_index)
Set a single bit in the bitset.
Definition fixed_bitset.h:188
static fixed_bitset_t * fixed_bitset_clear_all(fixed_bitset_t *bitset)
Clear all bits in the bitset.
Definition fixed_bitset.h:151
#define fixed_bitset_type(N)
Macro used to define a fixed-size bitset of a given size.
Definition fixed_bitset.h:48
static fixed_bitset_t * fixed_bitset_set_all(fixed_bitset_t *bitset)
Set all bits in the bitset.
Definition fixed_bitset.h:162
void clock_configure_int_divider(clock_handle_t clock, uint32_t src, uint32_t auxsrc, uint32_t src_freq, uint32_t int_divider)
Configure the specified clock to use the undivided input source.
Definition clocks.c:150
static float frequency_count_mhz(uint src)
Measure a clock's frequency using the frequency counter.
Definition clocks.h:416
static void clock_gpio_init_int_frac8(uint gpio, uint src, uint32_t div_int, uint8_t div_frac8)
Output an optionally divided clock to the specified gpio pin.
Definition clocks.h:480
static bool set_sys_clock_hz(uint32_t freq_hz, bool required)
Attempt to set a system clock frequency in hz.
Definition clocks.h:587
enum clock_dest_num_rp2350 clock_dest_num_t
Clock destination numbers on RP2350 (used as typedef clock_dest_num_t).
void clock_stop(clock_handle_t clock)
Stop the specified clock.
Definition clocks.c:33
bool clock_configure_mhz(clock_handle_t clock, uint32_t src, uint32_t auxsrc, uint32_t src_freq_mhz, uint32_t freq_mhz)
Configure the specified clock with 1MHz accuracy.
Definition clocks.c:126
void set_sys_clock_pll(uint32_t vco_freq, uint post_div1, uint post_div2)
Initialise the system clock.
Definition clocks.c:391
#define GPIO_TO_GPOUT_CLOCK_HANDLE
Returns the GPOUT clock number associated with a particular GPIO if there is one, or default_clk_hand...
Definition clocks.h:671
bool clock_configure(clock_handle_t clock, uint32_t src, uint32_t auxsrc, uint32_t src_freq, uint32_t freq)
Configure the specified clock with automatic clock divisor setup.
Definition clocks.c:99
void(* resus_callback_t)(void)
Resus callback function type.
Definition clocks.h:426
void clocks_enable_resus(resus_callback_t resus_callback)
Enable the resus function. Restarts clk_sys if it is accidentally stopped.
Definition clocks.c:245
void clock_configure_undivided(clock_handle_t clock, uint32_t src, uint32_t auxsrc, uint32_t src_freq)
Configure the specified clock to use the undivided input source.
Definition clocks.c:154
static void clock_gpio_init(uint gpio, uint src, float div)
Output an optionally divided clock to the specified gpio pin.
Definition clocks.h:507
enum clock_num_rp2350 clock_num_t
Clock numbers on RP2350 (used as typedef clock_num_t).
bool check_sys_clock_khz(uint32_t freq_khz, uint *vco_freq_out, uint *post_div1_out, uint *post_div2_out)
Check if a given system clock frequency is valid/attainable.
Definition clocks.c:449
void set_sys_clock_48mhz(void)
Initialise the system clock to 48MHz.
Definition clocks.c:357
void clock_set_reported_hz(clock_handle_t clock, uint hz)
Set the "current frequency" of the clock as reported by clock_get_hz without actually changing the cl...
Definition clocks.c:166
uint32_t clock_get_hz(clock_handle_t clock)
Get the current frequency of the specified clock.
Definition clocks.c:161
void clock_gpio_init_int_frac16(uint gpio, uint src, uint32_t div_int, uint16_t div_frac16)
Output an optionally divided clock to the specified gpio pin.
Definition clocks.c:269
static bool set_sys_clock_khz(uint32_t freq_khz, bool required)
Attempt to set a system clock frequency in khz.
Definition clocks.h:609
static clock_handle_t gpio_to_gpout_clock_handle(uint gpio, clock_handle_t default_clk_handle)
return the associated GPOUT clock for a given GPIO if any
Definition clocks.h:680
bool clock_configure_gpin(clock_handle_t clock, uint gpio, uint32_t src_freq, uint32_t freq)
Configure a clock to come from a gpio input.
Definition clocks.c:324
uint32_t frequency_count_khz(uint src)
Measure a clock's frequency using the frequency counter.
Definition clocks.c:171
bool check_sys_clock_hz(uint32_t freq_hz, uint *vco_freq_out, uint *post_div1_out, uint *post_div2_out)
Check if a given system clock frequency is valid/attainable.
Definition clocks.c:428
void panic(const char *fmt,...)
Displays a panic message and halts execution.
Definition panic.c:31