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.

MSP430FR5994: LaunchPad code behavior I need help understanding.

Part Number: MSP430FR5994
Hello everyone,
I am coming up the learning curve on the MSP430FR5994 and ran into two problems neither of which I can explain and need some help to understand. The code is rather simple, it simply uses the BCL UART to respond with " hello world " whenever a character "a" is typed on the CCS's terminal (any character other than "a" is ignored). This code works (with many thanks to Bruce and Matt). However, I am puzzled that the code stops functioning when I comment out a P5IFG = 0x00; statement inside the initGPIO function. I highlighted the problem statement in yellow. As is, the code works. Comment out the statement and it stops. Moving the statement outside of the function and into the main function doesn't change the behavior. The statement needs to be in the initGPIO function for some reason. Any ideas as to what's happening? 
1) The second problem is that Port5 interrupts from the two button on the Launchpad (P5.6 and P5.5) aren't being recognized when pressed. Did I lock up the port somehow? . Any help here would also be greatly appreciated. 
 
#include "driverlib.h"
uint32_t myMCLK = 0;
uint32_t mySMCLK = 0;
uint32_t myACLK = 0;
volatile uint8_t i;
volatile uint8_t j;
const char UCA0_string[] = {" Hello World "};
extern int mode;
extern int pingHost;
uint8_t RXData = 0;                               // UART Receive byte
int mode = 0;                                     // mode selection variable
int pingHost = 0;                                 // ping request from PC GUI
int noSDCard = 0;
Calendar calendar;                                // Calendar used for RTC

