Clocking System

Last modified by Microchip on 2026/10/15 14:28

Overview

The dsPIC33A Oscillator Module clocking system is based on three primary components:

  • Clock Sources
  • Phase-Locked Loop Generators (PLLGENs)
  • Clock Generators (CLKGENs)

clocking system

The CLKGENs are preassigned to the CPU and peripherals. Each clock generator selects a clock source from the available oscillators or PLLGENs and passes it to a selectable divider circuit. Each CLKGEN output is preassigned to the CPU or peripherals, and some are shared across multiple consumers.

Unlike previous dsPIC33 devices, the dsPIC33A uses Special Function Registers (SFRs) to control clock functions instead of configuration bits.

CLKGEN1 is dedicated to providing the CPU and Peripheral Clocks. On reset, CLKGEN1 is enabled with the 8 MHz FRC oscillator source. This provides an 8 MHz clock for the CPU and  8, 4, and 2 MHz clocks for the Fast, Standard, and Slow peripheral clocks, respectively, after reset.

Clock Sources

The dsPIC33A clock system is driven by a number of clock sources:

  • Internal Fast RC (FRC): 8 MHz nominal
  • Internal Backup Fast RC (BFRC): 8 MHz nominal
  • Internal Low-Power RC (LPRC): 32.786 kHz (implemented as BFRC/244)
  • Primary Oscillator (POSC): 3.5 MHz to 32 MHz (requires external crystal or resonator)
  • External clock sources (REF1, REF2)

Always refer to the product data sheet to confirm the exact oscillator specifications on your device.

Clock Generators

Clock generation in the dsPIC33A is built around multiple CLKGENs and PLLGENs.

clock generator

Each CLKGEN can select from up to 10 available clock sources, as shown in the diagram, providing flexibility for different application requirements.

Each CLKGEN is assigned to the CPU or specific peripherals, with some shared across multiple peripherals, for example in the dsPIC33AK512MPS512:

clkgen assignment

Always refer to the product data sheet to confirm the exact number of CLKGENs available on your device.

Each CLKGEN also includes a Fail-Safe Clock Monitor (FSCM). When enabled, the FSCM continuously monitors clock health and can automatically switch to a backup clock source if a clock failure occurs. In addition, each CLKGEN includes divider registers that allow developers to fine-tune the output frequency for their application needs.

Peripheral Bus Clock Divider

Clock generator 1, or CLKGEN1, is responsible for generating the CPU clock and the peripheral bus clocks used throughout the device.

peripheral clk divider v2

The Fast Speed peripheral bus clock, FPB, operates at the same frequency as the CPU clock, FOSC. An important point is that CLKGEN1 is always enabled. Unlike some other clock generators, it cannot be turned off because it provides the primary system clocking for the CPU and core peripherals.

CLKGEN1 also generates two additional peripheral bus speeds through clock division:

  • Standard Speed peripheral clock at FPB divided by 2
  • Slow Speed peripheral clock at FPB divided by 4

For example, if FPB is configured to 200 MHz:

  • FPB/2 operates at 100 MHz
  • FPB/4 operates at 50 MHz

These multiple bus clock speeds allow peripherals to run at frequencies appropriate for their performance requirements, helping balance system performance and power consumption.

Clock Domains Synchronization

While you can simply use CLKGEN1 for all device peripherals, the system application requirements may require unique and specific operational frequencies.

CLKGEN1 outputs are edge‑aligned and fully synchronous, meaning all clocks derived from CLKGEN1 transition together and maintain deterministic timing relationships.

When two CLKGENs use the same clock source and divisors, their outputs are not guaranteed to be phase‑aligned and should be considered asynchronous.

This distinction might matter for system design—use CLKGEN1 when precise clock alignment is required, and treat clocks from different CLKGENs as asynchronous unless explicitly synchronized.

Configuring the Clock Generator

Each clock generator contains a configuration register that configures clock switching, clock division, and fail-safe backup oscillator options. In this example, we’ve defined a clock initialization function which performs several configuration changes to the CPU and Peripheral Clock Generator (CLKGEN1):

  • Sets up the FRC as the backup oscillator
  • Changes the clock source to the BFRC
  • And divides this by 2, producing a 4 MHz CPU clock, and 4, 2, and 1 MHz peripheral clocks

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
void clocksInit(void)
{
   // CLK1GEN (CPU & Peripheral Clocks) Configuration Example
   
   // Default clock configuration:
   // CLKGEN1 enabled with 8 MHz FRC source
   // CPU clock = 8 MHz, Fast, Std. and Slow Peripheral clocks = 8, 4, and 2 MHz
   
   // Desired clock configuration:
   // CLKGEN1 enabled with 8 MHz BFRC source, and divided by 2
   // Fail-safe backup enabled (FRC)
   // CPU clock = 4 MHz, Fast, Std. and Slow Peripheral clocks = 4, 2, and 1 MHz

   // Enable CLKxGEN if not already enabled
   // CLK1CONbits.ON = 1;
   
   // Configure FRC as backup osc.
   CLK1CONbits.BOSC = 1;               // Set up FRC as backup osc.
   CLK1CONbits.FSCMEN = 1;             // Enable fail safe
       
   // Change clock source to BFRC and divide by 2
   CLK1CONbits.NOSC = 2;               // Select new osc. source = BFRC
   CLK1CONbits.OSWEN = 1;              // Request osc. switch to selection by NOSC
   while(CLK1CONbits.OSWEN);           // Wait for osc. switch    
   
    CLK1DIVbits.INTDIV = 1;             // Select new integer clock divisor
   CLK1CONbits.DIVSWEN = 1;            // Request change to new integer clock divisor
   while(CLK1CONbits.DIVSWEN)          // Wait for change to be completed   
   
   // Wait for all changes to be applied
   while(!CLK1CONbits.CLKRDY);         
   
   // Enable the CLK1GEN clock fail interrupt
   IFS0bits.C1FAILIF = 0;              
    IEC0bits.C1FAILIE = 1;
}

