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.

GPIO Interrupt Issue - Continuous "Fire" and Hang using various parameters.



Hi TI:

Brief Problem Description:
A GPIO Interrupt seems to 1) fire continuously or 2) fire way too many times (IE. somewhat like a debounce issue)

Setup:
Tiva TM4C123GXL using later versions of TI-RTOS and Code Composer.

Backgroud:
This is a simple circuit with a 2 wire anemometer, an LED, a 10K pull down resistor using 3.3V power supply.
Spin the anemometer and the LED briefly lights up once per revolution.
I attached PIN F0 to the circuit and slowly spun the anemometer. I used GPIO_read and validated correct reults.
Next, I wrote the Interrupt code to detect each revolution.

Code:
const GPIO_Callbacks EK_TM4C123GXL_gpioPortFCallbacks =
{
GPIO_PORTF_BASE, INT_GPIOF,
{gpio_PF0_WindSpeedCalculate, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
};

// skipped code here

//***********************************************************************************************************
// Wind Speed Detector / Unlock First
HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
HWREG(GPIO_PORTF_BASE + GPIO_O_CR) = 0x1;
GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_0); // PF0 - PIN 28 - Wind Speed Detector - PIN Must Be Unlocked First
//HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_M; // seems to have no affect.

//GPIOIntTypeSet(GPIO_PORTF_BASE, GPIO_PIN_0, GPIO_BOTH_EDGES | GPIO_DISCRETE_INT);
GPIOIntTypeSet(GPIO_PORTF_BASE, GPIO_PIN_0, GPIO_FALLING_EDGE | GPIO_DISCRETE_INT); // <- Falling Edge hangs the processor.

GPIOIntEnable(GPIO_PORTF_BASE, GPIO_PIN_0);

GPIO_init();

// skipped code here

Void gpio_PF0_WindSpeedCalculate(Void)
{
//GPIOIntClear(GPIO_PORTF_BASE, GPIO_BOTH_EDGES | GPIO_DISCRETE_INT);

GPIOIntClear(GPIO_PORTF_BASE, GPIO_FALLING_EDGE | GPIO_DISCRETE_INT); // <- Falling Edge hangs the processor.


iHitIt++;  // tracking # times the Interrupt fires.
}


Observations/Issues:
1.
//GPIOIntTypeSet(GPIO_PORTF_BASE, GPIO_PIN_0, GPIO_BOTH_EDGES | GPIO_DISCRETE_INT);
GPIOIntTypeSet(GPIO_PORTF_BASE, GPIO_PIN_0, GPIO_FALLING_EDGE | GPIO_DISCRETE_INT);

If I use GPIO_FALLING_EDGE, the processor seems to hang at startup. It will not do anything.
GPIO_BOTH_EDGES allows the code to "run" to full execution.

This is very odd to me.

2.
The current set of code causes the Interrupt to fire continuously. The anemometer is not spinning.

With small code variations, the Interrupt will only fire as the anemometer is spinning; but, the Interrupt
fires hundres of times per revolution. Once the spin stops, the Interrupt stops firing. This
reminds me of a debounce issue.

Since I have the pull-down resistor in the circuit, I "thought" I could generally deal with the
"debounce" issue. Guess not.

3.
What does the following line of code do?
//HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_M; // seems to have no affect.

I'm still new to this environment and the processor. 

Any insight would be greatly appreciated.