void initClocks (void){

   // Set DCO frequency to 8 MHz
   CS_setDCOFreq(CS_DCORSEL_0, CS_DCOFSEL_6);
   //Set external clock frequency to 32.768 KHz
   CS_setExternalClockSource(32768, 0);
   //Set ACLK=LFXT
   CS_initClockSignal(CS_ACLK, CS_LFXTCLK_SELECT, CS_CLOCK_DIVIDER_1);
   // Set SMCLK = DCO with frequency divider of 1
   CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);
   // Set MCLK = DCO with frequency divider of 1
   CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);
   //Start XT1 with no time out
   CS_turnOnLFXT(CS_LFXT_DRIVE_3);
   myACLK=CS_getACLK();
   mySMCLK=CS_getSMCLK(); //8MHz
   myMCLK=CS_getMCLK();   //16MHz
}
initTimers(void){
    myACLK=CS_getACLK();   //10KHZ
    Timer_A_initContinuousModeParam initA0 = {0}; //initializer selects TB1
    initA0.clockSource=TIMER_A_CLOCKSOURCE_ACLK;
    initA0.clockSourceDivider=TIMER_A_CLOCKSOURCE_DIVIDER_1;
    initA0.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_DISABLE;
    initA0.timerClear=TIMER_A_DO_CLEAR;
    initA0.startTimer=false;
    Timer_A_initContinuousMode(TIMER_A0_BASE,&initA0);
    __bis_SR_register(GIE);
}
void Init_BCL_UART()
{
    // Configure UART
    EUSCI_A_UART_initParam param = {};
    param.selectClockSource = EUSCI_A_UART_CLOCKSOURCE_ACLK;
    param.clockPrescalar = 3;  //set for 32.768KHz
    param.firstModReg = 0;
    param.secondModReg =  0x92; //3;//0x92;
    param.parity = EUSCI_A_UART_NO_PARITY;
    param.msborLsbFirst = EUSCI_A_UART_LSB_FIRST;
    param.numberofStopBits = EUSCI_A_UART_ONE_STOP_BIT;
    param.uartMode = EUSCI_A_UART_MODE;
    param.overSampling = EUSCI_A_UART_LOW_FREQUENCY_BAUDRATE_GENERATION;
    if(STATUS_FAIL == EUSCI_A_UART_init(EUSCI_A0_BASE, &param))
        return;
    EUSCI_A_UART_enable(EUSCI_A0_BASE);
    EUSCI_A_UART_clearInterrupt(EUSCI_A0_BASE,EUSCI_A_UART_RECEIVE_INTERRUPT);

       // Enable USCI_A0 RX interrupt
    EUSCI_A_UART_enableInterrupt(EUSCI_A0_BASE,
                                    EUSCI_A_UART_RECEIVE_INTERRUPT); // Enable interrupt
    myACLK=CS_getACLK();
    mySMCLK=CS_getSMCLK(); //8MHz
    myMCLK=CS_getMCLK();   //16MHz
}
void initGPIO()
{
        // 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_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_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
        GPIO_setOutputLowOnPin(GPIO_PORT_P5, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|                    GPIO_PIN7);
        GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
        GPIO_setOutputLowOnPin(GPIO_PORT_P7, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
        GPIO_setOutputLowOnPin(GPIO_PORT_P8, 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_P5, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|                    GPIO_PIN7);
        GPIO_setAsOutputPin(GPIO_PORT_P6, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
        GPIO_setAsOutputPin(GPIO_PORT_P7, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
        GPIO_setAsOutputPin(GPIO_PORT_P8, 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 PJ.4 and PJ.5 as Primary Module Function Input, LFXT.
        GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_PJ,GPIO_PIN4 + GPIO_PIN5,GPIO_PRIMARY_MODULE_FUNCTION);

    // Setup P1.0 and P1.1 LED
    GPIO_setAsOutputPin(GPIO_PORT_P1,GPIO_PIN0);
    GPIO_setAsOutputPin(GPIO_PORT_P1,GPIO_PIN1);
    //turn off leds
    GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0);
    GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN1);
    // Setup P5.5 and P5.6 as input buttons
    GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P5,GPIO_PIN5);
    GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P5,GPIO_PIN6);
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN5,GPIO_PRIMARY_MODULE_FUNCTION);
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN6,GPIO_PRIMARY_MODULE_FUNCTION);
    GPIO_selectInterruptEdge(GPIO_PORT_P5,GPIO_PIN5,GPIO_HIGH_TO_LOW_TRANSITION);
    GPIO_selectInterruptEdge(GPIO_PORT_P5,GPIO_PIN6,GPIO_HIGH_TO_LOW_TRANSITION);
    //P5IE = 0x60; //enable interrupts on P5.5 and P5.6
    GPIO_enableInterrupt(GPIO_PORT_P5,GPIO_PIN5);
    GPIO_enableInterrupt(GPIO_PORT_P5,GPIO_PIN6);
    //setup BCL UART Pins
    // Configure P2.0 - UCA0TXD and P2.1 - UCA0RXD
    GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN0, GPIO_SECONDARY_MODULE_FUNCTION);
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P2, GPIO_PIN1, GPIO_SECONDARY_MODULE_FUNCTION);
    //enable interrupts
    // commenting out the function below causes the EUSCI_A_UART to stop working.EUSCI_A_UART uses P2.0 & P2.1
    P5IFG = 0x00; //clear all Port 5 interrupt flags
    // Disable the GPIO power-on default high-impedance mode
    // to activate previously configured port settings
    //PMM_unlockLPM5();
}
void Init_RTC()
{
    //Setup Current Time for Calendar
    calendar.Seconds    = 0x55;
    calendar.Minutes    = 0x30;
    calendar.Hours      = 0x04;
    calendar.DayOfWeek  = 0x01;
    calendar.DayOfMonth = 0x30;
    calendar.Month      = 0x04;
    calendar.Year       = 0x2014;
    // Initialize RTC with the specified Calendar above
    RTC_C_initCalendar(RTC_C_BASE,&calendar,RTC_C_FORMAT_BCD);
    RTC_C_setCalendarEvent(RTC_C_BASE,RTC_C_CALENDAREVENT_MINUTECHANGE);
    RTC_C_clearInterrupt(RTC_C_BASE,RTC_C_TIME_EVENT_INTERRUPT);
    RTC_C_enableInterrupt(RTC_C_BASE,RTC_C_TIME_EVENT_INTERRUPT);
    //Start RTC Clock
    RTC_C_startClock(RTC_C_BASE);
}

