Clock Switching
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, PIC32 devices have 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.
// clock switching enabled and clock monitor enabled
#pragma config FCKSM = CSECME
// clock switching enabled and clock monitor disabled
#pragma config FCKSM = CSECMD
// clock switching disabled and clock monitor disabled (default)
#pragma config FCKSM = CSDCMD
The oscillator switching sequence is as follows:
- optional…determine the current clock source
- perform the unlock sequence to allow a write to the Oscillator Configuration register (OSCCON)
- configure the New Oscillator (NOSC) setting with the clock source you want to switch to
- initiate the oscillator switch by setting the Oscillator Switch Enable (OSWEN) bit
- optional…perform the lock sequence to prevent an unintended clock switch
The device will not permit direct switching between PLL clock sources and you should not change the PLL multiplier values or postscaler values when running from the PLL source. To perform either of these clock switching functions, follow these steps:
- Switch to a non-PLL source, such as FRC
- Modify the multiplier and postscaler values
- Switch to the desired PLL source
The following example code shows how to perform a clock switch using MPLAB® Harmony functions.
// Assume the current oscillator is the Primary Oscillator with the PLL and we want to
// change the PLL settings. We will need to switch to another non-PLL clock source
// (FRC in this case) to perform this switch.
// variable to hold the state of the current clock source
OSC_SYS_TYPE currOsc;
// assign FRC as the oscillator we want to switch to
OSC_SYS_TYPE newOsc=OSC_FRC;
// assign the current clock source to currOsc
currOsc = PLIB_OSC_CurrentSysClockGet(OSC_ID_0);
// if the current osc and new osc are different, perform the switch
if(currOsc != newOsc)
{
// unlocks the Oscillator Control register,
// configures the new oscillator setting to Primary Oscillator
// and initiates the oscillator switch
PLIB_OSC_SysClockSelect ( OSC_ID_0, newOsc );
// returns true when switch is complete
while (!PLIB_OSC_ClockSwitchingIsComplete(OSC_ID_0));
}
// change the PLL multiplier to 24
PLIB_OSC_SysPLLMultiplierSelect(OSC_ID_0, 24);
// change output divide to 256
PLIB_OSC_SysPLLOutputDivisorSet(OSC_ID_0, OSC_SYSPLL_OUT_DIV_256);
// Switch clock source back to the
// primary osc now using new PLL values
PLIB_OSC_SysClockSelect(OSC_ID_0, OSC_PRIMARY_WITH_PLL);
// returns true when switch is complete
while (!PLIB_OSC_ClockSwitchingIsComplete(OSC_ID_0));
The Primary Oscillator mode has two or three different sub-modes (XT, HS, and EC). These sub-modes are determined at program time and can not be changed at run time.
Detailed Overview
For more detail on the Clock Switching feature, please review the Oscillator family reference manual chapter for that device, for example:
- Section 6. Oscillators (PIC32MX795F512L)
- Section 42. Oscillators with Enhanced PLL (PIC32MZ2048EFG100)
The device data sheet should then be consulted to verify the specific features implemented in that device.