nRF52840: How to disable latch detect in SDK v17 GPIO interrupts?

We are in the process of porting from nRF SDK v15.3.0 to v17.1.0.

After updating, we’ve noticed that the device sometimes gets stuck. Investigation shows this is related to GPIO interrupt handling.

The nRF52840 supports two wakeup detect modes: Default detect (non-latch) and Latch detect (LDETECT). In our use case the interrupt source is not an edge but a signal that can stay active (high or low).

SDK v17 introduces new latch handling in the GPIO library. For nRF52840, this is always enabled through NRF_GPIO_LATCH_PRESENT macro.

We never explicitly enable latch mode (via NRF_GPIO->DETECTMODE = GPIO_DETECTMODE_DETECTMODE_LDETECT << GPIO_DETECTMODE_DETECTMODE_Pos;), however the ISR still uses latch detect clearing mechanisms even when this is not enabled.

Because our interrupt signals can stay active, the latch never resets → the MCU ends up stuck in the loop inside port_event_handle(uint32_t * latch) (called from interrupt context). This effectively makes every GPIO interrupt susceptible to the same issue if the input signal stays asserted.

We tested by commenting out #define NRF_GPIO_LATCH_PRESENT, and then everything works fine without latch handling — but this is not expected behaviour. We don’t want to modify the SDK just to achieve this. Is there a supported way to disable latch detect without patching the SDK?

  • For example, we use wake-up sense to detect charger input or button press. If the device starts with the charger already connected, the input is already LOW. Enabling wake-up sense on LOW at this time causes the device to get stuck in the same port_event_handle() ISR. It works fine if the charger is not connected (input HIGH) when enabling.

    Similarly, if a button gets stuck/jammed and stays LOW, we could run into the same issue, making it harder to detect the actual cause.

  • For example, we use wake-up sense to detect charger input or button press. If the device starts with the charger already connected, the input is already LOW

    This is was the assumption I made when you said the signal came from a charger earlier, and is why I meant ask if the active level would change depending on the charger state at the time of entering system off. How were you handling this in the previous version? Also, were you using GPIOTE PORT events or GPIO IN events previously?

    causes the device to get stuck in the same port_event_handle()

    This indicates that the input pin has not been disabled in the GPIOTE driver. In any case, if you set the sense level to low and the input is low, the device will immediately wake up again if you try to enter system off.

  • This is was the assumption I made when you said the signal came from a charger earlier, and is why I meant ask if the active level would change depending on the charger state at the time of entering system off. How were you handling this in the previous version? Also, were you using GPIOTE PORT events or GPIO IN events previously?

    With SDK 15, currently both .hi_accuracy=true and NRF_GPIO_PIN_SENSE_LOW is enabled. So I assume it uses both GPIOTE PORT events and GPIO IN events.

    Now with SDK 17, currently I am setting .hi_accuracy=false for pins which configure wakeup sense. 

    This indicates that the input pin has not been disabled in the GPIOTE driver. In any case, if you set the sense level to low and the input is low, the device will immediately wake up again if you try to enter system off.

    On power up we are doing, nrf_gpio_cfg(pin, NRF_GPIO_PIN_DIR_INPUT, NRF_GPIO_PIN_INPUT_CONNECT, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_S0S1, NRF_GPIO_PIN_SENSE_LOW);. It straight away goes stuck at port_event_handle() if the input is already low, with SDK 17. 

  • On power up we are doing, nrf_gpio_cfg(pin, NRF_GPIO_PIN_DIR_INPUT, NRF_GPIO_PIN_INPUT_CONNECT, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_S0S1, NRF_GPIO_PIN_SENSE_LOW);. It straight away goes stuck at port_event_handle() if the input is already low, with SDK 17. 

    The DETECT signal is not going to be deasserted until either the SENSE or input level changes. 

    It straight away goes stuck at port_event_handle() if the input is already low, with SDK 17. 

    And this is with .high_accuracy=true for that particular pin?

  • And this is with .high_accuracy=true for that particular pin?

    Based on my tests, it behaves same in this case with .hi_accuracy true / false. 

Related