@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 5 or 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 !defined(PLL_SYS_VCO_FREQ_HZ) || !defined(PLL_SYS_POSTDIV1) || !defined(PLL_SYS_POSTDIV2)
210#error PLL_SYS_VCO_FREQ_HZ, PLL_SYS_POSTDIV1 and PLL_SYS_POSTDIV2 must all be specified when using custom clock setup
211#endif
212
213// PICO_CONFIG: PLL_USB_REFDIV, PLL reference divider setting for PLL_USB, type=int, default=1, advanced=true, group=hardware_clocks
214#ifndef PLL_USB_REFDIV
215// backwards compatibility with deprecated PLL_COMMON_REFDIV
216#ifdef PLL_COMMON_REFDIV
217#define PLL_USB_REFDIV PLL_COMMON_REFDIV
218#else
219#define PLL_USB_REFDIV 1
220#endif
221#endif
222
223#ifndef PLL_USB_VCO_FREQ_HZ
224// For backwards compatibility define PLL_USB_VCO_FREQ_HZ if PLL_USB_VCO_FREQ_KHZ is defined
225#ifdef PLL_USB_VCO_FREQ_KHZ
226#define PLL_USB_VCO_FREQ_HZ (PLL_USB_VCO_FREQ_KHZ * KHZ)
227#endif
228#endif
229
230#if (USB_CLK_HZ == 48 * MHZ) && (XOSC_HZ == 12 * MHZ) && (PLL_USB_REFDIV == 1)
231// PLL settings for a USB clock of 48MHz.
232// PICO_CONFIG: PLL_USB_VCO_FREQ_HZ, USB clock PLL frequency, type=int, default=(1200 * MHZ), advanced=true, group=hardware_clocks
233#ifndef PLL_USB_VCO_FREQ_HZ
234#define PLL_USB_VCO_FREQ_HZ (1200 * MHZ)
235#endif
236// PICO_CONFIG: PLL_USB_POSTDIV1, USB clock PLL post divider 1 setting, type=int, default=5, advanced=true, group=hardware_clocks
237#ifndef PLL_USB_POSTDIV1
238#define PLL_USB_POSTDIV1 5
239#endif
240// PICO_CONFIG: PLL_USB_POSTDIV2, USB clock PLL post divider 2 setting, type=int, default=5, advanced=true, group=hardware_clocks
241#ifndef PLL_USB_POSTDIV2
242#define PLL_USB_POSTDIV2 5
243#endif
244#endif // USB_CLK_HZ == 48000000 && XOSC_HZ == 12000000 && PLL_COMMON_REFDIV == 1
245#if !defined(PLL_USB_VCO_FREQ_HZ) || !defined(PLL_USB_POSTDIV1) || !defined(PLL_USB_POSTDIV2)
246#error PLL_USB_VCO_FREQ_HZ, PLL_USB_POSTDIV1 and PLL_USB_POSTDIV2 must all be specified when using custom clock setup.
247#endif
248
249// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_HARDWARE_CLOCKS, Enable/disable assertions in the hardware_clocks module, type=bool, default=0, group=hardware_clocks
250#ifndef PARAM_ASSERTIONS_ENABLED_HARDWARE_CLOCKS
251#ifdef PARAM_ASSERTIONS_ENABLED_CLOCKS // backwards compatibility with SDK < 2.0.0
252#define PARAM_ASSERTIONS_ENABLED_HARDWARE_CLOCKS PARAM_ASSERTIONS_ENABLED_CLOCKS
253#else
254#define PARAM_ASSERTIONS_ENABLED_HARDWARE_CLOCKS 0
255#endif
256#endif
257
258typedef clock_num_t clock_handle_t;
259
271bool clock_configure(clock_handle_t clock, uint32_t src, uint32_t auxsrc, uint32_t src_freq, uint32_t freq);
272
283void clock_configure_undivided(clock_handle_t clock, uint32_t src, uint32_t auxsrc, uint32_t src_freq);
284
296void clock_configure_int_divider(clock_handle_t clock, uint32_t src, uint32_t auxsrc, uint32_t src_freq, uint32_t int_divider);
297
303void clock_stop(clock_handle_t clock);
304
311uint32_t clock_get_hz(clock_handle_t clock);
312
319uint32_t frequency_count_khz(uint src);
320
326void clock_set_reported_hz(clock_handle_t clock, uint hz);
327
329static inline float frequency_count_mhz(uint src) {
330 return ((float) (frequency_count_khz(src))) / KHZ;
331}
333
339typedef void (*resus_callback_t)(void);
340
349void clocks_enable_resus(resus_callback_t resus_callback);
350
359void clock_gpio_init_int_frac(uint gpio, uint src, uint32_t div_int, uint8_t div_frac);
360
368static inline void clock_gpio_init(uint gpio, uint src, float div)
369{
370 uint div_int = (uint)div;
371 uint8_t frac = (uint8_t)((div - (float)div_int) * (1u << CLOCKS_CLK_GPOUT0_DIV_INT_LSB));
372 clock_gpio_init_int_frac(gpio, src, div_int, frac);
373}
374
383bool clock_configure_gpin(clock_handle_t clock, uint gpio, uint32_t src_freq, uint32_t freq);
384
390void set_sys_clock_48mhz(void);
391
401void set_sys_clock_pll(uint32_t vco_freq, uint post_div1, uint post_div2);
402
412bool check_sys_clock_hz(uint32_t freq_hz, uint *vco_freq_out, uint *post_div1_out, uint *post_div2_out);
413
423bool check_sys_clock_khz(uint32_t freq_khz, uint *vco_freq_out, uint *post_div1_out, uint *post_div2_out);
424
436static inline bool set_sys_clock_hz(uint32_t freq_hz, bool required) {
437 uint vco, postdiv1, postdiv2;
438 if (check_sys_clock_hz(freq_hz, &vco, &postdiv1, &postdiv2)) {
439 set_sys_clock_pll(vco, postdiv1, postdiv2);
440 return true;
441 } else if (required) {
442 panic("System clock of %u Hz cannot be exactly achieved", freq_hz);
443 }
444 return false;
445}
446
458static inline bool set_sys_clock_khz(uint32_t freq_khz, bool required) {
459 uint vco, postdiv1, postdiv2;
460 if (check_sys_clock_khz(freq_khz, &vco, &postdiv1, &postdiv2)) {
461 set_sys_clock_pll(vco, postdiv1, postdiv2);
462 return true;
463 } else if (required) {
464 panic("System clock of %u kHz cannot be exactly achieved", freq_khz);
465 }
466 return false;
467}
468
469#ifdef __cplusplus
470}
471#endif
472
473#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 undividded input source.
Definition clocks.c:112
void clock_stop(clock_handle_t clock)
Stop the specified clock.
Definition clocks.c:33
bool clock_configure(clock_handle_t clock, uint32_t src, uint32_t auxsrc, uint32_t src_freq, uint32_t freq)
Configure the specified clock.
Definition clocks.c:98
void(* resus_callback_t)(void)
Resus callback function type.
Definition clocks.h:339
void clocks_enable_resus(resus_callback_t resus_callback)
Enable the resus function. Restarts clk_sys if it is accidentally stopped.
Definition clocks.c:207
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 undividded input source.
Definition clocks.c:116
static void clock_gpio_init(uint gpio, uint src, float div)
Output an optionally divided clock to the specified gpio pin.
Definition clocks.h:368
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:128
uint32_t clock_get_hz(clock_handle_t clock)
Get the current frequency of the specified clock.
Definition clocks.c:123
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:292
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:133
void clock_gpio_init_int_frac(uint gpio, uint src, uint32_t div_int, uint8_t div_frac)
Output an optionally divided clock to the specified gpio pin.
Definition clocks.c:231
void panic(const char *fmt,...)
Displays a panic message and halts execution.
static bool set_sys_clock_hz(uint32_t freq_hz, bool required)
Attempt to set a system clock frequency in hz.
Definition clocks.h:436
void set_sys_clock_pll(uint32_t vco_freq, uint post_div1, uint post_div2)
Initialise the system clock.
Definition clocks.c:354
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:412
void set_sys_clock_48mhz(void)
Initialise the system clock to 48MHz.
Definition clocks.c:325
static bool set_sys_clock_khz(uint32_t freq_khz, bool required)
Attempt to set a system clock frequency in khz.
Definition clocks.h:458
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:391