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.

EK-TM4C123GXL: How to use the interrupt for SW1 (GPIO pin PF4) on the Tive C Series Launchpad (TM4C123G).

Part Number: EK-TM4C123GXL

I'm attempting to write a program that will blink the blue LED on the board while SW1 is held down. I am trying to use interrupts to handle the state change, and have followed the example code posted here.

Here is my code:

#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include "inc/hw_memmap.h"
#include "driverlib/interrupt.h"
#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"


void onButtonDown(void);
void onButtonUp(void);

/**
 * Called when SW1 is pressed
 */
void onButtonDown(void) {
    if (GPIOIntStatus(GPIO_PORTF_BASE, false) & GPIO_PIN_4) {
        // PF4 was interrupt cause
        GPIOIntRegister(GPIO_PORTF_BASE, onButtonUp);   // Register our handler function for port F
        GPIOIntTypeSet(GPIO_PORTF_BASE, GPIO_PIN_4, GPIO_RISING_EDGE);          // Configure PF4 for rising edge trigger
        GPIOIntClear(GPIO_PORTF_BASE, GPIO_PIN_4);  // Clear interrupt flag

        while(1) {
            GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2);
            SysCtlDelay(20000000);
            GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);
        }
    }
}

/**
 * Called when SW1 is released
 */
void onButtonUp(void) {
    if (GPIOIntStatus(GPIO_PORTF_BASE, false) & GPIO_PIN_4) {
        // PF4 was interrupt cause
        GPIOIntRegister(GPIO_PORTF_BASE, onButtonDown); // Register our handler function for port F
        GPIOIntTypeSet(GPIO_PORTF_BASE, GPIO_PIN_4, GPIO_FALLING_EDGE);         // Configure PF4 for falling edge trigger
        GPIOIntClear(GPIO_PORTF_BASE, GPIO_PIN_4);  // Clear interrupt flag

        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);
    }
}


/**
 * main.c
 */
int main(void)
{
    SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_INT | SYSCTL_XTAL_16MHZ);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    while (!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOF))
    {
    }


    // Output pin F2 setup (LED)
    GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);


    // Input Pin F4 setup (SW1)
    GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_4);
    GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_4, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);

    GPIOIntDisable(GPIO_PORTF_BASE, GPIO_PIN_4);
    GPIOIntClear(GPIO_PORTF_BASE, GPIO_PIN_4);

    GPIOIntRegister(GPIO_PORTF_BASE, onButtonDown);
    GPIOIntTypeSet(GPIO_PORTF_BASE, GPIO_PIN_4, GPIO_FALLING_EDGE); // Configure PF4 for falling-edge trigger
    GPIOIntEnable(GPIO_PORTF_BASE, GPIO_PIN_4);

	while(1);
}

I have two issues.

The first is that when SW1 is being held down, the blue LED should be blinking on and off, but the LED only remains on.

The second issue is that the interrupt onButtonUp() is never being triggered after SW1 is released, and the program stays stuck in the while loop in onButtonDown().

Any help or tips on what I'm doing wrong would be appreciated.

Details:

Code Composer Version: 8.1.0.00011

TivaWare version 2.1.4.178

Compiler: TI v18.1.3


Apologies for any mistakes made in the post.

  • The reason for the first issue is that in the while loop of the onButtonDown routine you turn the LED on, delay, turn the LED off, and then immediately turn the LED on again. It is indeed "blinking" but it is off for much too short of a time for your eye to see. Try adding another call to SysCtlDelay after you turn off the LED.

    The second issue is more fundamental. By default, when you are in an interrupt routine, other interrupts are disabled. (This device does support nested interrupts, but that is a more advanced topic.) In your case, you never leave the interrupt routine onButtonDown(), so no more interrupts can be serviced. In general, your interrupt routine should be very short. I suggest in this case you define a static volatile bool variable that you set "true" in the function onButtonDown() and "false" in the function onButtonUp(). Also, in onButtonUp() turn the LED off. Then in your main routine, which is currently an empty while loop, you toggle the LED if the variable is "true".

    To make the operation completely interrupt driven, use a timer interrupt to toggle the LED. In the function onButtonDown() enable the timer interrupt. In the function onButtonUp() turn off the LED and disable the timer interrupt.