Atmel Software Framework

System Clock Management

See Quick Start Guide for the System Clock Management service (SAMG51).

The sysclk API covers the system clock and all clocks derived from it. The system clock is a chip-internal clock on which all synchronous clocks, i.e. CPU and bus/peripheral clocks, are based. The system clock is typically generated from one of a variety of sources, which may include crystal and RC oscillators as well as PLLs. The clocks derived from the system clock are sometimes also known as synchronous clocks, since they always run synchronously with respect to each other, as opposed to generic clocks which may run from different oscillators or PLLs.

Most applications should simply call sysclk_init() to initialize everything related to the system clock and its source (oscillator, PLL or DFLL), and leave it at that. More advanced applications, and platform-specific drivers, may require additional services from the clock system, some of which may be platform-specific.

Platform Dependencies

The sysclk API is partially chip- or platform-specific. While all platforms provide mostly the same functionality, there are some variations around how different bus types and clock tree structures are handled.

The following functions are available on all platforms with the same parameters and functionality. These functions may be called freely by portable applications, drivers and services:

The following functions are available on all platforms, but there may be variations in the function signature (i.e. parameters) and behavior. These functions are typically called by platform-specific parts of drivers, and applications that aren't intended to be portable:

All other functions should be considered platform-specific. Enabling/disabling clocks to specific peripherals as well as determining the speed of these clocks should be done by calling functions provided by the driver for that peripheral.

Functions

void sysclk_disable_usb (void)
 
void sysclk_enable_usb (void)
 

System Clock Initialization

void sysclk_init (void)
 Initialize the synchronous clock system. More...
 

Configuration Symbols

#define CONFIG_SYSCLK_SOURCE   SYSCLK_SRC_MAINCK_8M_RC
 Initial/static main system clock source. More...
 
#define CONFIG_SYSCLK_PRES   0
 Initial CPU clock divider (mck) More...
 

Master Clock Sources (MCK)

#define SYSCLK_SRC_SLCK_RC   0
 Internal 32kHz RC oscillator as master source clock. More...
 
#define SYSCLK_SRC_SLCK_XTAL   1
 External 32kHz crystal oscillator as master source clock. More...
 
#define SYSCLK_SRC_SLCK_BYPASS   2
 External 32kHz bypass oscillator as master source clock. More...
 
#define SYSCLK_SRC_MAINCK_8M_RC   3
 Internal 8MHz RC oscillator as master source clock. More...
 
#define SYSCLK_SRC_MAINCK_16M_RC   4
 Internal 16MHz RC oscillator as master source clock. More...
 
#define SYSCLK_SRC_MAINCK_24M_RC   5
 Internal 24MHz RC oscillator as master source clock. More...
 
#define SYSCLK_SRC_MAINCK_XTAL   6
 External crystal oscillator as master source clock. More...
 
#define SYSCLK_SRC_MAINCK_BYPASS   7
 External bypass oscillator as master source clock. More...
 
#define SYSCLK_SRC_PLLACK   8
 Use PLLACK as master source clock. More...
 

Master Clock Prescalers (MCK)

#define SYSCLK_PRES_1   PMC_MCKR_PRES_CLK_1
 Set master clock prescaler to 1. More...
 
#define SYSCLK_PRES_2   PMC_MCKR_PRES_CLK_2
 Set master clock prescaler to 2. More...
 
#define SYSCLK_PRES_4   PMC_MCKR_PRES_CLK_4
 Set master clock prescaler to 4. More...
 
#define SYSCLK_PRES_8   PMC_MCKR_PRES_CLK_8
 Set master clock prescaler to 8. More...
 
#define SYSCLK_PRES_16   PMC_MCKR_PRES_CLK_16
 Set master clock prescaler to 16. More...
 
#define SYSCLK_PRES_32   PMC_MCKR_PRES_CLK_32
 Set master clock prescaler to 32. More...
 
#define SYSCLK_PRES_64   PMC_MCKR_PRES_CLK_64
 Set master clock prescaler to 64. More...
 
#define SYSCLK_PRES_3   PMC_MCKR_PRES_CLK_3
 Set master clock prescaler to 3. More...
 

Querying the system clock

The following functions may be used to query the current frequency of the system clock and the CPU and bus clocks derived from it.

sysclk_get_main_hz() and sysclk_get_cpu_hz() can be assumed to be available on all platforms, although some platforms may define additional accessors for various chip-internal bus clocks. These are usually not intended to be queried directly by generic code.

static uint32_t sysclk_get_main_hz (void)
 Return the current rate in Hz of the main system clock. More...
 
static uint32_t sysclk_get_cpu_hz (void)
 Return the current rate in Hz of the CPU clock. More...
 
static uint32_t sysclk_get_peripheral_hz (void)
 Retrieves the current rate in Hz of the peripheral clocks. More...
 
static uint32_t sysclk_get_peripheral_bus_hz (const volatile void *module)
 Retrieves the current rate in Hz of the Peripheral Bus clock attached to the specified peripheral. More...
 

