# Clock switching hangs when switching back to original source

I am currently working on a project where the clock needs switching between the Primary Oscillator with PLL (POSCPLL) to the FRC and back again.

I have initialised the Clock as the PRIPLL by using the config bits:

#pragma config FNOSC = PRIPLL
#pragma config POSCMOD = HS
#pragma config FPLLMUL = MUL_20
#pragma config FPLLIDIV = DIV_2
#pragma config FPLLODIV = DIV_1
#pragma config FPBDIV = DIV_1
#pragma config FCKSM = CSECME


which sets the OSCCON to 0x01453360 and gives an 80MHz clock signal. I then use this function to switch to the FRC:

INTDisableInterrupts();
//Execute the System unlock sequence
SYSKEY = 0xAA996655;
SYSKEY = 0x556699AA;

OSCCONbits.NOSC = 000;
OSCConfig(OSC_FRC, 0, 0, OSC_FRC_POST_1);
mOSCSetPBDIV(OSC_PB_DIV_1);
//Initiate the clock switch
OSCCONbits.OSWEN = 1;
//Lock SYSKEY
SYSKEY = 0x33333333;
int k = 0;
//Wait until OSWEN = 0 and switch is complete
while (OSCCONbits.OSWEN == 1){
k++;
}
//Re-enable interrupts
INTEnableInterrupts();
SYSTEMConfig(GetStandbySystemClock(), SYS_CFG_ALL);


To switch back to the POSC PLL i use the same structure but change the value of NOSC to 011; and update the OSCConfig to

OSCConfig(OSC_POSC_PLL, OSC_PLL_MULT_20, OSC_PLL_POST_1, 0);


Which matches the sequence in the pragma config bits. However, when i run it on the PIC32MX, the debugger on a PICKIT3 cannot get past the function with these set-up bits, however it will allow for it to be set at half the speed (OSC_PLL_POST_2).

If the debugger is paused however, it can be seen that the OSCCON is the same, but when it is resumed, the software restarts.

If anyone could tell me if i have missed a setup bit to enable to switch back to the initial clock or if there is a better way to do this i would be extremely grateful!

Extra information: PIC32MX775F256L, Custom board, 8MHz Crystal (FOXSDLF/080-20), The crystal is connect to the OSC1 and OSC2 (pin 63 and pin 64), loading capacitors 22pF

EDIT I have now also tried setting the new clock source without using the OSCConfig function and using the hard values instead.

OSCCONbits.NOSC = 0b011;
OSCCONbits.PLLODIV = 0b000;
OSCCONbits.PLLMULT = 0b101;
OSCCONbits.PBDIV = 0b00;


When PLLODIV is 0b000 the same thing happens, However, when it is set to 0b001 it works and the system is half speed, as it is divided by two

EDIT 2

I have now tried to switch between clocks without using the #pragma config bits I have removed

#pragma config FPLLMUL = MUL_20
#pragma config FPLLODIV = DIV_1
#pragma config FNOSC = PRIPLL
#pragma config FPBDIV = DIV_1


I use the same functions to set up the clock in the first place, and get the desired outcome no problem. I then switch to the FRC clock, again no problems. Only when i try to switch back to the original clock do i encounter a problem. It is also not helped if i switch to the same clock with different parameters first before switching back to the correct ones via the FRC again. But it will work if i switch to the clock with different parameters first, then switch to the correct one via the FRC on start up.

I now have the code isolated to avoid any other code affecting the clock switching and still no difference.

• For the decimal number 10, decimal notation is: 10, hexadecimal notation: 0xA, octal notation: 012. There is no binary notation in C, but a common non-standard extension is 0b1010. Mar 13 '15 at 7:21

If you meant to set those bits as binary, you need to change this:

OSCCONbits.NOSC = 000;


to this:

OSCCONbits.NOSC = 0b000;


Also wherever you set NOSC back, it should be set to 0b011 not just 011.

A prefix of "0" actually makes the value octal in the XC32 compiler (as pointed out by @Lundin in comments), which is decimal 9, which == 0b1001, so this is certainly one problem that needs fixing.

Also, in the PIC32 Peripheral Library Guide it says:

"In general when switching to a higher CPU clock frequency the Peripheral Bus divisor should be set to the new lower value before changing the CPU frequency"

So, when going up/down speeds, you should be using the appropriate order of the following calls:

OSCConfig(OSC_FRC, 0, 0, OSC_FRC_POST_1);
mOSCSetPBDIV(OSC_PB_DIV_1);

• Thanks, i have added that in, but no changes to the outcome for my problem. It appears that by changing the PLLODIV to 0b001 it will not hang, but then obviously gives half the speed. Any ideas as to why it would hang setting the PLLODIV to 0b000?
– Matt Winstanley
Mar 12 '15 at 15:25
• @MattWinstanley I can't see any obvious problem with that in the datasheet. It's not that the PICKit is forcing a reset or something stupid is it? Mar 12 '15 at 15:31
• I have now tried it with an ICD3 programmer and again when it is not in debugging mode and the same thing happens again. This time it doesnt reset, but MPLAB wont allow you to resume the program. Its probably something ridiculously stupid, but just finding that one bit to change to make it work is proving more and more difficult!
– Matt Winstanley
Mar 12 '15 at 15:51
• @MattWinstanley See updated answer, it may be relevant? Mar 12 '15 at 16:04
• 011 is octal (dec 9) so this answer got some errors in it. Mar 13 '15 at 7:17