hardware_clocks

Typedefs

typedef void(* resus_callback_t) (void)
 Resus callback function type. More...
 

Enumerations

enum  clock_index {
  clk_gpout0 = 0 , clk_gpout1 , clk_gpout2 , clk_gpout3 ,
  clk_ref , clk_sys , clk_peri , clk_usb ,
  clk_adc , clk_rtc , CLK_COUNT
}
 Enumeration identifying a hardware clock. More...
 

Functions

void clocks_init (void)
 Initialise the clock hardware. More...
 
bool clock_configure (enum clock_index clk_index, uint32_t src, uint32_t auxsrc, uint32_t src_freq, uint32_t freq)
 Configure the specified clock. More...
 
void clock_stop (enum clock_index clk_index)
 Stop the specified clock. More...
 
uint32_t clock_get_hz (enum clock_index clk_index)
 Get the current frequency of the specified clock. More...
 
uint32_t frequency_count_khz (uint src)
 Measure a clocks frequency using the Frequency counter. More...
 
void clock_set_reported_hz (enum clock_index clk_index, uint hz)
 Set the "current frequency" of the clock as reported by clock_get_hz without actually changing the clock. More...
 
void clocks_enable_resus (resus_callback_t resus_callback)
 Enable the resus function. Restarts clk_sys if it is accidentally stopped. More...
 
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. More...
 
static void clock_gpio_init (uint gpio, uint src, float div)
 Output an optionally divided clock to the specified gpio pin. More...
 
bool clock_configure_gpin (enum clock_index clk_index, uint gpio, uint32_t src_freq, uint32_t freq)
 Configure a clock to come from a gpio input. More...
 

Detailed Description

Clock Management API

This API provides a high level interface to the clock functions.

The clocks block provides independent clocks to on-chip and external components. It takes inputs from a variety of clock sources allowing the user to trade off performance against cost, board area and power consumption. From these sources it uses multiple clock generators to provide the required clocks. This architecture allows the user flexibility to start and stop clocks independently and to vary some clock frequencies whilst maintaining others at their optimum frequencies

Please refer to the datasheet for more details on the RP2040 clocks.

The clock source depends on which clock you are attempting to configure. The first table below shows main clock sources. If 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 clock source, then you will need to use one of the entries from the subsequent tables.

Main Clock Sources

Source Reference Clock System Clock
ROSC CLOCKS_CLK_REF_CTRL_SRC_VALUE_ROSC_CLKSRC_PH
Auxiliary CLOCKS_CLK_REF_CTRL_SRC_VALUE_CLKSRC_CLK_REF_AUX CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX
XOSC CLOCKS_CLK_REF_CTRL_SRC_VALUE_XOSC_CLKSRC
Reference CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLK_REF

Auxiliary Clock Sources

The auxiliary clock sources available for use in the configure function depend on which clock is being configured. The following table describes the available values that can be used. Note that for clk_gpout[x], x can be 0-3.

Aux Source clk_gpout[x] clk_ref clk_sys
System PLL CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS
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
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
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
ROSC CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_ROSC_CLKSRC CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_ROSC_CLKSRC
XOSC CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_XOSC_CLKSRC CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_ROSC_CLKSRC
System clock CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLK_SYS
USB Clock CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLK_USB
ADC clock CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLK_ADC
RTC Clock CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLK_RTC
Ref clock CLOCKS_CLK_GPOUTx_CTRL_AUXSRC_VALUE_CLK_REF
Aux Source clk_peri clk_usb clk_adc
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
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
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
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
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
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
System clock CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLK_SYS
Aux Source clk_rtc
System PLL CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS
GPIO in 0 CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_CLKSRC_GPIN0
GPIO in 1 CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_CLKSRC_GPIN1
USB PLL CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB
ROSC CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_ROSC_CLKSRC_PH
XOSC CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_XOSC_CLKSRC

Example

#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/pll.h"
#include "hardware/structs/pll.h"
#include "hardware/structs/clocks.h"
void measure_freqs(void) {
uint f_pll_sys = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_PLL_SYS_CLKSRC_PRIMARY);
uint f_pll_usb = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_PLL_USB_CLKSRC_PRIMARY);
uint f_rosc = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_ROSC_CLKSRC);
uint f_clk_sys = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_SYS);
uint f_clk_peri = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_PERI);
uint f_clk_usb = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_USB);
uint f_clk_adc = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_ADC);
uint f_clk_rtc = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_RTC);
printf("pll_sys = %dkHz\n", f_pll_sys);
printf("pll_usb = %dkHz\n", f_pll_usb);
printf("rosc = %dkHz\n", f_rosc);
printf("clk_sys = %dkHz\n", f_clk_sys);
printf("clk_peri = %dkHz\n", f_clk_peri);
printf("clk_usb = %dkHz\n", f_clk_usb);
printf("clk_adc = %dkHz\n", f_clk_adc);
printf("clk_rtc = %dkHz\n", f_clk_rtc);
// Can't measure clk_ref / xosc as it is the ref
}
int main() {
printf("Hello, world!\n");
measure_freqs();
// Change clk_sys to be 48MHz. The simplest way is to take this from PLL_USB
// which has a source frequency of 48MHz
CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX,
CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB,
48 * MHZ,
48 * MHZ);
// Turn off PLL sys for good measure
pll_deinit(pll_sys);
// CLK peri is clocked from clk_sys so need to change clk_peri's freq
0,
CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLK_SYS,
48 * MHZ,
48 * MHZ);
// Re init uart now that clk_peri has changed
measure_freqs();
printf("Hello, 48MHz");
return 0;
}
bool clock_configure(enum clock_index clk_index, uint32_t src, uint32_t auxsrc, uint32_t src_freq, uint32_t freq)
Configure the specified clock.
Definition: clocks.c:48
uint32_t frequency_count_khz(uint src)
Measure a clocks frequency using the Frequency counter.
Definition: clocks.c:211
@ clk_peri
Peripheral clock for UART and SPI.
Definition: clocks.h:34
@ clk_sys
Processors, bus fabric, memory, memory mapped registers.
Definition: clocks.h:33
void pll_deinit(PLL pll)
Release/uninitialise specified PLL.
Definition: pll.c:75
bool stdio_init_all(void)
Initialize all of the present standard stdio types that are linked into the binary.
Definition: stdio.c:283