Enabling and disabling synchronous clocks

static void sysclk_enable_peripheral_clock (uint32_t ul_id)
 Enable a peripheral's clock. More...
 
static void sysclk_disable_peripheral_clock (uint32_t ul_id)
 Disable a peripheral's clock. More...
 

System Clock Source and Prescaler configuration

void sysclk_set_prescalers (uint32_t ul_pres)
 Set system clock prescaler configuration. More...
 
void sysclk_set_source (uint32_t ul_src)
 Change the source of the main system clock. More...
 

#define CONFIG_SYSCLK_PRES   0

Initial CPU clock divider (mck)

The MCK will run at

\[ f_{MCK} = \frac{f_{sys}}{\mathrm{CONFIG\_SYSCLK\_PRES}}\,\mbox{Hz} \]

after initialization.

Referenced by sysclk_get_cpu_hz(), sysclk_get_peripheral_hz(), and sysclk_init().

#define CONFIG_SYSCLK_SOURCE   SYSCLK_SRC_MAINCK_8M_RC

Initial/static main system clock source.

The main system clock will be configured to use this clock during initialization.

Referenced by sysclk_get_main_hz(), and sysclk_init().

#define SYSCLK_PRES_1   PMC_MCKR_PRES_CLK_1

Set master clock prescaler to 1.

Referenced by _app_exec(), and main().

#define SYSCLK_PRES_16   PMC_MCKR_PRES_CLK_16

Set master clock prescaler to 16.

#define SYSCLK_PRES_2   PMC_MCKR_PRES_CLK_2

Set master clock prescaler to 2.

Referenced by main().

#define SYSCLK_PRES_3   PMC_MCKR_PRES_CLK_3

Set master clock prescaler to 3.

Referenced by sysclk_get_cpu_hz(), and sysclk_get_peripheral_hz().

#define SYSCLK_PRES_32   PMC_MCKR_PRES_CLK_32

Set master clock prescaler to 32.

#define SYSCLK_PRES_4   PMC_MCKR_PRES_CLK_4

Set master clock prescaler to 4.

#define SYSCLK_PRES_64   PMC_MCKR_PRES_CLK_64

Set master clock prescaler to 64.

#define SYSCLK_PRES_8   PMC_MCKR_PRES_CLK_8

Set master clock prescaler to 8.

#define SYSCLK_SRC_MAINCK_16M_RC   4

Internal 16MHz RC oscillator as master source clock.

Referenced by sysclk_get_main_hz(), sysclk_init(), and sysclk_set_source().

#define SYSCLK_SRC_MAINCK_24M_RC   5

Internal 24MHz RC oscillator as master source clock.

Referenced by sysclk_get_main_hz(), sysclk_init(), and sysclk_set_source().

#define SYSCLK_SRC_MAINCK_8M_RC   3

Internal 8MHz RC oscillator as master source clock.

Referenced by main(), sysclk_get_main_hz(), sysclk_init(), and sysclk_set_source().

#define SYSCLK_SRC_MAINCK_BYPASS   7

External bypass oscillator as master source clock.

Referenced by sysclk_get_main_hz(), sysclk_init(), and sysclk_set_source().

#define SYSCLK_SRC_MAINCK_XTAL   6

External crystal oscillator as master source clock.

Referenced by main(), sysclk_get_main_hz(), sysclk_init(), and sysclk_set_source().

#define SYSCLK_SRC_PLLACK   8

Use PLLACK as master source clock.

Referenced by sysclk_get_main_hz(), sysclk_init(), and sysclk_set_source().

#define SYSCLK_SRC_SLCK_BYPASS   2

External 32kHz bypass oscillator as master source clock.

Referenced by sysclk_get_main_hz(), sysclk_init(), and sysclk_set_source().

#define SYSCLK_SRC_SLCK_RC   0

Internal 32kHz RC oscillator as master source clock.

Referenced by main(), sysclk_get_main_hz(), sysclk_init(), and sysclk_set_source().

#define SYSCLK_SRC_SLCK_XTAL   1

External 32kHz crystal oscillator as master source clock.

Referenced by sysclk_get_main_hz(), sysclk_init(), and sysclk_set_source().

static void sysclk_disable_peripheral_clock ( uint32_t  ul_id)
inlinestatic

Disable a peripheral's clock.

Parameters
ul_idId (number) of the peripheral clock.

References pmc_disable_periph_clk(), sysclk_disable_usb(), sysclk_enable_usb(), sysclk_init(), sysclk_set_prescalers(), and sysclk_set_source().

Referenced by flexcom_disable(), and spi_disable_clock().

void sysclk_disable_usb ( void  )
void sysclk_enable_usb ( void  )
static uint32_t sysclk_get_cpu_hz ( void  )
inlinestatic

Return the current rate in Hz of the CPU clock.

