dsPIC33A Clock System

Last modified by Microchip on 2025/02/03 13:49

Overview

The dsPIC33A clock system supplies clocking to the CPU and peripherals. The module is based on a number of clock generators (CLKGENs) and PLL generators (PLLGENs). The CLKGENs are preassigned to the CPU and peripherals. Each clock generator selects a clock source from the available oscillators or PLLs and passes it to a selectable divider circuit.

clock system overview v2

The clock system has the following main functions/features:

  • Multiple Oscillators
    • 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
  • Multiple 1.6 GHz Phase-Locked Loop (PLLs), each with:
    • Selectable clock source
    • A backup clock source
    • Primary and secondary outputs
  • Multiple Clock Generators, each with:
    • Selectable clock source
    • A backup clock source
    • Fail-safe clock monitors
  • Clock Monitor Module, providing
    • Clock failure detection
    • Clock frequency drift detection
    • Fault Injection capability
    • Frequency, pulse width and duty cycle measurements

Back to Top

Clock Generators

Here we see a detailed block diagram for the clock generator:

clock generator

Note that the clock generators are associated with a specific feature or peripheral, for example in the dsPIC33AK128MC106:

clock generator destinations

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 (PLL)

The Primary Oscillator and Internal FRC Oscillator sources can optionally use an on-chip PLL to obtain higher operating speeds.

phase lock loop

Several key requirements must be met to use the PLL:

  • The PLL Input Frequency (FPLLI)
  • The PLL VCO Output Frequency
  • The PLL Feedback Divider
  • The PLL Output Frequency

Consult your device data sheet for specific requirements for your device.

Using 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