SAM L10/L11 Clock System

Last modified by Microchip on 2023/11/14 15:11

Clock Distribution Overview

The SAM L10/L11 clock system configuration is done through the Oscillator Controller (OSCCTRL), the 32 kHz Oscillator Controller (OSC32KCTRL), the Generic Clock Controller (GCLK) and the Main Clock (MCLK).

Clock System Block Diagram

Related Peripherals

Clock Controllers and Clock Features

SAM L10 Clock System

  • The OSCCTRL controls all the clock sources which are:
    • 0.4-32 MHz Crystal Oscillator (XOSC)
      • Tunable gain control
      • Programmable start-up time
      • Crystal or external input clock on XIN pin
      • Clock failure detection with safe clock switch
      • Clock failure event output
    • 16 MHz Internal Oscillator (OSC16M)
      • Fast startup
      • 4/8/12/16 MHz output frequencies available
    • Ultra-Low Power Digital Frequency Locked Loop (DFLLULP)
      • Operates as a frequency multiplier against a known frequency in closed-loop mode
      • Optional frequency dithering
    • Fractional Digital Phase Locked Loop (FDPLL96M)
      • 48 MHz to 96 MHz output frequency
      • 32 kHz to 2 MHz reference clock
      • A selection of sources for the reference clock
      • Adjustable proportional integral controller Fractional part used to achieve 1/16th of reference clock step
  • The OSC32KCTRL controls the 32 KHz clock sources which are:
    • XOSC32K
      • External 32.768 kHz oscillator
      • 32.768 kHz crystal or external clock
    • OSCULP32K
      • Ultra-low power internal 32.768 kHz oscillator
      • Always ON
      • Frequency fine tuning

In addition to these features, each clock source controller has the Run in StandBy and the On Demand Clock Request capabilities, refer to the "On Demand Clock Request and Run in StandBy Capability" section on this page for more details.

Generic Clock Controller (GCLK)

GCLK Block DIagram

  • The GCLK controls the clock distribution of the system by implementing the following features:
    • Five GCLK Generators (GCLK0 to GCLK4) to source up to 64 Peripheral Clock Channels (GCLK_PERIPH)
    • Each GCLK Generator has a prescaler to divide internal or external clock sources
    • The Generic Clock Generator 0 provides the GCLKMAIN which is the clock used to generate synchronous clocks
    • One GCLK_IO pin for each generator can be used as a clock source for the GCLK or outputs a clock signal to the external world

Main Clock Controller (MCLK)

MCLK Block Diagram

  • The MCLK controller generates:
    • CPU, AHB, and APB system clocks
    • Safe run-time clock switching from GCLK
    • Module-level clock gating through maskable peripheral clocks

The Clock system implements two types of clock paths:

  • Asynchronous to the CPU Clock path
  • Synchronous to the CPU clock path

Generic clocks are considered asynchronous clocks as they can come from different clock sources, whereas CPU and bus clocks (coming from the MCLK) are considered synchronous to the CPU.

As a consequence, some peripherals accessed by the CPU need to be synchronized between the different clock domains.

Refer to the "Asynchronous or Synchronous Clock Path" section on this page.

Generic clocks are typically input clocks of the peripheral. As you can see in this block diagram, the peripheral clocks are fully independent, giving them maximum flexibility.

Clock-Tree Reset State

Clock System Reset state diagram

At reset, OSC16M is enabled and configured to run at 4 MHz.

Full Speed (32 MHz) Clock Configuration Example

Clock System Full-speed diagram

This example shows the usual configuration to clock the device to its maximum speed (32 MHz) using the FDPLL96MHz. The clock source is XOSC32K but it can be another one.

Code Snippet Example: How to Configure the Device at Full Speed Using the DPLL96MHz

/***
 *** This Example has no copyright and can be used by anyone.
 *** The following example is based on Device File Package
 *** required to compile the macro definitions used.
 *** The Device File Package is avaiblable by downloading Atmel Studio 7.
***/