int main(void) {
    WDT_A_hold(WDT_A_BASE);
    initGPIO();
    initClocks();
    initTimers();
    Init_BCL_UART();
    //P5IFG = 0x00;
 /*
    SDCardLib_setRTCTime(SDCardLib * lib, Calendar *curTime);
    SDCardLib_detectCard(SDCardLib * lib);

    SDCardLib_createDirectory(SDCardLib * lib, char * directoryName);
    SDCardLib_writeFile(SDCardLib * lib,
                               char * fileName, char *buffer, uint16_t bufsize,
                               uint16_t *actualsize);

    return (0);
*/
       PMM_unlockLPM5();   // Enable output pin settings - disable the GPIO power-on default high-impedance mode
      // PM5CTL0 &= ~LOCKLPM5;
       //start timer B1 and its interrupt
       Timer_A_startCounter(TIMER_A0_BASE,TIMER_A_CONTINUOUS_MODE);
       Timer_A_enableInterrupt(TIMER_A0_BASE);

        UCA0IE |= UCRXIE; //enable only receive interrupts
      //__bis_SR_register(GIE);//enable interrupts
       __enable_interrupt();

       while(1)
       {
           volatile uint8_t k;
           //EUSCI_A_UART_transmitData(EUSCI_A0_BASE,'K');
       }
}

