This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS/MSP430FR5969: 16Mhz HF External crystal TimerA continous code

Part Number: MSP430FR5969

Tool/software: Code Composer Studio

Hi,

I am working with msp430fr5969. I add a 16Mhz HF External crystal as the clock source. The code to configure clock source works well in noamal code without TimerA, as shown below. 

#include <msp430.h>

int main(void)
{
  WDTCTL = WDTPW | WDTHOLD;

  // Configure GPIO
  P1OUT = 0;
  P1DIR = BIT0;                             // For LED

//  P2DIR |= BIT0;
//  P2SEL0 |= BIT0;                           // Output ACLK
//  P2SEL1 |= BIT0;

  P3DIR |= BIT4;
  P3SEL0 |= BIT4;                           // Output SMCLK
  P3SEL1 |= BIT4;

  PJSEL0 |= BIT4 | BIT5 | BIT6 | BIT7;      // For XT1 and XT2

  // Disable the GPIO power-on default high-impedance mode to activate
  // previously configured port settings
  PM5CTL0 &= ~LOCKLPM5;

  // Clock System Setup - Used msp430fr5969.h to find definitions to set SMCLK to HFXTAL
  CSCTL0_H = CSKEY >> 8; // Unlock CS registers, password
  CSCTL1 = DCOFSEL_6;             // Set DCO to 16MHz
  CSCTL2 = SELA__VLOCLK | SELS__HFXTCLK | SELM__DCOCLK; // Set ACLK = VLOCLK, SMCLK = MCLK = HFXTAL
  CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1; // Set all dividers to 1
  CSCTL4 &= ~(LFXTOFF | HFXTOFF);
  CSCTL4 |= HFFREQ_2 | HFXTDRIVE_1;
  do
  {
  CSCTL5 &= ~ (LFXTOFFG | HFXTOFFG); // Clear LFXT and HFXT fault flag
  SFRIFG1 &= ~OFIFG;
  }while (SFRIFG1&OFIFG); // Test oscillator fault flag
  CSCTL0_H = 0; // Lock CS registers

//  CSCTL0_H = CSKEY >> 8;                    // Unlock CS registers
//  CSCTL1 = DCOFSEL_6;                       // Set DCO to 8MHz
//  CSCTL2 = SELA__LFXTCLK | SELS__HFXTCLK | SELM__DCOCLK;
//  CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1;     // Set all dividers to 1
//  CSCTL4 |= LFXTDRIVE_1 | HFXTDRIVE_1;
//  CSCTL4 &= ~(LFXTOFF | HFXTOFF);
//  do
//  {
//    CSCTL5 &= ~(LFXTOFFG | HFXTOFFG);       // Clear XT1 and XT2 fault flag
//    SFRIFG1 &= ~OFIFG;
//  }while (SFRIFG1&OFIFG);                   // Test oscillator fault flag
//  CSCTL0_H = 0;                             // Lock CS registers

  while (1) {
    P1OUT ^= 0x01;                          // Toggle LED
    __delay_cycles(8000000);                // Wait 8,000,000 CPU Cycles
  }
}

However, it doesn't work in code using TimerA. Below is my code. The program always dies in the cycle of crystal oscillation (loop in "do {} while" part).  I don't know why. 

#include "driverlib.h"
#include <msp430.h>

void Init_GPIO(void);
void Init_CLK(void);

#define COMPARE_VALUE 50000


void main (void)
{
    //Stop WDT
    WDT_A_hold(WDT_A_BASE);

    Init_GPIO();
    Init_CLK();

    //Start timer in continuous mode sourced by SMCLK
    Timer_A_initContinuousModeParam initContParam = {0};
    initContParam.clockSource = TIMER_A_CLOCKSOURCE_SMCLK;
    initContParam.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_1;
    initContParam.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_DISABLE;
    initContParam.timerClear = TIMER_A_DO_CLEAR;
    initContParam.startTimer = false; //Whether to start the timer immediately.
    Timer_A_initContinuousMode(TIMER_A1_BASE, &initContParam);  // "TIMER_A1_BASE" the base address of the TIMER_A module

    //Initiaze compare mode (Clears the capture-compare interrupt flag)
	Timer_A_clearCaptureCompareInterrupt(TIMER_A1_BASE,
		TIMER_A_CAPTURECOMPARE_REGISTER_0
		);

    Timer_A_initCompareModeParam initCompParam = {0};
    initCompParam.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_0;
    initCompParam.compareInterruptEnable = TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE;
    initCompParam.compareOutputMode = TIMER_A_OUTPUTMODE_OUTBITVALUE;
    initCompParam.compareValue = COMPARE_VALUE;
    Timer_A_initCompareMode(TIMER_A1_BASE, &initCompParam);

    Timer_A_startCounter( TIMER_A1_BASE,
    		TIMER_A_CONTINUOUS_MODE
                );

    // Request the disabling of the core voltage regulator when device enters
    // LPM3 (or LPM4) so that we can effectively enter LPM3.5 (or LPM4.5).
//    PMM_turnOffRegulator();

    //Enter LPM0, enable interrupts
    __bis_SR_register(LPM4_bits + GIE);

    //For debugger
    __no_operation();
}

