PIC24 Support Libraries
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, switch 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 <libpic30.h> // Has ___delay3232
68 #include "pic24_clockfreq.h"
69 #include "pic24_util.h"
70 #include "pic24_serial.h"
71 #include "pic24_unittest.h"
72 
73 #if SIM
74 // The simulator doesn't call this function, so omit it.
75 #elif !USE_CLOCK_TIMEOUT
76 // With no clock timeout support, define an empty function.
77 void checkClockTimeout(void) {
78 }
79 #else
80 /*
81  * The purpose of the clock timeout functions is
82  * output a meaningful error in case the clock switch
83  * does not occur. In this case, we assume the startup
84  * oscillator (the FRC) is still running.
85  */
86 # define CLOCKTIMEOUT_MAX 200000L
87 # if ( defined(__PIC24H__) || defined(__dsPIC33F__) || \
88  defined(__PIC24E__) || defined(__dsPIC33E__) )
89 # define FRC_FCY 3685000L
90 # elif ( defined(__PIC24F__) || defined(__PIC24FK__) )
91 # define FRC_FCY 4000000L
92 # else
93 # error "Unknown processor."
94 # endif
95 // Since the FRC is slow, and we only want to transmit, pick a baud rate divisor
96 // of 4 (BRGH == 1). In this case:
97 //
98 // * For the PIC24F/FK: given FCY == 4 MHz and DEFAULT_BAUDRATE == 57600:
99 // U1BRG = FCY/(4*baud) - 1 = 16. This gives an actual
100 // baud rate of baud = FCY/(4*(U1BRG + 1)) = 58,823 baud for an error of 2.1%.
101 // * If FCY == 3.685 MHz and DEFAULT_BAUDRATE == 230400:
102 // U1BRG = 3. This gives and actual baud rate of 230,312 for an error of
103 // 0.04%.
104 # define FRC_BRGH 1
105 
106 # if USE_HEARTBEAT
107 # define SET_HB_LED(x) (HB_LED = x)
108 # else
109 # define SET_HB_LED(x) (void) x
110 # endif
111 
112 // Per https://en.wikipedia.org/wiki/Morse_code#Representation.2C_timing.2C_and_speeds:
113 //
114 // 1. short mark, dot or "dit": "dot duration" is one time unit long
115 // 2. longer mark, dash or "dah": three time units long
116 // 3. inter-element gap between the dots and dashes within a character: one dot duration or one unit long
117 // 4. short gap (between letters): three time units long
118 // 5. medium gap (between words): seven time units long
119 # define FRC_CYCLE_PER_MS (FRC_FCY*0.001)
120 # define DOT_CYCLES (FRC_CYCLE_PER_MS*100)
121 # define DASH_CYCLES (DOT_CYCLES*3)
122 
123 static void morse_blink(const char* sz_morse_code) {
124  for (; *sz_morse_code; ++sz_morse_code) {
125  switch (*sz_morse_code) {
126  case '.':
127  SET_HB_LED(1);
128  __delay32(DOT_CYCLES);
129  break;
130 
131  case '-':
132  SET_HB_LED(1);
133  __delay32(DASH_CYCLES);
134  break;
135 
136  default:
137  // Anything not a dot or dash is a inter-letter gap (3 time units).
138  // There's always a dot delay at the end, so do 2 units here and 1 units there.
139  __delay32(DOT_CYCLES*2);
140  }
141 
142  // Insert an inter-element gap.
143  SET_HB_LED(0);
144  __delay32(DOT_CYCLES);
145  }
146 
147  // Insert medium gap (between words) of 7 units. We've already has a 1 unit
148  // gap, so delay 6 more.
149  __delay32(DOT_CYCLES*6);
150 }
151 
152 
153 static void configFrcUART(void) {
154  // Assume we're running on the FRC, since the initial clock switch failed.
155  // Get UART I/O pins mapped and general config done.
157 
158  // BRG register is probably wrong since it uses FCY, not FRC_FCY. Fix it.
159 # if (DEFAULT_UART == 1)
160  U1BRG = compute_brg(FRC_FCY, FRC_BRGH, DEFAULT_BAUDRATE);
161  U1MODEbits.BRGH = FRC_BRGH;
162 # elif (DEFAULT_UART == 2)
163  U2BRG = compute_brg(FRC_FCY, FRC_BRGH, DEFAULT_BAUDRATE);
164  U2MODEbits.BRGH = FRC_BRGH;
165 # elif (DEFAULT_UART == 3)
166  U3BRG = compute_brg(FRC_FCY, FRC_BRGH, DEFAULT_BAUDRATE);
167  U3MODEbits.BRGH = FRC_BRGH;
168 # elif (DEFAULT_UART == 4)
169  U4BRG = compute_brg(FRC_FCY, FRC_BRGH, DEFAULT_BAUDRATE);
170  U4MODEbits.BRGH = FRC_BRGH;
171 # else
172 # error "Invalid DEFAULT_UART."
173 # endif
174 }
175 
176 static uint32_t u32_timeoutCount;
177 static void checkClockTimeout(void) {
178  // Update the timeout. If the switch hasn't failed,
179  // simply return to wait for the switch a bit more.
180  u32_timeoutCount++;
181  if (u32_timeoutCount < CLOCKTIMEOUT_MAX) {
182  return;
183  }
184 
185  // The clock has failed. Initialize the minimal peripherals necessary to
186  // indicate a failure.
187  configFrcUART();
188  configHeartbeat();
189 
190  while(1) {
191  // If the string below was printed out, either:
192  // 1. Check the crystal / oscillator attached to your chip. It doesn't work.
193  // 2. Tell the library to use the built-in oscillator, instead of an external one.
194  // To do this, check your setting for the 'CLOCK_CONFIG' macro.
195  // Watch the compiler output window when pic24_clockfreq.c is compiled; a warning message
196  // there will tell you the selected value for CLOCK_CONFIG. Change this value to
197  // something that doesn't require an oscillator. See pic24_clockfreq.h for a list
198  // of valid choices.
199  // 3. Make sure that clock switching is allowed -- the FOSC configuration register
200  // bit field FCKSM must **not** be set to CSDCMD (which disables clock
201  // switching).
202  outString("\n\nYour clock choice failed to initialize. See " __FILE__
203  " line " TOSTRING(__LINE__) " for more details.");
204 
205  // Blink SOS on the heartbeat LED.
206  morse_blink("... --- ...");
207  }
208 }
209 #endif
210 
211 
212 void switchClock(uint8_t u8_source) {
213  // Create a union that mirrors the OSCCON structure
214  // with all its bit names but is also byte-accessable.
215  OSCCONBITS OSCCONBITS_copy;
216 
217  // Switch clock to use new choice specified by u8_choice.
218  // Valid values are 0-7.
219  // Throw an error if the source isn't in the list above.
220  ASSERT(u8_source < 8);
221  // 1. Disable interrupts per 7.11.2 FRM rev B under
222  // "A recommended code sequence for a clock switch
223  // includes the following:" heading.
224  // Assumes there are no priority 7 interrupts enabled.
225  asm("DISI #0x3FFF"); // Disable interrupts for a long time
226  // 2. Switch to the PLL. Use compiler built-ins to unlock
227  // clock switch registers. See 7.11.1 of the FRM rev B.
228  OSCCONBITS_copy = OSCCONbits; // Copy OSCCON bits.
229  OSCCONBITS_copy.NOSC = u8_source; // Select new clock source.
230  OSCCONBITS_copy.CLKLOCK = 0; // Allow clock switches.
231  OSCCONBITS_copy.OSWEN = 1; // Request clock switch.
232  // First write high byte, containing new clock source NOSC
233  __builtin_write_OSCCONH(BITS2BYTEH(OSCCONBITS_copy));
234  // Then write low byte, requesting clock switch with OSWEN
235  __builtin_write_OSCCONL(BITS2BYTEL(OSCCONBITS_copy));
236  asm("DISI #0"); // Re-enable them at the next instruction
237 
238 #ifndef SIM
239  // 3. Wait for switch to complete.
240  // Note that oscillator switching is not supported by
241  // the simulator, causing the statements below to
242  // run forever.
243 # if USE_CLOCK_TIMEOUT
244  u32_timeoutCount = 0;
245 # endif
246  while (_OSWEN == 1) {
247  checkClockTimeout();
248  }
249 
250  // 4. Wait for the PLL to lock if using the PLL.
251  // (Is this really necessary? It certainly can't hurt.)
252  if ( (u8_source == GET_OSC_SEL_BITS(FNOSC_FRCPLL)) ||
253  (u8_source == GET_OSC_SEL_BITS(FNOSC_PRIPLL)) ) {
254  while (_LOCK == 0) {
255  checkClockTimeout();
256  }
257  }
258 
259  // 5. Make sure clock switch worked
260  while (_COSC != u8_source) checkClockTimeout();
261 #endif
262 }
263 
264 #if IS_CLOCK_CONFIG(SIM_CLOCK)
265 # warning "Clock configured for simulation, FCY = 1 Mhz."
266 #endif
267 #if (GET_IS_SUPPORTED(SIM_CLOCK) && !defined(BOOTLOADER)) || IS_CLOCK_CONFIG(SIM_CLOCK)
268 void configClockSim(void) {
269 }
270 #endif
271 
272 
273 #if IS_CLOCK_CONFIG(FRCPLL_FCY16MHz)
274 # warning "Clock configured for FRCPLL, FCY = 16 MHz."
275 #endif
276 #if (GET_IS_SUPPORTED(FRCPLL_FCY16MHz) && !defined(BOOTLOADER)) || IS_CLOCK_CONFIG(FRCPLL_FCY16MHz)
277 void configClockFRCPLL_FCY16MHz(void) {
278  // To be safe: if this was run by a bootloader that chose FRCPLL mode,
279  // then we can't change the bits below. To do so, first switch to FRC,
280  // change bits, then switch back to FRCPLL.
281  switchClock(GET_OSC_SEL_BITS(FNOSC_FRC));
282  // Two cases:
283  // 1. Non-USB parts just have a FRC postscaler that feeds
284  // the 4x PLL block. Set this postscaler to 1 since the
285  // FRC runs at 8 MHz to get a 32 MHz FOSC = 16 MHz FCY.
286  _RCDIV = 0;
287 # ifdef _CPDIV
288  // The PLL multiplies this 4 MHz input to 96 MHz then
289  // divides it by 3 to 32 MHz. A second PLL prescaler
290  // then selects the final FOSC. Choose a prescale of
291  // 1 so FOSC = 32 MHz, giving FCY = 16 MHz.
292  _CPDIV = 0; // 0 means a prescale of 1
293 # endif
294 # ifdef _PLLDIV
295  // 2. USB parts have a more complex clocking scheme. The
296  // FRC postscaler feeds a PLL prescaler rather than
297  // directly determining FOSC. The
298  // PLL input must be 4 MHz, so choose a PLL prescaler
299  // of 2 since the FRC runs at 8 MHz.
300  _PLLDIV = 1; // 1 means a prescale of 2
301 # elif defined(PLLDIV_NODIV)
302 # warning "Ensure that the PLLDIV value is set to divide by 2 in the configuration bits for FRCPLL_FCY16MHz clock option!!"
303 # endif
304 # ifdef _PLLEN
305  _PLLEN = 1;
306 # warning "PLL Enabled."
307 # endif
308  switchClock(GET_OSC_SEL_BITS(FNOSC_FRCPLL));
309 }
310 #endif
311 
312 
313 #if IS_CLOCK_CONFIG(FRC_FCY4MHz)
314 # warning "Clock configured for FRC, FCY = 4 MHz."
315 # warning "Baud rates of 19200 or lower recommended for this clock choice."
316 #endif
317 #if (GET_IS_SUPPORTED(FRC_FCY4MHz) && !defined(BOOTLOADER)) || IS_CLOCK_CONFIG(FRC_FCY4MHz)
318 void configClockFRC_FCY4MHz(void) {
319  // Ensure that the FRC postscaler is at '1' and not its reset default of '2' (PIC24F family)
320  _RCDIV = 0;
321  switchClock(GET_OSC_SEL_BITS(FNOSC_FRC));
322 }
323 #endif
324 
325 
326 #if IS_CLOCK_CONFIG(PRI_NO_PLL_7372KHzCrystal)
327 # warning "Clock configured for a 7.372 MHz crystal primary oscillator, no PLL."
328 #endif
329 #if (GET_IS_SUPPORTED(PRI_NO_PLL_7372KHzCrystal) && !defined(BOOTLOADER)) || IS_CLOCK_CONFIG(PRI_NO_PLL_7372KHzCrystal)
330 void configClockPRI_NO_PLL_7372KHzCrystal(void) {
331  switchClock(GET_OSC_SEL_BITS(FNOSC_PRI));
332 }
333 #endif
334 
335 
336 #if IS_CLOCK_CONFIG(FRC_FCY3685KHz)
337 # warning "Clock configured for FRC, FCY = 3.685 MHz."
338 #endif
339 #if (GET_IS_SUPPORTED(FRC_FCY3685KHz) && !defined(BOOTLOADER)) || IS_CLOCK_CONFIG(FRC_FCY3685KHz)
340 void configClockFRC_FCY3685KHz(void) {
341  switchClock(GET_OSC_SEL_BITS(FNOSC_FRC));
342  // Choose no tuning on FRC to get 7.37 MHz nominal FOSC.
343  // Do after clock switch in case FRCPLL was in use, since
344  // that would alter PLL input frequency. (Might be OK, but
345  // this is perhaps safer.)
346  _TUN = 0;
347 }
348 #endif
349 
350 
351 #if IS_CLOCK_CONFIG(FRCPLL_FCY40MHz)
352 # warning "Clock configured for FRCPLL, FCY = 40 MHz."
353 #endif
354 #if (GET_IS_SUPPORTED(FRCPLL_FCY40MHz) && !defined(BOOTLOADER)) || IS_CLOCK_CONFIG(FRCPLL_FCY40MHz)
355 void configClockFRCPLL_FCY40MHz(void) {
356  // To be safe: if this was run by a bootloader that chose FRCPLL mode,
357  // then we can't change the bits below. To do so, first switch to FRC,
358  // change bits, then switch back to FRCPLL.
359  switchClock(GET_OSC_SEL_BITS(FNOSC_FRC));
360  // A concern: since the clock is +/- 2%, we could end
361  // up with a > 8.0 MHz processor clock! At 8 MHz, this would
362  // be 8.16 MHz, so the processor would run at 81.6 MHz.
363  // Ignore this for now; probably, the chip will still run.
364 
365  _TUN = 0; // Correct setting assuming the RC oscillator is exactly 7.37MHz.
366  // It may need to be tweaked however. Use the echo.c program, and a baud rate
367  // of 115,200 and increase/decrease TUN until you get no framing errors
368 
369  // Choose PLL factors: Fref after first prescale must be
370  // between 0.8 and 8.0 MHz. Choose a prescale of 9
371  // for Fref of 0.8189 MHz.
372  _PLLPRE = 7; // Prescale = PLLPRE + 2
373  // Fvco after multiply must be between 100 and 200 MHz.
374  // Pick 159.7 MHz, so multiply by 195.
375  _PLLDIV = 193; // Multiply = PLLDIV + 2
376  // Final desired Fosc = 79.8 MHz for an Fcy = 39.9 MHz.
377  // (See 7.7 of the FRM rev B). Pick 80 MHz, so postscale by 2.
378  _PLLPOST = 0; // Postscale = 2 * (PLLPOST + 1)
379  switchClock(GET_OSC_SEL_BITS(FNOSC_FRCPLL));
380 }
381 #endif
382 
383 #if IS_CLOCK_CONFIG(FRCPLL_FCY60MHz)
384 # warning "Clock configured for FRCPLL, FCY = 60 MHz."
385 #endif
386 #if (GET_IS_SUPPORTED(FRCPLL_FCY60MHz) && !defined(BOOTLOADER)) || IS_CLOCK_CONFIG(FRCPLL_FCY60MHz)
387 void configClockFRCPLL_FCY60MHz(void) {
388  // To be safe: if this was run by a bootloader that chose FRCPLL mode,
389  // then we can't change the bits below. To do so, first switch to FRC,
390  // change bits, then switch back to FRCPLL.
391  switchClock(GET_OSC_SEL_BITS(FNOSC_FRC));
392 
393  _TUN = 0; // Correct setting assuming the RC oscillator is exactly 7.37MHz.
394  // It may need to be tweaked however. Use the echo.c program, and a baud rate
395  // of 115,200 and increase/decrease TUN until you get no framing errors
396 
397  // For PIC24E Family, Fplli must be
398  // between 0.8 MHz and 8.0 MHz. Choose a prescale of 2
399  // for Fplli of 3.685 MHz.
400  _PLLPRE = 0; // Prescale = PLLPRE + 2
401  // Fsys after multiply must be between 120 and 340 MHz.
402  // Pick 240 MHz, so multiply by 65.
403  _PLLDIV = 63; // Multiply = PLLDIV + 2
404  // Final desired Fosc = 120 MHz for an Fcy = 60 MHz.
405  // Pick 120 MHz, so postscale by 2.
406  _PLLPOST = 0; // Postscale = 2 * (PLLPOST + 1)
407  switchClock(GET_OSC_SEL_BITS(FNOSC_FRCPLL));
408 }
409 #endif
410 
411 #if IS_CLOCK_CONFIG(FRCPLL_FCY70MHz)
412 # warning "Clock configured for FRCPLL, FCY = 70 MHz."
413 #endif
414 #if (GET_IS_SUPPORTED(FRCPLL_FCY70MHz) && !defined(BOOTLOADER)) || IS_CLOCK_CONFIG(FRCPLL_FCY70MHz)
415 void configClockFRCPLL_FCY70MHz(void) {
416  // To be safe: if this was run by a bootloader that chose FRCPLL mode,
417  // then we can't change the bits below. To do so, first switch to FRC,
418  // change bits, then switch back to FRCPLL.
419  switchClock(GET_OSC_SEL_BITS(FNOSC_FRC));
420 
421  _TUN = 0; // Correct setting assuming the RC oscillator is exactly 7.37MHz.
422  // It may need to be tweaked however. Use the echo.c program, and a baud rate
423  // of 115,200 and increase/decrease TUN until you get no framing errors
424 
425  // For PIC24E Family, Fplli must be
426  // between 0.8 MHz and 8.0 MHz. Choose a prescale of 2
427  // for Fplli of 3.685 MHz.
428  _PLLPRE = 0; // Prescale = PLLPRE + 2
429  // Fsys after multiply must be between 120 and 340 MHz.
430  // Pick 280 MHz, so multiply by 76.
431  _PLLDIV = 74; // Multiply = PLLDIV + 2
432  // Final desired Fosc = 140 MHz for an Fcy = 70 MHz.
433  // Pick 140 MHz, so postscale by 2.
434  _PLLPOST = 0; // Postscale = 2 * (PLLPOST + 1)
435  switchClock(GET_OSC_SEL_BITS(FNOSC_FRCPLL));
436 }
437 #endif
438 
439 
440 
441 #if IS_CLOCK_CONFIG(PRIPLL_7372KHzCrystal_40MHzFCY)
442 # warning "Clock configured for PRIPLL using a 7.3727 Mhz primary oscillator, FCY = 40 MHz."
443 #endif
444 #if (GET_IS_SUPPORTED(PRIPLL_7372KHzCrystal_40MHzFCY) && !defined(BOOTLOADER)) || IS_CLOCK_CONFIG(PRIPLL_7372KHzCrystal_40MHzFCY)
445 void configClockPRIPLL_7372KHzCrystal_40MHzFCY(void) {
446  // To be safe: if this was run by a bootloader that chose PRIPLL mode,
447  // then we can't change the bits below. To do so, first switch to FRC,
448  // change bits, then switch back to PRIPLL.
449  switchClock(GET_OSC_SEL_BITS(FNOSC_FRC));
450  //settings for Cycle time = 40 MHz, primary oscillator with PLL
451  _PLLPRE = 4; // Prescale = PLLPRE + 2
452  _PLLDIV = 128; // Multiply = PLLDIV + 2
453  _PLLPOST = 0; // Postscale = 2 * (PLLPOST + 1)
454  switchClock(GET_OSC_SEL_BITS(FNOSC_PRIPLL));
455 }
456 #endif
457 
458 #if IS_CLOCK_CONFIG(PRIPLL_8MHzCrystal_40MHzFCY)
459 # warning "Clock configured for PRIPLL using an 8.0 Mhz primary oscillator, FCY = 40 MHz."
460 #endif
461 #if (GET_IS_SUPPORTED(PRIPLL_8MHzCrystal_40MHzFCY) && !defined(BOOTLOADER)) || IS_CLOCK_CONFIG(PRIPLL_8MHzCrystal_40MHzFCY)
462 void configClockPRIPLL_8MHzCrystal_40MHzFCY(void) {
463  //settings for Cycle time = 40 MHz, primary oscillator with PLL
464  //These PLL settings will give an FCY == Crystal Freq * 10/2, or FOSC = Crystal Freq * 10
465  /*
466  This settings assumes the external crystal on is 8.0MHz
467  */
468  // To be safe: if this was run by a bootloader that chose PRIPLL mode,
469  // then we can't change the bits below. To do so, first switch to FRC,
470  // change bits, then switch back to PRIPLL.
471  switchClock(GET_OSC_SEL_BITS(FNOSC_FRC));
472  _PLLPRE = 0; // Prescale = PLLPRE + 2
473  _PLLDIV = 38; // Multiply = PLLDIV + 2
474  _PLLPOST = 0; // Postscale = 2 * (PLLPOST + 1)
475  switchClock(GET_OSC_SEL_BITS(FNOSC_PRIPLL));
476 }
477 #endif
478 
479 #if IS_CLOCK_CONFIG(PRIPLL_8MHzCrystal_16MHzFCY)
480 # warning "Clock configured for PRIPLL using a 8.0 Mhz primary oscillator, FCY = 16 MHz."
481 #endif
482 #if (GET_IS_SUPPORTED(PRIPLL_8MHzCrystal_16MHzFCY) && !defined(BOOTLOADER)) || IS_CLOCK_CONFIG(PRIPLL_8MHzCrystal_16MHzFCY)
483 void configClockPRIPLL_8MHzCrystal_16MHzFCY(void) {
484  // To be safe: if this was run by a bootloader that chose FRCPLL mode,
485  // then we can't change the bits below. To do so, first switch to FRC,
486  // change bits, then switch back to FRCPLL.
487  switchClock(GET_OSC_SEL_BITS(FNOSC_FRC));
488  // Two cases:
489  // 1. Non-USB parts just have a FRC postscaler that feeds
490  // the 4x PLL block. Set this postscaler to 1 since the
491  // FRC runs at 8 MHz to get a 32 MHz FOSC = 16 MHz FCY.
492  _RCDIV = 0;
493 # ifdef _CPDIV
494  // The PLL multiplies this 4 MHz input to 96 MHz then
495  // divides it by 3 to 32 MHz. A second PLL prescaler
496  // then selects the final FOSC. Choose a prescale of
497  // 1 so FOSC = 32 MHz, giving FCY = 16 MHz.
498  _CPDIV = 0; // 0 means a prescale of 1
499 # endif
500 # ifdef _PLLDIV
501  // 2. USB parts have a more complex clocking scheme. The
502  // FRC postscaler feeds a PLL prescaler rather than
503  // directly determining FOSC. The
504  // PLL input must be 4 MHz, so choose a PLL prescaler
505  // of 2 since the FRC runs at 8 MHz.
506  _PLLDIV = 1; // 1 means a prescale of 2
507 # elif defined(PLLDIV_NODIV)
508 # warning "Ensure that the PLLDIV value is set to divide by 2 in the configuration bits for PRIPLL_8MHzCrystal_16MHzFCY clock option!!"
509 # endif
510 # ifdef _PLLEN
511  _PLLEN = 1;
512 # warning "PLL Enabled."
513 # endif
514 
515  switchClock(GET_OSC_SEL_BITS(FNOSC_PRIPLL));
516 }
517 #endif
518 
519 #if IS_CLOCK_CONFIG(PRI_8MHzCrystal_4MHzFCY)
520 # warning "Clock configured for PRI using a 8.0 Mhz primary oscillator, FCY = 4 MHz."
521 # warning "Baud rates of 19200 or lower recommended for this clock choice."
522 #endif
523 #if (GET_IS_SUPPORTED(PRI_8MHzCrystal_4MHzFCY) && !defined(BOOTLOADER)) || IS_CLOCK_CONFIG(PRI_8MHzCrystal_4MHzFCY)
524 void configClockPRI_8MHzCrystal_4MHzFCY(void) {
525  // To be safe: if this was run by a bootloader that chose FRCPLL mode,
526  // then we can't change the bits below. To do so, first switch to FRC,
527  // change bits, then switch back to FRCPLL.
528  switchClock(GET_OSC_SEL_BITS(FNOSC_PRI));
529 }
530 #endif
void configHeartbeat(void)
Definition: pic24_util.c:89
Configures the system clock.
#define BITS2BYTEL(sfrBitfield)
Return the low byte (as a uint8_t) of a bitfield.
Definition: pic24_util.h:57
void configDefaultUART(uint32_t u32_baudRate)
Definition: pic24_serial.c:347
void outString(const char *psz_s)
Definition: pic24_serial.c:90
void switchClock(uint8_t u8_source)
uint16_t compute_brg(uint32_t u32_fcy, uint16_t u16_brgh, uint32_t u32_baudrate)
Definition: pic24_util.c:474
#define TOSTRING(x)
#define ASSERT(test)
#define BITS2BYTEH(sfrBitfield)
Return the high byte (as a uint8_t) of a bitfield.
Definition: pic24_util.h:59
#define GET_OSC_SEL_BITS(bits)
#define DEFAULT_BAUDRATE
unsigned char uint8_t
An abbreviation for an 8-bit unsigned integer.
Definition: dataXferImpl.h:194