xref: /btstack/port/archive/ez430-rf2560/firmware/hal_board.c (revision 1664436fd643daf66517dc309e6cc72448e8a86d)
1 /**
2  * @file  hal_board.c
3  *
4  * Copyright 2008 Texas Instruments, Inc.
5 ******************************************************************************/
6 #include "hal_board.h"
7 
8 #include "msp430x54x.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  * Commented out because fmax = 18 MHz
128  * ------------------------------------
129   case SYSCLK_20MHZ:
130     *setDcoRange = DCORSEL_20MHZ;
131     *setVCore = VCORE_20MHZ;
132     *setMultiplier = DCO_MULT_20MHZ;
133     break;
134   case SYSCLK_25MHZ:
135     *setDcoRange = DCORSEL_25MHZ;
136     *setVCore = VCORE_25MHZ;
137     *setMultiplier = DCO_MULT_25MHZ;
138     break;
139  *-------------------------------------*/
140   }
141 }
142 
143 /************************************************************************
144  * @brief  Set function for the PMM core voltage (PMMCOREV) setting
145  *
146  * @param  level Target VCore setting
147  *
148  * @return none
149  *************************************************************************/
halBoardSetVCore(unsigned char level)150 void halBoardSetVCore(unsigned char level)
151 {
152   unsigned int currentVCore;
153 
154   currentVCore = PMMCTL0 & PMMCOREV_3;      // Get actual VCore
155   // Change VCore step by step
156   while (level != currentVCore)
157   {
158     if (level > currentVCore)
159       halBoardSetVCoreUp(++currentVCore);
160     else
161       halBoardSetVCoreDown(--currentVCore);
162   }
163 }
164 
165 /************************************************************************
166  * @brief  Disables all supply voltage supervision and monitoring.
167  *
168  * @param  none
169  *
170  * @return none
171  *************************************************************************/
halBoardDisableSVS(void)172 void halBoardDisableSVS(void)
173 {
174   // Open PMM module registers for write access
175   PMMCTL0_H = 0xA5;
176 
177   SVSMLCTL &= ~( SVMLE + SVSLE + SVSLFP + SVMLFP );   // Disable Low side SVM
178   SVSMHCTL &= ~( SVMHE + SVSHE + SVSHFP + SVMHFP );   // Disable High side SVM
179   PMMCTL1 = PMMREFMD;
180 
181   // Lock PMM module registers for write access
182   PMMCTL0_H = 0x00;
183 }
184 
185 /************************************************************************
186  * @brief  Enables all supply voltage supervision and monitoring
187  *
188  * @param  none
189  *
190  * @return none
191  *************************************************************************/
halBoardEnableSVS(void)192 void halBoardEnableSVS(void)
193 {
194   // Open PMM module registers for write access
195   PMMCTL0_H = 0xA5;
196 
197   /*-----------
198    * NOTE: To attain the expected < 6 us wakeup from LPM modes, the following
199    * two lines must be commented out due to the fact that the PMM will hold
200    * the CPU until the reference is fully settled.
201    *----------*/
202   SVSMHCTL &= ~(SVSHFP+SVMHFP);             // Disable full-performance mode
203   SVSMLCTL &= ~(SVSLFP+SVMLFP);             // Disable full-performance mode
204   SVSMLCTL |= ( SVMLE + SVSLE);             // Enable Low side SVM
205   SVSMHCTL |= ( SVMHE + SVSHE);             // Enable High side SVM
206   PMMCTL1 &= ~PMMREFMD;
207 
208   // Lock PMM module registers for write access
209   PMMCTL0_H = 0x00;
210 }
211 
212 /************************************************************************
213  * @brief  Initialization routine for XT1.
214  *
215  * Sets the necessary internal capacitor values and loops until all
216  * ocillator fault flags remain cleared.
217  *
218  * @param  none
219  *
220  * @return none
221  *************************************************************************/
halBoardStartXT1(void)222 void halBoardStartXT1(void)
223 {
224   // Set up XT1 Pins to analog function, and to lowest drive
225   P7SEL |= 0x03;
226   UCSCTL6 |= XCAP_3 ;                       // Set internal cap values
227 
228   while(SFRIFG1 & OFIFG) {                  // Check OFIFG fault flag
229     while ( (SFRIFG1 & OFIFG))              // Check OFIFG fault flag
230     {
231       // Clear OSC fault flags
232       UCSCTL7 &= ~(DCOFFG + XT1LFOFFG + XT1HFOFFG + XT2OFFG);
233       SFRIFG1 &= ~OFIFG;                    // Clear OFIFG fault flag
234     }
235     UCSCTL6 &= ~(XT1DRIVE1_L+XT1DRIVE0);    // Reduce the drive strength
236   }
237 }
238 
239 /************************************************************************
240  * @brief  Set function for MCLK frequency.
241  *
242  * @param  systemClockSpeed Intended frequency of operation - SYSCLK_xxMHZ.
243  *
244  * @return none
245  *************************************************************************/
halBoardSetSystemClock(unsigned char systemClockSpeed)246 void halBoardSetSystemClock(unsigned char systemClockSpeed)
247 {
248   unsigned char setDcoRange = 0;
249   unsigned char setVCore = 0;
250   unsigned int  setMultiplier = 0;
251 
252   halBoardGetSystemClockSettings( systemClockSpeed, &setDcoRange,  \
253                                   &setVCore, &setMultiplier);
254 
255   if (setVCore > (PMMCTL0 & PMMCOREV_3))	// Only change VCore if necessary
256     halBoardSetVCore( setVCore );
257 
258   UCSCTL0 = 0x00;                           // Set lowest possible DCOx, MODx
259   UCSCTL1 = setDcoRange;                    // Select suitable range
260 
261   UCSCTL2 = setMultiplier + FLLD_1;         // Set DCO Multiplier
262   UCSCTL4 = SELA__XT1CLK | SELS__DCOCLKDIV  |  SELM__DCOCLKDIV ;
263 
264   // Worst-case settling time for the DCO when the DCO range bits have been
265   // changed is n x 32 x 32 x f_FLL_reference. See UCS chapter in 5xx UG
266   // for optimization.
267   // 32 x 32 x / f_FLL_reference (32,768 Hz) = .03125 = t_DCO_settle
268   // t_DCO_settle / (1 / 18 MHz) = 562500 = counts_DCO_settle
269 
270   // __delay_cycles(562500);
271   int i;
272   for (i=0;i<10;i++){
273     __delay_cycles(56250);
274   }
275 }
276 
277 /************************************************************************
278  * @brief  Initializes ACLK, MCLK, SMCLK outputs on P11.0, P11.1,
279  *         and P11.2, respectively.
280  *
281  * @param  none
282  *
283  * @return none
284  *************************************************************************/
halBoardOutputSystemClock(void)285 void halBoardOutputSystemClock(void)
286 {
287   P11DIR |= 0x07;
288   P11SEL |= 0x07;
289 }
290 
291 /************************************************************************
292  * @brief  Stops the output of ACLK, MCLK, SMCLK on P11.0, P11.1, and P11.2.
293  *
294  * @param  none
295  *
296  * @return none
297  *************************************************************************/
halBoardStopOutputSystemClock(void)298 void halBoardStopOutputSystemClock(void)
299 {
300   P11OUT &= ~0x07;
301   P11DIR |= 0x07;
302   P11SEL &= ~0x07;
303 }
304 
305 /************************************************************************
306  * @brief  Initializes all GPIO configurations.
307  *         TI example did set all ports to OUTPUT, we don't.
308  * @param  none
309  *
310  * @return none
311  *************************************************************************/
halBoardInit(void)312 void halBoardInit(void)
313 {
314 #if 0
315   // ORIGINAL EP
316   //Tie unused ports
317   PAOUT  = 0;
318   PADIR  = 0xFFFF;
319   PASEL  = 0;
320   PBOUT  = 0;
321   PBDIR  = 0xFFFF;
322   PBSEL  = 0;
323   PCOUT  = 0;
324   PCDIR  = 0xFFFF;
325   PCSEL  = 0;
326   PDOUT  = 0;
327   PDDIR  = 0xFFFF;
328   PDSEL  = 0;
329   PEOUT  = 0;
330   PEDIR  = 0xFEFF;                          // P10.0 to USB RST pin,
331                                             // ...if enabled with J5
332   PESEL  = 0;
333   P11OUT = 0;
334   P11DIR = 0xFF;
335   PJOUT  = 0;
336   PJDIR  = 0xFF;
337   P11SEL = 0;
338 #else
339   //Tie unused ports
340   PAOUT  = 0;
341   PADIR  = 0;
342   PASEL  = 0;
343   PBOUT  = 0;
344   PBDIR  = 0;
345   PBSEL  = 0;
346   PCOUT  = 0;
347   PCDIR  = 0;
348   PCSEL  = 0;
349   PDOUT  = 0;
350   PDDIR  = 0;
351   PDSEL  = 0;
352   PEOUT  = 0;
353   PEDIR  = 0;
354   PESEL  = 0;
355   P11OUT = 0;
356   P11DIR = 0;
357   PJOUT  = 0;
358   PJDIR  = 0;
359   P11SEL = 0;
360 #endif
361 
362   AUDIO_PORT_OUT = AUDIO_OUT_PWR_PIN ;
363   USB_PORT_DIR &= ~USB_PIN_RXD;             // USB RX Pin, Input with
364                                             // ...pulled down Resistor
365   USB_PORT_OUT &= ~USB_PIN_RXD;
366   USB_PORT_REN |= USB_PIN_RXD;
367 }
368