1 /**
2 * @file hal_board.c
3 *
4 * Copyright 2008 Texas Instruments, Inc.
5 ******************************************************************************/
6 #include "hal_board.h"
7
8 #include "msp430.h"
9
10 #include "hal_compat.h"
11 // #include "hal_adc.h"
12 // #include "hal_usb.h"
13
14 static void halBoardSetVCoreUp(unsigned char level);
15 static void halBoardSetVCoreDown(unsigned char level);
16 static void halBoardGetSystemClockSettings(unsigned char systemClockSpeed,
17 unsigned char *setDcoRange,
18 unsigned char *setVCore,
19 unsigned int *setMultiplier);
20
21 /************************************************************************
22 * @brief Increments the VCore setting.
23 *
24 * @param level The target VCore setting
25 *
26 * @return none
27 *************************************************************************/
halBoardSetVCoreUp(unsigned char level)28 static void halBoardSetVCoreUp (unsigned char level)
29 {
30 // Open PMM module registers for write access
31 PMMCTL0_H = 0xA5;
32
33 // Set SVS/M high side to new level
34 SVSMHCTL = (SVSMHCTL & ~(SVSHRVL0*3 + SVSMHRRL0)) | \
35 (SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level);
36
37 // Set SVM new Level
38 SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
39 // Set SVS/M low side to new level
40 SVSMLCTL = (SVSMLCTL & ~(SVSMLRRL_3)) | (SVMLE + SVSMLRRL0 * level);
41
42 while ((PMMIFG & SVSMLDLYIFG) == 0); // Wait till SVM is settled (Delay)
43 PMMCTL0_L = PMMCOREV0 * level; // Set VCore to x
44 PMMIFG &= ~(SVMLVLRIFG + SVMLIFG); // Clear already set flags
45
46 if ((PMMIFG & SVMLIFG))
47 while ((PMMIFG & SVMLVLRIFG) == 0); // Wait till level is reached
48
49 // Set SVS/M Low side to new level
50 SVSMLCTL = (SVSMLCTL & ~(SVSLRVL0*3 + SVSMLRRL_3)) | \
51 (SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level);
52
53 // Lock PMM module registers from write access
54 PMMCTL0_H = 0x00;
55 }
56
57 /************************************************************************
58 * @brief Decrements the VCore setting.
59 *
60 * @param level The target VCore.
61 *
62 * @return none
63 *************************************************************************/
halBoardSetVCoreDown(unsigned char level)64 static void halBoardSetVCoreDown(unsigned char level)
65 {
66 // Open PMM module registers for write access
67 PMMCTL0_H = 0xA5;
68
69 // Set SVS/M low side to new level
70 SVSMLCTL = (SVSMLCTL & ~(SVSLRVL0*3 + SVSMLRRL_3)) | \
71 (SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level);
72
73 while ((PMMIFG & SVSMLDLYIFG) == 0); // Wait till SVM is settled (Delay)
74 PMMCTL0_L = (level * PMMCOREV0); // Set VCore to new level
75 // Lock PMM module registers for write access
76
77 PMMCTL0_H = 0x00;
78 }
79
80 /************************************************************************
81 * @brief Get function for the DCORSEL, VCORE, and DCO multiplier settings
82 * that map to a given clock speed.
83 *
84 * @param systemClockSpeed Target DCO frequency - SYSCLK_xxMHZ.
85 *
86 * @param setDcoRange Pointer to the DCO range select bits.
87 *
88 * @param setVCore Pointer to the VCore level bits.
89 *
90 * @param setMultiplier Pointer to the DCO multiplier bits.
91 *
92 * @return none
93 ************************************************************************/
halBoardGetSystemClockSettings(unsigned char systemClockSpeed,unsigned char * setDcoRange,unsigned char * setVCore,unsigned int * setMultiplier)94 static void halBoardGetSystemClockSettings(unsigned char systemClockSpeed,
95 unsigned char *setDcoRange,
96 unsigned char *setVCore,
97 unsigned int *setMultiplier)
98 {
99 switch (systemClockSpeed)
100 {
101 case SYSCLK_1MHZ:
102 *setDcoRange = DCORSEL_1MHZ;
103 *setVCore = VCORE_1MHZ;
104 *setMultiplier = DCO_MULT_1MHZ;
105 break;
106 case SYSCLK_4MHZ:
107 *setDcoRange = DCORSEL_4MHZ;
108 *setVCore = VCORE_4MHZ;
109 *setMultiplier = DCO_MULT_4MHZ;
110 break;
111 case SYSCLK_8MHZ:
112 *setDcoRange = DCORSEL_8MHZ;
113 *setVCore = VCORE_8MHZ;
114 *setMultiplier = DCO_MULT_8MHZ;
115 break;
116 case SYSCLK_12MHZ:
117 *setDcoRange = DCORSEL_12MHZ;
118 *setVCore = VCORE_12MHZ;
119 *setMultiplier = DCO_MULT_12MHZ;
120 break;
121 case SYSCLK_16MHZ:
122 *setDcoRange = DCORSEL_16MHZ;
123 *setVCore = VCORE_16MHZ;
124 *setMultiplier = DCO_MULT_16MHZ;
125 break;
126 }
127 }
128
129 /************************************************************************
130 * @brief Set function for the PMM core voltage (PMMCOREV) setting
131 *
132 * @param level Target VCore setting
133 *
134 * @return none
135 *************************************************************************/
halBoardSetVCore(unsigned char level)136 void halBoardSetVCore(unsigned char level)
137 {
138 unsigned int currentVCore;
139
140 currentVCore = PMMCTL0 & PMMCOREV_3; // Get actual VCore
141 // Change VCore step by step
142 while (level != currentVCore)
143 {
144 if (level > currentVCore)
145 halBoardSetVCoreUp(++currentVCore);
146 else
147 halBoardSetVCoreDown(--currentVCore);
148 }
149 }
150
151 /************************************************************************
152 * @brief Initialization routine for XT1.
153 *
154 * Sets the necessary internal capacitor values and loops until all
155 * ocillator fault flags remain cleared.
156 *
157 * @param none
158 *
159 * @return none
160 *************************************************************************/
halBoardStartXT1(void)161 void halBoardStartXT1(void)
162 {
163 /* LFXT can take up to 1000ms to start.
164 * Go to the loop below 4 times for a total of 2 sec timout.
165 * If a timeout happens due to no XTAL present or a faulty XTAL
166 * the clock system will fall back to REFOCLK (~32kHz) */
167 P5SEL |= BIT4 + BIT5;
168 /* Set XTAL2 pins to output to reduce power consumption */
169 P5DIR |= BIT2 + BIT3;
170 /* Turn XT1 ON */
171 UCSCTL6 &= ~(XT1OFF);
172 /* Set XTAL CAPS to 12 pF */
173 UCSCTL6 |= XCAP_3;
174
175 do {
176 /* Clear Oscillator fault flags */
177 UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
178 /* Clear the Oscillator fault interrupt flag */
179 SFRIFG1 &= ~OFIFG;
180 /* Test the fault flag */
181 __delay_cycles(56250);
182 } while (SFRIFG1 & OFIFG);
183 /* Reduse drive strength to reduce power consumption */
184 UCSCTL6 &= ~(XT1DRIVE_3);
185 }
186
187 /************************************************************************
188 * @brief Set function for MCLK frequency.
189 *
190 * @param systemClockSpeed Intended frequency of operation - SYSCLK_xxMHZ.
191 *
192 * @return none
193 *************************************************************************/
halBoardSetSystemClock(unsigned char systemClockSpeed)194 void halBoardSetSystemClock(unsigned char systemClockSpeed)
195 {
196 unsigned char setDcoRange = 0;
197 unsigned char setVCore = 0;
198 unsigned int setMultiplier = 0;
199
200 halBoardGetSystemClockSettings( systemClockSpeed, &setDcoRange, \
201 &setVCore, &setMultiplier);
202
203 if (setVCore > (PMMCTL0 & PMMCOREV_3)) // Only change VCore if necessary
204 halBoardSetVCore( setVCore );
205
206 UCSCTL0 = 0x00; // Set lowest possible DCOx, MODx
207 UCSCTL1 = setDcoRange; // Select suitable range
208
209 UCSCTL2 = setMultiplier + FLLD_1; // Set DCO Multiplier
210 UCSCTL4 = SELA__XT1CLK | SELS__DCOCLKDIV | SELM__DCOCLKDIV ;
211
212 // Worst-case settling time for the DCO when the DCO range bits have been
213 // changed is n x 32 x 32 x f_FLL_reference. See UCS chapter in 5xx UG
214 // for optimization.
215 // 32 x 32 x / f_FLL_reference (32,768 Hz) = .03125 = t_DCO_settle
216 // t_DCO_settle / (1 / 18 MHz) = 562500 = counts_DCO_settle
217
218 // __delay_cycles(562500);
219 int i;
220 for (i=0;i<10;i++){
221 __delay_cycles(56250);
222 }
223 }
224
225 /************************************************************************
226 * @brief Initializes all GPIO configurations.
227 * TI example did set all ports to OUTPUT, we don't.
228 * @param none
229 *
230 * @return none
231 *************************************************************************/
halBoardInit(void)232 void halBoardInit(void)
233 {
234 //Tie unused ports
235 PAOUT = 0;
236 PADIR = 0;
237 PASEL = 0;
238 PBOUT = 0;
239 PBDIR = 0;
240 PBSEL = 0;
241 PCOUT = 0;
242 PCDIR = 0;
243 PCSEL = 0;
244 PDOUT = 0;
245 PDDIR = 0;
246 PDSEL = 0;
247 PJOUT = 0;
248 PJDIR = 0;
249
250 // AUDIO_PORT_OUT = AUDIO_OUT_PWR_PIN ;
251 // USB_PORT_DIR &= ~USB_PIN_RXD; // USB RX Pin, Input with
252 // // ...pulled down Resistor
253 // USB_PORT_OUT &= ~USB_PIN_RXD;
254 // USB_PORT_REN |= USB_PIN_RXD;
255 }
256