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
14 extern "C" {
15 #endif
16
17 /** \file hardware/clocks.h
18 * \defgroup hardware_clocks hardware_clocks
19 *
20 * \brief Clock Management API
21 *
22 * This API provides a high level interface to the clock functions.
23 *
24 * The clocks block provides independent clocks to on-chip and external components. It takes inputs from a variety of clock
25 * sources allowing the user to trade off performance against cost, board area and power consumption. From these sources
26 * it uses multiple clock generators to provide the required clocks. This architecture allows the user flexibility to start and
27 * stop clocks independently and to vary some clock frequencies whilst maintaining others at their optimum frequencies
28 *
29 * Please refer to the appropriate datasheet for more details on the RP-series clocks.
30 *
31 * The clock source depends on which clock you are attempting to configure. The first table below shows main clock sources. If
32 * you are not setting the Reference clock or the System clock, or you are specifying that one of those two will be using an auxiliary
33 * clock source, then you will need to use one of the entries from the subsequent tables.
34 *
35 * * \if rp2040_specific
36 * On RP2040 the clock sources are:
37 *
38 * **Main Clock Sources**
39 *
40 * Source | Reference Clock | System Clock
41 * -------|-----------------|---------
42 * ROSC | CLOCKS_CLK_REF_CTRL_SRC_VALUE_ROSC_CLKSRC_PH | |
43 * Auxiliary | CLOCKS_CLK_REF_CTRL_SRC_VALUE_CLKSRC_CLK_REF_AUX | CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX
44 * XOSC | CLOCKS_CLK_REF_CTRL_SRC_VALUE_XOSC_CLKSRC | |
45 * Reference | | CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLK_REF
46 *
47 * **Auxiliary Clock Sources**
48 *
49 * The auxiliary clock sources available for use in the configure function depend on which clock is being configured. The following table
50 * describes the available values that can be used. Note that for clk_gpout[x], x can be 0-3.
51 *
52 *
53 * Aux Source | clk_gpout[x] | clk_ref | clk_sys
54 * -----------|------------|---------|--------
55 * System PLL | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS | | CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS
56 * GPIO in 0 | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLKSRC_GPIN0 | CLOCKS_CLK_REF_CTRL_AUXSRC_VALUE_CLKSRC_GPIN0 | CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_GPIN0
57 * GPIO in 1 | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLKSRC_GPIN1 | CLOCKS_CLK_REF_CTRL_AUXSRC_VALUE_CLKSRC_GPIN1 | CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_GPIN1
58 * USB PLL | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB | CLOCKS_CLK_REF_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB| CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB
59 * ROSC | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_ROSC_CLKSRC | | CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_ROSC_CLKSRC
60 * XOSC | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_XOSC_CLKSRC | | CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_XOSC_CLKSRC
61 * System clock | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLK_SYS | | |
62 * USB Clock | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLK_USB | | |
63 * ADC clock | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLK_ADC | | |
64 * RTC Clock | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLK_RTC | | |
65 * Ref clock | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLK_REF | | |
66 *
67 * Aux Source | clk_peri | clk_usb | clk_adc
68 * -----------|-----------|---------|--------
69 * System PLL | CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS | CLOCKS_CLK_USB_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS | CLOCKS_CLK_ADC_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS
70 * GPIO in 0 | CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_GPIN0 | CLOCKS_CLK_USB_CTRL_AUXSRC_VALUE_CLKSRC_GPIN0 | CLOCKS_CLK_ADC_CTRL_AUXSRC_VALUE_CLKSRC_GPIN0
71 * GPIO in 1 | CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_GPIN1 | CLOCKS_CLK_USB_CTRL_AUXSRC_VALUE_CLKSRC_GPIN1 | CLOCKS_CLK_ADC_CTRL_AUXSRC_VALUE_CLKSRC_GPIN1
72 * USB PLL | CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB | CLOCKS_CLK_USB_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB | CLOCKS_CLK_ADC_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB
73 * ROSC | CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_ROSC_CLKSRC_PH | CLOCKS_CLK_USB_CTRL_AUXSRC_VALUE_ROSC_CLKSRC_PH | CLOCKS_CLK_ADC_CTRL_AUXSRC_VALUE_ROSC_CLKSRC_PH
74 * XOSC | CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_XOSC_CLKSRC | CLOCKS_CLK_USB_CTRL_AUXSRC_VALUE_XOSC_CLKSRC | CLOCKS_CLK_ADC_CTRL_AUXSRC_VALUE_XOSC_CLKSRC
75 * System clock | CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLK_SYS | | |
76 *
77 * Aux Source | clk_rtc
78 * -----------|----------
79 * System PLL | CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS
80 * GPIO in 0 | CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_CLKSRC_GPIN0
81 * GPIO in 1 | CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_CLKSRC_GPIN1
82 * USB PLL | CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB
83 * ROSC | CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_ROSC_CLKSRC_PH
84 * XOSC | CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_XOSC_CLKSRC
85 * \endif
86 *
87 * \if rp2350_specific
88 * On RP2350 the clock sources are:
89 * * **Main Clock Sources**
90 *
91 * Source | Reference Clock | System Clock
92 * -------|-----------------|---------
93 * ROSC | CLOCKS_CLK_REF_CTRL_SRC_VALUE_ROSC_CLKSRC_PH | |
94 * Auxiliary | CLOCKS_CLK_REF_CTRL_SRC_VALUE_CLKSRC_CLK_REF_AUX | CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX
95 * XOSC | CLOCKS_CLK_REF_CTRL_SRC_VALUE_XOSC_CLKSRC | |
96 * LPOSC | CLOCKS_CLK_REF_CTRL_SRC_VALUE_LPOSC_CLKSRC | |
97 * Reference | | CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLK_REF
98 *
99 * **Auxiliary Clock Sources**
100 *
101 * The auxiliary clock sources available for use in the configure function depend on which clock is being configured. The following table
102 * describes the available values that can be used. Note that for clk_gpout[x], x can be 0-3.
103 *
104 *
105 * Aux Source | clk_gpout[x] | clk_ref | clk_sys
106 * -----------|------------|---------|--------
107 * System PLL | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS | | CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS
108 * GPIO in 0 | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLKSRC_GPIN0 | CLOCKS_CLK_REF_CTRL_AUXSRC_VALUE_CLKSRC_GPIN0 | CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_GPIN0
109 * GPIO in 1 | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLKSRC_GPIN1 | CLOCKS_CLK_REF_CTRL_AUXSRC_VALUE_CLKSRC_GPIN1 | CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_GPIN1
110 * USB PLL | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB | CLOCKS_CLK_REF_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB| CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB
111 * ROSC | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_ROSC_CLKSRC | | CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_ROSC_CLKSRC
112 * XOSC | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_XOSC_CLKSRC | | CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_XOSC_CLKSRC
113 * LPOSC | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_LPOSC_CLKSRC | | |
114 * System clock | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLK_SYS | | |
115 * USB Clock | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLK_USB | | |
116 * ADC clock | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLK_ADC | | |
117 * REF clock | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLK_REF | | |
118 * PERI clock | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLK_PERI | | |
119 * HSTX clock | CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLK_PERI | | |
120
121 *
122 * Aux Source | clk_peri | clk_hstx | clk_usb | clk_adc
123 * -----------|-----------|----------|---------|--------
124 * System PLL | CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS | CLOCKS_CLK_HSTX_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS | CLOCKS_CLK_USB_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS | CLOCKS_CLK_ADC_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS
125 * GPIO in 0 | CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_GPIN0 | | CLOCKS_CLK_USB_CTRL_AUXSRC_VALUE_CLKSRC_GPIN0 | CLOCKS_CLK_ADC_CTRL_AUXSRC_VALUE_CLKSRC_GPIN0
126 * GPIO in 1 | CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_GPIN1 | | CLOCKS_CLK_USB_CTRL_AUXSRC_VALUE_CLKSRC_GPIN1 | CLOCKS_CLK_ADC_CTRL_AUXSRC_VALUE_CLKSRC_GPIN1
127 * USB PLL | CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB | CLOCKS_CLK_HSTX_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB | CLOCKS_CLK_USB_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB | CLOCKS_CLK_ADC_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB
128 * ROSC | CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_ROSC_CLKSRC_PH | | CLOCKS_CLK_USB_CTRL_AUXSRC_VALUE_ROSC_CLKSRC_PH | CLOCKS_CLK_ADC_CTRL_AUXSRC_VALUE_ROSC_CLKSRC_PH
129 * XOSC | CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_XOSC_CLKSRC | | CLOCKS_CLK_USB_CTRL_AUXSRC_VALUE_XOSC_CLKSRC | CLOCKS_CLK_ADC_CTRL_AUXSRC_VALUE_XOSC_CLKSRC
130 * System clock | CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLK_SYS | CLOCKS_CLK_HSTX_CTRL_AUXSRC_VALUE_CLK_SYS | | |
131 * \endif
132
133 *
134 * \section clock_example Example
135 * \addtogroup hardware_clocks
136 * \include hello_48MHz.c
137 */
138
139 #define PICO_KHZ 1000
140 #define PICO_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 * PICO_KHZ)
186 #endif
187 #endif
188
189 #if (SYS_CLK_HZ == 125 * PICO_MHZ || SYS_CLK_HZ == 150 * PICO_MHZ) && (XOSC_HZ == 12 * PICO_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 * PICO_MHZ), advanced=true, group=hardware_clocks
192 #ifndef PLL_SYS_VCO_FREQ_HZ
193 #define PLL_SYS_VCO_FREQ_HZ (1500 * PICO_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 * PICO_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 * PICO_KHZ)
227 #endif
228 #endif
229
230 #if (USB_CLK_HZ == 48 * PICO_MHZ) && (XOSC_HZ == 12 * PICO_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 * PICO_MHZ), advanced=true, group=hardware_clocks
233 #ifndef PLL_USB_VCO_FREQ_HZ
234 #define PLL_USB_VCO_FREQ_HZ (1200 * PICO_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
258 // 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
259 #ifndef PICO_CLOCK_GPIO_CLKDIV_ROUND_NEAREST
260 #define PICO_CLOCK_GPIO_CLKDIV_ROUND_NEAREST PICO_CLKDIV_ROUND_NEAREST
261 #endif
262
263 typedef clock_num_t clock_handle_t;
264
265 /*! \brief Configure the specified clock
266 * \ingroup hardware_clocks
267 *
268 * See the tables in the description for details on the possible values for clock sources.
269 *
270 * \param clock The clock to configure
271 * \param src The main clock source, can be 0.
272 * \param auxsrc The auxiliary clock source, which depends on which clock is being set. Can be 0
273 * \param src_freq Frequency of the input clock source
274 * \param freq Requested frequency
275 */
276 bool clock_configure(clock_handle_t clock, uint32_t src, uint32_t auxsrc, uint32_t src_freq, uint32_t freq);
277
278 /*! \brief Configure the specified clock to use the undividded input source
279 * \ingroup hardware_clocks
280 *
281 * See the tables in the description for details on the possible values for clock sources.
282 *
283 * \param clock The clock to configure
284 * \param src The main clock source, can be 0.
285 * \param auxsrc The auxiliary clock source, which depends on which clock is being set. Can be 0
286 * \param src_freq Frequency of the input clock source
287 */
288 void clock_configure_undivided(clock_handle_t clock, uint32_t src, uint32_t auxsrc, uint32_t src_freq);
289
290 /*! \brief Configure the specified clock to use the undividded input source
291 * \ingroup hardware_clocks
292 *
293 * See the tables in the description for details on the possible values for clock sources.
294 *
295 * \param clock The clock to configure
296 * \param src The main clock source, can be 0.
297 * \param auxsrc The auxiliary clock source, which depends on which clock is being set. Can be 0
298 * \param src_freq Frequency of the input clock source
299 * \param int_divider an integer divider
300 */
301 void clock_configure_int_divider(clock_handle_t clock, uint32_t src, uint32_t auxsrc, uint32_t src_freq, uint32_t int_divider);
302
303 /*! \brief Stop the specified clock
304 * \ingroup hardware_clocks
305 *
306 * \param clock The clock to stop
307 */
308 void clock_stop(clock_handle_t clock);
309
310 /*! \brief Get the current frequency of the specified clock
311 * \ingroup hardware_clocks
312 *
313 * \param clock Clock
314 * \return Clock frequency in Hz
315 */
316 uint32_t clock_get_hz(clock_handle_t clock);
317
318 /*! \brief Measure a clocks frequency using the Frequency counter.
319 * \ingroup hardware_clocks
320 *
321 * Uses the inbuilt frequency counter to measure the specified clocks frequency.
322 * Currently, this function is accurate to +-1KHz. See the datasheet for more details.
323 */
324 uint32_t frequency_count_khz(uint src);
325
326 /*! \brief Set the "current frequency" of the clock as reported by clock_get_hz without actually changing the clock
327 * \ingroup hardware_clocks
328 *
329 * \see clock_get_hz()
330 */
331 void clock_set_reported_hz(clock_handle_t clock, uint hz);
332
333 /// \tag::frequency_count_mhz[]
frequency_count_mhz(uint src)334 static inline float frequency_count_mhz(uint src) {
335 return ((float) (frequency_count_khz(src))) / PICO_KHZ;
336 }
337 /// \end::frequency_count_mhz[]
338
339 /*! \brief Resus callback function type.
340 * \ingroup hardware_clocks
341 *
342 * User provided callback for a resus event (when clk_sys is stopped by the programmer and is restarted for them).
343 */
344 typedef void (*resus_callback_t)(void);
345
346 /*! \brief Enable the resus function. Restarts clk_sys if it is accidentally stopped.
347 * \ingroup hardware_clocks
348 *
349 * The resuscitate function will restart the system clock if it falls below a certain speed (or stops). This
350 * could happen if the clock source the system clock is running from stops. For example if a PLL is stopped.
351 *
352 * \param resus_callback a function pointer provided by the user to call if a resus event happens.
353 */
354 void clocks_enable_resus(resus_callback_t resus_callback);
355
356 /*! \brief Output an optionally divided clock to the specified gpio pin.
357 * \ingroup hardware_clocks
358 *
359 * \param gpio The GPIO pin to output the clock to. Valid GPIOs are: 21, 23, 24, 25. These GPIOs are connected to the GPOUT0-3 clock generators.
360 * \param src The source clock. See the register field CLOCKS_CLK_GPOUT0_CTRL_AUXSRC for a full list. The list is the same for each GPOUT clock generator.
361 * \param div_int The integer part of the value to divide the source clock by. This is useful to not overwhelm the GPIO pin with a fast clock. This is in range of 1..2^24-1 on RP2040
362 * and 1..2^16-1 on RP2350
363 * \param div_frac16 The fractional part of the value to divide the source clock by. This is in range of 0..65535 (/65536).
364 */
365 void clock_gpio_init_int_frac16(uint gpio, uint src, uint32_t div_int, uint16_t div_frac16);
366
367 /*! \brief Output an optionally divided clock to the specified gpio pin.
368 * \ingroup hardware_clocks
369 *
370 * \param gpio The GPIO pin to output the clock to. Valid GPIOs are: 21, 23, 24, 25. These GPIOs are connected to the GPOUT0-3 clock generators.
371 * \param src The source clock. See the register field CLOCKS_CLK_GPOUT0_CTRL_AUXSRC for a full list. The list is the same for each GPOUT clock generator.
372 * \param div_int The integer part of the value to divide the source clock by. This is useful to not overwhelm the GPIO pin with a fast clock. This is in range of 1..2^24-1 on RP2040
373 * and 1..2^16-1 on RP2350
374 * \param div_frac8 The fractional part of the value to divide the source clock by. This is in range of 0..255 (/256).
375 */
clock_gpio_init_int_frac8(uint gpio,uint src,uint32_t div_int,uint8_t div_frac8)376 static inline void clock_gpio_init_int_frac8(uint gpio, uint src, uint32_t div_int, uint8_t div_frac8) {
377 return clock_gpio_init_int_frac16(gpio, src, div_int, (uint16_t)(div_frac8 << 8u));
378 }
379
380 // backwards compatibility
clock_gpio_init_int_frac(uint gpio,uint src,uint32_t div_int,uint8_t div_frac8)381 static inline void clock_gpio_init_int_frac(uint gpio, uint src, uint32_t div_int, uint8_t div_frac8) {
382 return clock_gpio_init_int_frac8(gpio, src, div_int, div_frac8);
383 }
384
385 /*! \brief Output an optionally divided clock to the specified gpio pin.
386 * \ingroup hardware_clocks
387 *
388 * \param gpio The GPIO pin to output the clock to. Valid GPIOs are: 21, 23, 24, 25. These GPIOs are connected to the GPOUT0-3 clock generators.
389 * \param src The source clock. See the register field CLOCKS_CLK_GPOUT0_CTRL_AUXSRC for a full list. The list is the same for each GPOUT clock generator.
390 * \param div The float amount to divide the source clock by. This is useful to not overwhelm the GPIO pin with a fast clock.
391 */
clock_gpio_init(uint gpio,uint src,float div)392 static inline void clock_gpio_init(uint gpio, uint src, float div)
393 {
394 uint div_int = (uint)div;
395 const int frac_bit_count = REG_FIELD_WIDTH(CLOCKS_CLK_GPOUT0_DIV_FRAC);
396 #if PICO_CLOCK_GPIO_CLKDIV_ROUND_NEAREST
397 div += 0.5f / (1 << frac_bit_count); // round to the nearest fraction
398 #endif
399 #if REG_FIELD_WIDTH(CLOCKS_CLK_GPOUT0_DIV_FRAC) == 16
400 uint16_t frac = (uint16_t)((div - (float)div_int) * (1u << frac_bit_count));
401 clock_gpio_init_int_frac16(gpio, src, div_int, frac);
402 #elif REG_FIELD_WIDTH(CLOCKS_CLK_GPOUT0_DIV_FRAC) == 8
403 uint8_t frac = (uint8_t)((div - (float)div_int) * (1u << frac_bit_count));
404 clock_gpio_init_int_frac8(gpio, src, div_int, frac);
405 #else
406 #error unsupported number of fractional bits
407 #endif
408 }
409
410 /*! \brief Configure a clock to come from a gpio input
411 * \ingroup hardware_clocks
412 *
413 * \param clock The clock to configure
414 * \param gpio The GPIO pin to run the clock from. Valid GPIOs are: 20 and 22.
415 * \param src_freq Frequency of the input clock source
416 * \param freq Requested frequency
417 */
418 bool clock_configure_gpin(clock_handle_t clock, uint gpio, uint32_t src_freq, uint32_t freq);
419
420 /*! \brief Initialise the system clock to 48MHz
421 * \ingroup hardware_clocks
422 *
423 * Set the system clock to 48MHz, and set the peripheral clock to match.
424 */
425 void set_sys_clock_48mhz(void);
426
427 /*! \brief Initialise the system clock
428 * \ingroup hardware_clocks
429 *
430 * \param vco_freq The voltage controller oscillator frequency to be used by the SYS PLL
431 * \param post_div1 The first post divider for the SYS PLL
432 * \param post_div2 The second post divider for the SYS PLL.
433 *
434 * See the PLL documentation in the datasheet for details of driving the PLLs.
435 */
436 void set_sys_clock_pll(uint32_t vco_freq, uint post_div1, uint post_div2);
437
438 /*! \brief Check if a given system clock frequency is valid/attainable
439 * \ingroup hardware_clocks
440 *
441 * \param freq_hz Requested frequency
442 * \param vco_freq_out On success, the voltage controlled oscillator frequency to be used by the SYS PLL
443 * \param post_div1_out On success, The first post divider for the SYS PLL
444 * \param post_div2_out On success, The second post divider for the SYS PLL.
445 * @return true if the frequency is possible and the output parameters have been written.
446 */
447 bool check_sys_clock_hz(uint32_t freq_hz, uint *vco_freq_out, uint *post_div1_out, uint *post_div2_out);
448
449 /*! \brief Check if a given system clock frequency is valid/attainable
450 * \ingroup hardware_clocks
451 *
452 * \param freq_khz Requested frequency
453 * \param vco_freq_out On success, the voltage controlled oscillator frequency to be used by the SYS PLL
454 * \param post_div1_out On success, The first post divider for the SYS PLL
455 * \param post_div2_out On success, The second post divider for the SYS PLL.
456 * @return true if the frequency is possible and the output parameters have been written.
457 */
458 bool check_sys_clock_khz(uint32_t freq_khz, uint *vco_freq_out, uint *post_div1_out, uint *post_div2_out);
459
460 /*! \brief Attempt to set a system clock frequency in hz
461 * \ingroup hardware_clocks
462 *
463 * Note that not all clock frequencies are possible; it is preferred that you
464 * use src/rp2_common/hardware_clocks/scripts/vcocalc.py to calculate the parameters
465 * for use with set_sys_clock_pll
466 *
467 * \param freq_hz Requested frequency
468 * \param required if true then this function will assert if the frequency is not attainable.
469 * \return true if the clock was configured
470 */
set_sys_clock_hz(uint32_t freq_hz,bool required)471 static inline bool set_sys_clock_hz(uint32_t freq_hz, bool required) {
472 uint vco, postdiv1, postdiv2;
473 if (check_sys_clock_hz(freq_hz, &vco, &postdiv1, &postdiv2)) {
474 set_sys_clock_pll(vco, postdiv1, postdiv2);
475 return true;
476 } else if (required) {
477 panic("System clock of %u Hz cannot be exactly achieved", freq_hz);
478 }
479 return false;
480 }
481
482 /*! \brief Attempt to set a system clock frequency in khz
483 * \ingroup hardware_clocks
484 *
485 * Note that not all clock frequencies are possible; it is preferred that you
486 * use src/rp2_common/hardware_clocks/scripts/vcocalc.py to calculate the parameters
487 * for use with set_sys_clock_pll
488 *
489 * \param freq_khz Requested frequency
490 * \param required if true then this function will assert if the frequency is not attainable.
491 * \return true if the clock was configured
492 */
set_sys_clock_khz(uint32_t freq_khz,bool required)493 static inline bool set_sys_clock_khz(uint32_t freq_khz, bool required) {
494 uint vco, postdiv1, postdiv2;
495 if (check_sys_clock_khz(freq_khz, &vco, &postdiv1, &postdiv2)) {
496 set_sys_clock_pll(vco, postdiv1, postdiv2);
497 return true;
498 } else if (required) {
499 panic("System clock of %u kHz cannot be exactly achieved", freq_khz);
500 }
501 return false;
502 }
503
504 #ifdef __cplusplus
505 }
506 #endif
507
508 #endif
509