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