Author Topic: How do i switch clock in a PIC32MX? (AKA:why doesn't it switch)  (Read 4312 times)

0 Members and 1 Guest are viewing this topic.

Online JPorticiTopic starter

  • Super Contributor
  • ***
  • Posts: 3461
  • Country: it
Hi, unfortunately the microchip forum isn't being helpful. Only answer i received so far was a reminder of a thing clearly stated in the datasheet :/

This is my first project wit ha PIC32 that has gone over the "tinkering" phase.
I am using a PIC32MX530F128H (because it's the cheapest MCU with both CAN and USB that i feel combfortable using)
The MCU is being clocked at 48MHz with a 8 MHz crystal oscillator.

FSCM and Clock Switching are enabled. In case of an oscillator fail the FSCM will automatically switch to the FRC, issue the Oscillator fail interrupt and then the code should perform the switch to FRC+PLL and keep the unit running at 48 MHz.
-The accuracy of the FRC should be good enough in the temperature range not to cause problems until the next power cycle
-USB Module can be clocked by either the FRC (8 MHz) or the USB PLL or POSC. It is said that to function properly the module must be clocked at 48 MHz, but then again they let you use the FRC. I think in this case the USB module would work as a LS device. Fine with me. USB is a feature, not the main feature.

My problem is, i can't perform a clock switch.
I tried following the procedure written in the datasheet, looked at code examples, which used libraries (i go bare metal) and i made sure that my code was the same as the code produced by the library, but nothing.

I created a project where the device boots in PRI+PLL then tries to switch to FRC. Pic Hangs after clock switch enable. If i run in debug mode the PIC halts at the clock switch enable (note: no breakpoints set) and if i single-step i see the COSC bits remain unchanged, it hasn't performed the switch.

XC32 v1.44
Device: PIC32MX530F128H
Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/60001290E.pdf
Errata: http://ww1.microchip.com/downloads/en/DeviceDoc/80000616C.pdf
Relevant Reference Manual Chapter: http://ww1.microchip.com/downloads/en/DeviceDoc/61112H.pdf

if someone can take his time to look at this..
Unfortunately i don't have a PIC32MX demoboard at hand so i can't ask microchip support. Well i can but usually in this cases they stall because they don't have the same hardware to test.
Note i didn't disable interrupts or DMA in this example as i'm not using those. In the main application i did disable them during the switch, same results.

Code: [Select]
// DEVCFG3
// USERID = No Setting
#pragma config PMDL1WAY = OFF           // Peripheral Module Disable Configuration (Allow multiple reconfigurations)
#pragma config IOL1WAY = OFF            // Peripheral Pin Select Configuration (Allow multiple reconfigurations)
#pragma config FUSBIDIO = ON            // USB USID Selection (Controlled by the USB Module)
#pragma config FVBUSONIO = ON           // USB VBUS ON Selection (Controlled by USB Module)

// DEVCFG2
#pragma config FPLLIDIV = DIV_2         // PLL Input Divider (2x Divider)
#pragma config FPLLMUL = MUL_24         // PLL Multiplier (24x Multiplier)
#pragma config UPLLIDIV = DIV_2         // USB PLL Input Divider (2x Divider)
#pragma config UPLLEN = ON              // USB PLL Enable (Enabled)
#pragma config FPLLODIV = DIV_2         // System PLL Output Clock Divider (PLL Divide by 2)

// DEVCFG1
#pragma config FNOSC = PRIPLL           // Oscillator Selection Bits (Primary Osc w/PLL (XT+,HS+,EC+PLL))
#pragma config FSOSCEN = OFF            // Secondary Oscillator Enable (Disabled)
#pragma config IESO = ON                // Internal/External Switch Over (Enabled)
#pragma config POSCMOD = HS             // Primary Oscillator Configuration (HS osc mode)
#pragma config OSCIOFNC = OFF           // CLKO Output Signal Active on the OSCO Pin (Disabled)
#pragma config FPBDIV = DIV_1           // Peripheral Clock Divisor (Pb_Clk is Sys_Clk/1)
#pragma config FCKSM = CSECME           // Clock Switching and Monitor Selection (Clock Switch Enable, FSCM Enabled)
#pragma config WDTPS = PS1048576        // Watchdog Timer Postscaler (1:1048576)
#pragma config WINDIS = OFF             // Watchdog Timer Window Enable (Watchdog Timer is in Non-Window Mode)
#pragma config FWDTEN = OFF             // Watchdog Timer Enable (WDT Disabled (SWDTEN Bit Controls))
#pragma config FWDTWINSZ = WINSZ_25     // Watchdog Timer Window Size (Window Size is 25%)

// DEVCFG0
#pragma config JTAGEN = OFF             // JTAG Enable (JTAG Disabled)
#pragma config ICESEL = ICS_PGx1        // ICE/ICD Comm Channel Select (Communicate on PGEC1/PGED1)
#pragma config PWP = OFF                // Program Flash Write Protect (Disable)
#pragma config BWP = OFF                // Boot Flash Write Protect bit (Protection Disabled)
#pragma config CP = OFF                 // Code Protect (Protection Disabled)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>

int main() {
  volatile int cnt1 = 0,cnt2 = 1;
 
  WDTCONbits.ON = 0;
  TRISBCLR = 0xFFFF;
  ANSELBCLR = 0xFFFF;
  LATBCLR = 0xFFFF;
 
  for (cnt1=0;cnt1<10;cnt1++) {
    for (cnt2=0;cnt2<500000;cnt2++) {
      asm("NOP");
    }
    LATBINV = 0xFFFF;
  }
 
  /* Clock Switch to FRC */
  SYSKEY = 0;
  SYSKEY = 0xAA996655;
  SYSKEY = 0x556699AA;
 
  OSCCONCLR = _OSCCON_NOSC_MASK;

//OSCCON will remain unlocked until i write to SYSKEY again, the manual says. I tried unlocking again and it didn't make any difference so i commented it out
//  SYSKEY = 0;
//  SYSKEY = 0xAA996655;
//  SYSKEY = 0x556699AA;
  OSCCONSET = _OSCCON_OSWEN_MASK;    //In run mode device never gets past here. tried by flashing a LED. in debug mode debugger halts here even if no breakpoints set.
 
  while (OSCCONbits.OSWEN);
 
  while(OSCCONbits.COSC != 0);
 
 
  for (cnt1=0;cnt1<10;cnt1++) {
    for (cnt2=0;cnt2<500000;cnt2++) {
      asm("NOP");
    }
    LATBINV = 0xFFFF;
  }
 
  while(1) {
    asm("NOP");
  }
 
  return 0;
}
 

Offline mikeselectricstuff

  • Super Contributor
  • ***
  • Posts: 13748
  • Country: gb
    • Mike's Electric Stuff
Re: How do i switch clock in a PIC32MX? (AKA:why doesn't it switch)
« Reply #1 on: March 15, 2018, 10:47:54 am »
Without looking in detail I wonder if maybe the RC osc is powered off if the config doesn't use it, and there is something explicit that needs doing to enable it before selecting it as an osc source.

I wouldn't put too much faith in datasheet examples as these are sometimes copy-pasted from other devices and subtle differences sometimes get missed. Also check that the header-file constants  (e.g. _OSCCON_OSWEN_MASK ) are actually correct.

Also worth trying switching between different osc modes to try to eliminate things - e.g. try switching to a non-RC osc to see if the issue is with the switching, or the RC osc
 
Youtube channel:Taking wierd stuff apart. Very apart.
Mike's Electric Stuff: High voltage, vintage electronics etc.
Day Job: Mostly LEDs
 

Online JPorticiTopic starter

  • Super Contributor
  • ***
  • Posts: 3461
  • Country: it
Re: How do i switch clock in a PIC32MX? (AKA:why doesn't it switch)
« Reply #2 on: March 15, 2018, 11:34:09 am »
Hi mike, yes i verified that the defines in the include file are correct (i was already bitten by this..)

According to the manual, if the oscillator source is powered down it gets enabled, then after the stabilization period the clock switching occours, then OSWEN bit is cleared. But in the meantime, the device keeps using the current oscillator.

If i cause an oscillator fail (by for example shorting the crystal pins) the device does indeed switch to FRC, then sets the FSCM interrupt bit.

I also tried switching from FRC to FRC+PLL (with FRCDIV = 0 -> FRC = 8 MHz, same as crystal so i didn't have to change the PLL parameters) but same error. And that is actually what i'm interested in achieving.
 

Offline Howardlong

  • Super Contributor
  • ***
  • Posts: 5319
  • Country: gb
Re: How do i switch clock in a PIC32MX? (AKA:why doesn't it switch)
« Reply #3 on: March 15, 2018, 11:56:44 am »
Here's some old code I used some years ago for a PIC32MX230F064B which has a reasonably similar, if not identical, clock module to you device.

It boots in FRCPLL 40MHz mode, then switches to 8MHz FRC for a short while, then to a 40MHz PRIPLL based on EC of 8MHz because the internal FRC is not accurate enough for the USB peripheral. It's been a long time, but I think you need to switch to a non PLL mode before switching back to a PLL mode.

Some notes...

There's also a slight complication as this code is in the bootloader, so it has to re-initialise stuff in the event that the main application fails (e.g., non-POR reset or trap of some sort).

On my board, the 8MHz EC is not available at boot, it is derived from an external clock distribution chain that needs initialising.

It looks like if it fails PRIPLL, it tries to set itself back to FRCPLL.

Code: [Select]
#pragma config FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FPLLODIV = DIV_2
#pragma config POSCMOD = EC, FNOSC = FRCPLL, FPBDIV = DIV_1
#pragma config FCKSM = CSECME
#pragma config FSOSCEN = OFF

#pragma config UPLLEN = ON, UPLLIDIV = DIV_2, FVBUSONIO = OFF, FUSBIDIO = OFF
#pragma config JTAGEN = OFF   
#pragma config IESO = OFF, OSCIOFNC = OFF       
#pragma config ICESEL = ICS_PGx1

#pragma config FWDTEN = ON, WDTPS = PS2048

#pragma config PMDL1WAY = OFF      // Allow multiple PMD reconfigurations
#pragma config IOL1WAY  = OFF      // Allow multiple PPS reconfigurations

#if defined(__DEBUG) || !defined(CODEPROTECT)
#pragma config CP       = OFF      // Code Protect: OFF
#pragma config BWP      = OFF      // Boot Flash Write Protect: OFF
#pragma config PWP      = OFF      // Program Flash Write Protect: OFF
#else
#pragma config CP       = ON       // Code Protect: ON
#pragma config BWP      = ON      // Boot Flash Write Protect: ON
#pragma config PWP      = PWP19K      // Program Flash Write Protect: ON /**** HL ****/
#endif

Code: [Select]

// from legacy peripheral library lock.h:

#ifdef _DMAC
    #define mSYSTEMUnlock(intStat, dmaSusp) do{intStat=INTDisableInterrupts(); dmaSusp=DmaSuspend(); \
                        SYSKEY = 0, SYSKEY = 0xAA996655, SYSKEY = 0x556699AA;}while(0)
#else
    #define mSYSTEMUnlock(intStat, dmaSusp) do{intStat=INTDisableInterrupts(); \
                        SYSKEY = 0, SYSKEY = 0xAA996655, SYSKEY = 0x556699AA;}while(0)
#endif  // _DMAC

#ifdef _DMAC
    #define mSYSTEMLock(intStat, dmaSusp)   do{SYSKEY = 0x33333333; DmaResume(dmaSusp); INTRestoreInterrupts(intStat);}while(0)
#else
    #define mSYSTEMLock(intStat, dmaSusp)   do{SYSKEY = 0x33333333; INTRestoreInterrupts(intStat);}while(0)
#endif // _DMAC

Code: [Select]
static BOOL MyBoardSwitchOscSet(int nOsc,int nCount)
{
// Call with nCount==-1 for no timeout
OSCCONbits.NOSC=nOsc;
OSCCONSET=1;
while (OSCCONbits.OSWEN!=0)
{
if (nCount>=0)
{
nCount--;
if (nCount<=0)
{
return FALSE;
}
ClearWDT();
}
}
return TRUE;
}

static void MyBoardSwitchOsc(void)
{
static int nCount=0;
int nIntStatus;
int nDMASuspend;
BOOL b;

mSYSTEMUnlock(nIntStatus,nDMASuspend);

MyBoardSwitchOscSet(0,-1); // Set to basic FRC mode to start with (won't work otherwise)
b=MyBoardSwitchOscSet(3,100000); // Try PRIPLL with timout

if (!b || OSCCONbits.NOSC!=OSCCONbits.COSC || OSCCONbits.CF || !OSCCONbits.SLOCK)
{
MyBoardSwitchOscSet(0,-1); // Basic FRC
MyBoardSwitchOscSet(1,-1); // Try FRCPLL if possible
}
mSYSTEMLock(nIntStatus,nDMASuspend);

if (OSCCONbits.COSC!=3)
{
LEDStateHalt(LED_BAD_OSCILLATOR);
}
}


« Last Edit: March 15, 2018, 02:14:49 pm by Howardlong »
 

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 826
Re: How do i switch clock in a PIC32MX? (AKA:why doesn't it switch)
« Reply #4 on: March 15, 2018, 02:02:34 pm »
Maybe I have not read thoroughly enough, but I have had a problem with pic32mm if I have the fuses set to pll enabled. The clock will lockup (on reset in my case) when the pll mul is higher than a certain setting (I was using mul of 12x). Bottom line, set fuses to use frc and do the switching yourself. I think this is what the MCC generated code does also (for pic32mm at least), even if a pll mode is selected for fuses it sets to use frcdiv then changes clock in startup code. In the pic32mm, the problem seemed to be that the reset pll mul value was 1x, the user (me) set pll mul value was 12x, and a reset would cause the pll mul to reset and the clock couldn't lock when the jump from 12x to the reset 1x value takes place on reset. Your chip is probably different, though.

Quote
-USB Module can be clocked by either the FRC (8 MHz) or the USB PLL or POSC. It is said that to function properly the module must be clocked at 48 MHz, but then again they let you use the FRC. I think in this case the USB module would work as a LS device. Fine with me. USB is a feature, not the main feature.
The FRC for the USB is only for low speed. But, there is nothing stopping you from using an output clock (timer, refclko, anything) back in to the EXT OSC pin so you can ultimately be clocking the FS usb from FRC.

I wouldn't be surprised if the frc is good enough. I have played with a pic32mx-lower-end-28pindip-with-usb and did exactly that- used the internal frc, set something up to output a clock (refclko, unless also being used, then a timer can be used), physically connected to ext clk in (whatever mode is ext- EC or something), created a routine in the usb code to get a number of sof packets before ever responding, timed them with cp0 counter, adjusted tun to get 1ms, then let the usb continue. While running, I kept timing the sof packets and kept adjusting tun as needed.  In the end, I could manually adjust tun to either end and usb never complained so I think the frc in that particular mx was accurate enough. I also set up a routine to output the tun info via uart, sprayed the chip with cold spray, watch the tun value- although it would change, I could not get to end of the tun range.
 

Online JPorticiTopic starter

  • Super Contributor
  • ***
  • Posts: 3461
  • Country: it
Re: How do i switch clock in a PIC32MX? (AKA:why doesn't it switch)
« Reply #5 on: March 15, 2018, 02:11:22 pm »
Thanks howard, your code is basically what's in the provided code examples but i decided to give it another try.
I disabled both interrupt and DMA in my sample project, even if i thought i wouldn't matter, because no interrupts are used and no DMA-Enabled peripheral is used.

It is now working in "Run" mode: I can switch between clocks, check for a FSCM event by polling the interrupt bit and perform the switch again.
Start from FRC -> switch to PRI+PLL. on FSCM event switch to FRC to clear the Clock Fail bit and then switch to FRC+PLL.

However i keep having the same issue during debugging, but at this point i can just assume that i can't perform a clock switch during debug, even though there is no mention of this in the datasheet/manual.

EDIT: But it's not working in the main application, but now i know that it is only a software problem and i have at least one good reference to check against to.
« Last Edit: March 15, 2018, 02:56:04 pm by JPortici »
 

Offline Howardlong

  • Super Contributor
  • ***
  • Posts: 5319
  • Country: gb
Re: How do i switch clock in a PIC32MX? (AKA:why doesn't it switch)
« Reply #6 on: March 15, 2018, 03:50:32 pm »
I have a PIC32MX1/2/5 Starter Kit dev board in the lab, but I'm out and about at the moment. I can try to put your code on that if it helps, but it will be a couple of hours before I'm back.

I do happen to have an ESK II on me, and besides a few minor chip and board compatibility adjustments, I have you code working on that in the debugger, successfully changing from PRIPLL to FRC.

ESK II version:
Code: [Select]
// DEVCFG3
// USERID = No Setting
//#pragma config PMDL1WAY = OFF           // Peripheral Module Disable Configuration (Allow multiple reconfigurations)
//#pragma config IOL1WAY = OFF            // Peripheral Pin Select Configuration (Allow multiple reconfigurations)
#pragma config FUSBIDIO = ON            // USB USID Selection (Controlled by the USB Module)
#pragma config FVBUSONIO = ON           // USB VBUS ON Selection (Controlled by USB Module)

// DEVCFG2
//#pragma config FPLLIDIV = DIV_2         // PLL Input Divider (2x Divider)
#pragma config FPLLIDIV = DIV_3         // PLL Input Divider (2x Divider)
//#pragma config FPLLMUL = MUL_24         // PLL Multiplier (24x Multiplier)
#pragma config FPLLMUL = MUL_20         // PLL Multiplier (24x Multiplier)
#pragma config UPLLIDIV = DIV_2         // USB PLL Input Divider (2x Divider)
#pragma config UPLLEN = ON              // USB PLL Enable (Enabled)
#pragma config FPLLODIV = DIV_2         // System PLL Output Clock Divider (PLL Divide by 2)

// DEVCFG1
#pragma config FNOSC = PRIPLL           // Oscillator Selection Bits (Primary Osc w/PLL (XT+,HS+,EC+PLL))
#pragma config FSOSCEN = OFF            // Secondary Oscillator Enable (Disabled)
#pragma config IESO = ON                // Internal/External Switch Over (Enabled)
#pragma config POSCMOD = HS             // Primary Oscillator Configuration (HS osc mode)
#pragma config OSCIOFNC = OFF           // CLKO Output Signal Active on the OSCO Pin (Disabled)
#pragma config FPBDIV = DIV_1           // Peripheral Clock Divisor (Pb_Clk is Sys_Clk/1)
#pragma config FCKSM = CSECME           // Clock Switching and Monitor Selection (Clock Switch Enable, FSCM Enabled)
#pragma config WDTPS = PS1048576        // Watchdog Timer Postscaler (1:1048576)
//#pragma config WINDIS = OFF             // Watchdog Timer Window Enable (Watchdog Timer is in Non-Window Mode)
#pragma config FWDTEN = OFF             // Watchdog Timer Enable (WDT Disabled (SWDTEN Bit Controls))
//#pragma config FWDTWINSZ = WINSZ_25     // Watchdog Timer Window Size (Window Size is 25%)

// DEVCFG0
//#pragma config JTAGEN = OFF             // JTAG Enable (JTAG Disabled)
//#pragma config ICESEL = ICS_PGx1        // ICE/ICD Comm Channel Select (Communicate on PGEC1/PGED1)
#pragma config ICESEL = ICS_PGx2        // ICE/ICD Comm Channel Select (Communicate on PGEC1/PGED1)
#pragma config PWP = OFF                // Program Flash Write Protect (Disable)
#pragma config BWP = OFF                // Boot Flash Write Protect bit (Protection Disabled)
#pragma config CP = OFF                 // Code Protect (Protection Disabled)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>

int main() {
  volatile int cnt1 = 0,cnt2 = 1;
 
  WDTCONbits.ON = 0;
  TRISBCLR = 0xFFFF;
//  ANSELBCLR = 0xFFFF;
  LATBCLR = 0xFFFF;
 
  for (cnt1=0;cnt1<10;cnt1++) {
    for (cnt2=0;cnt2<500000;cnt2++) {
      asm("NOP");
    }
    LATBINV = 0xFFFF;
  }
 
  /* Clock Switch to FRC */
  SYSKEY = 0;
  SYSKEY = 0xAA996655;
  SYSKEY = 0x556699AA;
 
  OSCCONCLR = _OSCCON_NOSC_MASK;

//OSCCON will remain unlocked until i write to SYSKEY again, the manual says. I tried unlocking again and it didn't make any difference so i commented it out
//  SYSKEY = 0;
//  SYSKEY = 0xAA996655;
//  SYSKEY = 0x556699AA;
  OSCCONSET = _OSCCON_OSWEN_MASK;    //In run mode device never gets past here. tried by flashing a LED. in debug mode debugger halts here even if no breakpoints set.
 
  while (OSCCONbits.OSWEN);
 
  while(OSCCONbits.COSC != 0);
 
 
  for (cnt1=0;cnt1<10;cnt1++) {
    for (cnt2=0;cnt2<500000;cnt2++) {
      asm("NOP");
    }
    LATBINV = 0xFFFF;
  }
 
  while(1) {
    asm("NOP");
  }
 
  return 0;
}
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4784
  • Country: pm
  • It's important to try new things..
Re: How do i switch clock in a PIC32MX? (AKA:why doesn't it switch)
« Reply #7 on: March 15, 2018, 04:47:15 pm »
This forum pic32mx/mz may help
https://chipkit.net/forum/
 

Online JPorticiTopic starter

  • Super Contributor
  • ***
  • Posts: 3461
  • Country: it
Re: How do i switch clock in a PIC32MX? (AKA:why doesn't it switch)
« Reply #8 on: March 15, 2018, 05:47:06 pm »
I have a PIC32MX1/2/5 Starter Kit dev board in the lab, but I'm out and about at the moment. I can try to put your code on that if it helps, but it will be a couple of hours before I'm back.

I do happen to have an ESK II on me, and besides a few minor chip and board compatibility adjustments, I have you code working on that in the debugger, successfully changing from PRIPLL to FRC.

ESK II version:
Code: [Select]
// DEVCFG3
// USERID = No Setting
//#pragma config PMDL1WAY = OFF           // Peripheral Module Disable Configuration (Allow multiple reconfigurations)
//#pragma config IOL1WAY = OFF            // Peripheral Pin Select Configuration (Allow multiple reconfigurations)
#pragma config FUSBIDIO = ON            // USB USID Selection (Controlled by the USB Module)
#pragma config FVBUSONIO = ON           // USB VBUS ON Selection (Controlled by USB Module)

// DEVCFG2
//#pragma config FPLLIDIV = DIV_2         // PLL Input Divider (2x Divider)
#pragma config FPLLIDIV = DIV_3         // PLL Input Divider (2x Divider)
//#pragma config FPLLMUL = MUL_24         // PLL Multiplier (24x Multiplier)
#pragma config FPLLMUL = MUL_20         // PLL Multiplier (24x Multiplier)
#pragma config UPLLIDIV = DIV_2         // USB PLL Input Divider (2x Divider)
#pragma config UPLLEN = ON              // USB PLL Enable (Enabled)
#pragma config FPLLODIV = DIV_2         // System PLL Output Clock Divider (PLL Divide by 2)

// DEVCFG1
#pragma config FNOSC = PRIPLL           // Oscillator Selection Bits (Primary Osc w/PLL (XT+,HS+,EC+PLL))
#pragma config FSOSCEN = OFF            // Secondary Oscillator Enable (Disabled)
#pragma config IESO = ON                // Internal/External Switch Over (Enabled)
#pragma config POSCMOD = HS             // Primary Oscillator Configuration (HS osc mode)
#pragma config OSCIOFNC = OFF           // CLKO Output Signal Active on the OSCO Pin (Disabled)
#pragma config FPBDIV = DIV_1           // Peripheral Clock Divisor (Pb_Clk is Sys_Clk/1)
#pragma config FCKSM = CSECME           // Clock Switching and Monitor Selection (Clock Switch Enable, FSCM Enabled)
#pragma config WDTPS = PS1048576        // Watchdog Timer Postscaler (1:1048576)
//#pragma config WINDIS = OFF             // Watchdog Timer Window Enable (Watchdog Timer is in Non-Window Mode)
#pragma config FWDTEN = OFF             // Watchdog Timer Enable (WDT Disabled (SWDTEN Bit Controls))
//#pragma config FWDTWINSZ = WINSZ_25     // Watchdog Timer Window Size (Window Size is 25%)

// DEVCFG0
//#pragma config JTAGEN = OFF             // JTAG Enable (JTAG Disabled)
//#pragma config ICESEL = ICS_PGx1        // ICE/ICD Comm Channel Select (Communicate on PGEC1/PGED1)
#pragma config ICESEL = ICS_PGx2        // ICE/ICD Comm Channel Select (Communicate on PGEC1/PGED1)
#pragma config PWP = OFF                // Program Flash Write Protect (Disable)
#pragma config BWP = OFF                // Boot Flash Write Protect bit (Protection Disabled)
#pragma config CP = OFF                 // Code Protect (Protection Disabled)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>

int main() {
  volatile int cnt1 = 0,cnt2 = 1;
 
  WDTCONbits.ON = 0;
  TRISBCLR = 0xFFFF;
//  ANSELBCLR = 0xFFFF;
  LATBCLR = 0xFFFF;
 
  for (cnt1=0;cnt1<10;cnt1++) {
    for (cnt2=0;cnt2<500000;cnt2++) {
      asm("NOP");
    }
    LATBINV = 0xFFFF;
  }
 
  /* Clock Switch to FRC */
  SYSKEY = 0;
  SYSKEY = 0xAA996655;
  SYSKEY = 0x556699AA;
 
  OSCCONCLR = _OSCCON_NOSC_MASK;

//OSCCON will remain unlocked until i write to SYSKEY again, the manual says. I tried unlocking again and it didn't make any difference so i commented it out
//  SYSKEY = 0;
//  SYSKEY = 0xAA996655;
//  SYSKEY = 0x556699AA;
  OSCCONSET = _OSCCON_OSWEN_MASK;    //In run mode device never gets past here. tried by flashing a LED. in debug mode debugger halts here even if no breakpoints set.
 
  while (OSCCONbits.OSWEN);
 
  while(OSCCONbits.COSC != 0);
 
 
  for (cnt1=0;cnt1<10;cnt1++) {
    for (cnt2=0;cnt2<500000;cnt2++) {
      asm("NOP");
    }
    LATBINV = 0xFFFF;
  }
 
  while(1) {
    asm("NOP");
  }
 
  return 0;
}

hm. Then there may also be a problem in my hardware. I assembled two boards and they behave the same
if it's not too much trouble, which board did you use? i'll check the schematic
thank you very very much :)
 

Offline Howardlong

  • Super Contributor
  • ***
  • Posts: 5319
  • Country: gb
Re: How do i switch clock in a PIC32MX? (AKA:why doesn't it switch)
« Reply #9 on: March 15, 2018, 06:02:26 pm »
No, there is something wrong, I have the same problem with a PIC32MX570F512L on the PIC32MX1/2/5 SK.

It breakpoints unexpectedly at the

Code: [Select]
  while (OSCCONbits.OSWEN);

I'm fiddling with it now.
 

Online NorthGuy

  • Super Contributor
  • ***
  • Posts: 3146
  • Country: ca
Re: How do i switch clock in a PIC32MX? (AKA:why doesn't it switch)
« Reply #10 on: March 15, 2018, 06:49:09 pm »
FSCM and Clock Switching are enabled.

Have you tried disabling the clock monitor? It is not necessary for clock switching. You can use CSECMD.

When it breaks, have you checked the contents of the OSCCON. What clock it is running on? Is the CF bit set?

 

Offline Howardlong

  • Super Contributor
  • ***
  • Posts: 5319
  • Country: gb
Re: How do i switch clock in a PIC32MX? (AKA:why doesn't it switch)
« Reply #11 on: March 15, 2018, 07:26:32 pm »
The OP's original code works perfectly on a breadboarded PIC32MX270F256B with an 8MHz crystal (plus 2 * 22pF to Vss)  and one change to the POSCMOD to XT rather than HS.

It breakpoints on the PIC32MX570F512L on the SK (with some mods to use just the onboard LEDs on PORTD and not PORTB.)

The break happens as soon as you set the OSWEN bit to 1.

I tried a many different options, including switching to/from FRC and FRCDIV, PRI to and from FRC etc, without PLL, but nothing works.

I also added an exception handler, but it's not called.

I do have some PIC32MX570F512-H and -L in stock, which I could breakout and test, but I'm not sure how much more that is going to tell us that the SK doesn't.

I did also try using CSECMD, but it makes no difference.

The two examples in Harmony I could find for the SK don't do any oscillator switching.

It does seem to work perfectly well in non-debug mode. Essentially, it suggests that if you clock switch this part, you can't use a debugger with it.

I am pretty confident this is either a silicon bug or something wrong with the debugger software interface. I tried the SK both with the PKOB and a RealICE through an I/O expansion baord, same problem.

As such, unless there is something "special" about this chip I've not noticed, I'm now fairly confident the OP has found a silicon bug.

Edit: CF bit is NOT set when it breaks.
« Last Edit: March 15, 2018, 07:28:27 pm by Howardlong »
 

Online NorthGuy

  • Super Contributor
  • ***
  • Posts: 3146
  • Country: ca
Re: How do i switch clock in a PIC32MX? (AKA:why doesn't it switch)
« Reply #12 on: March 16, 2018, 04:17:06 am »
The debugger for these has the "Break on clock mode switch" settings. May be you just have this ticked? Click on breakpoints, then select an "Event" breakpoint and this setting is right there.

Even if you don't have it ticked, chances are there's a bug in the debugger which activates the event anyway.
 

Offline Howardlong

  • Super Contributor
  • ***
  • Posts: 5319
  • Country: gb
Re: How do i switch clock in a PIC32MX? (AKA:why doesn't it switch)
« Reply #13 on: March 16, 2018, 06:11:50 am »
There are no event breakpoints selected.

Seems possible, although when it breaks, the clock switch doesn't happen either.

I tried with an ICD 4, same problem, although this debugger has a ton of other issues!
 

Online JPorticiTopic starter

  • Super Contributor
  • ***
  • Posts: 3461
  • Country: it
Re: How do i switch clock in a PIC32MX? (AKA:why doesn't it switch)
« Reply #14 on: March 16, 2018, 06:54:59 am »
No, there is something wrong, I have the same problem with a PIC32MX570F512L on the PIC32MX1/2/5 SK.

It breakpoints unexpectedly at the

Code: [Select]
  while (OSCCONbits.OSWEN);

I'm fiddling with it now.

 :popcorn:
I always tell myself i can't be the first one that did this, so it must be a problem on my side. most of the time it's true.
one of the things i wanted to try today was if the PK3 and ICD3 would behave differently but apparently there is a bigger problem.
PIC32MX2xx and 5xx only difference is the presence of CANbus, but i don't know how it can make a difference.

The debugger for these has the "Break on clock mode switch" settings. May be you just have this ticked? Click on breakpoints, then select an "Event" breakpoint and this setting is right there.

Even if you don't have it ticked, chances are there's a bug in the debugger which activates the event anyway.

I'm not sure of it, because if i cause a clock fail event the clock switches, but the debugger doesn't halt in that moment. it halts when i manually switch.

Things i want to try today:
- The sample code worked (in run mode) if i polled the FSCM bit. I'll try using the interrupt and seeing if it changes. EDIT: IT DOES. Works in interrupt mode.
- If i get it to work, port it to the main application where the current code doesn't work. EDIT: See Below It *works*. Clock switching happens. However POSC isn't shut down. Probably because USB PLL can't be disabled in software
- check if there are related debugger settings and check if PK3 behaves differently EDIT: IT DOESN'T

Latest Edit: I can confirm that the code Works in run mode now.
-I can perform a switch, but not while debugging.
-Posc is not being shut down because the USB module is ON and of course the USB PLL is active, regardless of the UFRCEN bit in OSCCON
-If i comment out the USB initialization routine Posc is shut down after the clock switch.
-The USB clock change happens like this
    USUSPEND bit Set ( "The 48 MHz USB clock will be gated off. The transceiver is placed in a low-power state." )
    UFRCEN bit is Set
    Clock Switch is performed
    USUSPEND bit is Cleared
-If i attach a usb cable after the clock switch the device doesn't get recognized. hoped the device would be recognized as LS, but i haven't looked into it yet.

I shall open a ticket and point them to this thread, maybe they can tell me why clock switch doesn't work while debugging, but it works for other variant of what probably is the same silicon
« Last Edit: March 16, 2018, 10:25:37 am by JPortici »
 

Offline Howardlong

  • Super Contributor
  • ***
  • Posts: 5319
  • Country: gb
Re: How do i switch clock in a PIC32MX? (AKA:why doesn't it switch)
« Reply #15 on: March 16, 2018, 10:30:57 am »
Here is my ab-initio code to reproduce the problem on the SK.

The only time it doesn't break is when NOSC==COSC.

Code: [Select]

// PIC32MX570F512L Configuration Bit Settings

// 'C' source line config statements

// DEVCFG3
// USERID = No Setting
#pragma config PMDL1WAY = OFF           // Peripheral Module Disable Configuration (Allow multiple reconfigurations)
#pragma config IOL1WAY = OFF            // Peripheral Pin Select Configuration (Allow multiple reconfigurations)
#pragma config FUSBIDIO = OFF           // USB USID Selection (Controlled by Port Function)
#pragma config FVBUSONIO = OFF          // USB VBUS ON Selection (Controlled by Port Function)

// DEVCFG2
#pragma config FPLLIDIV = DIV_2         // PLL Input Divider (2x Divider)
#pragma config FPLLMUL = MUL_20         // PLL Multiplier (20x Multiplier)
#pragma config UPLLIDIV = DIV_2         // USB PLL Input Divider (2x Divider)
#pragma config UPLLEN = OFF             // USB PLL Enable (Disabled and Bypassed)
#pragma config FPLLODIV = DIV_256       // System PLL Output Clock Divider (PLL Divide by 256)

// DEVCFG1
#pragma config FNOSC = FRCDIV           // Oscillator Selection Bits (Fast RC Osc w/Div-by-N (FRCDIV))
#pragma config FSOSCEN = OFF            // Secondary Oscillator Enable (Disabled)
#pragma config IESO = OFF               // Internal/External Switch Over (Disabled)
#pragma config POSCMOD = OFF            // Primary Oscillator Configuration (Primary osc disabled)
#pragma config OSCIOFNC = OFF           // CLKO Output Signal Active on the OSCO Pin (Disabled)
#pragma config FPBDIV = DIV_1           // Peripheral Clock Divisor (Pb_Clk is Sys_Clk/1)
#pragma config FCKSM = CSECMD           // Clock Switching and Monitor Selection (Clock Switch Enable, FSCM Disabled)
#pragma config WDTPS = PS1048576        // Watchdog Timer Postscaler (1:1048576)
#pragma config WINDIS = OFF             // Watchdog Timer Window Enable (Watchdog Timer is in Non-Window Mode)
#pragma config FWDTEN = OFF             // Watchdog Timer Enable (WDT Disabled (SWDTEN Bit Controls))
#pragma config FWDTWINSZ = WINSZ_25     // Watchdog Timer Window Size (Window Size is 25%)

// DEVCFG0
#pragma config JTAGEN = OFF             // JTAG Enable (JTAG Disabled)
#pragma config ICESEL = ICS_PGx2        // ICE/ICD Comm Channel Select (Communicate on PGEC2/PGED2)
#pragma config PWP = OFF                // Program Flash Write Protect (Disable)
#pragma config BWP = OFF                // Boot Flash Write Protect bit (Protection Disabled)
#pragma config CP = OFF                 // Code Protect (Protection Disabled)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>

#define NEWOSC 0b000

/* From DS60001290E page 78
NOSC<2:0>: New Oscillator Selection bits
111 = Internal Fast RC Oscillator (FRC) divided by OSCCON<FRCDIV> bits
110 = Internal Fast RC Oscillator (FRC) divided by 16
101 = Internal Low-Power RC (LPRC) Oscillator
100 = Secondary Oscillator (SOSC)
011 = Primary Oscillator with PLL module (XTPLL, HSPLL or ECPLL)
010 = Primary Oscillator (XT, HS or EC)
001 = Internal Fast Internal RC Oscillator with PLL module via Postscaler (FRCPLL)
000 = Internal Fast Internal RC Oscillator (FRC)
On Reset, these bits are set to the value of the FNOSC Configuration bits (DEVCFG1<2:0>)
*/

static unsigned int _nExceptionCode;
static unsigned int _nExceptionAddr;

void __attribute__ ((nomips16)) _general_exception_handler(void)
{
asm volatile("mfc0 %0,$13":"=r" (_nExceptionCode));
asm volatile("mfc0 %0,$14":"=r" (_nExceptionAddr));

    while (1)
    {
        Nop();
    }
}

int main(void)
{
    SYSKEY=0;
    SYSKEY=0xAA996655;
    SYSKEY=0x556699AA;
   
    OSCCONbits.NOSC=NEWOSC;
   
    OSCCONbits.OSWEN=1;
   
    SYSKEY=0x33333333;

    Nop(); // <--- breakpoints here
    Nop();
    Nop();
    Nop();
    Nop();
    Nop();
   
    while (OSCCONbits.OSWEN!=0)
    {
        Nop();
    }
   
    while (1)
    {
        Nop();
    }
    return 0;
}
 

Online JPorticiTopic starter

  • Super Contributor
  • ***
  • Posts: 3461
  • Country: it
Re: How do i switch clock in a PIC32MX? (AKA:why doesn't it switch)
« Reply #16 on: March 16, 2018, 12:40:32 pm »
On a related note:
Quote from: PIC32MX Manual, Chapter 27.4.4.4: Clock Requirements
The USB OTG module can also use the on-board Fast RC oscillator (FRC) as a clock source.
When using this clock source, the USB OTG module will not meet the USB timing requirements.
The FRC clock source is intended to allow the USB OTG module to detect a USB wake-up and
report it to the interrupt controller when operating in low-power modes. The USB OTG module
must be running from the Primary oscillator before beginning USB transmissions

Oh well, no usb during faults. Understood.
 

Offline Howardlong

  • Super Contributor
  • ***
  • Posts: 5319
  • Country: gb
Re: How do i switch clock in a PIC32MX? (AKA:why doesn't it switch)
« Reply #17 on: March 16, 2018, 02:00:06 pm »
On a related note:
Quote from: PIC32MX Manual, Chapter 27.4.4.4: Clock Requirements
The USB OTG module can also use the on-board Fast RC oscillator (FRC) as a clock source.
When using this clock source, the USB OTG module will not meet the USB timing requirements.
The FRC clock source is intended to allow the USB OTG module to detect a USB wake-up and
report it to the interrupt controller when operating in low-power modes. The USB OTG module
must be running from the Primary oscillator before beginning USB transmissions

Oh well, no usb during faults. Understood.

In my first PIC32MX230F064B design a few years ago, I discounted using the FRC for USB, not only would it be out of spec for FS, but there's no documented way to wire it internally to the 48MHz USB PLL, I assume that's for a reason. (It's a shame because a few PICs like the pic24fj32gb002 do have internal FRCs good enough for USB use).

 

Online JPorticiTopic starter

  • Super Contributor
  • ***
  • Posts: 3461
  • Country: it
Re: How do i switch clock in a PIC32MX? (AKA:why doesn't it switch)
« Reply #18 on: March 16, 2018, 02:27:11 pm »
I wouldn't have said no to LS USB.
More recent parts do come with crystal-less usb.
 

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 826
Re: How do i switch clock in a PIC32MX? (AKA:why doesn't it switch)
« Reply #19 on: March 16, 2018, 03:29:04 pm »
Quote
but there's no documented way to wire it internally to the 48MHz USB PLL
See my previous post.

The part I was using was a MX250, and maybe it has a better frc than the part you are using, but I couldn't get the usb to fail.
 

Offline Howardlong

  • Super Contributor
  • ***
  • Posts: 5319
  • Country: gb
Re: How do i switch clock in a PIC32MX? (AKA:why doesn't it switch)
« Reply #20 on: March 16, 2018, 04:04:20 pm »
Quote
but there's no documented way to wire it internally to the 48MHz USB PLL
See my previous post.

The part I was using was a MX250, and maybe it has a better frc than the part you are using, but I couldn't get the usb to fail.

Indeed, I am sure it does work... sometimes, as a bit of a hack. It's not something I'd consider recommending for a production product though. I remember spending some time investigating doing just that, but I didn't want to risk the enormous cost of 10k returned units for the price of a 10c crystal (actually in my case, it wasn't even that, I used an existing unused onboard clock distribution output with a TCXO reference).

[FWIW, there are two MX250s, the 28-44 pinners, and the 64-100 pinners. (It looks like the problem we are seeing is only on the 64-100 pinners)]
 

Online JPorticiTopic starter

  • Super Contributor
  • ***
  • Posts: 3461
  • Country: it
Re: How do i switch clock in a PIC32MX? (AKA:why doesn't it switch)
« Reply #21 on: March 16, 2018, 06:40:25 pm »
besides, i'm not even sure if i'll use USB in the end.
I'm using this board as a training ground on USB (on dsPIC/PIC32) SD Card and FAT Filesystem.

But given the fact that the average target user is probably going to have a smartphone at hand rather than a computer (and we will put a BLE module) we may get to remove USB completely and scale back to a dsPIC or another MCU that get in a smaller package, but still with CAN, SPI, 2x UART and possibly RTCC (much wider selection).
Add another bonus, the bootloader is easier to implement!
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf