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.

TM4C1290NCPDT: GPIO Interrupt doesn't stop on port L

Part Number: TM4C1290NCPDT
Other Parts Discussed in Thread: TM4C1294NCPDT, ENERGIA

Hello,

I have a code that uses an interrupt on an input pin to make some calculations.

Currently it works just fine when I use ports M, D, A or B (I've tested them all).

The problem is I need to make it work specifically on port L pin 3, but when I do it the interrupt gets called everytime and the program gets stuck.

I even tried to make the timer1 interrupt (which I'm also using) to work on priority C0 and the GPIO to work on priority E0 but stil not even the Timer interrupt gets called because the program is stuck on port L interrupt.

I enable all of the GPIOs I used to test the code:

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOM);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOL);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

I set the Pin Type to Input: (Here I'm only showing it for the Port L, when I tested the other ones I just changed this line to the port to be tested).

 GPIOPinTypeGPIOInput(GPIO_PORTL_BASE, GPIO_PIN_3);

I set up the interrupts:

GPIOIntRegister(GPIO_PORTL_BASE, TacHandler);
GPIOIntTypeSet(GPIO_PORTL_BASE, GPIO_PIN_3, GPIO_FALLING_EDGE);
GPIOIntEnable(GPIO_PORTL_BASE, GPIO_INT_PIN_3);

And on the interrupt handler "TacHandler" I clear the interrupt:

void TacHandler(void){
GPIOIntClear(GPIO_PORTL_BASE, GPIO_PIN_3);
freqCalc();
}

inline void freqCalc(void){
pulseCounter++;
}

But as I said the GPIO interrupt keeps getting called and the software gets stuck. When I try on the other pins I get the result I want just fine.

I didn't initialize anything other than GPIO and TIMER1, therefore I'm not using Analog Comparator, USB or Quadrature Encoder (I did see they can be set to work on pin PL3).

I'm using the Launchpad board.

Is it not possible to use the PL3 for this?

Thank you.

  • Hello Leonardo.
    Is it maybe the case in your code that another interrupt handler uses my mistake the same TacHandler() routine or maybe access the same resource freqCalc? Is pulseCounter a global variable? I'm thinking of possible deadlocks....
    John

  • Leonardo, another thought of mine is that the 'inline' qualifier maybe mess things. inline says to the compiler to put the code of this function in the flat address space ONCE and does not keep an address for this peace of code. INT calls need an address to handle things, like a function. inline usually is used for chunks of code to speed-up code execution when available flash memory is not an issue and we have plenty of it so that code may be repeated as many times as it is statically called.

    John

  • Hello John,

    I work with Leonardo in this project.

    Only handlers of GPIO L and TIMER1 are active.

    When we try other pins, in another GPIO, we get the expected result.


    Do you have any other suggestion?

    Thanks.
  • Hi, John,
    I have only a TIMER1 interrupt (with a completely different handler) and the GPIO_PORTL one.
    I also removed the inline function, by simply putting the pulseCounter (which is a global variable) increment on the handle itself.
    Also, what's weird is the fact that the algorithm works when I use other ports, but just doesn't work exactly on the one I need it to work (the L port).
  • O.K. If you only use GPIO-L and don't use any other GPIO, does the problem remain? Do not initialize any other GPIO in your code but L only. Check if in that case you still experience the same problem. If it is so, then maybe your L port is malfunctioning.
    John
  • Also, try your code as is, but use another GPIO instead L to check if problem remains.
    John
  • Leonardo Muricy said:
    ... port L pin 3 ... (yet) the interrupt gets called everytime - and the program gets stuck.

    Do not these conditions (below) usually cause an (unwanted) return to the (just executed) interrupt handler:

    • the "interrupt clear" is placed too far (down) in the ISR.    (clearly - that's not your case)    Note: (some) finite time is required for the ISR clear to complete!
    • the ISR is (so) short/brief - that the "interrupt clear" may fail to complete    Note: same explanation as provided, above.
    • the Port you've chosen does not "fully/properly" support or manage a "UNIQUE, individual BIT, ISR"  Note: MOST Ports do NOT support such exhaustive - bit-based - unique interrupts!

    It is my belief that the MCU's "Start-Up file" should reveal the presence of a, "Port Only" Interrupt.    (i.e. there will NOT exist "individually listed port bits" - w/in that port - w/in the Interrupt Vector Table Listing!)

    I believe that this may be cured by replacing your parameter, "GPIO_INT_PIN_3" with (instead) the name of your (full) Port L interrupt.   (TacHandler)

    Firm/I have no experience w/129x devices.    I'd expect that if "differences" in GPIO Ports (or in the management of Port Interrupts) exist - such data would appear w/in the MCU manual.    Have you truly (deeply) read/reviewed the manual - in pursuit of such detail?

    *** [edit]  Kindly visit (next) post below - which well illustrates the identification of, "Port vs. Port-Bit Triggered" Interrupt Capability.    I tried to "color code" for clarity - Syntax highlighter killed that...

    Now you noted that this ISR gets "called everytime" - yet is it possible that (instead) it is called just once - and is "never" (fully/properly) cleared?    That would appear to produce a similar effect - would it not?

    As always - this (may) be (also) an errata issue - wise to check there - too...

  • *** [edit] Thru good fortune - another poster here has provided the "Start-Up file" for the TM4C1294 (similar) MCU.    This provides an excellent illustration as regards the difference between, "Entire Port vs. Individual Port Bits" - serving as interrupt triggers.

        IntDefaultHandler,                      // GPIO Port M     Note: illustrates "Port's Trigger of an Interrupt."
        IntDefaultHandler,                      // GPIO Port N
        0,                                      // Reserved
        IntDefaultHandler,                      // Tamper
        IntDefaultHandler,                      // GPIO Port P (Summary or P0)  And this - "Individual Port Bits Trigger!
        IntDefaultHandler,                      // GPIO Port P1
        IntDefaultHandler,                      // GPIO Port P2
        IntDefaultHandler,                      // GPIO Port P3
        IntDefaultHandler,                      // GPIO Port P4
        IntDefaultHandler,                      // GPIO Port P5
        IntDefaultHandler,                      // GPIO Port P6
        IntDefaultHandler,                      // GPIO Port P7

    It is thus (almost) certain that your MCU (lacks) the ability to produce such, "individual Port Bit Interrupts."     You may (still) achieve your objective by employing the "normal" Entire Port's interrupt vector.

    This excess posting resulted from my (inability) to "color code" w/in the command of the "Syntax Highlighter."   (which proved Syntax Tormentor.)
      

  • Dear Leonardo, at the manual of TM4C1294NCPDT, page 742, prints that only Ports P & Q support pin interrupts.
    ■ Programmable control for GPIO interrupts
    – Interrupt generation masking
    – Edge-triggered on rising, falling, or both
    – Level-sensitive on High or Low values
    – Per-pin interrupts available on Port P and Port Q <------------------

    However, the bit-banding feature, page 109, if properly understood, can be used to signal interrupts on any bit/pin, of any GPIO port.
    For example, ENERGIA IDE, (free to download and install) using a similar trick, via functions attachInterupt() and detachInterrupt() [energia.nu, click on top-menu <Reference> and go down] does exactly this on other port's pins:
    **********************************************************
    volatile int state = HIGH;
    volatile int flag = HIGH;
    int count = 0;

    void setup()
    {
    Serial.begin(9600);

    pinMode(GREEN_LED, OUTPUT);
    digitalWrite(GREEN_LED, state);

    /* Enable internal pullup.
    * Without the pin will float and the example will not work */
    pinMode(PUSH2, INPUT_PULLUP);
    attachInterrupt(PUSH2, blink, FALLING); // Interrupt is fired whenever button is pressed
    }

    void loop()
    {
    digitalWrite(GREEN_LED, state); //LED starts ON
    if(flag)
    {
    count++;
    Serial.println(count);
    flag = LOW;
    }
    }

    void blink()
    {
    state = !state;
    flag = HIGH;
    }
    **************************************************************************

    There are many more tricks one can employ to use any event happening on TM4C1294xxxxx as an interrupt driver.
    Bets regards,
    John
  • First of all thank you all for your help.
    I do know port L doesn't have individual interrupts for each pin, but I'm used to setting the interrupt that way, and it usually works.

    I did try the exact same code on ports A, B and D and it worked perfectly! It just doesn't work on port L, which is the one port I really need to use.
    I'll try to run the code without enabling the orther ports and them without setting the pin individually.
  • Might you have "missed" the two posts - arriving last evening (5:14 & 11:38) - which may add insight to your issue?
  • Hi, cb1_mobile.
    I did see the last two posts, but basically they are about the fact that it is only possible to use the interrupts on the entire port, although it is possible to tweak it so I can use it on individual ports, like done in that Energia sketch.
    The thing is, just like port L, port B for example is also not possible to use with individual pins, that's why I still don't undestand the issue.
  • Thank you - minus feedback - I had no idea if our effort had been noted.

    If ports & operation are as you report - and NO errata lists and/or details - I too am, "at a loss."    This type issue then (usually) demands the attention/response from the vendor - always equipped w/"inside information."

    W/in my first post was the suggestion to identify your (whole port) interrupt by its name - not by the, "Port-Pin" reference.    Had you tried that?

    In addition - it should (most always) be possible to identify the, "individual bit, trigger source" via (very) early testing - w/in the (whole port) ISR.   This appears the best (perhaps only) method to, "force Port_L" to your requirement...

  • Well, this is weird.
    I got access to another Launchpad board that a coworker was using.
    I loaded the exact same code I was using, on the exact same port (port L) and it worked. The interrupts got cleared as they should and the counting was perfect.
    Them the even weirder thing happened. I imediatly after that tried once more to load the code on the now suspect board and it worked...
    I'm not sure how it is possible to have 2 different behaviors with the same code on the same board, but the fact is it worked after I used a different one.
    I believe there is a hardware problem with my device
  • Leonardo Muricy said:
    I believe there is a hardware problem with my device

    Perhaps not!    Are you programming via vendor's "ICDI?"

    Firm/I note very (improved) results via (world's best selling) "J-Link" JTAG/SWD Pod.    Preventing the LOSS of  time/effort - may justify - the (discounted) cost of a superior device...   (PM me for discount details)

  • And - it dawns too - that your ability to achieve, "Individual, Port-Bit, interrupt detection" - when said Port is "not" specifically described/defined as including that capability - may not "continue" w/in "future/different" MCU production runs!

    "Exploiting" an "undocumented feature/behavior" - may not always prove (fully) robust - and may completely "fail" upon revision updates...
  • Yes, I'm aware of that. I'll probably just change it to interrupt the entire Port instead, just checking wich pins are read afterwars.

    Thank you for your help
  • Ok - good that you have that awareness.

    Having past worked at (similar) giant semi firm - I know that the "chip inter-connect resources" - required to accommodate/support, "Unique/automatic, Port-Bit, interrupt source resolution" are much increased - thus raising the IC's cost.

    I recall that the "main intent" of such, "individual Port-Bit interrupts" was to "Speed the Service" of such interrupts - especially when "multiple bits w/in that same Port were "highly" active!"    (I don't believe that overlaps (your) requirement.)

    This usually explains why such, "fully accommodating (i.e. bit interrupting) Ports" are "reduced in number" - when compared to their (more) standard "Port only" implementations...