Skip to content
Snippets Groups Projects
hal_mcu.c 10.12 KiB
/******************************************************************************
 *  Filename: hal_mcu.c
 *
 *  Description: Configuration of MCU core registers
 *
 *  Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
 *
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *    Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 *    Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 *    Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *  Modified by Edward Longman for the MSP430FR5994
 *
 *******************************************************************************/

#include "msp430.h"
// TODO Provide the define statements needed from this file.
#include "../radio_drv/hal_spi_rf.h"

#if defined (__MSP430F5438A__)
/*******************************************************************************
 * @brief Setup all the peripherals of the MSP430, set the CPU speed to 16MHz,
 *        enable the 32KHz and configure WDT for a 1 sec tick speed.
 *
 *        (MSP430F5438 version)
 *
 * @param  none
 *
 * @return none
 *******************************************************************************/
void msp_setup(void) {

	BUTTON_DIR  	&= ~BUTTON_PIN;           // Set output direction
	BUTTON_OUT 		=   BUTTON_PIN;           // Set output direction
	BUTTON_PxIE  	|=  BUTTON_PIN;           // interrupt enabled
	BUTTON_PxIES 	|=  BUTTON_PIN;           // Hi/lo edge
	BUTTON_REN 		|=  BUTTON_PIN;           // Pull up resistor
	BUTTON_PxIFG 	&= ~BUTTON_PIN;           // IFG cleared

	// Setup the XTAL ports to use the external 32K oscillilator
	P7SEL |= 0x03;                            // Select XT1
	UCSCTL6 |= XCAP_3;                        // Internal load cap

	// Loop until XT1,XT2 & DCO stabilizes
	do  {
		UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG);
		// Clear XT2,XT1,DCO fault flags
		SFRIFG1 &= ~OFIFG;                      // Clear fault flags
	} while (SFRIFG1&OFIFG);                  // Test oscillator fault flag
	UCSCTL6 &= ~(XT1DRIVE_3);                 // Xtal is now stable, reduce drive

	// Set up clock system on MCU to fit your system
	// Target specific implementation
	UCSCTL0 = 0x00;                           // Set lowest possible DCOx, MODx
	UCSCTL1 = DCORSEL_6;                      // Select suitable range
	UCSCTL2 = 488;                            // DCO = 488 * 32768Hz ~= 16MHz
	UCSCTL4 = SELA__XT1CLK | SELS__DCOCLK | SELM__DCOCLK ;

	// Setup Watch dog timer for 1 second tick using 32Khz XTAL on MSP430F5438A
	WDTCTL = WDT_ADLY_1000;                    // WDT 15.6ms, ACLK, interval timer
	SFRIE1 |= WDTIE;                           // Enable WDT interrupt
}

#endif

#if defined (__MSP430F5529__)
/*******************************************************************************
 * @brief Setup all the peripherals of the MSP430, set the CPU speed to 16MHz,
 *        enable the 32KHz and configure WDT for a 1 sec tick speed.
 *
 *        (MSP430F5529 version)
 *
 * @param  none
 *
 * @return none
 *******************************************************************************/
void msp_setup(void) {
    // Enable the interupts on port 2 to catch the user button (TRXEB)

    BUTTON_DIR   &= ~BUTTON_PIN;       // input direction
    BUTTON_OUT   |=  BUTTON_PIN;       // set high on port
    BUTTON_PxIE  |=  BUTTON_PIN;       // enable interupt
    BUTTON_PxIES |=  BUTTON_PIN;       // Hi/lo edge
    BUTTON_REN   |=  BUTTON_PIN;       // Pull up resistor
    BUTTON_PxIES &= ~BUTTON_PIN;       // IFG cleared

    // Setup the XTAL ports to use the external 32K oscillilator
    P5SEL |= BIT4+BIT5;                            // Select XT1
    UCSCTL6 |= XCAP_3;                             // Internal load cap

    // Loop until XT1,XT2 & DCO stabilizes
    do  {
        UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
        // Clear XT2,XT1,DCO fault flags
        SFRIFG1 &= ~OFIFG;                      // Clear fault flags
    } while (SFRIFG1&OFIFG);                  // Test oscillator fault flag
    UCSCTL6 &= ~(XT1DRIVE_3);                 // Xtal is now stable, reduce drive

    // Set up clock system on MCU to fit your system
    // Target specific implementation
    UCSCTL0 = 0x00;                           // Set lowest possible DCOx, MODx
    UCSCTL1 = DCORSEL_6;                      // Select suitable range
    UCSCTL2 = 488;                            // DCO = 488 * 32768Hz ~= 16MHz
    UCSCTL4 = SELA__XT1CLK | SELS__DCOCLK | SELM__DCOCLK ;

    // Setup Watch dog timer for 1 second tick using 32Khz XTAL on MSP430F5438A
    WDTCTL = WDT_ADLY_1000;                    // WDT 15.6ms, ACLK, interval timer
    SFRIE1 |= WDTIE;                           // Enable WDT interrupt
}

#endif


#if defined (__MSP430G2553__)
/*******************************************************************************
 * @brief Setup all the peripherals of the MSP430, set the CPU speed to 16MHz,
 *        enable the 32KHz and configure WDT for a 1 sec tick speed.
 *
 *        (MSP430G2553 version)
 *
 * @param  none
 *
 * @return none
 *******************************************************************************/
