2 * Copyright (c) 2014, Texas Instruments Incorporated
\r
3 * All rights reserved.
\r
5 * Redistribution and use in source and binary forms, with or without
\r
6 * modification, are permitted provided that the following conditions
\r
9 * * Redistributions of source code must retain the above copyright
\r
10 * notice, this list of conditions and the following disclaimer.
\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
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
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
32 //*****************************************************************************
\r
34 // cs.c - Driver for the cs Module.
\r
36 //*****************************************************************************
\r
38 //*****************************************************************************
\r
40 //! \addtogroup cs_api cs
\r
43 //*****************************************************************************
\r
45 #include "inc/hw_regaccess.h"
\r
46 #include "inc/hw_memmap.h"
\r
48 #if defined(__MSP430_HAS_CS__) || defined(__MSP430_HAS_SFR__)
\r
53 //*****************************************************************************
\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
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
70 //*****************************************************************************
\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
76 //*****************************************************************************
\r
77 #define CS_VLOCLK_FREQUENCY 10000
\r
78 #define CS_MODCLK_FREQUENCY 5000000
\r
79 #define CS_LFMODCLK_FREQUENCY 39062
\r
81 //*****************************************************************************
\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
87 //*****************************************************************************
\r
88 #define LFXT_FREQUENCY_THRESHOLD 50000
\r
90 //*****************************************************************************
\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
98 //*****************************************************************************
\r
99 static uint32_t privateLFXTClockFrequency = 0;
\r
101 //*****************************************************************************
\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
109 //*****************************************************************************
\r
110 static uint32_t privateHFXTClockFrequency = 0;
\r
112 static uint32_t privateCSASourceClockFromDCO(uint8_t clockdivider)
\r
114 uint32_t CLKFrequency = 0;
\r
116 if(HWREG16(CS_BASE + OFS_CSCTL1) & DCORSEL)
\r
118 switch(HWREG16(CS_BASE + OFS_CSCTL1) & DCOFSEL_7)
\r
121 CLKFrequency = CS_DCO_FREQ_1 / clockdivider;
\r
124 CLKFrequency = CS_DCO_FREQ_5 / clockdivider;
\r
127 CLKFrequency = CS_DCO_FREQ_6 / clockdivider;
\r
130 CLKFrequency = CS_DCO_FREQ_7 / clockdivider;
\r
133 CLKFrequency = CS_DCO_FREQ_8 / clockdivider;
\r
136 CLKFrequency = CS_DCO_FREQ_9 / clockdivider;
\r
140 CLKFrequency = CS_DCO_FREQ_10 / clockdivider;
\r
149 switch(HWREG16(CS_BASE + OFS_CSCTL1) & DCOFSEL_7)
\r
152 CLKFrequency = CS_DCO_FREQ_1 / clockdivider;
\r
155 CLKFrequency = CS_DCO_FREQ_2 / clockdivider;
\r
158 CLKFrequency = CS_DCO_FREQ_3 / clockdivider;
\r
161 CLKFrequency = CS_DCO_FREQ_4 / clockdivider;
\r
164 CLKFrequency = CS_DCO_FREQ_5 / clockdivider;
\r
167 CLKFrequency = CS_DCO_FREQ_6 / clockdivider;
\r
171 CLKFrequency = CS_DCO_FREQ_7 / clockdivider;
\r
179 return (CLKFrequency);
\r
182 static uint32_t privateCSAComputeCLKFrequency(uint16_t CLKSource,
\r
183 uint16_t CLKSourceDivider)
\r
185 uint32_t CLKFrequency = 0;
\r
186 uint8_t CLKSourceFrequencyDivider = 1;
\r
189 // Determine Frequency divider
\r
190 for(i = 0; i < CLKSourceDivider; i++)
\r
192 CLKSourceFrequencyDivider *= 2;
\r
195 // Unlock CS control register
\r
196 HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;
\r
198 // Determine clock source based on CLKSource
\r
201 // If LFXT is selected as clock source
\r
202 case SELM__LFXTCLK:
\r
203 CLKFrequency = (privateLFXTClockFrequency /
\r
204 CLKSourceFrequencyDivider);
\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
210 HWREG8(CS_BASE + OFS_CSCTL5) &= ~(LFXTOFFG);
\r
211 //Clear OFIFG fault flag
\r
212 HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG;
\r
214 if(HWREG8(CS_BASE + OFS_CSCTL5) & LFXTOFFG)
\r
216 CLKFrequency = CS_LFMODCLK_FREQUENCY;
\r
223 (CS_VLOCLK_FREQUENCY / CLKSourceFrequencyDivider);
\r
226 case SELM__LFMODOSC:
\r
228 (CS_LFMODCLK_FREQUENCY / CLKSourceFrequencyDivider);
\r
234 privateCSASourceClockFromDCO(CLKSourceFrequencyDivider);
\r
240 (CS_MODCLK_FREQUENCY / CLKSourceFrequencyDivider);
\r
244 case SELM__HFXTCLK:
\r
246 (privateHFXTClockFrequency / CLKSourceFrequencyDivider);
\r
248 if(HWREG8(CS_BASE + OFS_CSCTL5) & HFXTOFFG)
\r
250 HWREG8(CS_BASE + OFS_CSCTL5) &= ~HFXTOFFG;
\r
251 //Clear OFIFG fault flag
\r
252 HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG;
\r
255 if(HWREG8(CS_BASE + OFS_CSCTL5) & HFXTOFFG)
\r
257 CLKFrequency = CS_MODCLK_FREQUENCY;
\r
262 // Lock CS control register
\r
263 HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;
\r
265 return (CLKFrequency);
\r
268 void CS_setExternalClockSource(uint32_t LFXTCLK_frequency,
\r
269 uint32_t HFXTCLK_frequency)
\r
271 privateLFXTClockFrequency = LFXTCLK_frequency;
\r
272 privateHFXTClockFrequency = HFXTCLK_frequency;
\r
275 void CS_initClockSignal(uint8_t selectedClockSignal,
\r
276 uint16_t clockSource,
\r
277 uint16_t clockSourceDivider)
\r
279 //Verify User has selected a valid Frequency divider
\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
289 // Unlock CS control register
\r
290 HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;
\r
292 switch(selectedClockSignal)
\r
296 (CS_LFXTCLK_SELECT == clockSource) ||
\r
297 (CS_VLOCLK_SELECT == clockSource) ||
\r
298 (CS_LFMODOSC_SELECT == clockSource)
\r
301 clockSourceDivider = clockSourceDivider << 8;
\r
302 clockSource = clockSource << 8;
\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
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
319 clockSource = clockSource << 4;
\r
320 clockSourceDivider = clockSourceDivider << 4;
\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
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
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
344 // Lock CS control register
\r
345 HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;
\r
348 void CS_turnOnLFXT(uint16_t lfxtdrive)
\r
350 assert(privateLFXTClockFrequency != 0);
\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
357 // Unlock CS control register
\r
358 HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;
\r
360 //Switch ON LFXT oscillator
\r
361 HWREG16(CS_BASE + OFS_CSCTL4) &= ~LFXTOFF;
\r
363 //Highest drive setting for LFXTstartup
\r
364 HWREG16(CS_BASE + OFS_CSCTL4_L) |= LFXTDRIVE1_L + LFXTDRIVE0_L;
\r
366 HWREG16(CS_BASE + OFS_CSCTL4) &= ~LFXTBYPASS;
\r
368 //Wait for Crystal to stabilize
\r
369 while(HWREG8(CS_BASE + OFS_CSCTL5) & LFXTOFFG)
\r
371 //Clear OSC flaut Flags fault flags
\r
372 HWREG8(CS_BASE + OFS_CSCTL5) &= ~(LFXTOFFG);
\r
374 //Clear OFIFG fault flag
\r
375 HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG;
\r
378 //set requested Drive mode
\r
379 HWREG16(CS_BASE + OFS_CSCTL4) = (HWREG16(CS_BASE + OFS_CSCTL4) &
\r
384 // Lock CS control register
\r
385 HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;
\r
388 void CS_bypassLFXT(void)
\r
390 //Verify user has set frequency of LFXT with SetExternalClockSource
\r
391 assert(privateLFXTClockFrequency != 0);
\r
393 // Unlock CS control register
\r
394 HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;
\r
396 assert(privateLFXTClockFrequency < LFXT_FREQUENCY_THRESHOLD);
\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
401 //Wait until LFXT stabilizes
\r
402 while(HWREG8(CS_BASE + OFS_CSCTL5) & LFXTOFFG)
\r
404 //Clear OSC flaut Flags fault flags
\r
405 HWREG8(CS_BASE + OFS_CSCTL5) &= ~(LFXTOFFG);
\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
413 // Lock CS control register
\r
414 HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;
\r
417 bool CS_turnOnLFXTWithTimeout(uint16_t lfxtdrive,
\r
420 assert(privateLFXTClockFrequency != 0);
\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
427 assert(timeout > 0);
\r
429 // Unlock CS control register
\r
430 HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;
\r
432 //Switch ON LFXT oscillator
\r
433 HWREG16(CS_BASE + OFS_CSCTL4) &= ~LFXTOFF;
\r
435 //Highest drive setting for LFXTstartup
\r
436 HWREG16(CS_BASE + OFS_CSCTL4_L) |= LFXTDRIVE1_L + LFXTDRIVE0_L;
\r
438 HWREG16(CS_BASE + OFS_CSCTL4) &= ~LFXTBYPASS;
\r
440 while((HWREG8(CS_BASE + OFS_CSCTL5) & LFXTOFFG) && --timeout)
\r
442 //Clear OSC fault Flags fault flags
\r
443 HWREG8(CS_BASE + OFS_CSCTL5) &= ~(LFXTOFFG);
\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
453 //set requested Drive mode
\r
454 HWREG16(CS_BASE + OFS_CSCTL4) = (HWREG16(CS_BASE + OFS_CSCTL4) &
\r
458 // Lock CS control register
\r
459 HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;
\r
460 return (STATUS_SUCCESS);
\r
464 // Lock CS control register
\r
465 HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;
\r
466 return (STATUS_FAIL);
\r
470 bool CS_bypassLFXTWithTimeout(uint32_t timeout)
\r
472 assert(privateLFXTClockFrequency != 0);
\r
474 assert(privateLFXTClockFrequency < LFXT_FREQUENCY_THRESHOLD);
\r
476 assert(timeout > 0);
\r
478 // Unlock CS control register
\r
479 HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;
\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
484 while((HWREG8(CS_BASE + OFS_CSCTL5) & LFXTOFFG) && --timeout)
\r
486 //Clear OSC fault Flags fault flags
\r
487 HWREG8(CS_BASE + OFS_CSCTL5) &= ~(LFXTOFFG);
\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
495 // Lock CS control register
\r
496 HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;
\r
500 return (STATUS_SUCCESS);
\r
504 return (STATUS_FAIL);
\r
508 void CS_turnOffLFXT(void)
\r
510 // Unlock CS control register
\r
511 HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;
\r
513 //Switch off LFXT oscillator
\r
514 HWREG16(CS_BASE + OFS_CSCTL4) |= LFXTOFF;
\r
516 // Lock CS control register
\r
517 HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;
\r
520 void CS_turnOnHFXT(uint16_t hfxtdrive)
\r
522 assert(privateHFXTClockFrequency != 0);
\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
529 // Unlock CS control register
\r
530 HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;
\r
532 // Switch ON HFXT oscillator
\r
533 HWREG16(CS_BASE + OFS_CSCTL4) &= ~HFXTOFF;
\r
535 //Disable HFXTBYPASS mode and Switch on HFXT oscillator
\r
536 HWREG16(CS_BASE + OFS_CSCTL4) &= ~HFXTBYPASS;
\r
538 //If HFFrequency is 16MHz or above
\r
539 if(privateHFXTClockFrequency > 16000000)
\r
541 HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_3;
\r
543 //If HFFrequency is between 8MHz and 16MHz
\r
544 else if(privateHFXTClockFrequency > 8000000)
\r
546 HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_2;
\r
548 //If HFFrequency is between 0MHz and 4MHz
\r
549 else if(privateHFXTClockFrequency < 4000000)
\r
551 HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_0;
\r
553 //If HFFrequency is between 4MHz and 8MHz
\r
556 HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_1;
\r
559 while(HWREG8(CS_BASE + OFS_CSCTL5) & HFXTOFFG)
\r
561 //Clear OSC flaut Flags
\r
562 HWREG8(CS_BASE + OFS_CSCTL5) &= ~(HFXTOFFG);
\r
564 //Clear OFIFG fault flag
\r
565 HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG;
\r
568 HWREG16(CS_BASE + OFS_CSCTL4) = (HWREG16(CS_BASE + OFS_CSCTL4) &
\r
569 ~(CS_HFXT_DRIVE_24MHZ_32MHZ)
\r
573 // Lock CS control register
\r
574 HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;
\r
577 void CS_bypassHFXT(void)
\r
579 //Verify user has initialized value of HFXTClock
\r
580 assert(privateHFXTClockFrequency != 0);
\r
582 // Unlock CS control register
\r
583 HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;
\r
585 //Switch off HFXT oscillator and set it to BYPASS mode
\r
586 HWREG16(CS_BASE + OFS_CSCTL4) |= (HFXTBYPASS + HFXTOFF);
\r
588 //Set correct HFFREQ bit for FR58xx/FR59xx devices
\r
590 //If HFFrequency is 16MHz or above
\r
591 if(privateHFXTClockFrequency > 16000000)
\r
593 HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_3;
\r
595 //If HFFrequency is between 8MHz and 16MHz
\r
596 else if(privateHFXTClockFrequency > 8000000)
\r
598 HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_2;
\r
600 //If HFFrequency is between 0MHz and 4MHz
\r
601 else if(privateHFXTClockFrequency < 4000000)
\r
603 HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_0;
\r
605 //If HFFrequency is between 4MHz and 8MHz
\r
608 HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_1;
\r
611 while(HWREG8(CS_BASE + OFS_CSCTL5) & HFXTOFFG)
\r
613 //Clear OSC fault Flags
\r
614 HWREG8(CS_BASE + OFS_CSCTL5) &= ~(HFXTOFFG);
\r
616 //Clear OFIFG fault flag
\r
617 HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG;
\r
620 // Lock CS control register
\r
621 HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;
\r
624 bool CS_turnOnHFXTWithTimeout(uint16_t hfxtdrive,
\r
627 //Verify user has initialized value of HFXTClock
\r
628 assert(privateHFXTClockFrequency != 0);
\r
630 assert(timeout > 0);
\r
632 // Unlock CS control register
\r
633 HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;
\r
635 //Switch on HFXT oscillator
\r
636 HWREG16(CS_BASE + OFS_CSCTL4) &= ~HFXTOFF;
\r
638 // Disable HFXTBYPASS mode
\r
639 HWREG16(CS_BASE + OFS_CSCTL4) &= ~HFXTBYPASS;
\r
641 //Set correct HFFREQ bit for FR58xx/FR59xx devices based
\r
642 //on HFXTClockFrequency
\r
644 //If HFFrequency is 16MHz or above
\r
645 if(privateHFXTClockFrequency > 16000000)
\r
647 HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_3;
\r
649 //If HFFrequency is between 8MHz and 16MHz
\r
650 else if(privateHFXTClockFrequency > 8000000)
\r
652 HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_2;
\r
654 //If HFFrequency is between 0MHz and 4MHz
\r
655 else if(privateHFXTClockFrequency < 4000000)
\r
657 HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_0;
\r
659 //If HFFrequency is between 4MHz and 8MHz
\r
662 HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_1;
\r
665 while((HWREG8(CS_BASE + OFS_CSCTL5) & HFXTOFFG) && --timeout)
\r
667 //Clear OSC fault Flags fault flags
\r
668 HWREG8(CS_BASE + OFS_CSCTL5) &= ~(HFXTOFFG);
\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
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
683 // Lock CS control register
\r
684 HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;
\r
685 return (STATUS_SUCCESS);
\r
689 // Lock CS control register
\r
690 HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;
\r
691 return (STATUS_FAIL);
\r
695 bool CS_bypassHFXTWithTimeout(uint32_t timeout)
\r
697 //Verify user has initialized value of HFXTClock
\r
698 assert(privateHFXTClockFrequency != 0);
\r
700 assert(timeout > 0);
\r
702 // Unlock CS control register
\r
703 HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;
\r
705 //If HFFrequency is 16MHz or above
\r
706 if(privateHFXTClockFrequency > 16000000)
\r
708 HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_3;
\r
710 //If HFFrequency is between 8MHz and 16MHz
\r
711 else if(privateHFXTClockFrequency > 8000000)
\r
713 HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_2;
\r
715 //If HFFrequency is between 0MHz and 4MHz
\r
716 else if(privateHFXTClockFrequency < 4000000)
\r
718 HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_0;
\r
720 //If HFFrequency is between 4MHz and 8MHz
\r
723 HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_1;
\r
726 //Switch off HFXT oscillator and enable BYPASS mode
\r
727 HWREG16(CS_BASE + OFS_CSCTL4) |= (HFXTBYPASS + HFXTOFF);
\r
729 while((HWREG8(CS_BASE + OFS_CSCTL5) & HFXTOFFG) && --timeout)
\r
731 //Clear OSC fault Flags fault flags
\r
732 HWREG8(CS_BASE + OFS_CSCTL5) &= ~(HFXTOFFG);
\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
740 // Lock CS control register
\r
741 HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;
\r
745 return (STATUS_SUCCESS);
\r
749 return (STATUS_FAIL);
\r
753 void CS_turnOffHFXT(void)
\r
755 // Unlock CS control register
\r
756 HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;
\r
758 //Switch off HFXT oscillator
\r
759 HWREG16(CS_BASE + OFS_CSCTL4) |= HFXTOFF;
\r
761 // Lock CS control register
\r
762 HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;
\r
765 void CS_enableClockRequest(uint8_t selectClock)
\r
768 (CS_ACLK == selectClock)||
\r
769 (CS_SMCLK == selectClock)||
\r
770 (CS_MCLK == selectClock)||
\r
771 (CS_MODOSC == selectClock));
\r
773 // Unlock CS control register
\r
774 HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;
\r
776 HWREG8(CS_BASE + OFS_CSCTL6) |= selectClock;
\r
778 // Lock CS control register
\r
779 HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;
\r
782 void CS_disableClockRequest(uint8_t selectClock)
\r
785 (CS_ACLK == selectClock)||
\r
786 (CS_SMCLK == selectClock)||
\r
787 (CS_MCLK == selectClock)||
\r
788 (CS_MODOSC == selectClock));
\r
790 // Unlock CS control register
\r
791 HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;
\r
793 HWREG8(CS_BASE + OFS_CSCTL6) &= ~selectClock;
\r
795 // Lock CS control register
\r
796 HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;
\r
799 uint8_t CS_getFaultFlagStatus(uint8_t mask)
\r
802 (CS_HFXTOFFG == mask)||
\r
803 (CS_LFXTOFFG == mask)
\r
805 return (HWREG8(CS_BASE + OFS_CSCTL5) & mask);
\r
808 void CS_clearFaultFlag(uint8_t mask)
\r
811 (CS_HFXTOFFG == mask)||
\r
812 (CS_LFXTOFFG == mask)
\r
815 // Unlock CS control register
\r
816 HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;
\r
818 HWREG8(CS_BASE + OFS_CSCTL5) &= ~mask;
\r
820 // Lock CS control register
\r
821 HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;
\r
824 uint32_t CS_getACLK(void)
\r
827 uint16_t ACLKSource = (HWREG16(CS_BASE + OFS_CSCTL2) & SELA_7);
\r
828 ACLKSource = ACLKSource >> 8;
\r
830 //Find ACLK frequency divider
\r
831 uint16_t ACLKSourceDivider = HWREG16(CS_BASE + OFS_CSCTL3) & SELA_7;
\r
832 ACLKSourceDivider = ACLKSourceDivider >> 8;
\r
834 return (privateCSAComputeCLKFrequency(
\r
836 ACLKSourceDivider));
\r
839 uint32_t CS_getSMCLK(void)
\r
841 //Find SMCLK source
\r
842 uint16_t SMCLKSource = HWREG8(CS_BASE + OFS_CSCTL2) & SELS_7;
\r
844 SMCLKSource = SMCLKSource >> 4;
\r
846 //Find SMCLK frequency divider
\r
847 uint16_t SMCLKSourceDivider = HWREG16(CS_BASE + OFS_CSCTL3) & SELS_7;
\r
848 SMCLKSourceDivider = SMCLKSourceDivider >> 4;
\r
850 return (privateCSAComputeCLKFrequency(
\r
852 SMCLKSourceDivider)
\r
856 uint32_t CS_getMCLK(void)
\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
863 return (privateCSAComputeCLKFrequency(
\r
869 void CS_turnOffVLO(void)
\r
871 // Unlock CS control register
\r
872 HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;
\r
874 HWREG16(CS_BASE + OFS_CSCTL4) |= VLOOFF;
\r
876 // Lock CS control register
\r
877 HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;
\r
880 uint16_t CS_clearAllOscFlagsWithTimeout(uint32_t timeout)
\r
882 assert(timeout > 0);
\r
884 // Unlock CS control register
\r
885 HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;
\r
889 // Clear all osc fault flags
\r
890 HWREG8(CS_BASE + OFS_CSCTL5) &= ~(LFXTOFFG + HFXTOFFG);
\r
892 // Clear the global osc fault flag.
\r
893 HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG;
\r
895 // Check LFXT fault flags
\r
897 while((HWREG8(SFR_BASE + OFS_SFRIFG1) & OFIFG) && --timeout);
\r
899 // Lock CS control register
\r
900 HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;
\r
902 return (HWREG8(CS_BASE + OFS_CSCTL5) & (LFXTOFFG + HFXTOFFG));
\r
905 void CS_setDCOFreq(uint16_t dcorsel,
\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
918 //Verify user has selected a valid DCO Frequency Range option
\r
920 (dcorsel == CS_DCORSEL_0)||
\r
921 (dcorsel == CS_DCORSEL_1));
\r
923 //Unlock CS control register
\r
924 HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY;
\r
926 // Set user's frequency selection for DCO
\r
927 HWREG16(CS_BASE + OFS_CSCTL1) = (dcorsel + dcofsel);
\r
929 // Lock CS control register
\r
930 HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00;
\r
934 //*****************************************************************************
\r
936 //! Close the doxygen group for cs_api
\r
939 //*****************************************************************************
\r