PIC32MX Oscillator

 Summary

The PIC32MX oscillator is highly configurable. The many different clock options allow you to maximize device performance while controlling power consumption on other parts of the device. The sections below provide code examples to configure this oscillator for your specific needs.

PIC32 Oscillator Configuration Spreadsheet

Download this Microsoft Excel file which simulates the PIC32 oscillator configuration settings. Most configuration options are provided for you. It will also keep you out of trouble by highlighting incompatible configurations. Note the tabs at the bottom of the spreadsheet that select PIC32MX or PIC32MZ configurations.


Primary Oscillator (POSC)

External Clock and Oscillator Modes

posc_1.PNG

The Primary Oscillator (POSC) uses the OSC1 and OSC2 pins. POSC can be configured for an External Clock Input (EC mode) or an External Crystal or Resonator (XT or HS mode).

The clock frequencies associated with these modes are device dependent. Please see the specific device datasheet for details.

#pragma config POSCMOD = EC  //default = external clock
#pragma config POSCMOD = HS  //default = high-speed crystal

External Clock Mode with Output Clock

posc_2.PNG

When the POSC is in EC mode, the OSC1 pin is a high-impedance input that can be driven by a CMOS driver.

EC mode also disables the internal feedback buffer allowing the OSC2/CLKO pin to be used for other functions (general purpose I/O or as a clock out). The output clock provided on the CLKO pin is the Peripheral Bus Clock (PBCLK).

#pragma config OSCIOFNC = ON  // clock out enabled
#pragma config OSCIOFNC = OFF // clock out disabled

Fast Reference Clock Oscillator (FRC)

frc.PNG

The Fast RC (FRC) oscillator is a fast (8 MHz nominal), user-trimmable, internal RC oscillator. The output can drive the System Phased-Lock Loop (PLL) or be divided by 16 or divided using the programmable FRCDIV bits.

The FRCDIV bits configure a selectable output divider that allows the choice of a lower clock frequency from seven different options, plus the direct 8 MHz output. Available lower frequency options range from 4 MHz (divide-by-2) to 31 kHz (divide-by-256).

The FRC Oscillator Tuning (OSCTUN) register allows the user to fine-tune the FRC oscillator over a range of approximately ±12% (typical). Each bit increment or decrement changes the factory calibrated frequency of the FRC oscillator by a fixed amount.

The following MPLAB® Harmony function examples configure the FRC divider and tune values at run-time.

// FRCDIV = FRC/1
PLIB_OSC_FRCDivisorSelect(OSC_ID_0, OSC_FRC_DIV_1);
// Tune = 0 (no deviation from nominal)
PLIB_OSC_FRCTuningSelect(OSC_ID_0, 0);

Low-Power Reference Clock Oscillator (LPRC)

lprc.PNG

Low-Power RC (LPRC) Oscillator

The Low-Power RC (LPRC) oscillator is different from the Fast RC oscillator. It oscillates at a nominal frequency of 31.25 kHz. The LPRC oscillator is the clock source for the Power-up Timer (PWRT), Watchdog Timer (WDT), Fail-Safe Clock Monitor (FSCM), and Phase-Locked Loop (PLL) reference circuits. It may also be used to provide a low-frequency clock source option for the device in those applications where power consumption is critical and timing accuracy is not required.

// default System clock = LPRC
#pragma config FNOSC = LPRC
...
// System Clock = LPRC (run-time config)
PLIB_OSC_SysClockSelect(OSC_ID_0, OSC_LPRC);

Secondary Oscillator (SOSC)

sosc.PNG

Secondary Oscillator (SOSC)

The Secondary Oscillator (SOSC) is designed specifically for low-power operation with an external 32 to 100 KHz crystal. The oscillator is connected to the SOSCO and SOSCI device pins and serves as a secondary crystal clock source for low-power operation. It can also drive Timer1 and/or the Real-Time Clock and Calendar (RTCC) module for Real-Time Clock (RTC) applications.

The following code sample demonstrates how to (a) enable the secondary oscillator for a specific device using configuration bit settings, and (b) how to perform simple run-time modification using the MPLAB® Harmony PLIB APIs

// Enable Secondary oscillator by default
#pragma config FSOSCEN = ON
// default System clock = Secondary oscillator
#pragma config FNOSC = SOSC

// Run-time configuration using Harmony functions shown below

// System Clock = SOSC (run-time config)
PLIB_OSC_SysClockSelect(OSC_ID_0, OSC_SECONDARY);
// Enable Secondary oscillator
PLIB_OSC_SecondaryEnable(OSC_ID_0);
// Disable Secondary oscillator
PLIB_OSC_SecondaryDisable(OSC_ID_0);

