Electronic – Clock switching hangs when switching back to original source

cclockembeddedpic

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

Thanks in advance

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.

Best Answer

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);