//******************************************************************************
//
//This is the TIMER1_A3 interrupt vector service routine.
//
//******************************************************************************
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=TIMER1_A0_VECTOR
__interrupt
#elif defined(__GNUC__)
__attribute__((interrupt(TIMER1_A0_VECTOR)))
#endif
void TIMER1_A0_ISR (void)
{
    uint16_t compVal = Timer_A_getCaptureCompareCount(TIMER_A1_BASE,
    		TIMER_A_CAPTURECOMPARE_REGISTER_0)
    		+ COMPARE_VALUE;

    //Toggle P1.0
    GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);


    //Add Offset to CCR0
    Timer_A_setCompareValue(TIMER_A1_BASE,
        TIMER_A_CAPTURECOMPARE_REGISTER_0,
        compVal
        );
}


/*
 * CLOCK Initialization
 */
void Init_CLK()
{
    // Configure one FRAM waitstate as required by the device datasheet for MCLK
    // operation beyond 8MHz _before_ configuring the clock system.
    FRCTL0 = FRCTLPW | NWAITS_1;

//    // Clock System Setup
//    CSCTL0_H = CSKEY >> 8;                    // Unlock CS registers
//    CSCTL1 = DCORSEL | DCOFSEL_4;             // Set DCO to 16MHz
//    CSCTL2 = SELA__VLOCLK | SELS__DCOCLK | SELM__DCOCLK; // Set SMCLK = MCLK = DCO,
//                                                // ACLK = VLOCLK
//    CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1;     // Set all dividers
//    CSCTL0_H = 0;                             // Lock CS registers


    // Clock System Setup - Used msp430fr5969.h to find definitions to set SMCLK to HFXTAL
    CSCTL0_H = CSKEY >> 8; // Unlock CS registers, password
    CSCTL1 = DCOFSEL_6;             // Set DCO to 16MHz
    CSCTL2 = SELA__VLOCLK | SELS__HFXTCLK | SELM__DCOCLK; // Set ACLK = VLOCLK, SMCLK = MCLK = HFXTAL
    CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1; // Set all dividers to 1
    CSCTL4 &= ~(LFXTOFF | HFXTOFF);
    CSCTL4 |= HFFREQ_2 | HFXTDRIVE_1;
    do
    {
    CSCTL5 &= ~ (LFXTOFFG | HFXTOFFG); // Clear LFXT and HFXT fault flag
    SFRIFG1 &= ~OFIFG;
    }while (SFRIFG1&OFIFG); // Test oscillator fault flag
    CSCTL0_H = 0; // Lock CS registers


//      CSCTL0_H = CSKEY >> 8;                    // Unlock CS registers
//      CSCTL1 = DCOFSEL_6;                       // Set DCO to 8MHz
//      CSCTL2 = SELA__LFXTCLK | SELS__HFXTCLK | SELM__DCOCLK;
//      CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1;     // Set all dividers to 1
//      CSCTL4 |= LFXTDRIVE_1 | HFXTDRIVE_1;
//      CSCTL4 &= ~(LFXTOFF | HFXTOFF);
//      do
//      {
//        CSCTL5 &= ~(LFXTOFFG | HFXTOFFG);       // Clear XT1 and XT2 fault flag
//        SFRIFG1 &= ~OFIFG;
//      }while (SFRIFG1&OFIFG);                   // Test oscillator fault flag
//      CSCTL0_H = 0;                             // Lock CS registers

}

/*
 * GPIO Initialization
 */
