This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

GPIOTE interrupt

I'm trying to use the GPIOTE to generate an interrupt when a pin makes a transition. It appears everything is working except the interrupt never gets triggered. NRF_GPIOTE->EVENTS_IN[0] and NRF_GPIOTE->EVENTS_port both get set to 0x1 when I press button4 on the nrf52840-PDK. So I think the GPIOTE module is detecting the change but the interrupt signal never gets raised.

I've looked thru the SDK code, Zypher RTOS, and Adafruit's Bluefruit implementations but I can't figure out what they're doing differently than me. (I've even checked the PDK's errata!) It's probably something obvious but I've been staring at the code long enough that I'm not seeing it.

So if anyone has any ideas what I might be doing wrong or how I might narrow it down, I'd love to hear about it.

Mike

Here's my code that is supposed to be setting the pin up:

        gpio_handlers[slot].handler = handler;
        gpio_handlers[slot].data = data;
        gpio_handlers[slot].pin = pin;
        gpio_handlers[slot].set = true;

        NRF_GPIOTE->INTENCLR = 1 << 31;
        port->PIN_CNF[index] &= ~GPIO_PIN_CNF_SENSE_Msk;
        if (rising == true)
            port->PIN_CNF[index] |= (GPIO_PIN_CNF_SENSE_High << GPIO_PIN_CNF_SENSE_Pos);
        else
            port->PIN_CNF[index] |= (GPIO_PIN_CNF_SENSE_Low << GPIO_PIN_CNF_SENSE_Pos);

        NRF_GPIOTE->CONFIG[slot] =
            (index << GPIOTE_CONFIG_PSEL_Pos) |
#ifdef GPIOTE_CONFIG_PORT_Pos
            (pnum << GPIOTE_CONFIG_PORT_Pos) |
#endif
            (polarity << GPIOTE_CONFIG_POLARITY_Pos) |
            (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos);

        NRF_GPIOTE->EVENTS_IN[slot] = 0;
        dummy = NRF_GPIOTE->EVENTS_IN[slot];

        NRF_GPIOTE->EVENTS_PORT = 0;
        dummy = NRF_GPIOTE->EVENTS_PORT;

        NRF_GPIOTE->INTENSET = (1 << 31) | (1 << slot);

  • NVIC_EnableIRQ(GPIOTE_IRQn); is missing. You also want to set up priority properly when using softdevice.

  • NVIC_EnableIRQ() is called from nrf52_gpio_init(), which is called from __start().

    Whether I'm running with or without the softdevice, I still don't get the GPIOTE interrupt. The GPIOTE interrupt is configured with the same priority as the UART0 interrupt, which does work.

  • Here's the GPIO and GPIOTE register values after the button has been pushed in case that would help identify my problem:

    (gdb) print /x *port
    $1 = {RESERVED0 = {0x0 <repeats 321 times>}, OUT = 0x10000, OUTSET = 0x10000,
      OUTCLR = 0x10000, IN = 0x2050140, DIR = 0x10060, DIRSET = 0x10060,
      DIRCLR = 0x10060, LATCH = 0x2000000, DETECTMODE = 0x0, RESERVED1 = {
        0x0 <repeats 67 times>, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0 <repeats 14 times>,
        0x1, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0 <repeats 13 times>, 0x1,
        0x0 <repeats 12 times>}, PIN_CNF = {0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1,
        0x0, 0x0, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x2, 0x2, 0x2, 0x2, 0x2,
        0x2, 0x2, 0x2, 0x3000c, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2}}
    (gdb) print /x *gpiote
    $2 = {TASKS_OUT = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, RESERVED0 = {0x0,
        0x0, 0x0, 0x0}, TASKS_SET = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
      RESERVED1 = {0x0, 0x0, 0x0, 0x0}, TASKS_CLR = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
        0x0, 0x0}, RESERVED2 = {0x0 <repeats 32 times>}, EVENTS_IN = {0x1, 0x0,
        0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, RESERVED3 = {0x0 <repeats 23 times>},
      EVENTS_PORT = 0x1, RESERVED4 = {0x0 <repeats 96 times>, 0x80000001},
      INTENSET = 0x80000001, INTENCLR = 0x80000001, RESERVED5 = {
        0x0 <repeats 129 times>}, CONFIG = {0x31901, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
        0x0}}
    (gdb)

  • Hi Mike,

     

    Judging by your readout, you are setting NRF_GPIO->PIN_CNF[25] = 0x3000C;

    P0.25 configured with pull-up and sense=LOW (SENSE generates EVENTS_PORT).

    Then, you are configuring GPIOTE IN[0] to use the same pin, P0.25, with a TOGGLE event.

    EVENTS_IN[0] is set, meaning that this has been triggered, and so is EVENTS_PORT.

    I suspect that you ideally wanted to use the NRF_GPIOTE->EVENTS_PORT to do this? Right now, it looks like you have used the P0.25 for both EVENTS_PORT and EVENTS_IN[0].

     

    Best regards,

    Håkon

  • Right now I'm trying to get any interrupt from the pin on any edge. Originally I was looking for the failing edge but switch to toggle to try and broaden the possibility of getting something.

    My understanding was that the PORT event was triggered when any of the IN events occurred. Since both the IN[0] and PORT events show a positive event, I would have thought one of them would have triggered the interrupt.

    So, back to my original quest, if I don't enable the PORT bit in INTENSET and only set IN[0]'s bit, should I get the GPIOTE interrupt? Or do I want the PORT event and not the IN event?

    Should I ignore all of the SENSE stuff since I want edge triggered interrupts?

Related