PIC24 Support Libraries
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pic24_clockfreq.c
Go to the documentation of this file.
1 /*
2  * "Copyright (c) 2008 Robert B. Reese, Bryan A. Jones, J. W. Bruce ("AUTHORS")"
3  * All rights reserved.
4  * (R. Reese, reese_AT_ece.msstate.edu, Mississippi State University)
5  * (B. A. Jones, bjones_AT_ece.msstate.edu, Mississippi State University)
6  * (J. W. Bruce, jwbruce_AT_ece.msstate.edu, Mississippi State University)
7  *
8  * Permission to use, copy, modify, and distribute this software and its
9  * documentation for any purpose, without fee, and without written agreement is
10  * hereby granted, provided that the above copyright notice, the following
11  * two paragraphs and the authors appear in all copies of this software.
12  *
13  * IN NO EVENT SHALL THE "AUTHORS" BE LIABLE TO ANY PARTY FOR
14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
15  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE "AUTHORS"
16  * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17  *
18  * THE "AUTHORS" SPECIFICALLY DISCLAIMS ANY WARRANTIES,
19  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21  * ON AN "AS IS" BASIS, AND THE "AUTHORS" HAS NO OBLIGATION TO
22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
23  *
24  * Please maintain this header in its entirety when copying/modifying
25  * these files.
26  *
27  *
28  */
29 
30 
31 
32 // Documentation for this file. If the \file tag isn't present,
33 // this file won't be documented.
34 /** \file
35  * Configure and possibly switch the processor clock to the
36  * desired frequency, based on selections made in
37  * pic24_clockfreq.h. Each entry in the \ref CLOCK_CONFIG
38  * table should have a corresponding block of code in this
39  * file to configure the clock. Typical code structure is:
40  *
41  * \code
42 #if IS_CLOCK_CONFIG(FRCPLL_FCY16MHz)
43 #warning Clock configured for FRCPLL, FCY = 16 MHz
44 #endif
45 #if GET_IS_SUPPORTED(FRCPLL_FCY16MHz)
46 void configClockFRCPLL_FCY16MHz(void) {
47  ... code to configure this clock ...
48  // Typically, after setup code above, swtich to
49  // the newly configured oscillator.
50  switchClock(OSC_SEL_BITS);
51 }
52 #endif
53  * \endcode
54  *
55  * Notes: is some modes, the configuration bit settings suggest
56  * that a clock switch unnecessary. For example, FNOSC_PRI
57  * or FNOSC_FRC should require no clock switching. However, if
58  * this was run from a bootloader, it may switch the clock away
59  * from the settings determined by the configuration bits,
60  * so a switch is still performed.
61  * Likewise, in the PIC24F/H modes that use the PLL, the bootloader
62  * could be using the PLL. In this can, PLL settings can't be
63  * changed. So, the code switches to the FRC, changes PLL bits
64  * (when it's guaranteed to be safe), then switch back to the PLL.
65  */
66 
67 #include "pic24_clockfreq.h"
68 #include "pic24_util.h"
69 #include "pic24_serial.h"
70 #include "pic24_unittest.h"
71 
72 #if !USE_CLOCK_TIMEOUT
73 //empty functions
74 void checkClockTimeout(void) {
75 }
76 #else
77 /*
78 The purpose of the clock timeout functions is
79 output a meaningful error in case the clock switch
80 does not occur.
81 
82 */
83 #define CLOCKTIMEOUT_MAX 200000L
84 #if ( defined(__PIC24H__) || defined(__dsPIC33F__) )
85 #define FRC_FCY 40000000L
86 #elif ( defined(__PIC24F__) || defined(__PIC24FK__) )
87 #define FRC_FCY 16000000L
88 #elif ( defined(__PIC24E__) || defined(__dsPIC33E__) )
89 #define FRC_FCY 60000000L
90 #else
91 #error Unknown processor.
92 #endif
93 #define FRC_BRGH 0
94 
95 
96 static void configFrcUART(void) {
97  float f_brg;
98  uint16_t UxBRG;
99  // First, switch to a known-good clock
100 #if ( defined(__PIC24H__) || defined(__dsPIC33F__) )
101  configClockFRCPLL_FCY40MHz();
102 #elif ( defined(__PIC24E__) || defined(__dsPIC33E__) )
103  configClockFRCPLL_FCY60MHz();
104 #elif ( defined(__PIC24F__) || defined(__PIC24FK__) )
105 //safe choice: FCY=16 MHz, FRC+PLL
106  configClockFRCPLL_FCY16MHz();
107 #else
108 #error Unknown processor
109 #endif
110 
111  // Second, get UART I/O pins mapped and general config done.
113  // BRG register is probably wrong since not using defined FCY. Fix it.
114 #if (FRC_BRGH == 0)
115  f_brg = (((float) FRC_FCY)/((float) DEFAULT_BAUDRATE)/16.0) - 1.0;
116 #else
117  f_brg = (((float) FRC_FCY)/((float) DEFAULT_BAUDRATE)/4.0) - 1.0;
118 #endif
119  UxBRG = roundFloatToUint16(f_brg);
120  switch (DEFAULT_UART) {
121 #if (NUM_UART_MODS >= 1)
122  case 1 :
123  U1BRG = UxBRG;
124  U1MODEbits.BRGH = FRC_BRGH;
125  break;
126 #endif
127 #if (NUM_UART_MODS >= 2)
128  case 2 :
129  U2BRG = UxBRG;
130  U2MODEbits.BRGH = FRC_BRGH;
131  break;
132 #endif
133 #if (NUM_UART_MODS >= 3)
134  case 3 :
135  U3BRG = UxBRG;
136  U3MODEbits.BRGH = FRC_BRGH;
137  break;
138 #endif
139 #if (NUM_UART_MODS >= 4)
140  case 4 :
141  U4BRG = UxBRG;
142  U4MODEbits.BRGH = FRC_BRGH;
143  break;
144 #endif
145  default :
146  ASSERT(0);
147  }
148 }
149 
150 static void checkClockTimeout(void) {
151  static uint32_t u32_timeoutCount = 0;
152 
153  // See if the clock has already failed. If so, return to allow
154  // diagnostic code to perform (hopefully safe) clock switches
155  // in order to report errors.
156  if (u32_timeoutCount == 0xFFFFFFFF) return;
157 
158  // Otherwise, update timeout. If we the switch hasn't failed,
159  // simple return to wait for the switch a bit more.
160  u32_timeoutCount++;
161  if (u32_timeoutCount < CLOCKTIMEOUT_MAX) return;
162 
163  // Clock switch failed. Mark this in the timeout.
164  u32_timeoutCount = 0xFFFFFFFF;
165 
166  configFrcUART();
167  outString("\n\n"
168  "Your clock choice failed to initialize, have switched to internal Fast RC oscillator +PLL.\n"
169  "Check your setting for the 'CLOCK_CONFIG' macro.\n"
170  "Watch the compiler output window when pic24_clockfreq.c is compiled, a warning message\n"
171  "will tell you the selected value for 'CLOCK_CONFIG'.\n"
172  "In MPLAB, use Project->Build Options->Project, then click on MPLAB C30 tab to see if \n"
173  "the macro is defined there. If the macro is selecting an external crystal (the primary oscillator),\n"
174  "and your board does not have a crystal, you will get this message.\n"
175  "Delete the macro definition from the MPLAB project if you want to use the default \n"
176  "clock choice of FRC + PLL.\n"
177  "You must recompile and reprogram with an appropriate CLOCK_CONFIG choice for this code to execute.\n");
178 
179  while(1) {
180  doHeartbeat(); // never return.
181  }
182 }
183 #endif
184 
185 
186 void switchClock(uint8_t u8_source) {
187  // Create a union that mirrors the OSCCON structure
188  // with all its bit names but is also byte-accessable.
189  OSCCONBITS OSCCONBITS_copy;
190 
191  // Switch clock to use new choice specified by u8_choice.
192  // Valid values are 0-7.
193  // Throw an error if the source isn't in the list above.
194  ASSERT(u8_source < 8);
195  // 1. Disable interrupts per 7.11.2 FRM rev B under
196  // "A recommended code sequence for a clock switch
197  // includes the following:" heading.
198  // Assumes there are no priority 7 interrupts enabled.
199  asm("DISI #0x3FFF"); // Disable interrupts for a long time
200  // 2. Switch to the PLL. Use compiler built-ins to unlock
201  // clock switch registers. See 7.11.1 of the FRM rev B.
202  OSCCONBITS_copy = OSCCONbits; // Copy OSCCON bits
203  OSCCONBITS_copy.NOSC = u8_source; // Select new clock source
204  OSCCONBITS_copy.OSWEN = 1; // Request clock switch
205  // First write high byte, containing new clock source NOSC
206  __builtin_write_OSCCONH(BITS2BYTEH(OSCCONBITS_copy));
207  // Then write low byte, requesting clock switch with OSWEN
208  __builtin_write_OSCCONL(BITS2BYTEL(OSCCONBITS_copy));
209  asm("DISI #0"); // Re-enable them at the next instruction
210 
211 #ifndef SIM
212  // 3. Wait for switch to complete.
213  // Note that oscillator switching is not supported by
214  // the simulator, causing the statements below to
215  // run forever.
216  while (_OSWEN == 1) {
217  checkClockTimeout();
218  }
219 
220  // 4. Wait for the PLL to lock if using the PLL.
221  // (Is this really necessary? It certainly can't hurt.)
222  if ( (u8_source == GET_OSC_SEL_BITS(FNOSC_FRCPLL)) ||
223  (u8_source == GET_OSC_SEL_BITS(FNOSC_PRIPLL)) ) {
224  while (_LOCK == 0) {
225  checkClockTimeout();
226  }
227  }
228 
229  // 5. Make sure clock switch worked
230  while (_COSC != u8_source) checkClockTimeout();
231 #endif
232 }
233 
234 #if IS_CLOCK_CONFIG(SIM_CLOCK)
235 #warning Clock configured for simulation, FCY = 1 Mhz
236 #endif
237 #if GET_IS_SUPPORTED(SIM_CLOCK)
238 void configClockSim(void) { }
239 #endif
240 
241 
242 #if IS_CLOCK_CONFIG(FRCPLL_FCY16MHz)
243 #warning Clock configured for FRCPLL, FCY = 16 MHz
244 #endif
245 #if GET_IS_SUPPORTED(FRCPLL_FCY16MHz)
246 void configClockFRCPLL_FCY16MHz(void) {
247  // To be safe: if this was run by a bootloader that chose FRCPLL mode,
248  // then we can't change the bits below. To do so, first switch to FRC,
249  // change bits, then switch back to FRCPLL.
250  switchClock(GET_OSC_SEL_BITS(FNOSC_FRC));
251  // Two cases:
252  // 1. Non-USB parts just have a FRC postscaler that feeds
253  // the 4x PLL block. Set this postscaler to 1 since the
254  // FRC runs at 8 MHz to get a 32 MHz FOSC = 16 MHz FCY.
255  _RCDIV = 0;
256 #ifdef _CPDIV
257  // The PLL multiplies this 4 MHz input to 96 MHz then
258  // divides it by 3 to 32 MHz. A second PLL prescaler
259  // then selects the final FOSC. Choose a prescale of
260  // 1 so FOSC = 32 MHz, giving FCY = 16 MHz.
261  _CPDIV = 0; // 0 means a prescale of 1
262 #endif
263 #ifdef _PLLDIV
264  // 2. USB parts have a more complex clocking scheme. The
265  // FRC postscaler feeds a PLL prescaler rather than
266  // directly determining FOSC. The
267  // PLL input must be 4 MHz, so choose a PLL prescaler
268  // of 2 since the FRC runs at 8 MHz.
269  _PLLDIV = 1; // 1 means a prescale of 2
270 #elif defined(PLLDIV_NODIV)
271 #warning Ensure that the PLLDIV value is set to divide by 2 in the configuration bits for FRCPLL_FCY16MHz clock option!!
272 #endif
273 #ifdef _PLLEN
274  _PLLEN = 1;
275 #warning PLL Enabled
276 #endif
277  switchClock(GET_OSC_SEL_BITS(FNOSC_FRCPLL));
278 }
279 #endif
280 
281 
282 #if IS_CLOCK_CONFIG(FRC_FCY4MHz)
283 #warning Clock configured for FRC, FCY = 4 MHz.
284 #warning Baud rates of 19200 or lower recommended for this clock choice.
285 #endif
286 #if GET_IS_SUPPORTED(FRC_FCY4MHz)
287 void configClockFRC_FCY4MHz(void) {
288  // Ensure that the FRC postscaler is at '1' and not its reset default of '2' (PIC24F family)
289  _RCDIV = 0;
290  switchClock(GET_OSC_SEL_BITS(FNOSC_FRC));
291 }
292 #endif
293 
294 
295 #if IS_CLOCK_CONFIG(PRI_NO_PLL_7372KHzCrystal)
296 #warning Clock configured for a 7.372 MHz crystal primary oscillator, no PLL
297 #endif
298 #if GET_IS_SUPPORTED(PRI_NO_PLL_7372KHzCrystal)
299 void configClockPRI_NO_PLL_7372KHzCrystal(void) {
300  switchClock(GET_OSC_SEL_BITS(FNOSC_PRI));
301 }
302 #endif
303 
304 
305 #if IS_CLOCK_CONFIG(FRC_FCY3685KHz)
306 #warning Clock configured for FRC, FCY = 3.685 MHz
307 #warning Baud rates of 9600 or lower recommended for this clock choice.
308 #endif
309 #if GET_IS_SUPPORTED(FRC_FCY3685KHz)
310 void configClockFRC_FCY3685KHz(void) {
311  switchClock(GET_OSC_SEL_BITS(FNOSC_FRC));
312  // Choose no tuning on FRC to get 7.37 MHz nominal FOSC.
313  // Do after clock switch in case FRCPLL was in use, since
314  // that would alter PLL input frequency. (Might be OK, but
315  // this is perhaps safer.)
316  _TUN = 0;
317 }
318 #endif
319 
320 
321 #if IS_CLOCK_CONFIG(FRCPLL_FCY40MHz)
322 #warning Clock configured for FRCPLL, FCY = 40 MHz
323 #endif
324 #if GET_IS_SUPPORTED(FRCPLL_FCY40MHz)
325 void configClockFRCPLL_FCY40MHz(void) {
326  // To be safe: if this was run by a bootloader that chose FRCPLL mode,
327  // then we can't change the bits below. To do so, first switch to FRC,
328  // change bits, then switch back to FRCPLL.
329  switchClock(GET_OSC_SEL_BITS(FNOSC_FRC));
330  //settings for Cycle time = 40 MHz, internal oscillator with PLL
331  // Tune the internal oscialltor to 6.85 MHz. Each unit
332  // in the register below = 0.375% of the 7.37 MHz
333  // nominal frequency in 2's complement per register 7-6
334  // in section 7.4 of the FRM rev B. So:
335  // Sanity check: -32*0.375% = -12% -> 6.4856 MHz per data sheet.
336  // +30*0.375% = 11.25% -> 8.1991 Mhz not 8.23 MHz
337  // given in the data sheet!
338  // However, +31*0.375% = 11.625% -> 8.2268 MHz, so the above
339  // is a typo. This error has been reported to Microchip and
340  // confirmed. It should be fixed in next rev of data sheet.
341  // Another concern: since the clock is +/- 2%, we could end
342  // up with a > 8.0 MHz processor clock! At 8 MHz, this would
343  // be 8.16 MHz, so the processor would run at 81.6 MHz.
344  // Ignore this for now; probably, the chip will still run.
345 
346  _TUN = -19; // Correct setting assuming the RC oscillator is exactly 7.37MHz.
347  // It may need to be tweaked however. Use the echo.c program, and a baud rate
348  // of 115,200 and increase/decrease TUN until you get no framing errors
349 
350  // Choose PLL factors: Fref after first prescale must be
351  // between 0.8 and 8.0 MHz. Choose a prescale of 8
352  // for Fref of 0.856 MHz.
353  _PLLPRE = 6; // Prescale = PLLPRE + 2
354  // Fvco after multiply must be between 100 and 200 MHz.
355  // Pick 160 MHz, so multiply by 187.
356  _PLLDIV = 185; // Multiply = PLLDIV + 2
357  // Final desired Fosc = 80 MHz for an Fcy = 40 MHz.
358  // (See 7.7 of the FRM rev B). Pick 80 MHz, so postscale by 2.
359  _PLLPOST = 0; // Postscale = 2 * (PLLPOST + 1)
360  switchClock(GET_OSC_SEL_BITS(FNOSC_FRCPLL));
361 }
362 #endif
363 
364 #if IS_CLOCK_CONFIG(FRCPLL_FCY60MHz)
365 #warning Clock configured for FRCPLL, FCY = 60 MHz
366 #endif
367 #if GET_IS_SUPPORTED(FRCPLL_FCY60MHz)
368 void configClockFRCPLL_FCY60MHz(void) {
369  // To be safe: if this was run by a bootloader that chose FRCPLL mode,
370  // then we can't change the bits below. To do so, first switch to FRC,
371  // change bits, then switch back to FRCPLL.
372  switchClock(GET_OSC_SEL_BITS(FNOSC_FRC));
373 
374  _TUN = 0; // Correct setting assuming the RC oscillator is exactly 7.37MHz.
375  // It may need to be tweaked however. Use the echo.c program, and a baud rate
376  // of 115,200 and increase/decrease TUN until you get no framing errors
377 
378  // For PIC24E Family, Fref must be
379  // between 3 MHz and 5.5 MHz. Choose a prescale of 2
380  // for Fref of 3.685 MHz.
381  _PLLPRE = 0; // Prescale = PLLPRE + 2
382  // Fvco after multiply must be between 120 and 340 MHz.
383  // Pick 240 MHz, so multiply by 65.
384  _PLLDIV = 63; // Multiply = PLLDIV + 2
385  // Final desired Fosc = 120 MHz for an Fcy = 60 MHz.
386  // Pick 120 MHz, so postscale by 2.
387  _PLLPOST = 0; // Postscale = 2 * (PLLPOST + 1)
388  switchClock(GET_OSC_SEL_BITS(FNOSC_FRCPLL));
389 }
390 #endif
391 
392 #if IS_CLOCK_CONFIG(FRCPLL_FCY70MHz)
393 #warning Clock configured for FRCPLL, FCY = 70 MHz
394 #endif
395 #if GET_IS_SUPPORTED(FRCPLL_FCY70MHz)
396 void configClockFRCPLL_FCY70MHz(void) {
397  // To be safe: if this was run by a bootloader that chose FRCPLL mode,
398  // then we can't change the bits below. To do so, first switch to FRC,
399  // change bits, then switch back to FRCPLL.
400  switchClock(GET_OSC_SEL_BITS(FNOSC_FRC));
401 
402  _TUN = 0; // Correct setting assuming the RC oscillator is exactly 7.37MHz.
403  // It may need to be tweaked however. Use the echo.c program, and a baud rate
404  // of 115,200 and increase/decrease TUN until you get no framing errors
405 
406  // For PIC24E Family, Fref must be
407  // between 3 MHz and 5.5 MHz. Choose a prescale of 2
408  // for Fref of 3.685 MHz.
409  _PLLPRE = 0; // Prescale = PLLPRE + 2
410  // Fvco after multiply must be between 120 and 340 MHz.
411  // Pick 280 MHz, so multiply by 76.
412  _PLLDIV = 74; // Multiply = PLLDIV + 2
413  // Final desired Fosc = 140 MHz for an Fcy = 70 MHz.
414  // Pick 140 MHz, so postscale by 2.
415  _PLLPOST = 0; // Postscale = 2 * (PLLPOST + 1)
416  switchClock(GET_OSC_SEL_BITS(FNOSC_FRCPLL));
417 }
418 #endif
419 
420 
421 
422 #if IS_CLOCK_CONFIG(PRIPLL_7372KHzCrystal_40MHzFCY)
423 #warning Clock configured for PRIPLL using a 7.3727 Mhz primary oscillator, FCY = 40 MHz
424 #endif
425 #if GET_IS_SUPPORTED(PRIPLL_7372KHzCrystal_40MHzFCY)
426 void configClockPRIPLL_7372KHzCrystal_40MHzFCY(void) {
427  // To be safe: if this was run by a bootloader that chose PRIPLL mode,
428  // then we can't change the bits below. To do so, first switch to FRC,
429  // change bits, then switch back to PRIPLL.
430  switchClock(GET_OSC_SEL_BITS(FNOSC_FRC));
431  //settings for Cycle time = 40 MHz, primary oscillator with PLL
432  _PLLPRE = 4; // Prescale = PLLPRE + 2
433  _PLLDIV = 128; // Multiply = PLLDIV + 2
434  _PLLPOST = 0; // Postscale = 2 * (PLLPOST + 1)
435  switchClock(GET_OSC_SEL_BITS(FNOSC_PRIPLL));
436 }
437 #endif
438 
439 #if IS_CLOCK_CONFIG(PRIPLL_8MHzCrystal_40MHzFCY)
440 #warning Clock configured for PRIPLL using an 8.0 Mhz primary oscillator, FCY = 40 MHz
441 #endif
442 #if GET_IS_SUPPORTED(PRIPLL_8MHzCrystal_40MHzFCY)
443 void configClockPRIPLL_8MHzCrystal_40MHzFCY(void) {
444  //settings for Cycle time = 40 MHz, primary oscillator with PLL
445  //These PLL settings will give an FCY == Crystal Freq * 10/2, or FOSC = Crystal Freq * 10
446  /*
447  This settings assumes the external crystal on is 8.0MHz
448  */
449  // To be safe: if this was run by a bootloader that chose PRIPLL mode,
450  // then we can't change the bits below. To do so, first switch to FRC,
451  // change bits, then switch back to PRIPLL.
452  switchClock(GET_OSC_SEL_BITS(FNOSC_FRC));
453  _PLLPRE = 0; // Prescale = PLLPRE + 2
454  _PLLDIV = 38; // Multiply = PLLDIV + 2
455  _PLLPOST = 0; // Postscale = 2 * (PLLPOST + 1)
456  switchClock(GET_OSC_SEL_BITS(FNOSC_PRIPLL));
457 }
458 #endif
459 
460 #if IS_CLOCK_CONFIG(PRIPLL_8MHzCrystal_16MHzFCY)
461 #warning Clock configured for PRIPLL using a 8.0 Mhz primary oscillator, FCY = 16 MHz
462 #endif
463 #if GET_IS_SUPPORTED(PRIPLL_8MHzCrystal_16MHzFCY)
464 void configClockPRIPLL_8MHzCrystal_16MHzFCY(void) {
465  // To be safe: if this was run by a bootloader that chose FRCPLL mode,
466  // then we can't change the bits below. To do so, first switch to FRC,
467  // change bits, then switch back to FRCPLL.
468  switchClock(GET_OSC_SEL_BITS(FNOSC_FRC));
469  // Two cases:
470  // 1. Non-USB parts just have a FRC postscaler that feeds
471  // the 4x PLL block. Set this postscaler to 1 since the
472  // FRC runs at 8 MHz to get a 32 MHz FOSC = 16 MHz FCY.
473  _RCDIV = 0;
474 #ifdef _CPDIV
475  // The PLL multiplies this 4 MHz input to 96 MHz then
476  // divides it by 3 to 32 MHz. A second PLL prescaler
477  // then selects the final FOSC. Choose a prescale of
478  // 1 so FOSC = 32 MHz, giving FCY = 16 MHz.
479  _CPDIV = 0; // 0 means a prescale of 1
480 #endif
481 #ifdef _PLLDIV
482  // 2. USB parts have a more complex clocking scheme. The
483  // FRC postscaler feeds a PLL prescaler rather than
484  // directly determining FOSC. The
485  // PLL input must be 4 MHz, so choose a PLL prescaler
486  // of 2 since the FRC runs at 8 MHz.
487  _PLLDIV = 1; // 1 means a prescale of 2
488 #elif defined(PLLDIV_NODIV)
489 #warning Ensure that the PLLDIV value is set to divide by 2 in the configuration bits for PRIPLL_8MHzCrystal_16MHzFCY clock option!!
490 #endif
491 #ifdef _PLLEN
492  _PLLEN = 1;
493 #warning PLL Enabled
494 #endif
495 
496  switchClock(GET_OSC_SEL_BITS(FNOSC_PRIPLL));
497 }
498 #endif
499 
500 #if IS_CLOCK_CONFIG(PRI_8MHzCrystal_4MHzFCY)
501 #warning Clock configured for PRI using a 8.0 Mhz primary oscillator, FCY = 4 MHz
502 #endif
503 #if GET_IS_SUPPORTED(PRI_8MHzCrystal_4MHzFCY)
504 void configClockPRI_8MHzCrystal_4MHzFCY(void) {
505  // To be safe: if this was run by a bootloader that chose FRCPLL mode,
506  // then we can't change the bits below. To do so, first switch to FRC,
507  // change bits, then switch back to FRCPLL.
508  switchClock(GET_OSC_SEL_BITS(FNOSC_PRI));
509 }
510 #endif