#pragma vector = USCI_A0_VECTOR
__interrupt void USCI_A0_ISR(void)
{
    switch(__even_in_range(UCA0IV,18))
    {
        case 0x00: // Vector 0: No interrupts
            break;
        case 0x02: // Vector 2: UCRXIFG
            if (UCA0RXBUF =='a'){
                i=0;
                UCA0IE |= UCTXIE; //received "a", enable transmit response
                UCA0TXBUF = UCA0_string[j];
            }
            break;
        case 0x04:  // Vector 4: UCTXIFG
            UCA0TXBUF = UCA0_string[j++];
           if (j==   sizeof(UCA0_string) - 1) {
                UCA0IE &= ~UCTXIE;
            }
           if(j>= sizeof(UCA0_string))j=0;
        break;
        case 0x06:  // Vector 6: UCSTTIFG
            break;
        case 0x08:  // Vector 8: UCTXCPTIFG
            break;
        default: break;
    }
}
#pragma vector=TIMER0_A1_VECTOR
__interrupt void TIMER_A0_ISR(void)
{
    switch(__even_in_range(TA0IV, 14))
    {
        case 0:                         // none
            break;
        case 2:                         // CCR1 IFG
            break;
        case 4:                         // CCR2 IFG
            break;
        case 6:                         // CCR3 IFG
            break;
        case 8:                         // CCR4 IFG
            break;
        case 10:                        // CCR5 IFG
            break;
        case 12:                        // CCR6 IFG
            break;
        case 14:                        // TAOIFG
            GPIO_toggleOutputOnPin(GPIO_PORT_P1,GPIO_PIN0);
            Timer_A_clearTimerInterrupt(TIMER_A0_BASE);
            break;
        default:                        // never executed
            break;
    }
}
#pragma vector=PORT5_VECTOR
__interrupt void ISR_P5_Handler (void){
  switch (P5IFG)
        {
            case 0x20:                  //P5.5 interrupt
                P5IFG &= ~BIT5;         //clear IFG
                P1OUT |= BIT1;          //Grn LED port 1.1
                _delay_cycles(80000);   //wait
                P1OUT &= ~BIT1;         //Turn Off LED
                break;
            case 0x40:                  //P5.6 interrupts
                P5IFG &= ~BIT6;         //clear IFG
                int i;
                for (i=3;i>0;i-- ){     //flash 3 times
                    P1OUT |= BIT1;      //Grn LED port 1.1
                    _delay_cycles(80000);
                    P1OUT ^= BIT1;
                    _delay_cycles(80000);
                }
                break;
            default:                    //Never executed
                break;
        }
}
/*
#pragma vector=PORT5_VECTOR
__interrupt void ISR_BUTTON_P55(void){
    _delay_cycles(1000); //wait for debounce
    //P1OUT &= ~BIT0;
    P5IFG = 0x00;       //clear Interrupt flag
    P5OUT |= BIT5;
    _delay_cycles(800000);
    P1OUT &= ~BIT0;
}
#pragma vector=PORT5_VECTOR
__interrupt void ISR_BUTTON_P56(void)
{
    _delay_cycles(10); //wait for debounce
    P1IFG = 0x00;//clear Interrupt flag
    P6OUT &= ~BIT6;
    for (j=6; j>0; j--) //three flashes - cycle through code twice per flash
        {
        P6OUT ^= BIT6;
        _delay_cycles(200000);//replace with timer
        }
    P5OUT &= ~BIT6;
    //test uart pragma
    //UCA1IE |= UCTXIE; //enable txie
}
*/
#pragma vector=RTC_VECTOR
__interrupt void RTC_ISR(void)
{
    switch(__even_in_range(RTCIV, 16))
    {
        case RTCIV_NONE: break;         //No interrupts
        case RTCIV_RTCOFIFG: break;     //RTCOFIFG
        case RTCIV_RTCRDYIFG: break;    //RTCRDYIFG
        case RTCIV_RTCTEVIFG:           //RTCEVIFG
            //Interrupts every 5 seconds
            __no_operation();           //for debugging
            __bic_SR_register_on_exit(LPM3_bits);    // exit LPM3
            break;
        case RTCIV_RTCAIFG: break;      //RTCAIFG
        case RTCIV_RT0PSIFG: break;     //RT0PSIFG
        case RTCIV_RT1PSIFG: break;     //RT1PSIFG
        default: break;
    }
}
  • > GPIO_selectInterruptEdge(GPIO_PORT_P5,GPIO_PIN5,GPIO_HIGH_TO_LOW_TRANSITION);
    > GPIO_enableInterrupt(GPIO_PORT_P5,GPIO_PIN5);
    Setting a P5IES bit can cause that P5IFG bit to be set. Also setting P5REN. [Ref UG (SLAU367O) Sec 12.2.6.2, 12.2.6] So as soon as you enable interrupts, you'll go to the ISR (with both IFGs set). You should call GPIO_clearInterrupt as the last thing before enabling, or just set P5IFG=0 as you're doing.

    > switch (P5IFG)
    This switch doesn't check for both bits being set (your case above); in that case it doesn't clear either IFG, and recurses forever through the ISR. For what you want to do, you should probably just check them individually.
    ----------------------------------------
    > GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN5,GPIO_PRIMARY_MODULE_FUNCTION);
    > GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN6,GPIO_PRIMARY_MODULE_FUNCTION);
    These set P5.5/.6 to alternate function (UCA2), just after setting them to GPIO (buttons). I think you don't want these lines.
    ----------------------------------------
    Unsolicited:
    > case 0x20: //P5.5 interrupt
    > P5IFG &= ~BIT5; //clear IFG
    > P1OUT |= BIT1; //Grn LED port 1.1
    > _delay_cycles(80000); //wait
    > P1OUT &= ~BIT1; //Turn Off LED
    You're not explicitly de-bouncing, but you get that effect from the delay_cycles() call. What's missing: The IFG will be set (over and over) as the button bounces. You should clear the IFG after you're pretty sure the bouncing has stopped -- here, at the end of the "case", not the beginning. The symptom here will be that the button appears to be pushed twice.
    ----------------------------------------
    Unsolicited:
    Please don't post code with large blocks commented out. It makes it very difficult to scan, particularly without code tags.
  • Thank you Bruce !!!

    I had left an enable interrupt in the initTimers() which caused the interrupts to be enabled prematurely. Thank you!!

    You were right on the second issue. The
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5,
    GPIO_PIN6,GPIO_PRIMARY_MODULE_FUNCTION);

    was indeed the cause of the problem. I expanded macro and it selected the wrong function module. I eliminated those two statements and cleaned up the handler per your suggestions. The code is much cleaner and is fully functional. Thank you very much!!

**Attention** This is a public forum