void Init_GPIO()
{
    // Set all GPIO pins to output low for low power
    GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
    GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
    GPIO_setOutputLowOnPin(GPIO_PORT_P3, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
    GPIO_setOutputLowOnPin(GPIO_PORT_P4, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
    GPIO_setOutputLowOnPin(GPIO_PORT_PJ, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7|GPIO_PIN8|GPIO_PIN9|GPIO_PIN10|GPIO_PIN11|GPIO_PIN12|GPIO_PIN13|GPIO_PIN14|GPIO_PIN15);

    GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
    GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
    GPIO_setAsOutputPin(GPIO_PORT_P3, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
    GPIO_setAsOutputPin(GPIO_PORT_P4, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
    GPIO_setAsOutputPin(GPIO_PORT_PJ, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7|GPIO_PIN8|GPIO_PIN9|GPIO_PIN10|GPIO_PIN11|GPIO_PIN12|GPIO_PIN13|GPIO_PIN14|GPIO_PIN15);


    //Set P1.0 to output direction
    GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);


//    // Set PJ.4 and PJ.5 as Primary Module Function Input, LFXT.
//    GPIO_setAsPeripheralModuleFunctionInputPin(
//           GPIO_PORT_PJ,
//           GPIO_PIN4 + GPIO_PIN5,
//           GPIO_PRIMARY_MODULE_FUNCTION
//           );

    // Disable the GPIO power-on default high-impedance mode
    // to activate previously configured port settings
    PMM_unlockLPM5();
}


Thanks.

zzx

  • >    GPIO_setAsOutputPin(GPIO_PORT_PJ, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7|GPIO_PIN8|GPIO_PIN9|GPIO_PIN10|GPIO_PIN11|GPIO_PIN12|GPIO_PIN13|GPIO_PIN14|GPIO_PIN15);

    This function clears the PJSEL0 bits, in particular for PJ.4-7 (HFXT/LFXT). Try something like:

    >  GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_PJ, GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);

  • Thank you very much. It works. However, there still exist some other problems.

    1) The function Init_CLK() in my code above and the below code dco_init() have the same function. Does this mean that msp430fr5969 don't need 16Mhz HF External crystal to work at 16Mhz? Just configure DCO is ok ?

    void dco_init(void)
    {  
      // Configure one FRAM waitstate as required by the device datasheet for MCLK
      // operation beyond 8MHz _before_ configuring the clock system.
      FRCTL0 = FRCTLPW | NWAITS_1;
    
      // Clock System Setup
      CSCTL0_H = CSKEY >> 8;                    // Unlock CS registers
      CSCTL1 = DCORSEL | DCOFSEL_4;             // Set DCO to 16MHz
      CSCTL2 = SELA__VLOCLK | SELS__DCOCLK | SELM__DCOCLK; // Set SMCLK = MCLK = DCO,
                                                // ACLK = VLOCLK
      CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1;     // Set all dividers
      CSCTL0_H = 0;                             // Lock CS registers
    }

    2)The example code above using timerA continuous mode operation with CCR0 interrupt. The notes are as follows. The COMPARE_VALUE 50000 means "Toggles every 50000 SMCLK cycles". I change the code pin1.0 above to pin1.5(I/O) and test the frequency in pin1.5 is 158HZ. When I set COMPARE_VALUE=5, the frequency is 121HZ. In theory, the frequency should be 158*10000HZ. I don't know why.

    //******************************************************************************
    //!  TIMER_A, Toggle P1.0, CCR0 Cont. Mode ISR, DCO SMCLK
    //!
    //!  Toggle P1.0 using software and TA_0 ISR. Toggles every
    //!  50000 SMCLK cycles. SMCLK provides clock source for TACLK.
    //!  During the TA_0 ISR, P1.0 is toggled and 50000 clock cycles are added to
    //!  CCR0. TA_0 ISR is triggered every 50000 cycles. CPU is normally off and
    //!  used only during TA_ISR.
    //!  ACLK = n/a, MCLK = SMCLK = TACLK = default DCO ~1.045MHz
    //!
    //!  Tested On: MSP430FR5969
    //!         ---------------
    //!     /|\|               |
    //!      | |               |
    //!      --|RST            |
    //!        |               |
    //!        |           P1.0|-->LED
    //!
    //! This example uses the following peripherals and I/O signals.  You must
    //! review these and change as needed for your own board:
    //! - TimerA peripheral
    //! - GPIO peripheral
    //!
    //! This example uses the following interrupt handlers.  To use this example
    //! in your own application you must add these interrupt handlers to your
    //! vector table.
    //! - Timer A0
    //!

  • 1) The DCO runs fine at 16MHz. It's less accurate than a crystal, but it's lower power and starts up much faster. Different things are important in different applications.

    2) 5 MCLK(=SMCLK) cycles is not long enough to run the ISR (figure a minimum of 25 MCLKs + whatever you want to do). As a result, the +5 update "misses" and the timer has to make a full round (65536+5 ticks) before it reaches the new CCR0. My calculator says 16MHz/(65536+5) =~244 ISRs/sec. Each ISR is half a pin cycle, so the pin would cycle at (244/2)=122Hz.

    Unsolicited: Unless you have a strong reason not to, I suggest you run MCLK and SMCLK from the same clock source (either DCO or HFXT). There are various corners of the system where you have to be very careful when these two are running asynchronously to one another.