Thank you.

  • Hello Rick,

    1. The Pin PF0 and PD7 are locked port due to NMI function. Hence use of these pins requires the user to explicitly unlock it and then program it. Once unlocked and reprogrammed, till the time the entire device is not reset the HWREG for unlock shall not have any further effect.
    2. when you mention it is hung, can you describe in what function is it hung? Is it hung in the interrupt handler callback function? Also if you tie the pin low or high does it still behave the same?

    Regards
    Amit
  • Hi Amit:

    #1 - Thank you.  This is very helpful

    #2 - Right now, I am "caught".  The program will not compile due to new functionality.  I will get back with you in two days,

    I will follow your suggestion regarding wiring the pin High and then Low and checking results.

    Regarding the hang, the program does not appear to call the main Task.  I have a system_print at the very top that never gets called.

    I will hope to get back to you on Wednesday night.

    Thank you.

    Rick

  • Hello Rick

    Chances are that it may be NMI handler and hence its main tasks are not getting called

    Regards
    Amit
  • Hi Amit:

    Thank you for your reply.

    #1 - Pin PFO - Unlock.   My question about the code is highlighted in Yellow.  The examples that I followed have this line in the code.  It just does not seem like I need it; but, I am not down in the HWREG level with this processor (yet), so its does not make sense to me.  Can you explain that?

    HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;

    HWREG(GPIO_PORTF_BASE + GPIO_O_CR) = 0x1;

    GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_0); // PF0 - PIN 28 - Wind Speed Detector - PIN Must Be Unlocked First

    HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_M;  

    #2 - The Hang occurs when I have this Constant in the Interrupt:  See Yellow highlight.  

    The hang seems to occur after I call BIOS_start(); but, the code never begins executing in my main task.

    GPIOIntClear(GPIO_PORTF_BASE, GPIO_FALLING_EDGE | GPIO_DISCRETE_INT);

    This tells me that I may not understand how to clear the Interrupt for that Pin.  Can you shed some light on that?

    Tying the Pin High or Low seems to result in the Interrupt continuously firing.

    If I tie it high, my Interrupt counter climbs very high, very quickly.

    If it is tied low, the Interrupt counter seems to increment with the running code.  Very steadily, one increment at a time.

    Again, any thoughts would be greatly appreciated.

    Thank you.

    Rick

     

     

  • Hello Rick,

    Writting the LOCK register is not required once it is unlocked. But writting a 0x0 will revert it back to locked state preventing any unwanted write to the Commit register

    As for the second point, the Usage of the GPIOIntClear is to have the second parameter as the Pin status (or pin number) to clear the interrupt.

    Regards
    Amit
  • Hi Amit:

    Thank you for the Lock register information.  That makes sense.

    Regarding GPIOIntClear, your suggestion regarding use of the Pin number had a positive effect.  The processor does not hang.  Unfortunately, the code still does not work as hoped for.

    GPIOIntClear(GPIO_PORTF_BASE, GPIO_PIN_0);  // New Code.

    Regarding the setup, I've coded 2 configurations.

    1. GPIOIntTypeSet(GPIO_PORTF_BASE, GPIO_PIN_0, GPIO_FALLING_EDGE | GPIO_DISCRETE_INT);  

    This configuration causes the Interrupt to continually fire; but, at a fairly "slow" rate (~10) times between each Console message.

    The Anemometer is not spinning.


    2. GPIOIntTypeSet(GPIO_PORTF_BASE, GPIO_PIN_0, GPIO_HIGH_LEVEL | GPIO_DISCRETE_INT);

    This configuration causes the Interrupt to only fire when there is one revolution of the Anemometer.  However, the Interrupt fires thousands of times during each spin between Console messages.  If I manually apply power, this method has the same affect, the Interrupt is hit thousands of times.  As soon as it stops spinning or I disconnect power, Interrupts do not fire.  So, this is close; but, not what I hoped for.  I am using a 10K pull down resistor in the Circuit.  I was hoping to get it to a place where the Interrupt would only fire once per revolution.

    While reading notes, I found this statement.

    The NMI signal is an alternate function for either GPIO port pin PD7 or PF0. The alternate function must be enabled in the GPIO for the signal to be used as an interrupt, as described in “General-Purpose Input/Outputs (GPIOs)” on page 647.

    Note that enabling the NMI alternate function requires the use of the GPIO lock and commit function just like the GPIO port pins associated with JTAG/SWD functionality, see page 682.

    The active sense of the NMI signal is High; asserting the enabled NMI signal above VIH initiates the NMI interrupt sequence.

    It seems like the UNLOCK code allows me to use this; but, I wasn't sure if there was something else that I was missing.

    Any thoughts would be greatly appreciated.

    Thanks

    Rick

  • Hello Rick,

    The High Level Interrupt will be fired as long as the signal remains high. Hence it is no wonder that you get thousands of interrupt. As for the edge interrupt, I will remove the GPIO_DISCRETE_INT parameter, connect a Pull Down on the pin (or enable the GPIOPDR) and connect a scope to see why the interrupt fires even if there is no edge.

    Regards
    Amit
  • Might it make sense to "escape this PF0 plague" - refocus more properly upon the main issue - by simply switching to a, "Non-NMI pin?"

    KISS teaches that one should avoid unnecessary complexity - surely there exists one free pin - unburdened by this long known/duly noted (and uncorrected) plague...

  • Hi Amit and cb1-

    I laughed out when cb1- said go to another PIN and keep it simple. The advice was excellent, I just completed doing that. Unfortunately, for the life of me, I could not figure out why I couldn't get the interrupt to fire on the new Pin. Out of disgust, I mowed the yard.

    Also, Amit's guidance on the PIN was great since it forced me to go deeper into the documentation. All good lessons learned.

    Here is where I landed. I commented out almost all of the code, disconnected the main bread board from power and isolated the PIN, a 10K resistor and an LED on a separate non powered board.

    Lo and behold, the Interrupt starts working, unfortunately with similar results. The Interrupt not working at all, was probably a conflict somewhere in the code. If anything else, I'm understanding how to setup interrupts on Pins. The documentation is much clearer to me. Now, I have to dig into the Docs more.

    And now the evil, there is no power on the board but I see a faint glow on the LED. Pin -> 10K -> LED -> (-). I should be able to figure this out. Of course, that bothers me. As of this week, I do not have a Scope. Next week, different story. :-) I also have an I2C issue; but, that is for another day.

    Now the question. cb1- said to switch to a non-NMI pin. I do not know where to look to track that down. Hints would be great. The Pin I am currently using is PB3. Not sure if that has the same issue as PF0.

    Regardless, all of this is great stuff. I appreciate the input.

    Rick
  • Rick,

    Thumbs up for mowing the yard! Now, just create a disgust-to-electricity -converter and go through all the functions of the Tiva! :-)

    Only PD7 and PF0 have the NMI. If you haven't already, I suggest you download the Tiva C Series Pinmux utility from www.ti.com/.../tm4c_pinmux - you can easily check what functions are available for each pin!

    Best,
    Veikko
  • Veikko,

    Great idea! Very sad and very funny at the same time.

    All of the issues are resolved.

    Thank you Amit, and cb1-.

    I made a few programming tweaks and found a problem with grounding. (Dang!)

    Rick