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?

Parents
  • Hello,

    I have not been able to find any other similar reports with this issue. The latch register is used to reduce the chance of missing pin events, which can occur more easily when multiple pins have sense enabled in applications where the GPIOTE IRQ may be blocked or preempted by other interrupts.

    The driver doesn't enable the LDETECT mode, so the latch register bits are not going trigger the PORT event either. The driver will always uses the LATCH register as long as it's supported by the HW (indicated by the presence of the NRF_GPIO_LATCH_PRESENT symbol). This was not designed to be configurable as there are no known drawbacks of using it. It should only make the interrupt handling more robust.

    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.

    Note that the sense level is reconfigured in the ISR to prevent exactly this:

    Is the input signal free of glitches?

    Best regards,

    Vidar

Reply
  • Hello,

    I have not been able to find any other similar reports with this issue. The latch register is used to reduce the chance of missing pin events, which can occur more easily when multiple pins have sense enabled in applications where the GPIOTE IRQ may be blocked or preempted by other interrupts.

    The driver doesn't enable the LDETECT mode, so the latch register bits are not going trigger the PORT event either. The driver will always uses the LATCH register as long as it's supported by the HW (indicated by the presence of the NRF_GPIO_LATCH_PRESENT symbol). This was not designed to be configurable as there are no known drawbacks of using it. It should only make the interrupt handling more robust.

    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.

    Note that the sense level is reconfigured in the ISR to prevent exactly this:

    Is the input signal free of glitches?

    Best regards,

    Vidar

Children
  • Thanks for the quick response.

    I don’t think the input signal is completely glitch-free, since it is triggered by the charger connector — that’s probably why the port event is firing.

    From what I observe, it ends up calling port_event_handle, and then contuine; on the below check, so the level reconfiguration is not happening, continues again on the while loop non stop. 

    How to configure this properly ?

    nrfx_gpiote_in_config_t interruptConfig = {
        .sense = NRF_GPIOTE_POLARITY_TOGGLE,
        .pull = NRF_GPIO_PIN_NOPULL,
        .is_watcher = false,
        .hi_accuracy = true,
        .skip_gpio_setup = true,
    };

    I tried configuring .hi_accuracy = false, to force use port events. But still the behaviour is similar, as it is unable to find a matching latch bit set in following, if (nrf_bitmask_bit_is_set(pin, latch))


    I have not been able to find any other similar reports with this issue. The latch register is used to reduce the chance of missing pin events, which can occur more easily when multiple pins have sense enabled in applications where the GPIOTE IRQ may be blocked or preempted by other interrupts.

    The driver doesn't enable the LDETECT mode, so the latch register bits are not going trigger the PORT event either. The driver will always uses the LATCH register as long as it's supported by the HW (indicated by the presence of the NRF_GPIO_LATCH_PRESENT symbol). This was not designed to be configurable as there are no known drawbacks of using it. It should only make the interrupt handling more robust.

    I’m not sure I fully understand — if LDETECT is not enabled, how does using the LATCH register make the interrupt handling more robust?


    As per the nRF documentation I see: A PORT event is triggered if the DETECT signal was low before enabling the sense mechanism”. If I understand correctly, the current port event handler doesn’t account for this case.

  • Port event is not enabled when .hi_accuracy is set to 'true'. If this is the configuration you are using for all your interrupt pins, then port_event_handle() should never have been called. 

    Ligo George said:
    as it is unable to find a matching latch bit set in following, if (nrf_bitmask_bit_is_set(pin, latch))

    Is it always latched for the same pin?

    Ligo George said:
    I’m not sure I fully understand — if LDETECT is not enabled, how does using the LATCH register make the interrupt handling more robust?

    because the latch bit will still be set even if the DETECT signal has been deasserted.

    Ligo George said:
    As per the nRF documentation I see: A PORT event is triggered if the DETECT signal was low before enabling the sense mechanism”. If I understand correctly, the current port event handler doesn’t account for this case.

    This case appears to have been considered based on the comment here: 

  • Port event is not enabled when .hi_accuracy is set to 'true'. If this is the configuration you are using for all your interrupt pins, then port_event_handle() should never have been called. 

    .hi_accuracy is set to true for all our interrupts, but still port_event_handle() is getting called. Based on my testing, port_event_handle() is getting called especially in cases like A PORT event is triggered if the DETECT signal was low before enabling the sense mechanism, even if .hi_accuracy is set to true, and it is stuck in while loop. 

    Is it always latched for the same pin?

    Yes, but with .hi_accuracy is set to true, it continues with next iteration from if(m_cb.port_handlers_pins[i] == PIN_NOT_USED). 

    because the latch bit will still be set even if the DETECT signal has been deasserted.

    Will latch bit staying set matter if the detect mode is "non-latch" ?

    This case appears to have been considered based on the comment here: 

    But for me the code execution never reaches here, as I mentioned before.

  • .hi_accuracy is set to true for all our interrupts, but still port_event_handle() is getting called. Based on my testing, port_event_handle() is getting called especially in cases like A PORT event is triggered if the DETECT signal was low before enabling the sense mechanism, even if .hi_accuracy is set to true, and it is stuck in while loop. 

    This suggests that you have pins configured with SENSE enabled, but this is not done by the GPIOTE driver when .hi_accuracy is set to 'true'.  

    Will latch bit staying set matter if the detect mode is "non-latch" ?

    Yes.

    But for me the code execution never reaches here, as I mentioned before.

    Then the given pin has not been initialized with hi_accuracy=false.

    GPIOTE inputs initialzied with .hi_accuracy=true should not be configured with SENSE enabled.

    EDIT I can see now how this could lead to the driver becoming stuck in the ISR. The solution should be to make sure sense is not enabled for inputs initialized with .hi_accuracy enabled.

  • Yes, that is right.

    GPIOTE inputs are initialized with .hi_accuracy=true and SENSE is enabled. This was working fine with SDK 15. 

    Do you have any official documentation mentioning the same ?

Related