Lab 4. Configure 200 MHz Operation
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:

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.
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).
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
{
// 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 <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:

Confirm the red RGB LED is toggling every 100 ms:

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.