Detailed Overview

For more detail on the Secondary Oscillator module for a specific PIC32 device, please view the Oscillator family reference manual chapter for that device, for example:

The device data sheet should then be consulted to verify the specific features implemented in that device.

System PLL (SPLL)

The System Phase-Locked Loop (PLL) has a user-selectable input divider, multiplier, and output divider to provide a wide range of output frequencies. The oscillator circuit will consume more current when the PLL is enabled.

System PLL Input Selection

spll_input.PNG

The System PLL can use the Fast RC (FRC) Oscillator or the Primary Oscillator (POSC) as the input. The input is indirectly determined by the System Clock (SYSCLK) setting (FNOSC bits).

On reset, the SYSCLK setting is copied to the Current Oscillator (COSC) setting. COSC determines the input to the PLL.

The input to the System PLL can be changed at run-time but the input divider can not. If you want to change the input to the System PLL at run-time, POSC must be 8 to 10 MHz. This is needed to satisfy the PLL multiplier input requirements (4 to 5 MHz) for both FRC and POSC inputs.

The default input can be configured at program time using #pragma statements and MPLAB® Harmony functions can be used to configure it at run-time.

// Default input is Fast RC Oscillator with the System PLL
#pragma config FNOSC = FRCPLL
// Default input is Primary Oscillator with the System PLL
#pragma config FNOSC = PRIPLL
//Run-time configuration using Harmony functions shown below
...
// PLL input is FRC
PLIB_OSC_SysClockSelect(OSC_ID_0, OSC_FRC_WITH_PLL);
// PLL input is POSC
PLIB_OSC_SysClockSelect(OSC_ID_0, OSC_PRIMARY_WITH_PLL);

System PLL Input Divider

spll_input_div.PNG

The input divider must be chosen such that the resulting frequency applied to the PLL multiplier is between 4 and 5 MHz. The input divider options are as follows:
÷1, ÷2, ÷3, ÷4, ÷5, ÷6, ÷10, ÷12

The default divide value is programmable but it can not be changed at run-time.

// default PLL input divider = 1
#pragma config FPLLIDIV = DIV_1
// default PLL input divider = 12 (max)
#pragma config FPLLIDIV = DIV_12

System PLL Multiplier

spll_mult.PNG

The multiplier options are as follows:
x15, x16, x17, x18, x19, x20, x21, x24

// default PLL multiply = 15
#pragma config FPLLMULT = MUL_15
// default PLL multiply = 24
#pragma config FPLLMULT = MUL_24
...
// run-time config sets PLL multiplier to 15
PLIB_OSC_SysPLLMultiplierSelect(OSC_ID_0, 15);

System PLL Output Divider

spll_output_div.PNG

The System PLL output clock divider options are as follows:
÷1, ÷2, ÷4, ÷8, ÷16, ÷32, ÷64, ÷256

Ensure the output is less than or equal to the maximum device frequency (see specific device datasheet).

// default PLL output divider = 2
#pragma config FPLLODIV = DIV_2
// default PLL output divider = 32
#pragma config FPLLODIV = DIV_32
...
// set PLL output divider to 2
PLIB_OSC_SysPLLOutputDivisorSet(OSC_ID_0, OSC_SYSPLL_OUT_DIV_2);

System PLL Lock Status

The System PLL requires some time to achieve lock when a clock source is first applied. The SLOCK status bit can be checked to determine if enough time has passed to ensure a stable PLL output.

When the clock input to the PLL is changed, the hardware automatically clears this bit. After the PLL start-up timer has expired, the bit is automatically set. Please refer to the specific device datasheet for PLL lock time ("TLOCK" = 2 ms max).

The PLL lock status bit will be set upon the expiration of the timer even if the PLL has not achieved a lock. If the PLL does not stabilize during start-up, SLOCK may neither reflect the status of the PLL lock nor detect when the PLL loses lock during normal operation.

The following MPLAB® Harmony function returns the state of the PLL lock status. You are responsible for checking this status anytime you change the input to the System PLL.

// variable to hold the status of PLL lock
bool clockPLL_st;
// function returns value of PLL lock status                                  
clockPLL_st = PLIB_OSC_PLLClockIsLocked(OSC_ID_0);

System Clock (SYSCLK)

System Clock (SYSCLK) Generation

sysclk.PNG

The System Clock (SYSCLK) provides the time base for the CPU, peripheral clock, DMA, interrupts, and Flash. SYSCLK is determined from one of the input clocks shown in the diagram: System Phased- Lock Loop output (POSC or FRC with PLL), Primary Oscillator, Fast RC Oscillator, FRCDIV16, FRCDIV, Low-Power RC Oscillator, or Secondary Oscillator.

