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/TM4C123GH6PM: Interrupt Handler

Part Number: TM4C123GH6PM
Other Parts Discussed in Thread: EK-TM4C123GXL

Tool/software: Code Composer Studio

Hello all, 

I am trying to run the project below on my development board and it suppose to blink the LED light until SW1 or SW2 is pressed. The prototype its suppose to use for the interrupt is "void GPIOF_Handler(void)". I am not sure if that is correct of how it is suppose use the interrupt correctly. As of right now when I press either button the LED just stalls in the current position it is at. 

I am trying to figure out if I am missing a header file for the prototype or am I suppose to declare it at a different point in the code to make sure it runs.

If anyone can help me and or explain it, I would greatly appreciate it. 

Thank you.

#include <stdint.h>
#include <tm4c123gh6pm.h>
#include <stdbool.h>
#include <hw_types.h>
#include <interrupt.h>
void delay_ms(int n);
bool IntMasterEnable(void);
bool IntMasterDisable(void);
extern void GPIOFIntHandler(void);
int main(void)
{
    SYSCTL_RCGCGPIO_R |= 0x20;              /* enable clock to PORTF */
    /* PORTF0 has special function, need to unlock to modify */
    GPIO_PORTF_LOCK_R = 0x4C4F434B;         /* unlock commit register */
    GPIO_PORTF_CR_R = 0x01;                 /* make PORTF0 configurable */
    GPIO_PORTF_LOCK_R = 0;                   /* lock commit register */
    /* configure PORTF for switch input and LED output */
    GPIO_PORTF_DIR_R &= ~0x11;              /* make PORTF4 input for switch */
    GPIO_PORTF_DIR_R |= 0x0E;               /* make PORTF3, 2, 1 output for LEDs */
    GPIO_PORTF_DEN_R |= 0x1F;               /* make PORTF-0 digital pins */
    GPIO_PORTF_PUR_R |= 0x11;               /* enable pull up for PORTF4, 0 */
    /* configure PORTF4, 0 for falling edge trigger interrupt */
    GPIO_PORTF_IS_R &= ~0x11;               /* make bit 4, 0 edge sensitive */
    GPIO_PORTF_IBE_R &= ~0x11;              /* trigger is controlled by IEV */
    GPIO_PORTF_IEV_R &= ~0x11;              /* falling edge trigger */
    GPIO_PORTF_ICR_R |= 0x11;               /* clear any prior interrupt */
    GPIO_PORTF_IM_R |= 0x11;                /* unmask interrupt */
    /* enable interrupt in NVIC and set priority to 3 */
    NVIC_PRI30_R = 3 << 5;                  /* set interrupt priority to 3 */
    NVIC_EN0_R |= 0x40000000;               /* enable IRQ 30 ( D30 of ISER[0]) */
    bool IntMasterEnable();
    /* toggle the red LED (PF1) continuously */
    while(1)
    {
        GPIO_PORTF_DATA_R |= 0x02;
        delay_ms(500);
        GPIO_PORTF_DATA_R &= ~0x02;
        delay_ms(500);
    }
}
/* SW1 is connected to PF4 pin, SW2 is connected to PF0. */
/* Both of them trigger PORTF interrupt */
void GPIOF_Handler(void)
{
    int i;
    volatile int readback;
    /* toggle green LED (PF3) three times */
    for (i = 0; i < 3; i++)
            {
                GPIO_PORTF_DATA_R |= 0x08;
                delay_ms(500);
                GPIO_PORTF_DATA_R &= ~0x08;
                delay_ms(500);
            }
    GPIO_PORTF_ICR_R |= 0x11;       /* clear the interrupt flag before return */
    readback = GPIO_PORTF_ICR_R;    /* a read to force clearing of interrupt flag */
}

/* delay n milliseconds (16 MHz CPU clock) */
void delay_ms(int n)
{
    int i, j;
    for(i = 0; i < n; i++)
        for(j = 0; j < 3180; j++)
        {} /* do nothing for 1 ms */
}
/* This function is called by the startup assembly code to perform system specific
 * initialization tasks
 */
