1 /*******************************************************************************
2  *
3  * HAL_UCS.c
4  * Provides Functions to Initialize the UCS/FLL and clock sources
5  *
6  *
7  * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
8  *
9  *
10  *  Redistribution and use in source and binary forms, with or without
11  *  modification, are permitted provided that the following conditions
12  *  are met:
13  *
14  *    Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  *
17  *    Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the
20  *    distribution.
21  *
22  *    Neither the name of Texas Instruments Incorporated nor the names of
23  *    its contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37  *
38  * Created: Version 1.0 11/24/2009
39  * Updated: Version 2.0 12/15/2010
40  *          Added Functions: XT2_Stop() and XT1_Stop()
41  *          Modified all functions to preserve drive settings
42  *
43  ******************************************************************************/
44 
45 #include "msp430.h"
46 #include "HAL_UCS.h"
47 
48 /*******************************************************************************
49  * Check and define required Defines
50  ******************************************************************************/
51 #ifndef XT1LFOFFG               // Defines if not available in header file
52 #define XT1LFOFFG   0
53 #endif
54 
55 #ifndef XT1HFOFFG               // Defines if not available in header file
56 #define XT1HFOFFG   0
57 #endif
58 
59 #ifndef XT2OFFG                 // Defines if not available in header file
60 #define XT2OFFG     0
61 #endif
62 
63 #ifndef XTS                     // Defines if not available in header file
64 #define XTS         0
65 #endif
66 
67 #ifndef XT2DRIVE_3              // Defines if not available in header file
68 #define XT2DRIVE_3  0
69 #endif
70 
LFXT_Start(uint16_t xtdrive)71 void LFXT_Start(uint16_t xtdrive)
72 {
73   // If the drive setting is not already set to maximum
74   // Set it to max for LFXT startup
75   if ((UCSCTL6 & XT1DRIVE_3)!= XT1DRIVE_3) {
76     UCSCTL6_L |= XT1DRIVE1_L + XT1DRIVE0_L; // Highest drive setting for XT1startup
77   }
78 
79   while (SFRIFG1 & OFIFG) {   // Check OFIFG fault flag
80     UCSCTL7 &= ~(DCOFFG+XT1LFOFFG+XT1HFOFFG+XT2OFFG); // Clear OSC flaut Flags fault flags
81     SFRIFG1 &= ~OFIFG;        // Clear OFIFG fault flag
82   }
83 
84   UCSCTL6 = (UCSCTL6 & ~(XT1DRIVE_3)) | (xtdrive); // set requested Drive mode
85 }
86 
LFXT_Start_Timeout(uint16_t xtdrive,uint16_t timeout)87 uint16_t LFXT_Start_Timeout(uint16_t xtdrive, uint16_t timeout)
88 {
89  // If the drive setting is not already set to maximum
90   // Set it to max for LFXT startup
91   if ((UCSCTL6 & XT1DRIVE_3)!= XT1DRIVE_3) {
92    UCSCTL6_L |= XT1DRIVE1_L+XT1DRIVE0_L; // Highest drive setting for XT1startup
93   }
94 
95   while ((SFRIFG1 & OFIFG) && timeout--){   // Check OFIFG fault flag
96     UCSCTL7 &= ~(DCOFFG+XT1LFOFFG+XT1HFOFFG+XT2OFFG); // Clear OSC flaut Flags fault flags
97     SFRIFG1 &= ~OFIFG;        // Clear OFIFG fault flag
98   }
99 
100   UCSCTL6 = (UCSCTL6 & ~(XT1DRIVE_3)) |(xtdrive); // set Drive mode
101 
102   if (timeout)
103     return (UCS_STATUS_OK);
104   else
105     return (UCS_STATUS_ERROR);
106 }
107 
XT1_Start(uint16_t xtdrive)108 void XT1_Start(uint16_t xtdrive)
109 {
110   // Check if drive value is the expected one
111   if ((UCSCTL6 & XT1DRIVE_3) != xtdrive) {
112     UCSCTL6 &= ~XT1DRIVE_3;                 // Clear XT1drive field
113     UCSCTL6 |= xtdrive;                     // Set requested value
114   }
115 
116   UCSCTL6 &= ~XT1OFF;                       // Enable XT1
117   UCSCTL6 |= XTS;                           // Enable HF mode
118 
119   while (SFRIFG1 & OFIFG) {   // Check OFIFG fault flag
120     UCSCTL7 &= ~(DCOFFG+XT1LFOFFG+XT1HFOFFG+XT2OFFG); // Clear OSC flaut Flags
121     SFRIFG1 &= ~OFIFG;        // Clear OFIFG fault flag
122   }
123 }
124 
XT1_Start_Timeout(uint16_t xtdrive,uint16_t timeout)125 uint16_t XT1_Start_Timeout(uint16_t xtdrive, uint16_t timeout)
126 {
127   // Check if drive value is the expected one
128   if ((UCSCTL6 & XT1DRIVE_3) != xtdrive) {
129     UCSCTL6 &= ~XT1DRIVE_3;                 // Clear XT1drive field
130     UCSCTL6 |= xtdrive;                     // Set requested value
131   }
132 
133   UCSCTL6 &= ~XT1OFF;                       // Enable XT1
134   UCSCTL6 |= XTS;                           // Enable HF mode
135 
136   while ((SFRIFG1 & OFIFG) && timeout--) {  // Check OFIFG fault flag
137     UCSCTL7 &= ~(DCOFFG+XT1LFOFFG+XT1HFOFFG+XT2OFFG); // Clear OSC flaut Flags
138     SFRIFG1 &= ~OFIFG;                      // Clear OFIFG fault flag
139   }
140 
141   if (timeout) {
142     return UCS_STATUS_OK;
143   }
144   else {
145     return UCS_STATUS_ERROR;
146   }
147 }
148 
XT1_Bypass(void)149 void XT1_Bypass(void)
150 {
151   UCSCTL6 |= XT1BYPASS;
152 
153   while (SFRIFG1 & OFIFG) {   // Check OFIFG fault flag
154     UCSCTL7 &= ~(DCOFFG+XT1LFOFFG+XT1HFOFFG+XT2OFFG); // Clear OSC flaut Flags
155     SFRIFG1 &= ~OFIFG;        // Clear OFIFG fault flag
156   }
157 }
158 
XT1_Stop(void)159 void XT1_Stop(void)
160 {
161   UCSCTL6 |= XT1OFF;                         // Switch off XT1 oscillator
162 }
163 
XT2_Start(uint16_t xtdrive)164 void XT2_Start(uint16_t xtdrive)
165 {
166     // Check if drive value is the expected one
167     if ((UCSCTL6 & XT2DRIVE_3) != xtdrive)
168     {
169         UCSCTL6 &= ~XT2DRIVE_3;                 // Clear XT2drive field
170         UCSCTL6 |= xtdrive;                     // Set requested value
171     }
172     UCSCTL6 &= ~XT2OFF;
173     while (SFRIFG1 & OFIFG)
174     {                 // Check OFIFG fault flag
175         UCSCTL7 &= ~(DCOFFG+XT1LFOFFG+XT1HFOFFG+XT2OFFG); // Clear OSC flaut Flags
176         SFRIFG1 &= ~OFIFG;                      // Clear OFIFG fault flag
177     }
178 }
179 
180 #pragma optimize = low
XT2_Start_Timeout(uint16_t xtdrive,uint16_t timeout)181 uint16_t XT2_Start_Timeout(uint16_t xtdrive, uint16_t timeout)
182 {
183     uint16_t timeoutint = timeout;
184     // Check if drive value is the expected one
185     if ((UCSCTL6 & XT2DRIVE_3) != xtdrive)
186     {
187         UCSCTL6 &= ~XT2DRIVE_3;                 // Clear XT2drive field
188         UCSCTL6 |= xtdrive;                     // Set requested value
189     }
190 
191     UCSCTL6 &= ~XT2OFF;
192 
193     while ((SFRIFG1 & OFIFG) && timeoutint--)
194     {  // Check OFIFG fault flag
195         UCSCTL7 &= ~(DCOFFG+XT1LFOFFG+XT1HFOFFG+XT2OFFG); // Clear OSC flaut Flags
196         SFRIFG1 &= ~OFIFG;
197     }
198 
199     if (timeoutint)
200     {
201         return UCS_STATUS_OK;
202     }
203     else
204     {
205         return UCS_STATUS_ERROR;
206     }
207 }
208 
XT2_Bypass(void)209 void XT2_Bypass(void)
210 {
211 #ifdef XT2BYPASS              // On devices without XT2 this function will be empty
212   UCSCTL6 |= XT2BYPASS;
213 
214   while (SFRIFG1 & OFIFG) {   // Check OFIFG fault flag
215     UCSCTL7 &= ~(DCOFFG+XT1LFOFFG+XT1HFOFFG+XT2OFFG); // Clear OSC flaut Flags
216     SFRIFG1 &= ~OFIFG;        // Clear OFIFG fault flag
217   }
218 #endif
219 }
220 
XT2_Stop(void)221 void XT2_Stop(void)
222 {
223   UCSCTL6 |= XT2OFF;                         // Switch off XT2 oscillator
224 }
225 
Init_FLL_Settle(uint16_t fsystem,uint16_t ratio)226 void Init_FLL_Settle(uint16_t fsystem, uint16_t ratio)
227 {
228   volatile uint16_t x = ratio * 32;
229 
230   Init_FLL(fsystem, ratio);
231 
232   while (x--) {
233    __delay_cycles(30);
234   }
235 }
236 
Init_FLL(uint16_t fsystem,uint16_t ratio)237 void Init_FLL(uint16_t fsystem, uint16_t ratio)
238 {
239   uint16_t d, dco_div_bits;
240   uint16_t mode = 0;
241 
242   // Save actual state of FLL loop control, then disable it. This is needed to
243   // prevent the FLL from acting as we are making fundamental modifications to
244   // the clock setup.
245   uint16_t srRegisterState = __get_SR_register() & SCG0;
246   __bic_SR_register(SCG0);
247 
248   d = ratio;
249   dco_div_bits = FLLD__2;        // Have at least a divider of 2
250 
251   if (fsystem > 16000) {
252     d >>= 1 ;
253     mode = 1;
254   }
255   else {
256     fsystem <<= 1;               // fsystem = fsystem * 2
257   }
258 
259   while (d > 512) {
260     dco_div_bits = dco_div_bits + FLLD0;  // Set next higher div level
261     d >>= 1;
262   }
263 
264   UCSCTL0 = 0x0000;              // Set DCO to lowest Tap
265 
266   UCSCTL2 &= ~(0x03FF);          // Reset FN bits
267   UCSCTL2 = dco_div_bits | (d - 1);
268 
269   if (fsystem <= 630)            //           fsystem < 0.63MHz
270 	UCSCTL1 = DCORSEL_0;
271   else if (fsystem <  1250)      // 0.63MHz < fsystem < 1.25MHz
272 	UCSCTL1 = DCORSEL_1;
273   else if (fsystem <  2500)      // 1.25MHz < fsystem <  2.5MHz
274 	UCSCTL1 = DCORSEL_2;
275   else if (fsystem <  5000)      // 2.5MHz  < fsystem <    5MHz
276 	UCSCTL1 = DCORSEL_3;
277   else if (fsystem <  10000)     // 5MHz    < fsystem <   10MHz
278 	UCSCTL1 = DCORSEL_4;
279   else if (fsystem <  20000)     // 10MHz   < fsystem <   20MHz
280 	UCSCTL1 = DCORSEL_5;
281   else if (fsystem <  40000)     // 20MHz   < fsystem <   40MHz
282 	UCSCTL1 = DCORSEL_6;
283   else
284 	UCSCTL1 = DCORSEL_7;
285 
286   while (SFRIFG1 & OFIFG) {                               // Check OFIFG fault flag
287     UCSCTL7 &= ~(DCOFFG+XT1LFOFFG+XT1HFOFFG+XT2OFFG);     // Clear OSC flaut Flags
288     SFRIFG1 &= ~OFIFG;                                    // Clear OFIFG fault flag
289   }
290 
291   if (mode == 1) {                              		  // fsystem > 16000
292     SELECT_MCLK_SMCLK(SELM__DCOCLK + SELS__DCOCLK);       // Select DCOCLK
293   }
294   else {
295     SELECT_MCLK_SMCLK(SELM__DCOCLKDIV + SELS__DCOCLKDIV); // Select DCODIVCLK
296   }
297 
298   __bis_SR_register(srRegisterState);	                  // Restore previous SCG0
299 }
300