blob: 0b67ec7e6135a0d2b4b7a08e2c19006a0e79bcaa [file] [log] [blame]
//*******************************************************************************
// Provides Functions to Initialize the UCS/FLL and clock sources
// File: hal_ucs.c
//
// Texas Instruments
//
// Version 1.2
// 11/24/09
//
// V1.0 Initial Version
// V1.1 Added timeout function
// V1.1 Added parameter for XTDrive
//*******************************************************************************
#include "msp430.h"
#include "hal_UCS.h"
//************************************************************************
// Check and define required Defines
//************************************************************************
#ifndef XT1LFOFFG // Defines if not available in header file
#define XT1LFOFFG 0
#endif
#ifndef XT1HFOFFG // Defines if not available in header file
#define XT1HFOFFG 0
#endif
#ifndef XT2OFFG // Defines if not available in header file
#define XT2OFFG 0
#endif
#ifndef XTS // Defines if not available in header file
#define XTS 0
#endif
#ifndef XT2DRIVE_3 // Defines if not available in header file
#define XT2DRIVE_3 0
#endif
//====================================================================
/**
* Startup routine for 32kHz Cristal on LFXT1
*
*/
void LFXT_Start(uint16_t xtdrive)
{
UCSCTL6_L |= XT1DRIVE1_L+XT1DRIVE0_L; // Highest drive setting for XT1 startup
while (SFRIFG1 & OFIFG) { // check OFIFG fault flag
UCSCTL7 &= ~(DCOFFG+XT1LFOFFG+XT1HFOFFG+XT2OFFG); // Clear OSC flaut Flags fault flags
SFRIFG1 &= ~OFIFG; // Clear OFIFG fault flag
}
UCSCTL6 = (UCSCTL6 & ~(XT1DRIVE_3)) |(xtdrive); // set Drive mode
}
//====================================================================
/**
* Startup routine for 32kHz Cristal on LFXT1 with timeout counter
*
*/
uint16_t LFXT_Start_Timeout(uint16_t xtdrive, uint16_t timeout)
{
UCSCTL6_L |= XT1DRIVE1_L+XT1DRIVE0_L; // Highest drive setting for XT1 startup
while ((SFRIFG1 & OFIFG) && timeout--){ // check OFIFG fault flag
UCSCTL7 &= ~(DCOFFG+XT1LFOFFG+XT1HFOFFG+XT2OFFG); // Clear OSC flaut Flags fault flags
SFRIFG1 &= ~OFIFG; // Clear OFIFG fault flag
}
UCSCTL6 = (UCSCTL6 & ~(XT1DRIVE_3)) |(xtdrive); // set Drive mode
if (timeout)
return (UCS_STATUS_OK);
else
return (UCS_STATUS_ERROR);
}
//====================================================================
/**
* Startup routine for XT1
*
*/
void XT1_Start(uint16_t xtdrive)
{
UCSCTL6 &= ~(XT1OFF | XT1DRIVE_3); // enable XT1
UCSCTL6 |= (XTS | xtdrive); // enable XT1 and set XT1Drive
while (SFRIFG1 & OFIFG) { // check OFIFG fault flag
UCSCTL7 &= ~(DCOFFG+XT1LFOFFG+XT1HFOFFG+XT2OFFG); // Clear OSC flaut Flags
SFRIFG1 &= ~OFIFG; // Clear OFIFG fault flag
}
}
//====================================================================
/**
* Startup routine for XT1 with timeout counter
*
*/
uint16_t XT1_Start_Timeout(uint16_t xtdrive, uint16_t timeout)
{
UCSCTL6 &= ~(XT1OFF | XT1DRIVE_3); // enable XT1
UCSCTL6 |= (XTS | xtdrive); // enable XT1 and set XT1Drive
while ((SFRIFG1 & OFIFG) && timeout--) { // check OFIFG fault flag
UCSCTL7 &= ~(DCOFFG+XT1LFOFFG+XT1HFOFFG+XT2OFFG); // Clear OSC flaut Flags
SFRIFG1 &= ~OFIFG; // Clear OFIFG fault flag
}
if (timeout)
return (UCS_STATUS_OK);
else
return (UCS_STATUS_ERROR);
}
//====================================================================
/**
* Use XT1 in Bypasss mode
*
*/
void XT1_Bypass(void)
{
UCSCTL6 |= XT1BYPASS;
while (SFRIFG1 & OFIFG) { // check OFIFG fault flag
UCSCTL7 &= ~(DCOFFG+XT1LFOFFG+XT1HFOFFG+XT2OFFG); // Clear OSC flaut Flags
SFRIFG1 &= ~OFIFG; // Clear OFIFG fault flag
}
}
//====================================================================
/**
* Startup routine for XT2
*
*/
void XT2_Start(uint16_t xtdrive)
{
UCSCTL6 &= ~(XT2OFF | XT2DRIVE_3); // enable XT2
UCSCTL6 |= (xtdrive); // Set XT2Drive
while (SFRIFG1 & OFIFG) { // check OFIFG fault flag
UCSCTL7 &= ~(DCOFFG+XT1LFOFFG+XT1HFOFFG+XT2OFFG); // Clear OSC flaut Flags
SFRIFG1 &= ~OFIFG; // Clear OFIFG fault flag
}
}
//====================================================================
/**
* Startup routine for XT2 with timeout counter
*
*/
uint16_t XT2_Start_Timeout(uint16_t xtdrive, uint16_t timeout)
{
UCSCTL6 &= ~XT2OFF; // Set XT2 On
UCSCTL6 &= ~XT2DRIVE_3; // enable XT2
UCSCTL6 |= (xtdrive); // Set XT2Drive
while ((SFRIFG1 & OFIFG) && timeout--){ // check OFIFG fault flag
UCSCTL7 &= ~(DCOFFG+XT1LFOFFG+XT1HFOFFG+XT2OFFG); // Clear OSC flaut Flags
SFRIFG1 &= ~OFIFG; // Clear OFIFG fault flag
}
if (timeout)
return (UCS_STATUS_OK);
else
return (UCS_STATUS_ERROR);
}
//====================================================================
/**
* Use XT2 in Bypasss mode
*
*/
void XT2_Bypass(void)
{
#ifdef XT2BYPASS // on devices without XT2 this function will be empty
UCSCTL6 |= XT2BYPASS;
while (SFRIFG1 & OFIFG) { // check OFIFG fault flag
UCSCTL7 &= ~(DCOFFG+XT1LFOFFG+XT1HFOFFG+XT2OFFG); // Clear OSC flaut Flags
SFRIFG1 &= ~OFIFG; // Clear OFIFG fault flag
}
#endif
}
//====================================================================
/**
* Initializes FLL of the UCS and wait till settled
*
* \param fsystem required system frequency (MCLK) in kHz
* \param ratio ratio between MCLK and FLLREFCLK
*/
void Init_FLL_Settle(uint16_t fsystem, uint16_t ratio)
{
volatile uint16_t x = ratio * 32;
// save actual state of FLL loop control
uint16_t globalInterruptState = __get_SR_register() & SCG0;
__bic_SR_register(SCG0); // Enable FLL loop control
Init_FLL(fsystem, ratio);
while(x--)
{
__delay_cycles(30);
}
__bis_SR_register(globalInterruptState); // restore previous state
}
//====================================================================
/**
* Initializes FLL of the UCS
*
* \param fsystem required system frequency (MCLK) in kHz
* \param ratio ratio between fsystem and FLLREFCLK
*/
static void Init_FLL(uint16_t fsystem, uint16_t ratio)
{
uint16_t d, dco_div_bits;
uint16_t mode = 0;
d = ratio;
dco_div_bits = FLLD__2; // Have at least a divider of 2
if (fsystem > 16000){
d >>= 1 ;
mode = 1;
}
else
fsystem <<= 1; // fsystem = fsystem * 2
while (d > 512)
{
dco_div_bits = dco_div_bits + FLLD0; // set next higher div level
d >>= 1;
}
UCSCTL0 = 0x000; // Set DCO to lowest Tap
UCSCTL2 &= ~(0x3FF); // Reset FN bits
UCSCTL2 = dco_div_bits | (d - 1);
if (fsystem <= 630) // fsystem < 0.63MHz
UCSCTL1= DCORSEL_0 ;
else if (fsystem < 1250) // 0.63MHz < fsystem < 1.25MHz
UCSCTL1= DCORSEL_1 ;
else if (fsystem < 2500) // 1.25MHz < fsystem < 2.5MHz
UCSCTL1= DCORSEL_2 ;
else if (fsystem < 5000) // 2.5MHz < fsystem < 5MHz
UCSCTL1= DCORSEL_3 ;
else if (fsystem < 10000) // 5MHz < fsystem < 10MHz
UCSCTL1= DCORSEL_4 ;
else if (fsystem < 20000) // 10MHz < fsystem < 20MHz
UCSCTL1= DCORSEL_5 ;
else if (fsystem < 40000) // 20MHz < fsystem < 40MHz
UCSCTL1= DCORSEL_6 ;
else
UCSCTL1= DCORSEL_7 ;
while (SFRIFG1 & OFIFG) { // check OFIFG fault flag
UCSCTL7 &= ~(DCOFFG+XT1LFOFFG+XT1HFOFFG+XT2OFFG); // Clear OSC flaut Flags
SFRIFG1 &= ~OFIFG; // Clear OFIFG fault flag
}
if (mode == 1) // fsystem > 16000
SELECT_MCLK_SMCLK(SELM__DCOCLK + SELS__DCOCLK); // select DCOCLK
else
SELECT_MCLK_SMCLK(SELM__DCOCLKDIV + SELS__DCOCLKDIV); // selcet DCODIVCLK
} // End of fll_init()