The PIC32MZ uses the Peripheral Bus Clock #7 (PBCLK7) to drive the core as SYSCLK.

The default configuration for SYSCLK is programmable and can also be changed at run-time. See the code examples below.

// default system clock = FRCDIV
#pragma config FNOSC = FRCDIV
// default system clock = Primary OSC (XT, HS, EC) with PLL
#pragma config FNOSC = PRIPLL
...    
// run-time config SYSCLK = FRCDIV
PLIB_OSC_SysClockSelect(OSC_ID_0, OSC_FRC_BY_FRCDIV);
// run-time config SYSCLK = POSC with PLL
PLIB_OSC_SysClockSelect(OSC_ID_0, OSC_PRIMARY_WITH_PLL);

Peripheral Bus Clock (PBCLK)

Peripheral Bus Clock (PBCLK)

pbclk.PNG

The peripheral clock is derived from the System Clock (SYSCLK) divided by the peripheral clock divisor setting (÷1, ÷2, ÷4, ÷8).

The peripheral bus frequency can be changed on the fly by writing a new value to the divisor bits. These bits are protected from accidental writes with an unlock sequence. A state machine ensures a stable transition from one clock frequency to another.

PBCLK can also be driven out the CLKO pin.

The default PBCLK divider can be configured at program time and the MPLAB® Harmony functions can be used to configure it at run-time. These functions will perform all unlocking/locking and state machine control for you.

// default PBCLK = SYSCLK/2
#pragma config FPBDIV = DIV_2    
...
// PBCLK=SYSCLK/2
PLIB_OSC_PBClockDivisorSet(OSC_ID_0, OSC_PERIPHERAL_BUS_1, 2);
// enable PBCLK
PLIB_OSC_PBOutputClockEnable(OSC_ID_0, OSC_PERIPHERAL_BUS_1);
// disable PBCLK
PLIB_OSC_PBOutputClockDisable(OSC_ID_0, OSC_PERIPHERAL_BUS_1);

Reference Clock (REFCLK)

Reference Clock

refclk.PNG

The Reference Clock can be used to drive the SPI peripheral or to generate a clock on the Reference Clock Output (REFCLKO) pin.

The reference clock can be derived from any of the following clock sources: System Phased-Lock Loop, Primary Oscillator, Fast RC, Low-Power RC, USB Phased-Lock Loop output (96 MHz), Secondary Oscillator, System Clock, Peripheral Bus Clock, and Reference Clock input.

Each reference clock has a high-precision divider based on this formula:

refclk_formula.PNG
  • refOscDiv can be any integer from 1 to 32768,
    • when refOscDiv = 0, the output clock = the input clock.
  • trimValue can be any integer from 1 to 512.
// ref clock base = FRC
PLIB_OSC_ReferenceOscBaseClockSelect (OSC_ID_0, OSC_REFERENCE_1, OSC_REF_BASECLOCK_FRC);
// disable ref clock
PLIB_OSC_ReferenceOscDisable(OSC_ID_0, OSC_REFERENCE_1);
// enable ref clock
PLIB_OSC_ReferenceOscEnable(OSC_ID_0, OSC_REFERENCE_1);
// refOscDiv = 32768
PLIB_OSC_ReferenceOscDivisorValueSet (OSC_ID_0, OSC_REFERENCE_1, 32768);
// trimValue = 256
PLIB_OSC_ReferenceOscTrimSet(OSC_ID_0, OSC_REFERENCE_1, 256);
// ref clock is driven out REFCLKO pin
PLIB_OSC_ReferenceOutputEnable(OSC_ID_0, OSC_REFERENCE_1);

USB Clock (USBCLK)

USB PLL Configuration

usb.PNG

The USB Clock can be derived from the 8 MHz internal FRC oscillator, 48 MHz POSC, or the USB PLL. For normal operation, the USB module requires an accurate 48 MHz clock.

The USB PLL input divider must be configured to provide 4 MHz to the multiplier. This divider is controlled by the UPLLIDIV setting with the following options:
÷1, ÷2, ÷3, ÷4, ÷5, ÷6, ÷10, ÷12

The internal 8 MHz FRC oscillator is available as a clock source to detect any USB activity during USB Suspend mode and bring the module out of the Suspend mode. This lowers power consumption while in Suspend mode.

The default USB PLL input divider and USB PLL enable can be configured at program time only. The USB clock source can be configured with the following MPLAB® Harmony function at run-time.

