Overview
With few limitations, applications are free to switch between any of the following clock sources at run-time:
- Primary Oscillator (POSC)
- Secondary Oscillator (SOSC)
- Fast RC Oscillator (FRC)
- Low Power RC Oscillator (LPRC)
To limit the possible side effects that could result from this flexibility, the clock system has a safeguard lock built into the switch process.
Clock switching is disabled by default. You can enable it with the clock switching and monitor (FCKSM) setting. See the example code below for PIC24FJ128GA010:
#pragma config FCKSM = CSECME // clock switching enabled and fail-safe clock monitor enabled
#pragma config FCKSM = CSECMD // clock switching enabled and fail-safe clock monitor disabled
#pragma config FCKSM = CSDCMD // clock switching disabled and fail-safe clock monitor disabled (default)
Primary Oscillator mode has three different submodes (XT, HS and EC), which are determined by the POSCMD Configuration bits. While an application can switch to and from Primary Oscillator mode in software, it cannot switch between the different primary submodes without reprogramming the device.
Switching Sequence
The oscillator switching sequence is as follows:
- If desired, read the COSC bits (OSCCON<14:12>) to determine the current oscillator source.
- Perform the unlock sequence to allow a write to the OSCCON register high-byte.
- Write the appropriate value to the NOSC control bits (OSCCON<10:8>) for the new oscillator source.
- Perform the unlock sequence to allow a write to the OSCCON register low-byte.
- Set the OSWEN bit to initiate the oscillator switch.
The following example code shows how to perform a clock switch from FRC (default) to POSC with PLL for a PIC24FJ128GA010 device, having 8 MHz external crystal. The example uses MPLAB® XC16 compiler __builtin_ functions to perform steps 2-3 and 4-5:
#include <xc.h>
#pragma config FNOSC = FRC // FRC selected as default oscillator
#pragma config POSCMOD = XT // XT Oscillator mode selected for POSC - must be done at build-time
#pragma config FCKSM = CSECMD // Clock switching is enabled. Fail-safe clock monitor is disabled.
int main(void)
{
// Initiate Clock Switch to Primary OSC with PLL (NOSC=0b011)
__builtin_write_OSCCONH(0x03);
// Start clock switching
__builtin_write_OSCCONL(0x01);
// Wait for Clock switch to occur (COSC = 0b011)
while (OSCCONbits.COSC != 0b011);
// Wait for PLL to lock
while(OSCCONbits.LOCK!=1);
...
}