void SystemInit(void)
{
    bool IntMasterDisable();
    /* Grant coprocessor access */
    /* This is required since TM4c123G has a floating point coprocessor */
    NVIC_CPAC_R |= 0x00F00000;
}
  • Hi Orlando,

      First of all, we are strongly against of the DRM (direct memory manipulation) style of coding. It is very prone to errors. Please use the TivaWare library to develop your code.   For whatever reason, if you must use DRM then this is what I will suggest. Look at TivaWare API and see how they are coded as far as setting up the GPIO registers to enable interrupt and how read/write to the Port F pins are done. 

     With all that said, what do you mean the LED just stalls?  I will suggest you put the breakpoint in the GPIOF_Handler. Does the processor jump to GPIOF_Handler() at all? If the GPIOF_Handler() is jumped to, check if the interrupt flags correctly cleared? You can use the register browser window to see if the register values are changing. Are you blinking too fast? If your blink rate is too fast, your eyes may not be able to see the LED in off state. Changing the blink rate, do you see the difference. These are the few things I will check first. 

      

  • Hey Charles,

    Thank you for replying. I am using DRM because the "textbook" I am using has the coding in some what that fashion. That was the best way I was able to decipher it. In the book the author is using Keil uVision IDE and I went with CCS. I am still learning how to code the MCU and I haven't tried using the TivaWare library. Would that be using codes in this manner below?

    GPIOIntTypeSet(GPIO_PORTM_BASE,GPIO_PIN_0,GPIO_FALLING_EDGE);    

    As for the LED light stalling. I meant while I have the main  while loop running, which has the LED flashing on and off every half second (500). Then, once I press a button (SW1 and SW2) the light stops blinking and depending in what state the LED was at the time I pressed a button (LED ON or OFF) it will stay in either of those states. I don't think the LED light should be blinking that fast during the interrupt routine since I am using the same time delay I used for the initial LED blink routine which I can see fine. After I pressed a button it will never return back to the original routine. 

    I am using 

    Code Composer Studio
     Version: 9.1.0.00010
    Again thank you for the information I really appreciate it.
  • Hi,

      Yes, GPIOIntTypeSet() is the TivaWare library function. It will make your life much easier if you use the TivaWare library. Earlier I asked you to put a breakpoint in the GPIOF_Handler(). You will get an interrupt when you press the switch and the processor will jump to GPIOF_Handler ISR. Does the processor halt at GPIOF_Handler each time you press the switch? If you are configuring for falling edge detect to generate an interrupt then you want to configure the pin with a pull up so that a falling edge can be detected. 

  • Charles,

    I already have GPIO_PORTF_PUR_R |= 0x11; should I relocate it to a different place or will if be fine where it is at?

    Also I set a break point  on the GPIOF_Handler and when I press the button nothing shows up. For the break point I have it set up to count and Action: Remain Halted.  Where exactly should I look to see if it jumped to the prototype?

    Thanks!

  • Hi,

      If you press the switch and the CPU does not halt at GPIOF_Handler then either the falling edge is not detected or the interrupt is not generated to the processor. You need to make sure you enable the GPIOF interrupt at the NVIC, in addition, the processor is also enabled for interrupt. 

      This is what would have looked like if you are using TivaWare. The code is configuring PJ0 for interrupt on a falling edge. 

    GPIOPadConfigSet(GPIO_PORTJ_BASE, GPIO_PIN_0, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU); 
    GPIOIntTypeSet(GPIO_PORTJ_BASE, GPIO_PIN_0, GPIO_FALLING_EDGE);
    GPIOIntRegister(GPIO_PORTJ_BASE, SW1Handler);
    GPIOIntEnable(GPIO_PORTJ_BASE, GPIO_INT_PIN_0);

    // Enable Port J interrupt in NVIC
    IntEnable(INT_GPIOJ);

    // Enable processor interrupts.
    IntMasterEnable();

  • Hi Charles,

    Is there a textbook or some type of media I can use to learn more on how to use the TivaWare library?

  • Hi Orlando,

      I don't think there is a textbook that is specifically written to use the TivaWare library. I will suggest you go through the examples provided in the TivaWare library. They are quite simple to use. Please go to the <TivaWare_Installation>/examples/boards/ek-tm4c123gxl and you will find examples to play with. Perhaps you can start with the hello, project0 and blinky examples. There are more examples for using the peripherals and you can find them under <TivaWare_Installation>/examples/peripherals/

      There is a TM4C123 training workshop at this site that provides step by step on how to use the TM4C123 MCU. I think you will quickly speed up on your understanding about the TivaWare as well as the general capabilities of the MCU. http://processors.wiki.ti.com/index.php/Getting_Started_with_the_TIVA%E2%84%A2_C_Series_TM4C123G_LaunchPad

  • Try add  GPIO_PORTF_AFSEL_R &= ~0x00000011;    GPIO_PORTF_AMSEL_R &= ~0x00000011;  GPIO_PORTF_PCTL_R &= ~0x000F000F;  when config PortF.

    Priority register isnt correct set. Interrupt Number (Bit in Interrupt Registers) of PortF is 30 (page 105 in datasheet).  Try NVIC_PRI7_R = (NVIC_PRI7_R & 0xFF0FFFFF) | 0x00400000;  - priority 2 . Look page 152 to see who to choose correct  priority register.

    I think this will solve your problem. 

  • Thank you for the information Charles. 

    I will go through the workshop and try to pick up some more information over it. 

    I greatly appreciate the assistance.

  • Hey Milan,

    I tried what you recommended and it is still doing the same thing as before. I have listed exactly what I did below see if you see anything wrong with it? Thank you for the help.

    #include <stdint.h>
    #include <tm4c123gh6pm.h>
    #include <stdbool.h>
    #include <hw_types.h>
    #include <interrupt.h>
    #include <hw_memmap.h>
    #include <gpio.h>
    void delay_ms(int n);
    bool IntMasterEnable(void);
    bool IntMasterDisable(void);
    void GPIOF_Handler(void);

    int main(void)
    {
        SYSCTL_RCGCGPIO_R |= 0x20;              /* enable clock to PORTF */
        /* PORTF0 has special function, need to unlock to modify */
        GPIO_PORTF_LOCK_R = 0x4C4F434B;         /* unlock commit register */
        GPIO_PORTF_CR_R = 0x11;                 /* make PORTF0 configurable */
        GPIO_PORTF_LOCK_R = 0;                   /* lock commit register */
        /* configure PORTF for switch input and LED output */
        GPIO_PORTF_DIR_R &= ~0x11;              /* make PORTF4 input for switch */
        GPIO_PORTF_DIR_R |= 0x0E;               /* make PORTF3, 2, 1 output for LEDs */
        GPIO_PORTF_DEN_R |= 0x1F;               /* make PORTF-0 digital pins */
        GPIO_PORTF_PUR_R |= 0x11;               /* enable pull up for PORTF4, 0 */
        /* configure PORTF4, 0 for falling edge trigger interrupt */
        GPIO_PORTF_IS_R &= ~0x11;               /* make bit 4, 0 edge sensitive */
        GPIO_PORTF_IBE_R &= ~0x11;              /* trigger is controlled by IEV */
        GPIO_PORTF_IEV_R &= ~0x11;              /* falling edge trigger */
        GPIO_PORTF_ICR_R |= 0x11;               /* clear any prior interrupt */
        GPIO_PORTF_IM_R |= 0x11;                /* unmask interrupt */

        GPIO_PORTF_AFSEL_R &= ~0x00000011;
        GPIO_PORTF_AMSEL_R &= ~0x00000011;
        GPIO_PORTF_PCTL_R &= ~0x000F000F;
        /* enable interrupt in NVIC and set priority to 3 */
        NVIC_PRI7_R = (NVIC_PRI7_R & ~0xFF0FFFFF) | 0x00400000;                  /* set interrupt priority to 3 */
        NVIC_EN0_R |= 0x40000000;               /* enable IRQ 30 ( D30 of ISER[0]) */
        bool IntMasterEnable();
        /* toggle the red LED (PF1) continuously */
        while(1)
        {
            GPIO_PORTF_DATA_R |= 0x02;
            delay_ms(500);
            GPIO_PORTF_DATA_R &= ~0x02;
            delay_ms(500);
        }
    }
    /* SW1 is connected to PF4 pin, SW2 is connected to PF0. */
    /* Both of them trigger PORTF interrupt */
    void GPIOF_Handler()
    {
        int i;
        volatile int readback;
        /* toggle green LED (PF3) three times */
        for (i = 0; i < 3; i++)
                {
                    GPIO_PORTF_DATA_R |= 0x08;
                    delay_ms(500);
                    GPIO_PORTF_DATA_R &= ~0x08;
                    delay_ms(500);
                }
        GPIO_PORTF_ICR_R |= 0x11;       /* clear the interrupt flag before return */
        readback = GPIO_PORTF_ICR_R;    /* a read to force clearing of interrupt flag */
    }
  • Het Charles,

    I set a breakpoint in the code and I think I figured out where the interrupt is going. It seems like its going into a default handler that has infinite loop. So I take it that is the reason why the LED stops blinking completely and gets stuck where it last was when the button is pressed. I am putting listing where the handler took the MCU when the buttons are pressed below.

    //*****************************************************************************
    //
    // This is the code that gets called when the processor receives an unexpected
    // interrupt.  This simply enters an infinite loop, preserving the system state
    // for examination by a debugger.
    //
    //*****************************************************************************
    static void
    IntDefaultHandler(void)
    {
        //
        // Go into an infinite loop.
        //
        while(1)
        {
        }

  • I make some correct in your code, and now work. Interrupts always call in tm4c123gh6pm_startup_ccs.c . Programing with registers is really difficult, try to read again datasheet when code doesnt work properly. GreenBlinkOnInterrupt.zip

  • Hi Milan,

      Thank you for helping out this post!

  • Hi Orlando,

      You didn't declare a vector for the GPIOF in the vector table and hence the MCU took the default vector which is just looping forever. Milan modified your project. Please take a look. Thanks to Milan. 

  • Labeling PORTF as the handler in the vector table tm4c123gh6pm_startup_ccs.c made the code work. It was getting lost when the interrupt occurred.

    I really appreciate the help. I never thought I was going to figure it out.

    Thank you,

    Orlando

  • Thank you Milan!!!!!! 

    That helped me very much I really appreciate you helping out.

    I didn't know I had to or could make a modification in tm4c123gh6pm_startup_ccs.c for the interrupts.