// if POSC = 12, default USB PLL input divide = 3
#pragma config UPLLIDIV = DIV_3
// default USB PLL enabled
#pragma config UPLLEN = ON
...
// following functions select POSC or FRC as input for the USB clock at run-time
PLIB_OSC_UsbClockSourceSelect(OSC_ID_0, SYS_OSC_USBCLK_PRIMARY);
// use for lower power during Suspend
PLIB_OSC_UsbClockSourceSelect(OSC_ID_0, SYS_OSC_USBCLK_FRC);

Two-Speed Start-up

Two-Speed Start-up

If an external crystal (Primary Oscillator) is providing a clock source for your device, you will need to wait for the oscillator and PLL to stabilize before executing any code after a Power-on Reset (POR) or exit from sleep (see Oscillator Start-up Timer and System PLL Lock Status for more information). If you want to start executing code before the oscillator has stabilized, you can use the "Two-Speed Start-up" option.

Two-Speed Start-up uses the internal Fast RC Oscillator (FRC) as the system clock source until the Primary Oscillator (POSC) has stabilized. This allows the CPU to begin running code while the oscillator is stabilizing. After it has stabilized, the clock source will automatically be switched to use the Primary Oscillator (POSC).

If you want to determine the clock source currently in use, the MPLAB® Harmony function shown in the example below can be used. It will return the current oscillator (COSC) setting found in the OSCCON register.

// Enable Two-Speed Start-up (Internal/External switch over)
#pragma config IESO = ON
...
// variable to hold the state of the current clock source
OSC_SYS_TYPE oscCurrent;
// assign the current clock source to oscCurrent
oscCurrent = PLIB_OSC_CurrentSysClockGet(OSC_ID_0);
                                              // 0 = FRC
                                              // 2 = POSC
                                              // 3 = POSC with PLL

The Watchdog Timer (WDT), if enabled, will continue to count at the same rate regardless of the SYSCLK frequency. Care must be taken to service the WDT during Two-Speed Start-up, taking into account the change in SYSCLK.

Detailed Overview

For more detail on the Two-Speed Start-up feature, please view the Oscillator family reference manual chapter for that device, for example:

The device data sheet should then be consulted to verify the specific features implemented in that device.

Fail-Safe Clock Monitor (FSCM)

Fail-Safe Clock Monitor

The Fail-Safe Clock Monitor (FSCM) monitors the Primary Oscillator (POSC) to ensure it is functional. If the POSC stops working, it will automatically switch the clock source to the internal Fast RC Oscillator (FRC) (or Backup FRC (BFRC) if available). The switch to the FRC or BFRC allows continued device operation.

The FSCM will generate an interrupt (optional on some devices) and you determine what code runs in that interrupt. You can retry the POSC to see if it recovers, or execute code appropriate for a clock failure.

The following code example shows how to enable the FSCM. It controls the clock switching and monitor (FCKSM) setting in one of the device configuration registers.

 // clock switching enabled and clock monitor enabled
#pragma config FCKSM = CSECME

All devices have at least one internal FRC oscillator. If your device also has a Backup FRC (BFRC) it will be used as the clock source instead. The BFRC is dedicated to the FSCM and can not be used for anything else.

Detailed Overview

For more detail on the Fail-Safe Clock Monitor feature, please review the Oscillator family reference manual chapter for that device, for example:

The device data sheet should then be consulted to verify the specific features implemented in that device.

Clock Switching

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:

  1. optional…determine the current clock source
  2. perform the unlock sequence to allow a write to the Oscillator Configuration register (OSCCON)
  3. configure the New Oscillator (NOSC) setting with the clock source you want to switch to
  4. initiate the oscillator switch by setting the Oscillator Switch Enable (OSWEN) bit
  5. 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:

  1. Switch to a non-PLL source, such as FRC
  2. Modify the multiplier and postscaler values
  3. 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:

The device data sheet should then be consulted to verify the specific features implemented in that device.

© 2024 Microchip Technology, Inc.
Notice: ARM and Cortex are the registered trademarks of ARM Limited in the EU and other countries.
Information contained on this site regarding device applications and the like is provided only for your convenience and may be superseded by updates. It is your responsibility to ensure that your application meets with your specifications. MICROCHIP MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND WHETHER EXPRESS OR IMPLIED, WRITTEN OR ORAL, STATUTORY OR OTHERWISE, RELATED TO THE INFORMATION, INCLUDING BUT NOT LIMITED TO ITS CONDITION, QUALITY, PERFORMANCE, MERCHANTABILITY OR FITNESS FOR PURPOSE. Microchip disclaims all liability arising from this information and its use. Use of Microchip devices in life support and/or safety applications is entirely at the buyer's risk, and the buyer agrees to defend, indemnify and hold harmless Microchip from any and all damages, claims, suits, or expenses resulting from such use. No licenses are conveyed, implicitly or otherwise, under any Microchip intellectual property rights.