@web-font-path: "roboto-debian.css";
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"
12
13#ifdef __cplusplus
14extern "C" {
15#endif
16
139#define KHZ 1000
140#define MHZ 1000000
141
142// \tag::pll_settings[]
143// There are two PLLs in RP-series microcontrollers:
144// 1. The 'SYS PLL' generates the system clock, the frequency is defined by `SYS_CLK_KHZ`.
145// 2. The 'USB PLL' generates the USB clock, the frequency is defined by `USB_CLK_KHZ`.
146//
147// The two PLLs use the crystal oscillator output directly as their reference frequency input; the PLLs reference
148// frequency cannot be reduced by the dividers present in the clocks block. The crystal frequency is defined by `XOSC_HZ` (or
149// `XOSC_KHZ` or `XOSC_MHZ`).
150//
151// The system's default definitions are correct for the above frequencies with a 12MHz
152// crystal frequency. If different frequencies are required, these must be defined in
153// the board configuration file together with the revised PLL settings
154// Use `vcocalc.py` to check and calculate new PLL settings if you change any of these frequencies.
155//
156// Default PLL configuration RP2040:
157// REF FBDIV VCO POSTDIV
158// PLL SYS: 12 / 1 = 12MHz * 125 = 1500MHz / 6 / 2 = 125MHz
159// PLL USB: 12 / 1 = 12MHz * 100 = 1200MHz / 5 / 5 = 48MHz
160//
161// Default PLL configuration RP2350:
162// REF FBDIV VCO POSTDIV
163// PLL SYS: 12 / 1 = 12MHz * 125 = 1500MHz / 5 / 2 = 150MHz
164// PLL USB: 12 / 1 = 12MHz * 100 = 1200MHz / 5 / 5 = 48MHz
165// \end::pll_settings[]
166
167#ifndef PLL_COMMON_REFDIV
168// backwards compatibility, but now deprecated
169#define PLL_COMMON_REFDIV 1
170#endif
171
172// PICO_CONFIG: PLL_SYS_REFDIV, PLL reference divider setting for PLL_SYS, type=int, default=1, advanced=true, group=hardware_clocks
173#ifndef PLL_SYS_REFDIV
174// backwards compatibility with deprecated PLL_COMMON_REFDIV
175#ifdef PLL_COMMON_REFDIV
176#define PLL_SYS_REFDIV PLL_COMMON_REFDIV
177#else
178#define PLL_SYS_REFDIV 1
179#endif
180#endif
181
182#ifndef PLL_SYS_VCO_FREQ_HZ
183// For backwards compatibility define PLL_SYS_VCO_FREQ_HZ if PLL_SYS_VCO_FREQ_KHZ is defined
184#ifdef PLL_SYS_VCO_FREQ_KHZ
185#define PLL_SYS_VCO_FREQ_HZ (PLL_SYS_VCO_FREQ_KHZ * KHZ)
186#endif
187#endif
188
189#if (SYS_CLK_HZ == 125 * MHZ || SYS_CLK_HZ == 150 * MHZ) && (XOSC_HZ == 12 * MHZ) && (PLL_SYS_REFDIV == 1)
190// PLL settings for standard 125/150 MHz system clock.
191// PICO_CONFIG: PLL_SYS_VCO_FREQ_HZ, System clock PLL frequency, type=int, default=(1500 * MHZ), advanced=true, group=hardware_clocks
192#ifndef PLL_SYS_VCO_FREQ_HZ
193#define PLL_SYS_VCO_FREQ_HZ (1500 * MHZ)
194#endif
195// 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
196#ifndef PLL_SYS_POSTDIV1
197#if SYS_CLK_HZ == 125 * MHZ
198#define PLL_SYS_POSTDIV1 6
199#else
200#define PLL_SYS_POSTDIV1 5
201#endif
202#endif
203// PICO_CONFIG: PLL_SYS_POSTDIV2, System clock PLL post divider 2 setting, type=int, default=2, advanced=true, group=hardware_clocks
204#ifndef PLL_SYS_POSTDIV2
205#define PLL_SYS_POSTDIV2 2
206#endif
207#endif // SYS_CLK_KHZ == 125000 && XOSC_KHZ == 12000 && PLL_COMMON_REFDIV == 1
208
209#if PICO_RP2040 && (SYS_CLK_HZ == 200 * MHZ) && (XOSC_HZ == 12 * MHZ) && (PLL_SYS_REFDIV == 1)
210// 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
211#ifndef SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST
212#define SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST 1
213#endif
214// 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
215#if SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST && !defined(SYS_CLK_VREG_VOLTAGE_MIN)
216#define SYS_CLK_VREG_VOLTAGE_MIN VREG_VOLTAGE_1_15
217#endif
218// PLL settings for fast 200 MHz system clock on RP2040
219#ifndef PLL_SYS_VCO_FREQ_HZ
220#define PLL_SYS_VCO_FREQ_HZ (1200 * MHZ)
221#endif
222#ifndef PLL_SYS_POSTDIV1
223#define PLL_SYS_POSTDIV1 6
224#endif
225#ifndef PLL_SYS_POSTDIV2
226#define PLL_SYS_POSTDIV2 1
227#endif
228#else
229#ifndef SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST
230#define SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST 0
231#endif
232#endif // PICO_RP2040 && SYS_CLK_KHZ == 200000 && XOSC_KHZ == 12000 && PLL_COMMON_REFDIV == 1
233
234// 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=bool, default=1, advanced=true, group=hardware_clocks
235#ifndef SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST_DELAY_US
236#define SYS_CLK_VREG_VOLTAGE_AUTO_ADJUST_DELAY_US 1000
237#endif
238
239#if !defined(PLL_SYS_VCO_FREQ_HZ) || !defined(PLL_SYS_POSTDIV1) || !defined(PLL_SYS_POSTDIV2)
240#error PLL_SYS_VCO_FREQ_HZ, PLL_SYS_POSTDIV1 and PLL_SYS_POSTDIV2 must all be specified when using custom clock setup
241#endif
242
243// PICO_CONFIG: PLL_USB_REFDIV, PLL reference divider setting for PLL_USB, type=int, default=1, advanced=true, group=hardware_clocks
244#ifndef PLL_USB_REFDIV
245// backwards compatibility with deprecated PLL_COMMON_REFDIV
246#ifdef PLL_COMMON_REFDIV
247#define PLL_USB_REFDIV PLL_COMMON_REFDIV
248#else
249#define PLL_USB_REFDIV 1
250#endif
251#endif
252
253#ifndef PLL_USB_VCO_FREQ_HZ
254// For backwards compatibility define PLL_USB_VCO_FREQ_HZ if PLL_USB_VCO_FREQ_KHZ is defined
255#ifdef PLL_USB_VCO_FREQ_KHZ
256#define PLL_USB_VCO_FREQ_HZ (PLL_USB_VCO_FREQ_KHZ * KHZ)
257#endif
258#endif
259
260#if (USB_CLK_HZ == 48 * MHZ) && (XOSC_HZ == 12 * MHZ) && (PLL_USB_REFDIV == 1)
261// PLL settings for a USB clock of 48MHz.
262// PICO_CONFIG: PLL_USB_VCO_FREQ_HZ, USB clock PLL frequency, type=int, default=(1200 * MHZ), advanced=true, group=hardware_clocks
263#ifndef PLL_USB_VCO_FREQ_HZ
264#define PLL_USB_VCO_FREQ_HZ (1200 * MHZ)
265#endif
266// PICO_CONFIG: PLL_USB_POSTDIV1, USB clock PLL post divider 1 setting, type=int, default=5, advanced=true, group=hardware_clocks
267#ifndef PLL_USB_POSTDIV1
268#define PLL_USB_POSTDIV1 5
269#endif
270// PICO_CONFIG: PLL_USB_POSTDIV2, USB clock PLL post divider 2 setting, type=int, default=5, advanced=true, group=hardware_clocks
271#ifndef PLL_USB_POSTDIV2
272#define PLL_USB_POSTDIV2 5
273#endif
274#endif // USB_CLK_HZ == 48000000 && XOSC_HZ == 12000000 && PLL_COMMON_REFDIV == 1
275#if !defined(PLL_USB_VCO_FREQ_HZ) || !defined(PLL_USB_POSTDIV1) || !defined(PLL_USB_POSTDIV2)
276#error PLL_USB_VCO_FREQ_HZ, PLL_USB_POSTDIV1 and PLL_USB_POSTDIV2 must all be specified when using custom clock setup.
277#endif
278
279// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_HARDWARE_CLOCKS, Enable/disable assertions in the hardware_clocks module, type=bool, default=0, group=hardware_clocks
280#ifndef PARAM_ASSERTIONS_ENABLED_HARDWARE_CLOCKS
281#ifdef PARAM_ASSERTIONS_ENABLED_CLOCKS // backwards compatibility with SDK < 2.0.0
282#define PARAM_ASSERTIONS_ENABLED_HARDWARE_CLOCKS PARAM_ASSERTIONS_ENABLED_CLOCKS
283#else
284#define PARAM_ASSERTIONS_ENABLED_HARDWARE_CLOCKS 0
285#endif
286#endif
287
288 // 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
289#ifndef PICO_CLOCK_GPIO_CLKDIV_ROUND_NEAREST
290#define PICO_CLOCK_GPIO_CLKDIV_ROUND_NEAREST PICO_CLKDIV_ROUND_NEAREST
291#endif
292
293typedef clock_num_t clock_handle_t;
294
319bool clock_configure(clock_handle_t clock, uint32_t src, uint32_t auxsrc, uint32_t src_freq, uint32_t freq);
320
331void clock_configure_undivided(clock_handle_t clock, uint32_t src, uint32_t auxsrc, uint32_t src_freq);
332
344void clock_configure_int_divider(clock_handle_t clock, uint32_t src, uint32_t auxsrc, uint32_t src_freq, uint32_t int_divider);
345
351void clock_stop(clock_handle_t clock);
352
359uint32_t clock_get_hz(clock_handle_t clock);
360
367uint32_t frequency_count_khz(uint src);
368
374void clock_set_reported_hz(clock_handle_t clock, uint hz);
375
377static inline float frequency_count_mhz(uint src) {
378 return ((float) (frequency_count_khz(src))) / KHZ;
379}
381
387typedef void (*resus_callback_t)(void);
388
397void clocks_enable_resus(resus_callback_t resus_callback);
398
408void clock_gpio_init_int_frac16(uint gpio, uint src, uint32_t div_int, uint16_t div_frac16);
409
419static inline void clock_gpio_init_int_frac8(uint gpio, uint src, uint32_t div_int, uint8_t div_frac8) {
420 return clock_gpio_init_int_frac16(gpio, src, div_int, (uint16_t)(div_frac8 << 8u));
421}
422
423// backwards compatibility
424static inline void clock_gpio_init_int_frac(uint gpio, uint src, uint32_t div_int, uint8_t div_frac8) {
425 return clock_gpio_init_int_frac8(gpio, src, div_int, div_frac8);
426}
427
435static inline void clock_gpio_init(uint gpio, uint src, float div)
436{
437 uint div_int = (uint)div;
438 const int frac_bit_count = REG_FIELD_WIDTH(CLOCKS_CLK_GPOUT0_DIV_FRAC);
439#if PICO_CLOCK_GPIO_CLKDIV_ROUND_NEAREST
440 div += 0.5f / (1 << frac_bit_count); // round to the nearest fraction
441#endif
442#if REG_FIELD_WIDTH(CLOCKS_CLK_GPOUT0_DIV_FRAC) == 16
443 uint16_t frac = (uint16_t)((div - (float)div_int) * (1u << frac_bit_count));
444 clock_gpio_init_int_frac16(gpio, src, div_int, frac);
445#elif REG_FIELD_WIDTH(CLOCKS_CLK_GPOUT0_DIV_FRAC) == 8
446 uint8_t frac = (uint8_t)((div - (float)div_int) * (1u << frac_bit_count));
447 clock_gpio_init_int_frac8(gpio, src, div_int, frac);
448#else
449#error unsupported number of fractional bits
450#endif
451}
452
461bool clock_configure_gpin(clock_handle_t clock, uint gpio, uint32_t src_freq, uint32_t freq);
462
468void set_sys_clock_48mhz(void);
469
479void set_sys_clock_pll(uint32_t vco_freq, uint post_div1, uint post_div2);
480
490bool check_sys_clock_hz(uint32_t freq_hz, uint *vco_freq_out, uint *post_div1_out, uint *post_div2_out);
491
501bool check_sys_clock_khz(uint32_t freq_khz, uint *vco_freq_out, uint *post_div1_out, uint *post_div2_out);
502
514static inline bool set_sys_clock_hz(uint32_t freq_hz, bool required) {
515 uint vco, postdiv1, postdiv2;
516 if (check_sys_clock_hz(freq_hz, &vco, &postdiv1, &postdiv2)) {
517 set_sys_clock_pll(vco, postdiv1, postdiv2);
518 return true;
519 } else if (required) {
520 panic("System clock of %u Hz cannot be exactly achieved", freq_hz);
521 }
522 return false;
523}
524
536static inline bool set_sys_clock_khz(uint32_t freq_khz, bool required) {
537 uint vco, postdiv1, postdiv2;
538 if (check_sys_clock_khz(freq_khz, &vco, &postdiv1, &postdiv2)) {
539 set_sys_clock_pll(vco, postdiv1, postdiv2);
540 return true;
541 } else if (required) {
542 panic("System clock of %u kHz cannot be exactly achieved", freq_khz);
543 }
544 return false;
545}
546
547#ifdef __cplusplus
548}
549#endif
550
551#endif
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:126
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:419
static bool set_sys_clock_hz(uint32_t freq_hz, bool required)
Attempt to set a system clock frequency in hz.
Definition clocks.h:514
void clock_stop(clock_handle_t clock)
Stop the specified clock.
Definition clocks.c:33
void set_sys_clock_pll(uint32_t vco_freq, uint post_div1, uint post_div2)
Initialise the system clock.
Definition clocks.c:380
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:98
void(* resus_callback_t)(void)
Resus callback function type.
Definition clocks.h:387
void clocks_enable_resus(resus_callback_t resus_callback)
Enable the resus function. Restarts clk_sys if it is accidentally stopped.
Definition clocks.c:221
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:130
static void clock_gpio_init(uint gpio, uint src, float div)
Output an optionally divided clock to the specified gpio pin.
Definition clocks.h:435
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:438
void set_sys_clock_48mhz(void)
Initialise the system clock to 48MHz.
Definition clocks.c:346
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:142
uint32_t clock_get_hz(clock_handle_t clock)
Get the current frequency of the specified clock.
Definition clocks.c:137
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:245
static bool set_sys_clock_khz(uint32_t freq_khz, bool required)
Attempt to set a system clock frequency in khz.
Definition clocks.h:536
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:313
enum clock_num_rp2040 clock_num_t
Clock numbers on RP2040 (used as typedef clock_num_t)
uint32_t frequency_count_khz(uint src)
Measure a clocks frequency using the Frequency counter.
Definition clocks.c:147
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:417
void panic(const char *fmt,...)
Displays a panic message and halts execution.
Definition panic.c:64