1 |
584 |
jeremybenn |
//*******************************************************************************
|
2 |
|
|
// Provides Functions to Initialize the UCS/FLL and clock sources
|
3 |
|
|
// File: hal_ucs.c
|
4 |
|
|
//
|
5 |
|
|
// Texas Instruments
|
6 |
|
|
//
|
7 |
|
|
// Version 1.2
|
8 |
|
|
// 11/24/09
|
9 |
|
|
//
|
10 |
|
|
// V1.0 Initial Version
|
11 |
|
|
// V1.1 Added timeout function
|
12 |
|
|
// V1.1 Added parameter for XTDrive
|
13 |
|
|
//*******************************************************************************
|
14 |
|
|
|
15 |
|
|
#include "msp430.h"
|
16 |
|
|
#include "hal_UCS.h"
|
17 |
|
|
|
18 |
|
|
//************************************************************************
|
19 |
|
|
// Check and define required Defines
|
20 |
|
|
//************************************************************************
|
21 |
|
|
|
22 |
|
|
#ifndef XT1LFOFFG // Defines if not available in header file
|
23 |
|
|
#define XT1LFOFFG 0
|
24 |
|
|
#endif
|
25 |
|
|
#ifndef XT1HFOFFG // Defines if not available in header file
|
26 |
|
|
#define XT1HFOFFG 0
|
27 |
|
|
#endif
|
28 |
|
|
#ifndef XT2OFFG // Defines if not available in header file
|
29 |
|
|
#define XT2OFFG 0
|
30 |
|
|
#endif
|
31 |
|
|
#ifndef XTS // Defines if not available in header file
|
32 |
|
|
#define XTS 0
|
33 |
|
|
#endif
|
34 |
|
|
#ifndef XT2DRIVE_3 // Defines if not available in header file
|
35 |
|
|
#define XT2DRIVE_3 0
|
36 |
|
|
#endif
|
37 |
|
|
|
38 |
|
|
//====================================================================
|
39 |
|
|
/**
|
40 |
|
|
* Startup routine for 32kHz Cristal on LFXT1
|
41 |
|
|
*
|
42 |
|
|
*/
|
43 |
|
|
void LFXT_Start(uint16_t xtdrive)
|
44 |
|
|
{
|
45 |
|
|
UCSCTL6_L |= XT1DRIVE1_L+XT1DRIVE0_L; // Highest drive setting for XT1 startup
|
46 |
|
|
|
47 |
|
|
while (SFRIFG1 & OFIFG) { // check OFIFG fault flag
|
48 |
|
|
UCSCTL7 &= ~(DCOFFG+XT1LFOFFG+XT1HFOFFG+XT2OFFG); // Clear OSC flaut Flags fault flags
|
49 |
|
|
SFRIFG1 &= ~OFIFG; // Clear OFIFG fault flag
|
50 |
|
|
}
|
51 |
|
|
UCSCTL6 = (UCSCTL6 & ~(XT1DRIVE_3)) |(xtdrive); // set Drive mode
|
52 |
|
|
}
|
53 |
|
|
|
54 |
|
|
//====================================================================
|
55 |
|
|
/**
|
56 |
|
|
* Startup routine for 32kHz Cristal on LFXT1 with timeout counter
|
57 |
|
|
*
|
58 |
|
|
*/
|
59 |
|
|
uint16_t LFXT_Start_Timeout(uint16_t xtdrive, uint16_t timeout)
|
60 |
|
|
{
|
61 |
|
|
UCSCTL6_L |= XT1DRIVE1_L+XT1DRIVE0_L; // Highest drive setting for XT1 startup
|
62 |
|
|
|
63 |
|
|
while ((SFRIFG1 & OFIFG) && timeout--){ // check OFIFG fault flag
|
64 |
|
|
UCSCTL7 &= ~(DCOFFG+XT1LFOFFG+XT1HFOFFG+XT2OFFG); // Clear OSC flaut Flags fault flags
|
65 |
|
|
SFRIFG1 &= ~OFIFG; // Clear OFIFG fault flag
|
66 |
|
|
}
|
67 |
|
|
UCSCTL6 = (UCSCTL6 & ~(XT1DRIVE_3)) |(xtdrive); // set Drive mode
|
68 |
|
|
if (timeout)
|
69 |
|
|
return (UCS_STATUS_OK);
|
70 |
|
|
else
|
71 |
|
|
return (UCS_STATUS_ERROR);
|
72 |
|
|
}
|
73 |
|
|
|
74 |
|
|
|
75 |
|
|
//====================================================================
|
76 |
|
|
/**
|
77 |
|
|
* Startup routine for XT1
|
78 |
|
|
*
|
79 |
|
|
*/
|
80 |
|
|
void XT1_Start(uint16_t xtdrive)
|
81 |
|
|
{
|
82 |
|
|
UCSCTL6 &= ~(XT1OFF | XT1DRIVE_3); // enable XT1
|
83 |
|
|
UCSCTL6 |= (XTS | xtdrive); // enable XT1 and set XT1Drive
|
84 |
|
|
|
85 |
|
|
while (SFRIFG1 & OFIFG) { // check OFIFG fault flag
|
86 |
|
|
UCSCTL7 &= ~(DCOFFG+XT1LFOFFG+XT1HFOFFG+XT2OFFG); // Clear OSC flaut Flags
|
87 |
|
|
SFRIFG1 &= ~OFIFG; // Clear OFIFG fault flag
|
88 |
|
|
}
|
89 |
|
|
}
|
90 |
|
|
|
91 |
|
|
//====================================================================
|
92 |
|
|
/**
|
93 |
|
|
* Startup routine for XT1 with timeout counter
|
94 |
|
|
*
|
95 |
|
|
*/
|
96 |
|
|
uint16_t XT1_Start_Timeout(uint16_t xtdrive, uint16_t timeout)
|
97 |
|
|
{
|
98 |
|
|
UCSCTL6 &= ~(XT1OFF | XT1DRIVE_3); // enable XT1
|
99 |
|
|
UCSCTL6 |= (XTS | xtdrive); // enable XT1 and set XT1Drive
|
100 |
|
|
|
101 |
|
|
while ((SFRIFG1 & OFIFG) && timeout--) { // check OFIFG fault flag
|
102 |
|
|
UCSCTL7 &= ~(DCOFFG+XT1LFOFFG+XT1HFOFFG+XT2OFFG); // Clear OSC flaut Flags
|
103 |
|
|
SFRIFG1 &= ~OFIFG; // Clear OFIFG fault flag
|
104 |
|
|
}
|
105 |
|
|
if (timeout)
|
106 |
|
|
return (UCS_STATUS_OK);
|
107 |
|
|
else
|
108 |
|
|
return (UCS_STATUS_ERROR);
|
109 |
|
|
}
|
110 |
|
|
|
111 |
|
|
//====================================================================
|
112 |
|
|
/**
|
113 |
|
|
* Use XT1 in Bypasss mode
|
114 |
|
|
*
|
115 |
|
|
*/
|
116 |
|
|
void XT1_Bypass(void)
|
117 |
|
|
{
|
118 |
|
|
UCSCTL6 |= XT1BYPASS;
|
119 |
|
|
|
120 |
|
|
while (SFRIFG1 & OFIFG) { // check OFIFG fault flag
|
121 |
|
|
UCSCTL7 &= ~(DCOFFG+XT1LFOFFG+XT1HFOFFG+XT2OFFG); // Clear OSC flaut Flags
|
122 |
|
|
SFRIFG1 &= ~OFIFG; // Clear OFIFG fault flag
|
123 |
|
|
}
|
124 |
|
|
}
|
125 |
|
|
|
126 |
|
|
//====================================================================
|
127 |
|
|
/**
|
128 |
|
|
* Startup routine for XT2
|
129 |
|
|
*
|
130 |
|
|
*/
|
131 |
|
|
void XT2_Start(uint16_t xtdrive)
|
132 |
|
|
{
|
133 |
|
|
UCSCTL6 &= ~(XT2OFF | XT2DRIVE_3); // enable XT2
|
134 |
|
|
UCSCTL6 |= (xtdrive); // Set XT2Drive
|
135 |
|
|
|
136 |
|
|
while (SFRIFG1 & OFIFG) { // check OFIFG fault flag
|
137 |
|
|
UCSCTL7 &= ~(DCOFFG+XT1LFOFFG+XT1HFOFFG+XT2OFFG); // Clear OSC flaut Flags
|
138 |
|
|
SFRIFG1 &= ~OFIFG; // Clear OFIFG fault flag
|
139 |
|
|
}
|
140 |
|
|
|
141 |
|
|
}
|
142 |
|
|
|
143 |
|
|
//====================================================================
|
144 |
|
|
/**
|
145 |
|
|
* Startup routine for XT2 with timeout counter
|
146 |
|
|
*
|
147 |
|
|
*/
|
148 |
|
|
uint16_t XT2_Start_Timeout(uint16_t xtdrive, uint16_t timeout)
|
149 |
|
|
{
|
150 |
|
|
UCSCTL6 &= ~XT2OFF; // Set XT2 On
|
151 |
|
|
UCSCTL6 &= ~XT2DRIVE_3; // enable XT2
|
152 |
|
|
UCSCTL6 |= (xtdrive); // Set XT2Drive
|
153 |
|
|
|
154 |
|
|
while ((SFRIFG1 & OFIFG) && timeout--){ // check OFIFG fault flag
|
155 |
|
|
UCSCTL7 &= ~(DCOFFG+XT1LFOFFG+XT1HFOFFG+XT2OFFG); // Clear OSC flaut Flags
|
156 |
|
|
SFRIFG1 &= ~OFIFG; // Clear OFIFG fault flag
|
157 |
|
|
}
|
158 |
|
|
if (timeout)
|
159 |
|
|
return (UCS_STATUS_OK);
|
160 |
|
|
else
|
161 |
|
|
return (UCS_STATUS_ERROR);
|
162 |
|
|
}
|
163 |
|
|
|
164 |
|
|
//====================================================================
|
165 |
|
|
/**
|
166 |
|
|
* Use XT2 in Bypasss mode
|
167 |
|
|
*
|
168 |
|
|
*/
|
169 |
|
|
void XT2_Bypass(void)
|
170 |
|
|
{
|
171 |
|
|
#ifdef XT2BYPASS // on devices without XT2 this function will be empty
|
172 |
|
|
UCSCTL6 |= XT2BYPASS;
|
173 |
|
|
|
174 |
|
|
while (SFRIFG1 & OFIFG) { // check OFIFG fault flag
|
175 |
|
|
UCSCTL7 &= ~(DCOFFG+XT1LFOFFG+XT1HFOFFG+XT2OFFG); // Clear OSC flaut Flags
|
176 |
|
|
SFRIFG1 &= ~OFIFG; // Clear OFIFG fault flag
|
177 |
|
|
}
|
178 |
|
|
#endif
|
179 |
|
|
}
|
180 |
|
|
|
181 |
|
|
//====================================================================
|
182 |
|
|
/**
|
183 |
|
|
* Initializes FLL of the UCS and wait till settled
|
184 |
|
|
*
|
185 |
|
|
* \param fsystem required system frequency (MCLK) in kHz
|
186 |
|
|
* \param ratio ratio between MCLK and FLLREFCLK
|
187 |
|
|
*/
|
188 |
|
|
void Init_FLL_Settle(uint16_t fsystem, uint16_t ratio)
|
189 |
|
|
{
|
190 |
|
|
volatile uint16_t x = ratio * 32;
|
191 |
|
|
// save actual state of FLL loop control
|
192 |
|
|
uint16_t globalInterruptState = __get_SR_register() & SCG0;
|
193 |
|
|
|
194 |
|
|
__bic_SR_register(SCG0); // Enable FLL loop control
|
195 |
|
|
|
196 |
|
|
Init_FLL(fsystem, ratio);
|
197 |
|
|
|
198 |
|
|
while(x--)
|
199 |
|
|
{
|
200 |
|
|
__delay_cycles(30);
|
201 |
|
|
}
|
202 |
|
|
|
203 |
|
|
__bis_SR_register(globalInterruptState); // restore previous state
|
204 |
|
|
|
205 |
|
|
}
|
206 |
|
|
|
207 |
|
|
//====================================================================
|
208 |
|
|
/**
|
209 |
|
|
* Initializes FLL of the UCS
|
210 |
|
|
*
|
211 |
|
|
* \param fsystem required system frequency (MCLK) in kHz
|
212 |
|
|
* \param ratio ratio between fsystem and FLLREFCLK
|
213 |
|
|
*/
|
214 |
|
|
static void Init_FLL(uint16_t fsystem, uint16_t ratio)
|
215 |
|
|
{
|
216 |
|
|
uint16_t d, dco_div_bits;
|
217 |
|
|
uint16_t mode = 0;
|
218 |
|
|
|
219 |
|
|
d = ratio;
|
220 |
|
|
dco_div_bits = FLLD__2; // Have at least a divider of 2
|
221 |
|
|
if (fsystem > 16000){
|
222 |
|
|
d >>= 1 ;
|
223 |
|
|
mode = 1;
|
224 |
|
|
}
|
225 |
|
|
else
|
226 |
|
|
fsystem <<= 1; // fsystem = fsystem * 2
|
227 |
|
|
|
228 |
|
|
while (d > 512)
|
229 |
|
|
{
|
230 |
|
|
dco_div_bits = dco_div_bits + FLLD0; // set next higher div level
|
231 |
|
|
d >>= 1;
|
232 |
|
|
}
|
233 |
|
|
|
234 |
|
|
UCSCTL0 = 0x000; // Set DCO to lowest Tap
|
235 |
|
|
|
236 |
|
|
UCSCTL2 &= ~(0x3FF); // Reset FN bits
|
237 |
|
|
UCSCTL2 = dco_div_bits | (d - 1);
|
238 |
|
|
|
239 |
|
|
if (fsystem <= 630) // fsystem < 0.63MHz
|
240 |
|
|
UCSCTL1= DCORSEL_0 ;
|
241 |
|
|
else if (fsystem < 1250) // 0.63MHz < fsystem < 1.25MHz
|
242 |
|
|
UCSCTL1= DCORSEL_1 ;
|
243 |
|
|
else if (fsystem < 2500) // 1.25MHz < fsystem < 2.5MHz
|
244 |
|
|
UCSCTL1= DCORSEL_2 ;
|
245 |
|
|
else if (fsystem < 5000) // 2.5MHz < fsystem < 5MHz
|
246 |
|
|
UCSCTL1= DCORSEL_3 ;
|
247 |
|
|
else if (fsystem < 10000) // 5MHz < fsystem < 10MHz
|
248 |
|
|
UCSCTL1= DCORSEL_4 ;
|
249 |
|
|
else if (fsystem < 20000) // 10MHz < fsystem < 20MHz
|
250 |
|
|
UCSCTL1= DCORSEL_5 ;
|
251 |
|
|
else if (fsystem < 40000) // 20MHz < fsystem < 40MHz
|
252 |
|
|
UCSCTL1= DCORSEL_6 ;
|
253 |
|
|
else
|
254 |
|
|
UCSCTL1= DCORSEL_7 ;
|
255 |
|
|
|
256 |
|
|
while (SFRIFG1 & OFIFG) { // check OFIFG fault flag
|
257 |
|
|
UCSCTL7 &= ~(DCOFFG+XT1LFOFFG+XT1HFOFFG+XT2OFFG); // Clear OSC flaut Flags
|
258 |
|
|
SFRIFG1 &= ~OFIFG; // Clear OFIFG fault flag
|
259 |
|
|
}
|
260 |
|
|
|
261 |
|
|
if (mode == 1) // fsystem > 16000
|
262 |
|
|
SELECT_MCLK_SMCLK(SELM__DCOCLK + SELS__DCOCLK); // select DCOCLK
|
263 |
|
|
else
|
264 |
|
|
SELECT_MCLK_SMCLK(SELM__DCOCLKDIV + SELS__DCOCLKDIV); // selcet DCODIVCLK
|
265 |
|
|
|
266 |
|
|
|
267 |
|
|
} // End of fll_init()
|