xref: /btstack/port/archive/msp430f5229lp-cc2564b/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 "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