/***
 ***Initialize the system
 ***
 *** Initialize the XOSC32K Oscillator (32 kHz On-board Crystal)
 *** Switch Performance level from PL0 (Default after reset) to PL2
 *** Configure Flash Wait States based on next Main Clock frequency (32 MHz <-> 2 WS)
 *** Initialize the DPLL to generate 64 MHz Set Main clock to DPLL/2
***/


void SystemInit(void)
{
/***
  *** Set XOSC32K Startup time
  *** (see "Start-Up Time for 32KHz External Crystal Oscillator"
  *** table from datasheet)
  *** Enable 32.768kHz output
  *** Enable Crystal Oscillator mode
  *** Enable XOSC32K
  ***/


 OSC32KCTRL->XOSC32K.reg =(OSC32KCTRL_XOSC32K_STARTUP(0x3)|
                           OSC32KCTRL_XOSC32K_EN32K       |
                           OSC32KCTRL_XOSC32K_XTALEN      |
                           OSC32KCTRL_XOSC32K_ENABLE);

/*** Write Synchronized ***/
while(!(OSC32KCTRL->STATUS.bit.XOSC32KRDY));     

/***
  *** Switch Performance level
  *** from PL0 (Default after reset) to PL2
  ***/

 PM->PLCFG.bit.PLSEL = 2;
while(PM->INTFLAG.bit.PLRDY == 0);

/***
  *** Configure Flash Wait States based
  *** on next Main Clock frequency (32 MHz <-> 2 WS)
  ***/

 NVMCTRL->CTRLB.bit.RWS = 2;

/***
  *** Set DPLL Ratio to generate 64MHz clock
  *** (64MHz/32.768kHz=1953.125
  *** => LDR=1952/LDRFRAC=2 <=>
  *** 64MHz=32.768*(LDR+1+LDRFRAC/16)
  ***/

 OSCCTRL->DPLLRATIO.reg = (OSCCTRL_DPLLRATIO_LDR(1952)|
 OSCCTRL_DPLLRATIO_LDRFRAC(2));

/*** Write Synchronized ***/
while((OSCCTRL->DPLLSYNCBUSY.bit.DPLLRATIO));

/*** Disable On-demand ***/
 OSCCTRL->DPLLCTRLA.bit.ONDEMAND = 0;

/***
  *** Set Lock time as automatic
  ***and reference clock to XOSC32KHz
  ***/

 OSCCTRL->DPLLCTRLB.reg = (OSCCTRL_DPLLCTRLB_LTIME(0)|
                           OSCCTRL_DPLLCTRLB_REFCLK_XOSC32K);

/*** Enable DPLL ***/
 OSCCTRL->DPLLCTRLA.bit.ENABLE = 1;
while(OSCCTRL->DPLLSYNCBUSY.bit.ENABLE);

/*** Wait for DPLL lock flag ***/
while(!OSCCTRL->DPLLSTATUS.bit.LOCK);

/***
  *** Set Generic clock 0
  ***(MAIN clock for CPU and synchronous clock)
  ***/

 GCLK->GENCTRL[0].reg = (GCLK_GENCTRL_SRC(0x07)|
                         GCLK_GENCTRL_DIV(2)|
                         GCLK_GENCTRL_GENEN);

/*** Write Synchronized ***/
while((GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL0));

/***
  *** Set Generic clock 1 (GCLK1),
  *** XOSC32K as source not divided
  ***/

 GCLK->GENCTRL[1].reg = (GCLK_GENCTRL_SRC_XOSC32K|
                         GCLK_GENCTRL_DIV(1)|
                         GCLK_GENCTRL_GENEN);

/*** Write Synchronized ***/
while((GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL1));    
}

How to Configure Clocks for Peripherals

System enable peripheral

All peripherals need two clock signals:

  • The generic clock from GCLK (asynchronous) in green
  • The interface clock from MCLK (synchronous) in light blue

There is no specific order in the configuration between asynchronous and synchronous clocks.

