mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-01-05 21:59:45 +00:00
368 lines
12 KiB
C
Executable File
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;
|
|
}
|