Notice the request/grant protocol in which the firmware requests, then waits for each configuration step to be completed before proceeding to the next step and finally polling for the CLKRDY flag to be clear before continuing. Also, notice in this example that we’ve enabled a clock failure interrupt to be issued in the event of a source clock failure and switchover to the backup clock source for CLKGEN1.

Back to Top

Phase-Locked Loop Generator (PLLGEN)

There are currently two PLLGENs available on the dsPIC33A which may be used to obtain higher operating speeds, using the supplied clock sources:

pll generator v2

Several key requirements must be met to use the PLL. Consult your device data sheet for specific requirements for your device.

Each PLL supports up to five selectable input clock sources, giving developers flexibility in choosing the PLL input time base.

Each PLL provides two configurable clock outputs to support different application needs. Although PLLNFOUT and PLLNVCO are both derived from the same PLL VCO, providing both outputs increases clocking flexibility. Both outputs maintain a 50% duty cycle.

Each PLL includes multiple divider and scaling registers, supporting output frequency scaling from 1:1 up to 1:65,534.

Together, the two PLLGEN blocks and CLKGEN modules support a wide range of frequencies for the various dsPIC33A peripherals.

Configuring the PLL With the 8 MHz FRC to Generate a 200 MHz System Clock

Each PLL contains several configuration registers that control the PLL and configure input and feedback dividers. In this example, we’ve defined a clock initialization function that configures PLL1 to produce a 200 MHz clock source, then updates CLKGEN1 to use this source to provide a 200 MHz CPU and peripheral clock source.

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
void clocksInit(void)
{
   // Default clock configuration:
   // CLKGEN1 enabled with 8 MHz FRC source
   // CPU clock = 8 MHz, Fast, Std and Slow Peripheral clocks = 8, 4, and 2 MHz
   
   // Desired clock configuration:
   // CLKGEN1 enabled with 200 MHz PLL1 source
   // Fail-safe backup enabled (BFRC))
   // CPU clock = 200 MHz, Fast, Std and Slow Peripheral clocks = 200, 100, and 50 MHz
   
   // Step 1. Configure/Enable PLL1
   
   // Enable the PLL1 Oscillator
   OSCCTRLbits.PLL1EN = 1;
   while(!OSCCTRLbits.PLL1RDY);
   
   // Configure backup oscillator in case of failure
   PLL1CONbits.BOSC = 2;               // BFRC as backup clock source
   PLL1CONbits.FSCMEN = 1;             // Enable fail-safe
   
   // Configure PLL values
   PLL1DIVbits.PLLFBDIV = 200;         // Feedback Divider
   PLL1DIVbits.PLLPRE = 1;             // Reference clock divider
   PLL1DIVbits.POSTDIV1 = 4;           // Post Divider #1
   PLL1DIVbits.POSTDIV2 = 2;           // Post Divider #2
   // PLL Fout = Fin*FBDIV / (PLLPRE * POSTDIV1 * POSTDIV2)
   // PLL Fout = 8M*200 / (1*4*2) = 200 MHz
   
   // Enable PLL Input and Feedback Divider update
   PLL1CONbits.PLLSWEN = 1;
   while(PLL1CONbits.PLLSWEN);
   
   // Enable PLL Output Divider update
   PLL1CONbits.FOUTSWEN = 1;
   while(PLL1CONbits.FOUTSWEN);
   
   // Select FRC as clock source for PLL1
   PLL1CONbits.NOSC = 1;
   
   // Enable the clock source switch
   PLL1CONbits.OSWEN = 1;
   while(PLL1CONbits.OSWEN);
   
   // Enable/Wait for the PLL clock to be ready
   PLL1CONbits.ON = 1;
   while(!PLL1CONbits.CLKRDY);
       
   // Step 2. Update CLKGEN1
   
   // Enable CLKxGEN if not already enabled
   // CLK1CONbits.ON = 1;
   
   // Configure BFRC as backup osc.
   CLK1CONbits.BOSC = 2;               // Set up BFRC as backup osc.
   CLK1CONbits.FSCMEN = 1;             // Enable fail safe
       
   // Change clock source to PLL1
   CLK1CONbits.NOSC = 5;               // Select new osc. source = PLL1
   CLK1CONbits.OSWEN = 1;              // Request osc. switch to selection by NOSC
   while(CLK1CONbits.OSWEN);           // Wait for osc. switch      
   
   // Wait for all changes to be applied
   while(!CLK1CONbits.CLKRDY);         
   
   // Enable the CLK1GEN clock fail interrupt
   IFS0bits.C1FAILIF = 0;              
    IEC0bits.C1FAILIE = 1;
}

Back to Top