Todo:
This function assumes that the CPU always runs at the system clock frequency. We want to support at least two more scenarios: Fixed CPU/bus clock dividers (config symbols) and dynamic CPU/bus clock dividers (which may change at run time). Ditto for all the bus clocks.
Returns
Frequency of the CPU clock, in Hz.

References CONFIG_SYSCLK_PRES, sysclk_get_main_hz(), and SYSCLK_PRES_3.

Referenced by adc_get_config_defaults(), at30tse_init(), configure_tc(), configure_tc_trigger(), flash_set_wait_state_adaptively(), freertos_usart_serial_init(), main(), nm_bus_init(), sysclk_init(), and time_tick_init().

static uint32_t sysclk_get_main_hz ( void  )
inlinestatic

Return the current rate in Hz of the main system clock.

Todo:
This function assumes that the main clock source never changes once it's been set up, and that PLL0 always runs at the compile-time configured default rate. While this is probably the most common configuration, which we want to support as a special case for performance reasons, we will at some point need to support more dynamic setups as well.

References CONFIG_SYSCLK_SOURCE, OSC_MAINCK_16M_RC_HZ, OSC_MAINCK_24M_RC_HZ, OSC_MAINCK_8M_RC_HZ, OSC_MAINCK_BYPASS_HZ, OSC_MAINCK_XTAL_HZ, OSC_SLCK_32K_BYPASS_HZ, OSC_SLCK_32K_RC_HZ, OSC_SLCK_32K_XTAL_HZ, pll_get_default_rate, SYSCLK_SRC_MAINCK_16M_RC, SYSCLK_SRC_MAINCK_24M_RC, SYSCLK_SRC_MAINCK_8M_RC, SYSCLK_SRC_MAINCK_BYPASS, SYSCLK_SRC_MAINCK_XTAL, SYSCLK_SRC_PLLACK, SYSCLK_SRC_SLCK_BYPASS, SYSCLK_SRC_SLCK_RC, and SYSCLK_SRC_SLCK_XTAL.

Referenced by sysclk_get_cpu_hz(), and sysclk_get_peripheral_hz().

static uint32_t sysclk_get_peripheral_bus_hz ( const volatile void *  module)
inlinestatic

Retrieves the current rate in Hz of the Peripheral Bus clock attached to the specified peripheral.

Parameters
modulePointer to the module's base address.
Returns
Frequency of the bus attached to the specified peripheral, in Hz.

References sysclk_get_peripheral_hz(), and UNUSED.

Referenced by main(), tc_waveform_initialize(), uart_config(), uart_open(), and usart_serial_init().

void sysclk_init ( void  )

Initialize the synchronous clock system.

This function will initialize the system clock and its source. This includes:

  • Mask all synchronous clocks except for any clocks which are essential for normal operation (for example internal memory clocks).
  • Set up the system clock prescalers as specified by the application's configuration file.
  • Enable the clock source specified by the application's configuration file (oscillator or PLL) and wait for it to become stable.
  • Set the main system clock source to the clock specified by the application's configuration file.

Since all non-essential peripheral clocks are initially disabled, it is the responsibility of the peripheral driver to re-enable any clocks that are needed for normal operation.

References CONFIG_SYSCLK_PRES, CONFIG_SYSCLK_SOURCE, EFC_FCMD_SPUI, EFC_FCMD_STUI, efc_perform_read_sequence(), osc_enable(), OSC_MAINCK_16M_RC, OSC_MAINCK_24M_RC, OSC_MAINCK_BYPASS, OSC_MAINCK_XTAL, OSC_SLCK_32K_BYPASS, OSC_SLCK_32K_RC, OSC_SLCK_32K_XTAL, osc_wait_ready(), pll_config_defaults, pll_enable(), pll_enable_source(), pll_wait_for_lock(), pmc_switch_mck_to_mainck(), pmc_switch_mck_to_pllack(), pmc_switch_mck_to_sclk(), sysclk_get_cpu_hz(), SYSCLK_SRC_MAINCK_16M_RC, SYSCLK_SRC_MAINCK_24M_RC, SYSCLK_SRC_MAINCK_8M_RC, SYSCLK_SRC_MAINCK_BYPASS, SYSCLK_SRC_MAINCK_XTAL, SYSCLK_SRC_PLLACK, SYSCLK_SRC_SLCK_BYPASS, SYSCLK_SRC_SLCK_RC, and SYSCLK_SRC_SLCK_XTAL.

Referenced by main(), prvSetupHardware(), and sysclk_disable_peripheral_clock().

void sysclk_set_prescalers ( uint32_t  ul_pres)

Set system clock prescaler configuration.

This function will change the system clock prescaler configuration to match the parameters.

Note
The parameters to this function are device-specific.
Parameters
cpu_shiftThe CPU clock will be divided by \(2^{mck\_pres}\)

References pmc_mck_set_prescaler().

Referenced by main(), and sysclk_disable_peripheral_clock().

void sysclk_set_source ( uint32_t  ul_src)