Content originally posted in LPCWare by Rob65 on Mon Jul 04 12:21:22 MST 2011
The FreeRTOS port that is included with the new LPCXpresso 4.0.5 does not use CMSIS per default. This means that the system is running on the 4 MHz internal RC oscillator without a PLL active.
I found this is a nice moment to remove the need for CMSIS in my application and take control of power and clocking myself.
Clock switching and PLL programming is not always as easy as it looks. As soon as you make one little mistake the system stops working and debugging is not possible anymore.
I tried to create a simple interface using just two functions:
[LIST]
[*]LPC_UseOscillator(osc)
switches the clock to the requested oscillator, being LPC_INTRC_OSC, LPC_MAIN_OSC or LPC_RTC_OSC.
[*]LPC_SetPLL0(cclk)
Programs PLL0 with the proper values to get the requested cclk (cpu clock).
cclk must be in range of the defined values in the table (I currently defined 10-100 MHz in 10 MHz steps).
[/LIST]
Both functions also reprogram the SysTick counter such that FreeRTOS keeps running at a 1 msec tick interval (as defined through configTICK_RATE_HZ)
It all seems to work, except for the RTC_OSC ...
I thought I had RTC_OSC working this morning but somehow I cannot reproduce this anymore...
Some explanation with the code could be nice.
I tried to capture most of the stuff in comments but there are some key points that might be worth mentioning:
[LIST]
[*]Before switching oscillators the PLL is disabled and stopped.
changing the input clock with a running PLL will unlock the PLL which results in a very strange clock behaviour.
[*]The same goes for PLL (re)programming. During switching the PLL will unlock and that's not something we like to present the Cortex core with.
[*]During clock switching or PLL repogramming the SysTick is disabled.
[*]The values needed to reprogram the PLL are given in the tables MainOscPLL0conf, IntRCOscPLL0conf and RTCOscPLL0conf.
Add values when needed.
[/LIST]
Adding a new value is easy, just calculate the numbers needed.
Suppose we want to have a frequency of 1.8432 MHz (for thos who still remember: that's 16 * 115200, resulting in a very nice clock for the uart).
[LIST=1]
[*]Find a Fcco frequency that is in range (275 - 550 MHz):
200 * 1.8 MHz = 368.64 MHz
[*]Find values for N that result in an integer M value :D
M = Fcco x N / (2 x Fin)
with a 12 MHz crystal: Fcco / (2 x Fin) = 15.36
N = 14 gives an M of 215.04 which is very close but
N = 25 gives an M of 384
[/LIST]
Check with the formula in the user manual:
Fcco = (2 x M x Fin) / N = (2 x 384x 12) / 25 = 368.64
Now with a CCLKCFG of 200 we get a cclk of: 368.64 / 200 = 1.8432 MHz
Since this frequency may be too slow, we can also define the cclk frequencies that are 2x 4x or 8x this value. Just use CCLKCFG of 100, 50 and 25
It all seems to work properly, switching back and forth between the main crystal and internal RC oscillator and programming the PLL at different values all behaves as expected.
Oh ... did I mention the PLL main oscillator values are for a 12 MHz crystal ???
You will need to change the table when using a different crystal.
Regards,
Rob