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 *************************************************************************/ 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 *************************************************************************/ 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 ************************************************************************/ 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 *************************************************************************/ 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 *************************************************************************/ 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 *************************************************************************/ 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 *************************************************************************/ 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 *************************************************************************/ 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 *************************************************************************/ 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 *************************************************************************/ 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 *************************************************************************/ 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