The following figure shows the configuration of the SERCOM0, but the same process can be applied to any other peripherals such as ADC, TC, etc.
The GCLK multiplexer ID number (#11 for the GCLK_SERCOM0_CORE ) can be found in the datasheet. (Refer to the table in the GCLK_PCHCTRLm register description).

Configuring a Peripheral can be realized in four steps:

  1. Enable the source clock (OSCCTRL / OSC32KCTRL)
  2. Enable and configure a Generic Clock Generator (GCLK)
  3. Enable and configure the appropriate Generic Clock Multiplexer to address the targeted peripheral (GCLK)
  4. Unmask the peripheral interface clock (MCLK)

Asynchronous or Synchronous Clock Path

Clock system synchronization diagram

As the CPU and the peripherals can be clocked from different clock sources, possibly with widely different clock speeds, some peripheral accesses by the CPU need to be synchronized between the different clock domains.

The interest in having such flexible architecture is mainly for power consumption optimization. In low power mode, peripherals can remain clocked by an external clock signal while all system clocks are OFF.

Write-Synchronized registers:

All peripherals are composed of one digital bus interface connected to the APB or AHB bus and running from a corresponding clock in the Main Clock domain, and one peripheral core running from the peripheral Generic Clock (GCLK).

Communication between these clock domains must be synchronized. This mechanism is implemented in hardware, so the synchronization process takes place even if the peripheral generic clock is running from the same clock source and on the same frequency as the bus interface.

All registers in the bus interface are accessible without synchronization.

All registers in the peripheral core are synchronized when written.

Some registers in the peripheral core are synchronized when read.

Each individual register description will have the properties Read-Synchronized and/or Write-Synchronized if a register needs to be synchronized. Each register that requires synchronization has its individual synchronizer and its individual synchronization status bit in the Synchronization Busy (SYNCBUSY) register.

Note: For registers requiring both read/write synchronization, the corresponding bit in SYNCBUSY is shared.

Write-Synchronization is triggered by writing to a register in the peripheral clock domain (GCLK). The respective bit in the SYNCBUSY register will be set when the write-synchronization starts and cleared when the write-synchronization is complete. When write-synchronization is ongoing for a register, any subsequent write attempts to this register will be discarded, and an error will be reported through the Peripheral Access Controller (PAC).

In order to check if synchronization is complete, the user can either poll the relevant bits in SYNCBUSY or use the Synchronisation Ready interrupt (if available). The Synchronization Ready interrupt flag will be set when all ongoing synchronizations are complete (i.e., when all bits in SYNCBUSY are 0).

Code Snippet: How to Configure a Write-Synchronized Peripheral (Timer Counter (TC)

/***
 *** This Example has no copyright and can be used by anyone.
 *** The following example is based on Device File Package
 *** required to compile the macro definitions used.
 *** The Device File Package is avaiblable by downloading Atmel Studio 7.
***/


/*** GCLK TC0 Peripheral Muxing Definition ***/
#define GCLK_TC0          14

/*** Curent 32KHz Clock Source Definition ***/
#define CURRENT_32KOSC    GCLK_GENCTRL_SRC_XOSC32K

void init_TC0_1KHz(void)
{
/*** Enable XOSC32K (32KHZ input clock for TC) ***/
 OSC32KCTRL->XOSC32K.reg |= (OSC32KCTRL_XOSC32K_ENABLE  |
                             OSC32KCTRL_XOSC32K_XTALEN  |
                             OSC32KCTRL_XOSC32K_EN1K    |
                             OSC32KCTRL_XOSC32K_EN32K   |
                             OSC32KCTRL_XOSC32K_RUNSTDBY|
                             OSC32KCTRL_XOSC32K_STARTUP(5));

/*** Wait until XOSC32K is ready ***/
while(OSC32KCTRL->STATUS.bit.XOSC32KRDY==0);

/*** Enable GCLK2 with XOSC32K
  *** as clock peripheral clock
    *** generator for TC0
    ***/

 GCLK->GENCTRL[2].reg = GCLK_GENCTRL_DIV(1) |
                        CURRENT_32KOSC|
                        GCLK_GENCTRL_GENEN;

/*** Wait for Clocks synchronzation(GENCTRL register is write synchronized) ***/
while((GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL2));    

/*** Link the Generic Clock Generator 2 to the TC0 Peripheral ***/
 GCLK->PCHCTRL[GCLK_TC0].reg = (GCLK_PCHCTRL_CHEN|GCLK_PCHCTRL_GEN_GCLK2);   

/*** Disable TC0 before configuring it...
  *** (COUNT8 register is Enable Protected and write synchronized)
  ***/

 TC0->COUNT8.CTRLA.bit.ENABLE = 0;

/*** Wait for Clocks synchronzation(COUNT8 register is write synchronized) ***/
while(TC0->COUNT8.SYNCBUSY.reg & TC_SYNCBUSY_ENABLE);

/*** TC0 configuration...
  *** 8-bit Timer counter mode,
  *** Run in SDBY
  *** On Demand enabled
  *** Prescaler = 1 (32KHz Divided by 1 gives 32KHz.)
  ***/

 TC0->COUNT8.CTRLA.reg |= (TC_CTRLA_MODE(TC_CTRLA_MODE_COUNT8_Val)|    
                           TC_CTRLA_RUNSTDBY                      |
                           TC_CTRLA_ONDEMAND                      |
                           TC_CTRLA_PRESCALER(TC_CTRLA_PRESCALER_DIV1_Val));

/*** TC0 Wave generator is used as Match frequency generator (MFRQ) ***/
 TC0->COUNT8.WAVE.reg    =    (TC_WAVE_WAVEGEN_MFRQ);

/*** TC0 is an event generator based on compare value
  *** These bit enables the generation of an event
  *** for every match or capture on channel 0.
  ***/

 TC0->COUNT8.EVCTRL.reg =    (TC_EVCTRL_MCEO0);        

/*** 32 is the number to get an event @ 1KHz frequency ***/
 TC0->COUNT8.CC[0].reg    =    32;                    

/*** Wait for Clocks synchronzation(COUNT8 register is write synchronized) ***/
while(TC0->COUNT8.SYNCBUSY.reg & TC_SYNCBUSY_CC0);

/*** Ensable TC0 once it is configuring...
  *** (COUNT8 register is Enable Protected and write synchronized)
  ***/

 TC0->COUNT8.CTRLA.bit.ENABLE = 1;

/*** Wait for Clocks synchronzation(COUNT8 register is write synchronized) ***/
while(TC0->COUNT8.SYNCBUSY.reg & TC_SYNCBUSY_ENABLE);        

}

On Demand and Run in StandBy Clocks

Standby diagram

On Demand Clock Request

The ONDEMAND bit is related to clock sources only (i.e., each clock source can run in on-demand mode). Setting this bit allows the clock source to be switched off automatically if no longer required by the peripheral or switched on if a peripheral requests it again.

The clock source is in a stopped state unless a peripheral is requesting the clock source. Clock requests propagate from the peripheral, via the GCLK, to the clock source. If one or more peripheral is using a clock source, the clock source will be started/kept running. As soon as the clock source is no longer needed and no peripheral has an active request, the clock source will be stopped until requested again.

The clock request can reach the clock source only if the peripheral, the generic clock and the clock from the Generic Clock Generator in-between are enabled. The time taken between a clock request being asserted and the clock source being ready depends on the clock source startup time, clock source frequency, and the divider used in the Generic Clock Generator.

 Timing Formulas and more details are provided in the product datasheet.

In Low Power mode, the clock request mechanism is still working if the modules are configured to run in Standby mode (RUNSTDBY bit set). Do not forget to consider the clock activation delays when using this feature.

Run in Standby Capability

The Run in Standby (RUNSTDBY) bit is related to Clock sources AND Peripherals (except EIC, TRAM, NVMCTRL, PORT, and PTC). This bit enables the capability for a clock source or a peripheral to run in STANDBY Low power mode without CPU interventions.

Here is a table that summarizes the device behaviors according to the ONDEMAND & RUNSTDBY bit configurations:

Standby chart

Once combined with the ON DEMAND Bit, a peripheral is then able to request its own clock asynchronously to run in STANDBY Low Power mode, performing tasks without waking up the CPU from STANDBY mode. This is called SleepWalking. In this SleepWalking mode, the CPU sleeps until a relevant event occurs (interrupts). This feature directly induced by the SAM L10/L11 architecture is vital to reach very low power consumption.

Learn More

Back to top