void msp_setup(void) {

	BUTTON_DIR  	&= ~BUTTON_PIN;           // Set output direction
	BUTTON_OUT 		=   BUTTON_PIN;           // Set output direction
	BUTTON_PxIE  	|=  BUTTON_PIN;           // interrupt enabled
	BUTTON_PxIES 	|=  BUTTON_PIN;           // Hi/lo edge
	BUTTON_REN 		|=  BUTTON_PIN;           // Pull up resistor
	BUTTON_PxIFG 	&= ~BUTTON_PIN;           // IFG cleared

	// set system clock to 16MHz
	DCOCTL  = CALDCO_16MHZ;
	BCSCTL1 = CALBC1_16MHZ;

	 // Setup Watch dog timer for a 1 second tick using a 32KHz external XTAL
	 BCSCTL1 |= DIVA_0;                        // ACLK/1 = 32.768KHz
	 WDTCTL = WDT_ADLY_1000;                   // WDT 1s interval timer
	 IE1 |= WDTIE;                             // Enable WDT interrupt

}
#endif

#if defined (__MSP430FR5994__)
//Define the Main Clock setup options. Done here for the delay function setup
#define DCO_RANGE_SEL DCORSEL
#define DCO_FREQ_SEL DCOFSEL_4
#define F_CPU_SCALE  DIVM_0

/**
 * @defgroup Delay_function
 * @brief Directives to create the _delay_us macro.
 * @{
 */
/**
 * @def _delay_us(__us)
 * @brief Delay for a specified time using the __delay_cycles primitive.
 *
 * @param[in] __us - time to delay for
 * @return none
 * @note Assumes using the internal DCO. Will need modification to work with
 *       XTAL. VLO is two innacurate (6%) for this to be a good delay anyway.
 *       Max possible delay is (2**32-1)*F_CPU
 *       That would be 178s for 24MHz.
 *       helped by https://docs.microsoft.com/en-us/cpp/preprocessor/hash-if-hash-elif-hash-else-and-hash-endif-directives-c-cpp?view=vs-2019
 *       and https://github.com/ab2tech/msp430/blob/master/include/msp/delay.h
 *
 */
#if DCO_RANGE_SEL==DCORSEL
  #define F_CPU_RANGE 16000000UL
#else
  #define F_CPU_RANGE 5330000UL
#endif

#if DCO_FREQ_SEL==DCOFSEL_0
  #define F_CPU F_CPU_RANGE*1.0
#elif DCO_FREQ_SEL==DCOFSEL_1
  #define F_CPU F_CPU_RANGE*1.25
#elif DCO_FREQ_SEL==DCOFSEL_2
  #define F_CPU F_CPU_RANGE*1.0
#else //DCO_FREQ_SEL==DCOFSEL_3
  #define F_CPU F_CPU_RANGE*1.5
#endif
#define F_CPU_SCALED_US F_CPU/(1<<F_CPU_SCALE)/1000000.0
            /* Number of CPU cycles per us */

#define _delay_us(__us) \
  if((uint32_t) (F_CPU_SCALED_US * __us) != F_CPU_SCALED_US * __us)\
        __delay_cycles((uint32_t) ( F_CPU_SCALED_US * __us)+1);\
  else __delay_cycles((uint32_t) ( F_CPU_SCALED_US * __us))
/** @} */

/*******************************************************************************
 * @brief Setup all the peripherals of the MSP430, set the CPU speed to 16MHz,
 *        enable the 250kHz and configure WDT for a 1 sec tick speed.
 *
 *        (MSP430FR5994 version)
 *
 * @param  none
 *
 * @return none
 *******************************************************************************/
void msp_setup(void) {

	// Enable the interupts on port 2 to catch the user button (TRXEB)

	BUTTON_DIR   &= ~BUTTON_PIN;       // input direction
	BUTTON_OUT   |=  BUTTON_PIN;       // set high on port
	BUTTON_PxIE  |=  BUTTON_PIN;       // enable interupt
	BUTTON_PxIES |=  BUTTON_PIN;       // Hi/lo edge
	BUTTON_REN   |=  BUTTON_PIN;       // Pull up resistor
	BUTTON_PxIES &= ~BUTTON_PIN;       // IFG cleared

	// Removed XTAL configuration and DCO Fault detection as not on exp430_fr5994

  // Unlock CS registers.
  CSCTL0_H = 0xA5;
  // Set DCO to 24MHz.
  CSCTL1 = DCO_RANGE_SEL + DCO_FREQ_SEL;
  // ACLK = VLO, SMCLK = MCLK = DCO
  CSCTL2 = SELA_1 + SELS_3 + SELM_3;
  // ACLK/1, SMCLK/8, MCLK/1
  CSCTL3 = DIVA_0 + DIVS_0 + F_CPU_SCALE;
  // Power down unused clocks.
  CSCTL4 = HFXTOFF + VLOOFF;
  // Lock clock registers.
  CSCTL0_H = 0;

	// Setup Watch dog timer for 0.5 second tick using 16MHz DCO on MSP430FR5994
    // WDT 0.5s @ 16mHz, SMCLK, interval timer
	WDTCTL= WDTPW0 + WDTSSEL_0 + WDTTMSEL + WDTIS_2;
	SFRIE1 |= WDTIE;                           // Enable WDT interrupt

  // Unlock the system.
  PM5CTL0 &= ~LOCKLPM5;
}
#endif