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.

Compiler/MSP430FR5869: GPIO Interrupt Fires Constantly

Part Number: MSP430FR5869


Tool/software: TI C/C++ Compiler

I am working on a device using the MSP430FR5869 which has several active-low buttons, and have been unable to get GPIO interrupts to work correctly.  I've used a logic analyzer to confirm that the pin of interest is being pulled up correctly, goes low when I press the button, and returns high when the button is released.  However, using the following code, the interrupt service routine fires constantly, even if I never press the button at all.  It does this no matter which pin I use.  Using Code Composer Studio to view the Port 3 registers, I see that the interrupt flag is always set, and appears to never clear.  I've tried clearing the interrupt flag manually, but that doesn't help (and the user manual says that shouldn't be necessary anyway).

Does anyone see something I'm doing wrong?

Thank you,

Adam J.

/******************************************************************************
 *  This example sets up a pin for an active-low GPIO interrupt.  An interrupt
 *  service routine fires when a pin goes low and decodes which pin it is.
 *****************************************************************************/

#include <msp430.h>
#include "driverlib.h"          // TI's driver library for MSP430FR5xx_6xx

int main(void)
{
    // Stop watchdog timer.
    WDTCTL = WDTPW | WDTHOLD;

    // Initializes system clocks to 16MHz with 1 wait-state.
    FRCTL0 = FRCTLPW | NWAITS_1;

    CS_setDCOFreq(CS_DCORSEL_1, CS_DCOFSEL_4);

    // Configure MCLK, SMCLK to be sourced by DCOCLK.
    CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_4);
    CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);

    // Configure as input pins.
    GPIO_setAsInputPin(GPIO_PORT_P3, GPIO_PIN7);

    // Enable the pull-up resistor.
    GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P3, GPIO_PIN7);

    // Disable the interrupt.
    GPIO_disableInterrupt(GPIO_PORT_P3, GPIO_PIN7);

    // Clear any pending interrupts.
    GPIO_clearInterrupt(GPIO_PORT_P3, GPIO_PIN7);

    // Set interrupt to trigger on a falling edge.
    GPIO_selectInterruptEdge(GPIO_PORT_P3, GPIO_PIN7, GPIO_HIGH_TO_LOW_TRANSITION);

    // Enable the interrupt.
    GPIO_enableInterrupt(GPIO_PORT_P3, GPIO_PIN7);

    // Enable global interrupts.
    __enable_interrupt();

    // Wait here forever.
    while (true);
}

/* Port 3 Interrupt Vector for ionKEY_R, ionKEY_U, ionKEY_L, ionKEY_D*/
#pragma vector=PORT3_VECTOR;
__interrupt void port3(void)
{
    // This bit will tell us what pin caused the interrupt to fire.
    // It's volatile so the compiler won't optimize it away.
    volatile uint8_t pin;

    // Figure out which pin in the port caused the interrupt.
    // You might think that we'd check the interrupt flag register, but no!
    // The user manual's example has us check the interrupt vector register.
    // Also, clearing the interrupt flag is not necessary, because according to
    // the user manual "any access (read or write) of the lower byte of the
    // PxIV register (either word or byte access) automatically resets the
    // highest pending interrupt flag."
    switch (__even_in_range(P3IV, 16))
    {
    case 0:     // Vector 0 - no interrupt
        break;
    case 2:     // Vector 2 - pin 0
        pin = 0;
        break;
    case 4:     // Vector 4 - pin 1
        pin = 1;
        break;
    case 6:     // Vector 6 - pin 2
        pin = 2;
        break;
    case 8:     // Vector 8 - pin 3
        pin = 3;
        break;
    case 10:    // Vector 10 - pin 4
        pin = 4;
        break;
    case 12:    // Vector 12 - pin 5
        pin = 5;
        break;
    case 14:    // Vector 14 - pin 6
        pin = 6;
        break;
    case 16:    // Vector 16 - pin 7
        pin = 7;// <-- This line will constantly be hit!  WHY???
        break;
    default:
        break;
    }
}

  • Hi Adam,
    after a RESET or Power On you should configure the following steps. In your code, I'm missing the second one. Did you try to clear the LOCKLPM5 bit?

    1. Initialize Ports: PxDIR, PxREN, PxOUT, and PxIES

    2. Clear LOCKLPM5

    3. If not wake-up from LPMx.5: clear all PxIFGs to avoid erroneous port interrupts 

    4. Enable port interrupts in PxIE

    Best regards,
    Tobias

  • Thank you!  That was it.  I added the following after line 22 in my example above, and now it works fine:

    // After power-up, clear the LOCKLPM5 bit in the PM5CTL0 register, or some
    // IO functions will remain locked. 
    PMM_unlockLPM5();

**Attention** This is a public forum