Lab 4. Configure 200 MHz Operation

Last modified by Microchip on 2026/04/09 14:41

Purpose

In this lab exercise, you will update the clocksInit() function in Lab 3 using the code example from the "dsPIC33A Clock System" page to set up PLL1 and CLKGEN1 on the dsPIC33A to produce a 200 MHz clock source for the CPU, enabling the maximum performance from this MCU.

Lab 4 functionality is identical to Lab 3, except the CPU now runs at 200 MHz.

To learn more details about configuring the dsPIC33A clock system, please visit the "dsPIC33A Clock System" page, or refer to the "dsPIC33AK512MPS512 Family Data Sheet".

Overview

The dsPIC33A family does not provide a 1:1 relationship between the CPU clock speed (in MHz) and the throughput of the CPU in Millions of Instructions Per Second (MIPS). While data memory can be accessed at 200 MHz with no wait states, the Non-Volatile Memory (NVM) program memory requires four wait states at 200 MHz.

For this reason, we have a Pre-Fetch Branch Unit (PBU) inserted between the program memory and the CPU that tries to achieve 200 MIPS performance:

Pre-Fetch Branch Unit (PBU)

  • The PBU contains an Instruction Stream Buffer (ISB) that fetches at least four instructions at a time from a 128-bit program memory bus and stores them in a series of instruction stream buffers. Linear code instructions are retrieved at 200 MHz, executed from the ISB.

  • The PBU also contains a 2 KB instruction cache, which helps with non-linear program flow by caching recently used program instructions.

Note: The PBU on these first dsPIC33A devices was made intentionally simple, with limited configuration capability. To get the maximum performance out of the device, simply set the CPU clock to 200 MHz and go!

This lab exercise is divided into the following sections:

Procedure

Part A. Update the clocksInit() Function and FCPU Macro in Lab 3

The following clock initialization function demonstrates how to configure PLL1 to produce a 200 MHz clock source using the default 8 MHz FRC clock source, then updates CLKGEN1 to use this source to provide a 200 MHz CPU and peripheral clock source to the system.

Replace the existing clocksInit() function in Lab 3 and update the FCPU macro.

Open Lab 3's main.c file and replace the existing clocksInit() function with the contents below (copy/paste).

  

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;
}

In main.c, update the FCPU Macro to 200 MHz as shown:

#include <xc.h>
#include
<stdio.h>
#include
<stdint.h>

//#define FCPU        8000000U
#define FCPU        200000000U

Part B. Run the Application

Build the project and program the application into the MCU.

Confirm the tick counter outputs in the serial terminal every 1s:

Serial Terminal

Confirm the red RGB LED is toggling every 100 ms:

RED RGB LED

Back to Top

Results

Re: Configuring a 200 MHz System Clock

Each Phase-Locked Loop (PLL) contains several configuration registers that control the PLL and configure input and feedback dividers. In this example, we defined a clock initialization function that configures PLL1 to produce a 200 MHz clock source using the 8 MHz FRC oscillator, then updates CLKGEN1 to use this source to provide a 200 MHz CPU and peripheral clock source.