I got a PIC24EP128MC206 because of its rated speed of 70 MIPS. (For whatever reason, it is rated in MIPS, while most other PIC24s are rated in MHz.)
Since my understanding is that one instruction on the PIC24 takes one Fcy clock cycle, I am trying to configure the clock so Fcy is as close to 70 MHz as possible. However it seems I can only run it at about half the rated speed -- around 31.5 MHz. Anything higher than that, and the PLL stops doing its thing.
I am using the internal FRC clock, since I don't need exact timing anywhere (not using UARTs for example). The nominal FRC frequency is 7.37 MHz, which can be adjusted from 6.52 MHz to 8.20 MHz using the OSCTUN register.
As a reference, I am using the PIC24EPXXXGP/MC20X datasheet. Here is the relevant section on setting up the clock:
and here is my setup code:
// configuration fuses for PIC24EP128MC206
_FICD( ICS_PGD1 & JTAGEN_OFF )
_FWDT( FWDTEN_OFF )
_FOSC( POSCMD_NONE & OSCIOFNC_OFF & IOL1WAY_ON & FCKSM_CSECME )
_FOSCSEL( FNOSC_FRC & IESO_ON )
_FGS( GWRP_OFF & GCP_OFF )
int main(void)
{
RCONbits.SWDTEN = 0; // Disable Watch Dog Timer
// configure Oscillator
// Fosc= Fin*M/(N1*N2), Fcy=Fosc/2
// with default 7.37 MHz FRC clk, Fcy = approx 7.37*34/(2*2*2) = 31.3 MHz
PLLFBD = 32; // M=34 (ANYTHING HIGHER DOESN'T WORK)
CLKDIVbits.PLLPRE = 0; // N1=2
CLKDIVbits.PLLPOST = 0; // N2=2
__builtin_write_OSCCONH(0x01); // set up to switch to FRC+PLL
__builtin_write_OSCCONL(OSCCON | 0x01); // do the switch
while(OSCCONbits.COSC != 0x00); // wait for switch to take place
while(OSCCONbits.LOCK != 1){ }; // wait for PLL lock
Fsys = 34*7.37/2 = 125.29 which is near but not below the acceptable range of 120 to 340 MHz.
With the values show above the clock works and I get a nice output of around 31.5 MHz as measured using the CLKO pin (which is the same as Fcy, the instruction cycle clock). The 31.5 MHz compares well with my calculated value of 31.3 MHz above, given that the 7.37 MHz FRC clock may be off somewhat.
I would like to use an M value of 76, which would give me an instruction cycle time of 70 MHz.
But if I make the value of M any higher than 34, the PLL becomes unstable and the clock output reverts to around 3.70 MHz, which is half of the FRC frequency (implying the PLL circuit is out of the picture). When it is running, I can sometimes see some flashes of the higher frequency on the scope, as if the PLL is trying to start up and can't stabilize. As one can see from my code sample, I am waiting for the PLL lock before continuing.
UPDATE: This seems somehow related to the final frequency, not the PLL Fsys frequency. I tried the following combination and it also worked:
PLLFBD = 120; // M=122 (ANYTHING HIGHER DOESN'T WORK)
CLKDIVbits.PLLPRE = 1; // N1=3
CLKDIVbits.PLLPOST = 0; // N2=4
which results in a PLL frequency of 300 MHz a Fcyc of 37.46 MHz (measured, 37.7).
I was a little concerned maybe you couldn't run at 70 MIPS using the internal FRC, but the datasheet for the PIC24E oscillator says "the FRC postscaler output can be used with the internal PLL to boost the system frequency (FOSC) up to 140 MHz for 70 MIPS instruction cycle execution." so I'm not trying to do the impossible.
Another UPDATE: I tried a second board and got the same results -- I can't seem to set Fcy to a frequency higher than 40 MHz without the PLL dropping out. I also tried hooking up a buffered 24 MHz clock into OSC1 and configuring the system to use that as a extral clock (EC) with PLL. Exactly same results.
How can I get a faster clock to work?
FINAL UPDATE: Turns out that the person doing the board layout put a 0.1 uF cap on VCAP without looking at the datasheet and I never caught it either. I swapped that out with a 10 uF 16v low ESR (datasheet called for 4.7 uF or higher) and now I can run at 70 MIPS. See accepted answer re how I found this was the problem.