btstack/port/ez430-rf2560/firmware/hal_board.c

368 lines
12 KiB
C
Executable File

/**
* @file hal_board.c
*
* Copyright 2008 Texas Instruments, Inc.
******************************************************************************/
#include "hal_board.h"
#include "msp430x54x.h"
#include "hal_compat.h"
#include "hal_adc.h"
#include "hal_usb.h"
static void halBoardSetVCoreUp(unsigned char level);
static void halBoardSetVCoreDown(unsigned char level);
static void halBoardGetSystemClockSettings(unsigned char systemClockSpeed,
unsigned char *setDcoRange,
unsigned char *setVCore,
unsigned int *setMultiplier);
/************************************************************************
* @brief Increments the VCore setting.
*
* @param level The target VCore setting
*
* @return none
*************************************************************************/
static void halBoardSetVCoreUp (unsigned char level)
{
// Open PMM module registers for write access
PMMCTL0_H = 0xA5;
// Set SVS/M high side to new level
SVSMHCTL = (SVSMHCTL & ~(SVSHRVL0*3 + SVSMHRRL0)) | \
(SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level);
// Set SVM new Level
SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
// Set SVS/M low side to new level
SVSMLCTL = (SVSMLCTL & ~(SVSMLRRL_3)) | (SVMLE + SVSMLRRL0 * level);
while ((PMMIFG & SVSMLDLYIFG) == 0); // Wait till SVM is settled (Delay)
PMMCTL0_L = PMMCOREV0 * level; // Set VCore to x
PMMIFG &= ~(SVMLVLRIFG + SVMLIFG); // Clear already set flags
if ((PMMIFG & SVMLIFG))
while ((PMMIFG & SVMLVLRIFG) == 0); // Wait till level is reached
// Set SVS/M Low side to new level
SVSMLCTL = (SVSMLCTL & ~(SVSLRVL0*3 + SVSMLRRL_3)) | \
(SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level);
// Lock PMM module registers from write access
PMMCTL0_H = 0x00;
}
/************************************************************************
* @brief Decrements the VCore setting.
*
* @param level The target VCore.
*
* @return none
*************************************************************************/
static void halBoardSetVCoreDown(unsigned char level)
{
// Open PMM module registers for write access
PMMCTL0_H = 0xA5;
// Set SVS/M low side to new level
SVSMLCTL = (SVSMLCTL & ~(SVSLRVL0*3 + SVSMLRRL_3)) | \
(SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level);
while ((PMMIFG & SVSMLDLYIFG) == 0); // Wait till SVM is settled (Delay)
PMMCTL0_L = (level * PMMCOREV0); // Set VCore to new level
// Lock PMM module registers for write access
PMMCTL0_H = 0x00;
}
/************************************************************************
* @brief Get function for the DCORSEL, VCORE, and DCO multiplier settings
* that map to a given clock speed.
*
* @param systemClockSpeed Target DCO frequency - SYSCLK_xxMHZ.
*
* @param setDcoRange Pointer to the DCO range select bits.
*
* @param setVCore Pointer to the VCore level bits.
*
* @param setMultiplier Pointer to the DCO multiplier bits.
*
* @return none
************************************************************************/
static void halBoardGetSystemClockSettings(unsigned char systemClockSpeed,
unsigned char *setDcoRange,
unsigned char *setVCore,
unsigned int *setMultiplier)
{
switch (systemClockSpeed)
{
case SYSCLK_1MHZ:
*setDcoRange = DCORSEL_1MHZ;
*setVCore = VCORE_1MHZ;
*setMultiplier = DCO_MULT_1MHZ;
break;
case SYSCLK_4MHZ:
*setDcoRange = DCORSEL_4MHZ;
*setVCore = VCORE_4MHZ;
*setMultiplier = DCO_MULT_4MHZ;
break;
case SYSCLK_8MHZ:
*setDcoRange = DCORSEL_8MHZ;
*setVCore = VCORE_8MHZ;
*setMultiplier = DCO_MULT_8MHZ;
break;
case SYSCLK_12MHZ:
*setDcoRange = DCORSEL_12MHZ;
*setVCore = VCORE_12MHZ;
*setMultiplier = DCO_MULT_12MHZ;
break;
case SYSCLK_16MHZ:
*setDcoRange = DCORSEL_16MHZ;
*setVCore = VCORE_16MHZ;
*setMultiplier = DCO_MULT_16MHZ;
break;
/*-------------------------------------
* Commented out because fmax = 18 MHz
* ------------------------------------
case SYSCLK_20MHZ:
*setDcoRange = DCORSEL_20MHZ;
*setVCore = VCORE_20MHZ;
*setMultiplier = DCO_MULT_20MHZ;
break;
case SYSCLK_25MHZ:
*setDcoRange = DCORSEL_25MHZ;
*setVCore = VCORE_25MHZ;
*setMultiplier = DCO_MULT_25MHZ;
break;
*-------------------------------------*/
}
}
/************************************************************************
* @brief Set function for the PMM core voltage (PMMCOREV) setting
*
* @param level Target VCore setting
*
* @return none
*************************************************************************/
void halBoardSetVCore(unsigned char level)
{
unsigned int currentVCore;
currentVCore = PMMCTL0 & PMMCOREV_3; // Get actual VCore
// Change VCore step by step
while (level != currentVCore)
{
if (level > currentVCore)
halBoardSetVCoreUp(++currentVCore);
else
halBoardSetVCoreDown(--currentVCore);
}
}
/************************************************************************
* @brief Disables all supply voltage supervision and monitoring.
*
* @param none
*
* @return none
*************************************************************************/
void halBoardDisableSVS(void)
{
// Open PMM module registers for write access
PMMCTL0_H = 0xA5;
SVSMLCTL &= ~( SVMLE + SVSLE + SVSLFP + SVMLFP ); // Disable Low side SVM
SVSMHCTL &= ~( SVMHE + SVSHE + SVSHFP + SVMHFP ); // Disable High side SVM
PMMCTL1 = PMMREFMD;
// Lock PMM module registers for write access
PMMCTL0_H = 0x00;
}
/************************************************************************
* @brief Enables all supply voltage supervision and monitoring
*
* @param none
*
* @return none
*************************************************************************/
void halBoardEnableSVS(void)
{
// Open PMM module registers for write access
PMMCTL0_H = 0xA5;
/*-----------
* NOTE: To attain the expected < 6 us wakeup from LPM modes, the following
* two lines must be commented out due to the fact that the PMM will hold
* the CPU until the reference is fully settled.
*----------*/
SVSMHCTL &= ~(SVSHFP+SVMHFP); // Disable full-performance mode
SVSMLCTL &= ~(SVSLFP+SVMLFP); // Disable full-performance mode
SVSMLCTL |= ( SVMLE + SVSLE); // Enable Low side SVM
SVSMHCTL |= ( SVMHE + SVSHE); // Enable High side SVM
PMMCTL1 &= ~PMMREFMD;
// Lock PMM module registers for write access
PMMCTL0_H = 0x00;
}
/************************************************************************
* @brief Initialization routine for XT1.
*
* Sets the necessary internal capacitor values and loops until all
* ocillator fault flags remain cleared.
*
* @param none
*
* @return none
*************************************************************************/
void halBoardStartXT1(void)
{
// Set up XT1 Pins to analog function, and to lowest drive
P7SEL |= 0x03;
UCSCTL6 |= XCAP_3 ; // Set internal cap values
while(SFRIFG1 & OFIFG) { // Check OFIFG fault flag
while ( (SFRIFG1 & OFIFG)) // Check OFIFG fault flag
{
// Clear OSC fault flags
UCSCTL7 &= ~(DCOFFG + XT1LFOFFG + XT1HFOFFG + XT2OFFG);
SFRIFG1 &= ~OFIFG; // Clear OFIFG fault flag
}
UCSCTL6 &= ~(XT1DRIVE1_L+XT1DRIVE0); // Reduce the drive strength
}
}
/************************************************************************
* @brief Set function for MCLK frequency.
*
* @param systemClockSpeed Intended frequency of operation - SYSCLK_xxMHZ.
*
* @return none
*************************************************************************/
void halBoardSetSystemClock(unsigned char systemClockSpeed)
{
unsigned char setDcoRange = 0;
unsigned char setVCore = 0;
unsigned int setMultiplier = 0;
halBoardGetSystemClockSettings( systemClockSpeed, &setDcoRange, \
&setVCore, &setMultiplier);
if (setVCore > (PMMCTL0 & PMMCOREV_3)) // Only change VCore if necessary
halBoardSetVCore( setVCore );
UCSCTL0 = 0x00; // Set lowest possible DCOx, MODx
UCSCTL1 = setDcoRange; // Select suitable range
UCSCTL2 = setMultiplier + FLLD_1; // Set DCO Multiplier
UCSCTL4 = SELA__XT1CLK | SELS__DCOCLKDIV | SELM__DCOCLKDIV ;
// Worst-case settling time for the DCO when the DCO range bits have been
// changed is n x 32 x 32 x f_FLL_reference. See UCS chapter in 5xx UG
// for optimization.
// 32 x 32 x / f_FLL_reference (32,768 Hz) = .03125 = t_DCO_settle
// t_DCO_settle / (1 / 18 MHz) = 562500 = counts_DCO_settle
// __delay_cycles(562500);
int i;
for (i=0;i<10;i++){
__delay_cycles(56250);
}
}
/************************************************************************
* @brief Initializes ACLK, MCLK, SMCLK outputs on P11.0, P11.1,
* and P11.2, respectively.
*
* @param none
*
* @return none
*************************************************************************/
void halBoardOutputSystemClock(void)
{
P11DIR |= 0x07;
P11SEL |= 0x07;
}
/************************************************************************
* @brief Stops the output of ACLK, MCLK, SMCLK on P11.0, P11.1, and P11.2.
*
* @param none
*
* @return none
*************************************************************************/
void halBoardStopOutputSystemClock(void)
{
P11OUT &= ~0x07;
P11DIR |= 0x07;
P11SEL &= ~0x07;
}
/************************************************************************
* @brief Initializes all GPIO configurations.
* TI example did set all ports to OUTPUT, we don't.
* @param none
*
* @return none
*************************************************************************/
void halBoardInit(void)
{
#if 0
// ORIGINAL EP
//Tie unused ports
PAOUT = 0;
PADIR = 0xFFFF;
PASEL = 0;
PBOUT = 0;
PBDIR = 0xFFFF;
PBSEL = 0;
PCOUT = 0;
PCDIR = 0xFFFF;
PCSEL = 0;
PDOUT = 0;
PDDIR = 0xFFFF;
PDSEL = 0;
PEOUT = 0;
PEDIR = 0xFEFF; // P10.0 to USB RST pin,
// ...if enabled with J5
PESEL = 0;
P11OUT = 0;
P11DIR = 0xFF;
PJOUT = 0;
PJDIR = 0xFF;
P11SEL = 0;
#else
//Tie unused ports
PAOUT = 0;
PADIR = 0;
PASEL = 0;
PBOUT = 0;
PBDIR = 0;
PBSEL = 0;
PCOUT = 0;
PCDIR = 0;
PCSEL = 0;
PDOUT = 0;
PDDIR = 0;
PDSEL = 0;
PEOUT = 0;
PEDIR = 0;
PESEL = 0;
P11OUT = 0;
P11DIR = 0;
PJOUT = 0;
PJDIR = 0;
P11SEL = 0;
#endif
AUDIO_PORT_OUT = AUDIO_OUT_PWR_PIN ;
USB_PORT_DIR &= ~USB_PIN_RXD; // USB RX Pin, Input with
// ...pulled down Resistor
USB_PORT_OUT &= ~USB_PIN_RXD;
USB_PORT_REN |= USB_PIN_RXD;
}