Group GPIO input interrupt for Two pins (or more) cannot trigger well.

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Group GPIO input interrupt for Two pins (or more) cannot trigger well.

2,252 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by kitahei88 on Sun Jul 12 07:26:09 MST 2015
Hello.
I'm using LPCxpresso1549.
I have problem for Group GPIO interrupt setting.
I want to make timing logging for multiple buttons with GINT.

I tested GINT for only one button , get on/off condition, It worked well.
The button is pulled up and set GINT for edge trigger .GINT0 is falling edge and GINT1 is rising edge.

Next , I expand the code for multiple buttons ,like below.

extern "C" void GINT0_IRQHandler(void)
{
        LPC_GINT0->CTRL |= (1<<0);      // clear interrupt status
        //
        Code like LED1 toggle.
        //
}
    
extern "C" void GINT1_IRQHandler(void)
{
        LPC_GINT1->CTRL |= (1<<0);      // clear interrupt status
        //
        Code for LED2 toggle
        //
}


void gint_init(void)
{
    LPC_SYSCON->SYSAHBCLKCTRL0 |= (1 << 19);                // enable GINT

    LPC_GINT0->PORT_ENA[0] = 0x0000FFFF ; // port 0 16pins(expand)
    LPC_GINT0->PORT_POL[0] = 0xFFFF0000;  // falling edge
    LPC_GINT0->CTRL |= (1<<0) | (0<<2);      // interrupt active, OR condition , edge trigger
    

    LPC_GINT1->PORT_ENA[0] = 0x0000FFFF ; // port 0 16pin(expand)
    LPC_GINT1->PORT_POL[0] = 0xFFFFFFFF;  // rising edge
    LPC_GINT1->CTRL |= (1<<0) | (0<<2) ;      // interrupt active, OR condition , edge trigger
    NVIC_EnableIRQ(GINT0_IRQn);                             // enable GINT0 interrupt
    NVIC_EnableIRQ(GINT1_IRQn);                             // enable GINT1 interrupt 
}


This code cannot work well.
I push one button , GINT0 interrupt was triggered, BUT press and hold the button , then press another button , interrupt was not triggered.

I found that same problem was occurred for LPC43xx
https://www.lpcware.com/content/forum/lpc43xx-gpio-group-interrupt

So LPC15xx or LPC43xx cannot do such things?
Should I use another MCU like LPC17xx?
Labels (1)
0 Kudos
Reply
2 Replies

1,624 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by kitahei88 on Fri Sep 25 18:15:05 MST 2015
Thank you for your solution.

I have got same solution that update PORT_POL mask at every time.
LPC1549 have two GINT, so I set GINT0 to "Button On trigger" and GINT1 to "Button Off trigger" , like your code.
It works well.

But the thing I really want to do is to get precise timing of multi-buttons (like keyboard logger).
This solution is very nice but its overhead that trigger timer is too long time.

So I give it up to use GINT , I add CPLD that trigger SCT input when the button conditions have changed.

Anyway, Your solution is good for using GINT.
Thank you.
0 Kudos
Reply

1,624 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by stephenlind on Mon Sep 21 11:43:23 MST 2015
I figured out a way to do this with the LPC1347, but in theory it should work with any of these grouped interrupt situations.

Here's the general problem:

1. When you set the OR mask here, the first button triggers the interrupt, so the second button is not recognized as a new state (no interrupt).

2. The same problem happens when you have two buttons pressed and you release one of them. Probably your POL mask is such that the interrupt only fires after *all* buttons have been released.

The solution:

- Use only one interrupt, which fires *every time any button changes state*
- Update the PORT_POL mask dynamically every time the button state changes.

How does this work?

void gint_update(void)
{
    LPC_SYSCON->SYSAHBCLKCTRL0 |= (1 << 19);                // enable GINT

    LPC_GINT0->PORT_ENA[0] = 0x0000FFFF ; // port 0 16pins(expand)

    // Set the mask for the current button state (pseudocode)
    LPC_GINT0->PORT_POL[0] = 0x00000000; // blank mask
    for (int i = 0; i < 16; i++) {
        int shouldSetFallingEdgeBit = false == buttonIsPressed(i);
        LPC_GINT0->PORT_POL[0] |= (shouldSetFallingEdgeBit << i);
    }

    LPC_GINT0->CTRL |= (1<<0) | (0<<2);      // interrupt active, OR condition , edge trigger
    NVIC_EnableIRQ(GINT0_IRQn);                             // enable GINT0 interrupt
}

extern "C" void GINT0_IRQHandler(void)
{
        LPC_GINT0->CTRL |= (1<<0);      // clear interrupt status
        //
        Poll the current button state, take appropriate action, store the button state for future use
        //

    // update the mask so that new button presses or releases will be handled
    gint_update();
}
0 Kudos
Reply