]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/MSP430FR5969_LaunchPad/driverlib/MSP430FR5xx_6xx/cs.c
ce324d1900c2fa995d29cb138b6630f7da35e0db
[freertos] / FreeRTOS / Demo / MSP430FR5969_LaunchPad / driverlib / MSP430FR5xx_6xx / cs.c
1 /* --COPYRIGHT--,BSD\r
2  * Copyright (c) 2014, Texas Instruments Incorporated\r
3  * All rights reserved.\r
4  *\r
5  * Redistribution and use in source and binary forms, with or without\r
6  * modification, are permitted provided that the following conditions\r
7  * are met:\r
8  *\r
9  * *  Redistributions of source code must retain the above copyright\r
10  *    notice, this list of conditions and the following disclaimer.\r
11  *\r
12  * *  Redistributions in binary form must reproduce the above copyright\r
13  *    notice, this list of conditions and the following disclaimer in the\r
14  *    documentation and/or other materials provided with the distribution.\r
15  *\r
16  * *  Neither the name of Texas Instruments Incorporated nor the names of\r
17  *    its contributors may be used to endorse or promote products derived\r
18  *    from this software without specific prior written permission.\r
19  *\r
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\r
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\r
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\r
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\r
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
31  * --/COPYRIGHT--*/\r
32 //*****************************************************************************\r
33 //\r
34 // cs.c - Driver for the cs Module.\r
35 //\r
36 //*****************************************************************************\r
37 \r
38 //*****************************************************************************\r
39 //\r
40 //! \addtogroup cs_api cs\r
41 //! @{\r
42 //\r
43 //*****************************************************************************\r
44 \r
45 #include "inc/hw_regaccess.h"\r
46 #include "inc/hw_memmap.h"\r
47 \r
48 #if defined(__MSP430_HAS_CS__) || defined(__MSP430_HAS_SFR__)\r
49 #include "cs.h"\r
50 \r
51 #include <assert.h>\r
52 \r
53 //*****************************************************************************\r
54 //\r
55 // The following value is used by CS_getACLK, CS_getSMCLK, CS_getMCLK to\r
56 // determine the operating frequency based on the available DCO frequencies.\r
57 //\r
58 //*****************************************************************************\r
59 #define CS_DCO_FREQ_1                                                   1000000\r
60 #define CS_DCO_FREQ_2                                                   2670000\r
61 #define CS_DCO_FREQ_3                                                   3330000\r
62 #define CS_DCO_FREQ_4                                                   4000000\r
63 #define CS_DCO_FREQ_5                                                   5330000\r
64 #define CS_DCO_FREQ_6                                                   6670000\r
65 #define CS_DCO_FREQ_7                                                   8000000\r
66 #define CS_DCO_FREQ_8                                                  16000000\r
67 #define CS_DCO_FREQ_9                                                  20000000\r
68 #define CS_DCO_FREQ_10                                                 24000000\r
69 \r
70 //*****************************************************************************\r
71 //\r
72 // Internal very low power VLOCLK, low frequency oscillator with 10kHz typical\r
73 // frequency, internal low-power oscillator MODCLK with 5 MHz typical\r
74 // frequency and LFMODCLK is MODCLK divided by 128.\r
75 //\r
76 //*****************************************************************************\r
77 #define CS_VLOCLK_FREQUENCY                                               10000\r
78 #define CS_MODCLK_FREQUENCY                                             5000000\r
79 #define CS_LFMODCLK_FREQUENCY                                             39062\r
80 \r
81 //*****************************************************************************\r
82 //\r
83 // The following value is used by CS_XT1Start, CS_bypassXT1,\r
84 // CS_XT1StartWithTimeout, CS_bypassXT1WithTimeout to properly set the XTS\r
85 // bit. This frequnecy threshold is specified in the User's Guide.\r
86 //\r
87 //*****************************************************************************\r
88 #define LFXT_FREQUENCY_THRESHOLD                                          50000\r
89 \r
90 //*****************************************************************************\r
91 //\r
92 // LFXT crystal frequency. Should be set with\r
93 // CS_externalClockSourceInit if LFXT is used and user intends to invoke\r
94 // CS_getSMCLK, CS_getMCLK, CS_getACLK and\r
95 // CS_turnOnLFXT, CS_LFXTByPass, CS_turnOnLFXTWithTimeout,\r
96 // CS_LFXTByPassWithTimeout.\r
97 //\r
98 //*****************************************************************************\r
99 static uint32_t privateLFXTClockFrequency = 0;\r
100 \r
101 //*****************************************************************************\r
102 //\r
103 // The HFXT crystal frequency. Should be set with\r
104 // CS_externalClockSourceInit if HFXT is used and user intends to invoke\r
105 // CS_getSMCLK, CS_getMCLK, CS_getACLK,\r
106 // CS_turnOnLFXT, CS_LFXTByPass, CS_turnOnLFXTWithTimeout,\r
107 // CS_LFXTByPassWithTimeout.\r
108 //\r
109 //*****************************************************************************\r
110 static uint32_t privateHFXTClockFrequency = 0;\r
111 \r
112 static uint32_t privateCSASourceClockFromDCO(uint8_t clockdivider)\r
113 {\r
114     uint32_t CLKFrequency = 0;\r
115 \r
116     if(HWREG16(CS_BASE + OFS_CSCTL1) & DCORSEL)\r
117     {\r
118         switch(HWREG16(CS_BASE + OFS_CSCTL1) & DCOFSEL_7)\r
119         {\r
120         case DCOFSEL_0:\r
121             CLKFrequency = CS_DCO_FREQ_1 / clockdivider;\r
122             break;\r
123         case DCOFSEL_1:\r
124             CLKFrequency = CS_DCO_FREQ_5 / clockdivider;\r
125             break;\r
126         case DCOFSEL_2:\r
127             CLKFrequency = CS_DCO_FREQ_6 / clockdivider;\r
128             break;\r
129         case DCOFSEL_3:\r
130             CLKFrequency = CS_DCO_FREQ_7 / clockdivider;\r
131             break;\r
132         case DCOFSEL_4:\r
133             CLKFrequency = CS_DCO_FREQ_8 / clockdivider;\r
134             break;\r
135         case DCOFSEL_5:\r
136             CLKFrequency = CS_DCO_FREQ_9 / clockdivider;\r
137             break;\r
138         case DCOFSEL_6:\r
139         case DCOFSEL_7:\r
140             CLKFrequency = CS_DCO_FREQ_10 / clockdivider;\r
141             break;\r
142         default:\r
143             CLKFrequency = 0;\r
144             break;\r
145         }\r
146     }\r
147     else\r
148     {\r
149         switch(HWREG16(CS_BASE + OFS_CSCTL1) & DCOFSEL_7)\r
150         {\r
151         case DCOFSEL_0:\r
152             CLKFrequency = CS_DCO_FREQ_1 / clockdivider;\r
153             break;\r
154         case DCOFSEL_1:\r
155             CLKFrequency = CS_DCO_FREQ_2 / clockdivider;\r
156             break;\r
157         case DCOFSEL_2:\r
158             CLKFrequency = CS_DCO_FREQ_3 / clockdivider;\r
159             break;\r
160         case DCOFSEL_3:\r
161             CLKFrequency = CS_DCO_FREQ_4 / clockdivider;\r
162             break;\r
163         case DCOFSEL_4:\r
164             CLKFrequency = CS_DCO_FREQ_5 / clockdivider;\r
165             break;\r
166         case DCOFSEL_5:\r
167             CLKFrequency = CS_DCO_FREQ_6 / clockdivider;\r
168             break;\r
169         case DCOFSEL_6:\r
170         case DCOFSEL_7:\r
171             CLKFrequency = CS_DCO_FREQ_7 / clockdivider;\r
172             break;\r
173         default:\r
174             CLKFrequency = 0;\r
175             break;\r
176         }\r
177     }\r
178 \r
179     return (CLKFrequency);\r
180 }\r
181 \r
182 static uint32_t privateCSAComputeCLKFrequency(uint16_t CLKSource,\r
183                                               uint16_t CLKSourceDivider)\r
184 {\r
185     uint32_t CLKFrequency = 0;\r
186     uint8_t CLKSourceFrequencyDivider = 1;\r
187     uint8_t i = 0;\r
188 \r
189     // Determine Frequency divider\r
190     for(i = 0; i < CLKSourceDivider; i++)\r
191     {\r
192         CLKSourceFrequencyDivider *= 2;\r
193     }\r
194 \r
195     // Unlock CS control register\r
196     HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;\r
197 \r
198     // Determine clock source based on CLKSource\r
199     switch(CLKSource)\r
200     {\r
201     // If LFXT is selected as clock source\r
202     case SELM__LFXTCLK:\r
203         CLKFrequency = (privateLFXTClockFrequency /\r
204                         CLKSourceFrequencyDivider);\r
205 \r
206         //Check if LFXTOFFG is not set. If fault flag is set\r
207         //VLO is used as source clock\r
208         if(HWREG8(CS_BASE + OFS_CSCTL5) & LFXTOFFG)\r
209         {\r
210             HWREG8(CS_BASE + OFS_CSCTL5) &= ~(LFXTOFFG);\r
211             //Clear OFIFG fault flag\r
212             HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG;\r
213 \r
214             if(HWREG8(CS_BASE + OFS_CSCTL5) & LFXTOFFG)\r
215             {\r
216                 CLKFrequency = CS_LFMODCLK_FREQUENCY;\r
217             }\r
218         }\r
219         break;\r
220 \r
221     case SELM__VLOCLK:\r
222         CLKFrequency =\r
223             (CS_VLOCLK_FREQUENCY / CLKSourceFrequencyDivider);\r
224         break;\r
225 \r
226     case SELM__LFMODOSC:\r
227         CLKFrequency =\r
228             (CS_LFMODCLK_FREQUENCY / CLKSourceFrequencyDivider);\r
229 \r
230         break;\r
231 \r
232     case SELM__DCOCLK:\r
233         CLKFrequency =\r
234             privateCSASourceClockFromDCO(CLKSourceFrequencyDivider);\r
235 \r
236         break;\r
237 \r
238     case SELM__MODOSC:\r
239         CLKFrequency =\r
240             (CS_MODCLK_FREQUENCY / CLKSourceFrequencyDivider);\r
241 \r
242         break;\r
243 \r
244     case SELM__HFXTCLK:\r
245         CLKFrequency =\r
246             (privateHFXTClockFrequency / CLKSourceFrequencyDivider);\r
247 \r
248         if(HWREG8(CS_BASE + OFS_CSCTL5) & HFXTOFFG)\r
249         {\r
250             HWREG8(CS_BASE + OFS_CSCTL5) &= ~HFXTOFFG;\r
251             //Clear OFIFG fault flag\r
252             HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG;\r
253         }\r
254 \r
255         if(HWREG8(CS_BASE + OFS_CSCTL5) & HFXTOFFG)\r
256         {\r
257             CLKFrequency = CS_MODCLK_FREQUENCY;\r
258         }\r
259         break;\r
260     }\r
261 \r
262     // Lock CS control register\r
263     HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;\r
264 \r
265     return (CLKFrequency);\r
266 }\r
267 \r
268 void CS_setExternalClockSource(uint32_t LFXTCLK_frequency,\r
269                                uint32_t HFXTCLK_frequency)\r
270 {\r
271     privateLFXTClockFrequency = LFXTCLK_frequency;\r
272     privateHFXTClockFrequency = HFXTCLK_frequency;\r
273 }\r
274 \r
275 void CS_initClockSignal(uint8_t selectedClockSignal,\r
276                         uint16_t clockSource,\r
277                         uint16_t clockSourceDivider)\r
278 {\r
279     //Verify User has selected a valid Frequency divider\r
280     assert(\r
281         (CS_CLOCK_DIVIDER_1 == clockSourceDivider) ||\r
282         (CS_CLOCK_DIVIDER_2 == clockSourceDivider) ||\r
283         (CS_CLOCK_DIVIDER_4 == clockSourceDivider) ||\r
284         (CS_CLOCK_DIVIDER_8 == clockSourceDivider) ||\r
285         (CS_CLOCK_DIVIDER_16 == clockSourceDivider) ||\r
286         (CS_CLOCK_DIVIDER_32 == clockSourceDivider)\r
287         );\r
288 \r
289     // Unlock CS control register\r
290     HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;\r
291 \r
292     switch(selectedClockSignal)\r
293     {\r
294     case CS_ACLK:\r
295         assert(\r
296             (CS_LFXTCLK_SELECT == clockSource)  ||\r
297             (CS_VLOCLK_SELECT == clockSource)   ||\r
298             (CS_LFMODOSC_SELECT == clockSource)\r
299             );\r
300 \r
301         clockSourceDivider = clockSourceDivider << 8;\r
302         clockSource = clockSource << 8;\r
303 \r
304         HWREG16(CS_BASE + OFS_CSCTL2) &= ~(SELA_7);\r
305         HWREG16(CS_BASE + OFS_CSCTL2) |= (clockSource);\r
306         HWREG16(CS_BASE + OFS_CSCTL3) &= ~(DIVA0 + DIVA1 + DIVA2);\r
307         HWREG16(CS_BASE + OFS_CSCTL3) |= clockSourceDivider;\r
308         break;\r
309     case CS_SMCLK:\r
310         assert(\r
311             (CS_LFXTCLK_SELECT == clockSource) ||\r
312             (CS_VLOCLK_SELECT == clockSource) ||\r
313             (CS_DCOCLK_SELECT == clockSource) ||\r
314             (CS_HFXTCLK_SELECT == clockSource) ||\r
315             (CS_LFMODOSC_SELECT == clockSource)||\r
316             (CS_MODOSC_SELECT == clockSource)\r
317             );\r
318 \r
319         clockSource = clockSource << 4;\r
320         clockSourceDivider = clockSourceDivider << 4;\r
321 \r
322         HWREG16(CS_BASE + OFS_CSCTL2) &= ~(SELS_7);\r
323         HWREG16(CS_BASE + OFS_CSCTL2) |= clockSource;\r
324         HWREG16(CS_BASE + OFS_CSCTL3) &= ~(DIVS0 + DIVS1 + DIVS2);\r
325         HWREG16(CS_BASE + OFS_CSCTL3) |= clockSourceDivider;\r
326         break;\r
327     case CS_MCLK:\r
328         assert(\r
329             (CS_LFXTCLK_SELECT == clockSource) ||\r
330             (CS_VLOCLK_SELECT == clockSource) ||\r
331             (CS_DCOCLK_SELECT == clockSource) ||\r
332             (CS_HFXTCLK_SELECT == clockSource) ||\r
333             (CS_LFMODOSC_SELECT == clockSource)||\r
334             (CS_MODOSC_SELECT == clockSource)\r
335             );\r
336 \r
337         HWREG16(CS_BASE + OFS_CSCTL2) &= ~(SELM_7);\r
338         HWREG16(CS_BASE + OFS_CSCTL2) |= clockSource;\r
339         HWREG16(CS_BASE + OFS_CSCTL3) &= ~(DIVM0 + DIVM1 + DIVM2);\r
340         HWREG16(CS_BASE + OFS_CSCTL3) |= clockSourceDivider;\r
341         break;\r
342     }\r
343 \r
344     // Lock CS control register\r
345     HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;\r
346 }\r
347 \r
348 void CS_turnOnLFXT(uint16_t lfxtdrive)\r
349 {\r
350     assert(privateLFXTClockFrequency != 0);\r
351 \r
352     assert((lfxtdrive == CS_LFXT_DRIVE_0) ||\r
353            (lfxtdrive == CS_LFXT_DRIVE_1) ||\r
354            (lfxtdrive == CS_LFXT_DRIVE_2) ||\r
355            (lfxtdrive == CS_LFXT_DRIVE_3));\r
356 \r
357     // Unlock CS control register\r
358     HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;\r
359 \r
360     //Switch ON LFXT oscillator\r
361     HWREG16(CS_BASE + OFS_CSCTL4) &= ~LFXTOFF;\r
362 \r
363     //Highest drive setting for LFXTstartup\r
364     HWREG16(CS_BASE + OFS_CSCTL4_L) |= LFXTDRIVE1_L + LFXTDRIVE0_L;\r
365 \r
366     HWREG16(CS_BASE + OFS_CSCTL4) &= ~LFXTBYPASS;\r
367 \r
368     //Wait for Crystal to stabilize\r
369     while(HWREG8(CS_BASE + OFS_CSCTL5) & LFXTOFFG)\r
370     {\r
371         //Clear OSC flaut Flags fault flags\r
372         HWREG8(CS_BASE + OFS_CSCTL5) &= ~(LFXTOFFG);\r
373 \r
374         //Clear OFIFG fault flag\r
375         HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG;\r
376     }\r
377 \r
378     //set requested Drive mode\r
379     HWREG16(CS_BASE + OFS_CSCTL4) = (HWREG16(CS_BASE + OFS_CSCTL4) &\r
380                                      ~(LFXTDRIVE_3)\r
381                                      ) |\r
382                                     (lfxtdrive);\r
383 \r
384     // Lock CS control register\r
385     HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;\r
386 }\r
387 \r
388 void CS_bypassLFXT(void)\r
389 {\r
390     //Verify user has set frequency of LFXT with SetExternalClockSource\r
391     assert(privateLFXTClockFrequency != 0);\r
392 \r
393     // Unlock CS control register\r
394     HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;\r
395 \r
396     assert(privateLFXTClockFrequency < LFXT_FREQUENCY_THRESHOLD);\r
397 \r
398     // Set LFXT in LF mode Switch off LFXT oscillator and enable BYPASS mode\r
399     HWREG16(CS_BASE + OFS_CSCTL4) |= (LFXTBYPASS + LFXTOFF);\r
400 \r
401     //Wait until LFXT stabilizes\r
402     while(HWREG8(CS_BASE + OFS_CSCTL5) & LFXTOFFG)\r
403     {\r
404         //Clear OSC flaut Flags fault flags\r
405         HWREG8(CS_BASE + OFS_CSCTL5) &= ~(LFXTOFFG);\r
406 \r
407         // Clear the global fault flag. In case the LFXT caused the global fault\r
408         // flag to get set this will clear the global error condition. If any\r
409         // error condition persists, global flag will get again.\r
410         HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG;\r
411     }\r
412 \r
413     // Lock CS control register\r
414     HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;\r
415 }\r
416 \r
417 bool CS_turnOnLFXTWithTimeout(uint16_t lfxtdrive,\r
418                               uint32_t timeout)\r
419 {\r
420     assert(privateLFXTClockFrequency != 0);\r
421 \r
422     assert((lfxtdrive == CS_LFXT_DRIVE_0) ||\r
423            (lfxtdrive == CS_LFXT_DRIVE_1) ||\r
424            (lfxtdrive == CS_LFXT_DRIVE_2) ||\r
425            (lfxtdrive == CS_LFXT_DRIVE_3));\r
426 \r
427     assert(timeout > 0);\r
428 \r
429     // Unlock CS control register\r
430     HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;\r
431 \r
432     //Switch ON LFXT oscillator\r
433     HWREG16(CS_BASE + OFS_CSCTL4) &= ~LFXTOFF;\r
434 \r
435     //Highest drive setting for LFXTstartup\r
436     HWREG16(CS_BASE + OFS_CSCTL4_L) |= LFXTDRIVE1_L + LFXTDRIVE0_L;\r
437 \r
438     HWREG16(CS_BASE + OFS_CSCTL4) &= ~LFXTBYPASS;\r
439 \r
440     while((HWREG8(CS_BASE + OFS_CSCTL5) & LFXTOFFG) && --timeout)\r
441     {\r
442         //Clear OSC fault Flags fault flags\r
443         HWREG8(CS_BASE + OFS_CSCTL5) &= ~(LFXTOFFG);\r
444 \r
445         // Clear the global fault flag. In case the LFXT caused the global fault\r
446         // flag to get set this will clear the global error condition. If any\r
447         // error condition persists, global flag will get again.\r
448         HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG;\r
449     }\r
450 \r
451     if(timeout)\r
452     {\r
453         //set requested Drive mode\r
454         HWREG16(CS_BASE + OFS_CSCTL4) = (HWREG16(CS_BASE + OFS_CSCTL4) &\r
455                                          ~(LFXTDRIVE_3)\r
456                                          ) |\r
457                                         (lfxtdrive);\r
458         // Lock CS control register\r
459         HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;\r
460         return (STATUS_SUCCESS);\r
461     }\r
462     else\r
463     {\r
464         // Lock CS control register\r
465         HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;\r
466         return (STATUS_FAIL);\r
467     }\r
468 }\r
469 \r
470 bool CS_bypassLFXTWithTimeout(uint32_t timeout)\r
471 {\r
472     assert(privateLFXTClockFrequency != 0);\r
473 \r
474     assert(privateLFXTClockFrequency < LFXT_FREQUENCY_THRESHOLD);\r
475 \r
476     assert(timeout > 0);\r
477 \r
478     // Unlock CS control register\r
479     HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;\r
480 \r
481     // Set LFXT in LF mode Switch off LFXT oscillator and enable BYPASS mode\r
482     HWREG16(CS_BASE + OFS_CSCTL4) |= (LFXTBYPASS + LFXTOFF);\r
483 \r
484     while((HWREG8(CS_BASE + OFS_CSCTL5) & LFXTOFFG) && --timeout)\r
485     {\r
486         //Clear OSC fault Flags fault flags\r
487         HWREG8(CS_BASE + OFS_CSCTL5) &= ~(LFXTOFFG);\r
488 \r
489         // Clear the global fault flag. In case the LFXT caused the global fault\r
490         // flag to get set this will clear the global error condition. If any\r
491         // error condition persists, global flag will get again.\r
492         HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG;\r
493     }\r
494 \r
495     // Lock CS control register\r
496     HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;\r
497 \r
498     if(timeout)\r
499     {\r
500         return (STATUS_SUCCESS);\r
501     }\r
502     else\r
503     {\r
504         return (STATUS_FAIL);\r
505     }\r
506 }\r
507 \r
508 void CS_turnOffLFXT(void)\r
509 {\r
510     // Unlock CS control register\r
511     HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;\r
512 \r
513     //Switch off LFXT oscillator\r
514     HWREG16(CS_BASE + OFS_CSCTL4) |= LFXTOFF;\r
515 \r
516     // Lock CS control register\r
517     HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;\r
518 }\r
519 \r
520 void CS_turnOnHFXT(uint16_t hfxtdrive)\r
521 {\r
522     assert(privateHFXTClockFrequency != 0);\r
523 \r
524     assert((hfxtdrive == CS_HFXT_DRIVE_4MHZ_8MHZ) ||\r
525            (hfxtdrive == CS_HFXT_DRIVE_8MHZ_16MHZ) ||\r
526            (hfxtdrive == CS_HFXT_DRIVE_16MHZ_24MHZ)||\r
527            (hfxtdrive == CS_HFXT_DRIVE_24MHZ_32MHZ));\r
528 \r
529     // Unlock CS control register\r
530     HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;\r
531 \r
532     // Switch ON HFXT oscillator\r
533     HWREG16(CS_BASE + OFS_CSCTL4) &= ~HFXTOFF;\r
534 \r
535     //Disable HFXTBYPASS mode and Switch on HFXT oscillator\r
536     HWREG16(CS_BASE + OFS_CSCTL4) &= ~HFXTBYPASS;\r
537 \r
538     //If HFFrequency is 16MHz or above\r
539     if(privateHFXTClockFrequency > 16000000)\r
540     {\r
541         HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_3;\r
542     }\r
543     //If HFFrequency is between 8MHz and 16MHz\r
544     else if(privateHFXTClockFrequency > 8000000)\r
545     {\r
546         HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_2;\r
547     }\r
548     //If HFFrequency is between 0MHz and 4MHz\r
549     else if(privateHFXTClockFrequency < 4000000)\r
550     {\r
551         HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_0;\r
552     }\r
553     //If HFFrequency is between 4MHz and 8MHz\r
554     else\r
555     {\r
556         HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_1;\r
557     }\r
558 \r
559     while(HWREG8(CS_BASE + OFS_CSCTL5) & HFXTOFFG)\r
560     {\r
561         //Clear OSC flaut Flags\r
562         HWREG8(CS_BASE + OFS_CSCTL5) &= ~(HFXTOFFG);\r
563 \r
564         //Clear OFIFG fault flag\r
565         HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG;\r
566     }\r
567 \r
568     HWREG16(CS_BASE + OFS_CSCTL4) = (HWREG16(CS_BASE + OFS_CSCTL4) &\r
569                                      ~(CS_HFXT_DRIVE_24MHZ_32MHZ)\r
570                                      ) |\r
571                                     (hfxtdrive);\r
572 \r
573     // Lock CS control register\r
574     HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;\r
575 }\r
576 \r
577 void CS_bypassHFXT(void)\r
578 {\r
579     //Verify user has initialized value of HFXTClock\r
580     assert(privateHFXTClockFrequency != 0);\r
581 \r
582     // Unlock CS control register\r
583     HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;\r
584 \r
585     //Switch off HFXT oscillator and set it to BYPASS mode\r
586     HWREG16(CS_BASE + OFS_CSCTL4) |= (HFXTBYPASS + HFXTOFF);\r
587 \r
588     //Set correct HFFREQ bit for FR58xx/FR59xx devices\r
589 \r
590     //If HFFrequency is 16MHz or above\r
591     if(privateHFXTClockFrequency > 16000000)\r
592     {\r
593         HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_3;\r
594     }\r
595     //If HFFrequency is between 8MHz and 16MHz\r
596     else if(privateHFXTClockFrequency > 8000000)\r
597     {\r
598         HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_2;\r
599     }\r
600     //If HFFrequency is between 0MHz and 4MHz\r
601     else if(privateHFXTClockFrequency < 4000000)\r
602     {\r
603         HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_0;\r
604     }\r
605     //If HFFrequency is between 4MHz and 8MHz\r
606     else\r
607     {\r
608         HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_1;\r
609     }\r
610 \r
611     while(HWREG8(CS_BASE + OFS_CSCTL5) & HFXTOFFG)\r
612     {\r
613         //Clear OSC fault Flags\r
614         HWREG8(CS_BASE + OFS_CSCTL5) &= ~(HFXTOFFG);\r
615 \r
616         //Clear OFIFG fault flag\r
617         HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG;\r
618     }\r
619 \r
620     // Lock CS control register\r
621     HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;\r
622 }\r
623 \r
624 bool CS_turnOnHFXTWithTimeout(uint16_t hfxtdrive,\r
625                               uint32_t timeout)\r
626 {\r
627     //Verify user has initialized value of HFXTClock\r
628     assert(privateHFXTClockFrequency != 0);\r
629 \r
630     assert(timeout > 0);\r
631 \r
632     // Unlock CS control register\r
633     HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;\r
634 \r
635     //Switch on HFXT oscillator\r
636     HWREG16(CS_BASE + OFS_CSCTL4) &= ~HFXTOFF;\r
637 \r
638     // Disable HFXTBYPASS mode\r
639     HWREG16(CS_BASE + OFS_CSCTL4) &= ~HFXTBYPASS;\r
640 \r
641     //Set correct HFFREQ bit for FR58xx/FR59xx devices based\r
642     //on HFXTClockFrequency\r
643 \r
644     //If HFFrequency is 16MHz or above\r
645     if(privateHFXTClockFrequency > 16000000)\r
646     {\r
647         HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_3;\r
648     }\r
649     //If HFFrequency is between 8MHz and 16MHz\r
650     else if(privateHFXTClockFrequency > 8000000)\r
651     {\r
652         HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_2;\r
653     }\r
654     //If HFFrequency is between 0MHz and 4MHz\r
655     else if(privateHFXTClockFrequency < 4000000)\r
656     {\r
657         HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_0;\r
658     }\r
659     //If HFFrequency is between 4MHz and 8MHz\r
660     else\r
661     {\r
662         HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_1;\r
663     }\r
664 \r
665     while((HWREG8(CS_BASE + OFS_CSCTL5) & HFXTOFFG) && --timeout)\r
666     {\r
667         //Clear OSC fault Flags fault flags\r
668         HWREG8(CS_BASE + OFS_CSCTL5) &= ~(HFXTOFFG);\r
669 \r
670         // Clear the global fault flag. In case the LFXT caused the global fault\r
671         // flag to get set this will clear the global error condition. If any\r
672         // error condition persists, global flag will get again.\r
673         HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG;\r
674     }\r
675 \r
676     if(timeout)\r
677     {\r
678         //Set drive strength for HFXT\r
679         HWREG16(CS_BASE + OFS_CSCTL4) = (HWREG16(CS_BASE + OFS_CSCTL4) &\r
680                                          ~(CS_HFXT_DRIVE_24MHZ_32MHZ)\r
681                                          ) |\r
682                                         (hfxtdrive);\r
683         // Lock CS control register\r
684         HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;\r
685         return (STATUS_SUCCESS);\r
686     }\r
687     else\r
688     {\r
689         // Lock CS control register\r
690         HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;\r
691         return (STATUS_FAIL);\r
692     }\r
693 }\r
694 \r
695 bool CS_bypassHFXTWithTimeout(uint32_t timeout)\r
696 {\r
697     //Verify user has initialized value of HFXTClock\r
698     assert(privateHFXTClockFrequency != 0);\r
699 \r
700     assert(timeout > 0);\r
701 \r
702     // Unlock CS control register\r
703     HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;\r
704 \r
705     //If HFFrequency is 16MHz or above\r
706     if(privateHFXTClockFrequency > 16000000)\r
707     {\r
708         HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_3;\r
709     }\r
710     //If HFFrequency is between 8MHz and 16MHz\r
711     else if(privateHFXTClockFrequency > 8000000)\r
712     {\r
713         HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_2;\r
714     }\r
715     //If HFFrequency is between 0MHz and 4MHz\r
716     else if(privateHFXTClockFrequency < 4000000)\r
717     {\r
718         HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_0;\r
719     }\r
720     //If HFFrequency is between 4MHz and 8MHz\r
721     else\r
722     {\r
723         HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_1;\r
724     }\r
725 \r
726     //Switch off HFXT oscillator and enable BYPASS mode\r
727     HWREG16(CS_BASE + OFS_CSCTL4) |= (HFXTBYPASS + HFXTOFF);\r
728 \r
729     while((HWREG8(CS_BASE + OFS_CSCTL5) & HFXTOFFG) && --timeout)\r
730     {\r
731         //Clear OSC fault Flags fault flags\r
732         HWREG8(CS_BASE + OFS_CSCTL5) &= ~(HFXTOFFG);\r
733 \r
734         // Clear the global fault flag. In case the LFXT caused the global fault\r
735         // flag to get set this will clear the global error condition. If any\r
736         // error condition persists, global flag will get again.\r
737         HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG;\r
738     }\r
739 \r
740     // Lock CS control register\r
741     HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;\r
742 \r
743     if(timeout)\r
744     {\r
745         return (STATUS_SUCCESS);\r
746     }\r
747     else\r
748     {\r
749         return (STATUS_FAIL);\r
750     }\r
751 }\r
752 \r
753 void CS_turnOffHFXT(void)\r
754 {\r
755     // Unlock CS control register\r
756     HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;\r
757 \r
758     //Switch off HFXT oscillator\r
759     HWREG16(CS_BASE + OFS_CSCTL4) |= HFXTOFF;\r
760 \r
761     // Lock CS control register\r
762     HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;\r
763 }\r
764 \r
765 void CS_enableClockRequest(uint8_t selectClock)\r
766 {\r
767     assert(\r
768         (CS_ACLK == selectClock)||\r
769         (CS_SMCLK == selectClock)||\r
770         (CS_MCLK == selectClock)||\r
771         (CS_MODOSC == selectClock));\r
772 \r
773     // Unlock CS control register\r
774     HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;\r
775 \r
776     HWREG8(CS_BASE + OFS_CSCTL6) |= selectClock;\r
777 \r
778     // Lock CS control register\r
779     HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;\r
780 }\r
781 \r
782 void CS_disableClockRequest(uint8_t selectClock)\r
783 {\r
784     assert(\r
785         (CS_ACLK == selectClock)||\r
786         (CS_SMCLK == selectClock)||\r
787         (CS_MCLK == selectClock)||\r
788         (CS_MODOSC == selectClock));\r
789 \r
790     // Unlock CS control register\r
791     HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;\r
792 \r
793     HWREG8(CS_BASE + OFS_CSCTL6) &= ~selectClock;\r
794 \r
795     // Lock CS control register\r
796     HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;\r
797 }\r
798 \r
799 uint8_t CS_getFaultFlagStatus(uint8_t mask)\r
800 {\r
801     assert(\r
802         (CS_HFXTOFFG == mask)||\r
803         (CS_LFXTOFFG == mask)\r
804         );\r
805     return (HWREG8(CS_BASE + OFS_CSCTL5) & mask);\r
806 }\r
807 \r
808 void CS_clearFaultFlag(uint8_t mask)\r
809 {\r
810     assert(\r
811         (CS_HFXTOFFG == mask)||\r
812         (CS_LFXTOFFG == mask)\r
813         );\r
814 \r
815     // Unlock CS control register\r
816     HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;\r
817 \r
818     HWREG8(CS_BASE + OFS_CSCTL5) &= ~mask;\r
819 \r
820     // Lock CS control register\r
821     HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;\r
822 }\r
823 \r
824 uint32_t CS_getACLK(void)\r
825 {\r
826     //Find ACLK source\r
827     uint16_t ACLKSource = (HWREG16(CS_BASE + OFS_CSCTL2) & SELA_7);\r
828     ACLKSource = ACLKSource >> 8;\r
829 \r
830     //Find ACLK frequency divider\r
831     uint16_t ACLKSourceDivider = HWREG16(CS_BASE + OFS_CSCTL3) & SELA_7;\r
832     ACLKSourceDivider = ACLKSourceDivider >> 8;\r
833 \r
834     return (privateCSAComputeCLKFrequency(\r
835                 ACLKSource,\r
836                 ACLKSourceDivider));\r
837 }\r
838 \r
839 uint32_t CS_getSMCLK(void)\r
840 {\r
841     //Find SMCLK source\r
842     uint16_t SMCLKSource = HWREG8(CS_BASE + OFS_CSCTL2) & SELS_7;\r
843 \r
844     SMCLKSource = SMCLKSource >> 4;\r
845 \r
846     //Find SMCLK frequency divider\r
847     uint16_t SMCLKSourceDivider = HWREG16(CS_BASE + OFS_CSCTL3) & SELS_7;\r
848     SMCLKSourceDivider = SMCLKSourceDivider >> 4;\r
849 \r
850     return (privateCSAComputeCLKFrequency(\r
851                 SMCLKSource,\r
852                 SMCLKSourceDivider)\r
853             );\r
854 }\r
855 \r
856 uint32_t CS_getMCLK(void)\r
857 {\r
858     //Find MCLK source\r
859     uint16_t MCLKSource = (HWREG16(CS_BASE + OFS_CSCTL2) & SELM_7);\r
860     //Find MCLK frequency divider\r
861     uint16_t MCLKSourceDivider = HWREG16(CS_BASE + OFS_CSCTL3) & SELM_7;\r
862 \r
863     return (privateCSAComputeCLKFrequency(\r
864                 MCLKSource,\r
865                 MCLKSourceDivider)\r
866             );\r
867 }\r
868 \r
869 void CS_turnOffVLO(void)\r
870 {\r
871     // Unlock CS control register\r
872     HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;\r
873 \r
874     HWREG16(CS_BASE + OFS_CSCTL4) |= VLOOFF;\r
875 \r
876     // Lock CS control register\r
877     HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;\r
878 }\r
879 \r
880 uint16_t CS_clearAllOscFlagsWithTimeout(uint32_t timeout)\r
881 {\r
882     assert(timeout > 0);\r
883 \r
884     // Unlock CS control register\r
885     HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;\r
886 \r
887     do\r
888     {\r
889         // Clear all osc fault flags\r
890         HWREG8(CS_BASE + OFS_CSCTL5) &= ~(LFXTOFFG + HFXTOFFG);\r
891 \r
892         // Clear the global osc fault flag.\r
893         HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG;\r
894 \r
895         // Check LFXT fault flags\r
896     }\r
897     while((HWREG8(SFR_BASE + OFS_SFRIFG1) & OFIFG) && --timeout);\r
898 \r
899     // Lock CS control register\r
900     HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;\r
901 \r
902     return (HWREG8(CS_BASE + OFS_CSCTL5) & (LFXTOFFG + HFXTOFFG));\r
903 }\r
904 \r
905 void CS_setDCOFreq(uint16_t dcorsel,\r
906                    uint16_t dcofsel)\r
907 {\r
908     assert(\r
909         (dcofsel == CS_DCOFSEL_0)||\r
910         (dcofsel == CS_DCOFSEL_1)||\r
911         (dcofsel == CS_DCOFSEL_2)||\r
912         (dcofsel == CS_DCOFSEL_3)||\r
913         (dcofsel == CS_DCOFSEL_4)||\r
914         (dcofsel == CS_DCOFSEL_5)||\r
915         (dcofsel == CS_DCOFSEL_6)\r
916         );\r
917 \r
918     //Verify user has selected a valid DCO Frequency Range option\r
919     assert(\r
920         (dcorsel == CS_DCORSEL_0)||\r
921         (dcorsel == CS_DCORSEL_1));\r
922 \r
923     //Unlock CS control register\r
924     HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;\r
925 \r
926     // Set user's frequency selection for DCO\r
927     HWREG16(CS_BASE + OFS_CSCTL1) = (dcorsel + dcofsel);\r
928 \r
929     // Lock CS control register\r
930     HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;\r
931 }\r
932 \r
933 #endif\r
934 //*****************************************************************************\r
935 //\r
936 //! Close the doxygen group for cs_api\r
937 //! @}\r
938 //\r
939 //*****************************************************************************\r