Typedef Documentation

◆ resus_callback_t

typedef void(* resus_callback_t) (void)

Resus callback function type.

User provided callback for a resus event (when clk_sys is stopped by the programmer and is restarted for them).

Enumeration Type Documentation

◆ clock_index

Enumeration identifying a hardware clock.

Enumerator
clk_gpout0 

GPIO Muxing 0.

clk_gpout1 

GPIO Muxing 1.

clk_gpout2 

GPIO Muxing 2.

clk_gpout3 

GPIO Muxing 3.

clk_ref 

Watchdog and timers reference clock.

clk_sys 

Processors, bus fabric, memory, memory mapped registers.

clk_peri 

Peripheral clock for UART and SPI.

clk_usb 

USB clock.

clk_adc 

ADC clock.

clk_rtc 

Real time clock.

Function Documentation

◆ clock_configure()

bool clock_configure ( enum clock_index  clk_index,
uint32_t  src,
uint32_t  auxsrc,
uint32_t  src_freq,
uint32_t  freq 
)

Configure the specified clock.

See the tables in the description for details on the possible values for clock sources.

Parameters
clk_indexThe clock to configure
srcThe main clock source, can be 0.
auxsrcThe auxiliary clock source, which depends on which clock is being set. Can be 0
src_freqFrequency of the input clock source
freqRequested frequency

◆ clock_configure_gpin()

bool clock_configure_gpin ( enum clock_index  clk_index,
uint  gpio,
uint32_t  src_freq,
uint32_t  freq 
)

Configure a clock to come from a gpio input.

Parameters
clk_indexThe clock to configure
gpioThe GPIO pin to run the clock from. Valid GPIOs are: 20 and 22.
src_freqFrequency of the input clock source
freqRequested frequency

◆ clock_get_hz()

uint32_t clock_get_hz ( enum clock_index  clk_index)

Get the current frequency of the specified clock.

Parameters
clk_indexClock
Returns
Clock frequency in Hz

◆ clock_gpio_init()

static void clock_gpio_init ( uint  gpio,
uint  src,
float  div 
)
inlinestatic

Output an optionally divided clock to the specified gpio pin.

Parameters
gpioThe GPIO pin to output the clock to. Valid GPIOs are: 21, 23, 24, 25. These GPIOs are connected to the GPOUT0-3 clock generators.
srcThe 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.
divThe float amount to divide the source clock by. This is useful to not overwhelm the GPIO pin with a fast clock.

◆ clock_gpio_init_int_frac()

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.

Parameters
gpioThe GPIO pin to output the clock to. Valid GPIOs are: 21, 23, 24, 25. These GPIOs are connected to the GPOUT0-3 clock generators.
srcThe 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.
div_intThe 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.
div_fracThe fractional part of the value to divide the source clock by. This is in range of 0..255 (/256).

◆ clock_set_reported_hz()

void clock_set_reported_hz ( enum clock_index  clk_index,
uint  hz 
)

Set the "current frequency" of the clock as reported by clock_get_hz without actually changing the clock.

See also
clock_get_hz()

◆ clock_stop()

void clock_stop ( enum clock_index  clk_index)

Stop the specified clock.

Parameters
clk_indexThe clock to stop

◆ clocks_enable_resus()

void clocks_enable_resus ( resus_callback_t  resus_callback)

Enable the resus function. Restarts clk_sys if it is accidentally stopped.

The resuscitate function will restart the system clock if it falls below a certain speed (or stops). This could happen if the clock source the system clock is running from stops. For example if a PLL is stopped.

Parameters
resus_callbacka function pointer provided by the user to call if a resus event happens.

◆ clocks_init()

void clocks_init ( void  )

Initialise the clock hardware.

Must be called before any other clock function.

◆ frequency_count_khz()

uint32_t frequency_count_khz ( uint  src)

Measure a clocks frequency using the Frequency counter.

Uses the inbuilt frequency counter to measure the specified clocks frequency. Currently, this function is accurate to +-1KHz. See the datasheet for more details.