LATCH Register does not correctly indicate GPIO after wakeup from SYSTEM OFF

Hello Nordic-Team,

 I am using the SENSING mechanism on GPIOs to wake up a firmware from SYSTEM OFF. Two GPIOs are used for this and it is crucial for the firmware to detect which GPIO caused the wakeup.

On a nRF54L05 (nRF54L15 used as nRF54L05) I am able to readout the GPIO that caused the wakeup, on a nRF54LS05B the corresponding bits for both GPIOs are set even if only one button was pressed, so that I cannot detect the wakeup reason.

Please find attached a test firmware which I used with nRF Connect SDK v3.3.0 on a nRF54L15-DK and a nRF54LS05-DK.

Button0 and Button1 are used to wakeup the firmware.

Best regards

sensing_test_app.zip

Parents
  • Hi,

     

    As we discussed in the meeting, I have recreated this issue locally, and it looks to be occurring on GPIOs configured with SENSE_LOW (ie. active low pins), where the NRF_Px->LATCH register then is not reflecting the wakeup source.

    This seems to work as intended if GPIO is configured as _SENSE_HIGH.

     

    I have reported the behaviour internally, and will update you.

     

    Kind regards,

    Håkon

  • Hi Håkon,

     thank you for your fast response. I have added a function with SYS_INIT to read the IN register of P1 at a very early stage. I see the same pattern there, so the input port actually seems to register a wrong input level on the GPIO pins.

    Regards

    Stefan

    SYS_INIT(sample_gpio, EARLY, 0);
  • [00:00:00.006,928] <inf>: check_reset_reason: reason = 0x00000100 OFF
    [00:00:00.006,932] <inf>: Wakeup from SYSTEM OFF detected
    [00:00:00.006,936] <err>: latch:        0x00002200      < P1_LATCH later read (I tried to clear the LATCH early, but as the bits in  P1_IN are still assigned it does not clear the LATCH)
    [00:00:00.006,939] <err>: gpio_in:      0x00002200    < P1_IN early read
    [00:00:00.006,942] <err>: gpio_latch:   0x00002200  < P1_LATCH early read 

  • Sorry, please ignore my posts from today! I confused myself, the IN register shows the actual level on the port, so having both set is perfectly ok for two GPIOs with PULLUPs....!

  • Hi,

     

    Stefan Schmidt said:
    Sorry, please ignore my posts from today! I confused myself, the IN register shows the actual level on the port, so having both set is perfectly ok for two GPIOs with PULLUPs....

    Thank you for updating, I am really glad to hear that you got the workaround running as expected.

     

    I haven't yet heard anything from R&D, but I will keep you updated.

     

    Kind regards,

    Håkon

  • Hi Håkon,

     my workaround is this tiny function that I register to the start of the mcuboot. It is called pretty early in mcuboot and writes the current value of the LATCH register into the LATCH register:

    Either the button is in the active state in this moment, then the corresponding bit in the LATCH will not be cleared, or it is still bouncing, so that a later matching condition will be latched.

    #ifdef CONFIG_MCUBOOT
    #include <hal/nrf_gpio.h>
    #include <zephyr/init.h>
    #include <zephyr/kernel.h>

    static int latch_workaround(void)
    {
        uint32_t p0_latch = NRF_P0->LATCH;
        NRF_P0->LATCH = p0_latch;
        return 0;
    }

    SYS_INIT(latch_workaround, PRE_KERNEL_1, 0);
    #endif

    Does that make sense?

    This is actually the position in the init process of the mcuboot:


    EARLY
      __init_nordicsemi_nrf54l_init: nordicsemi_nrf54l_init(NULL)
      __init_sys_clock_driver_init: sys_clock_driver_init(NULL)
    PRE_KERNEL_1
      __init_latch_workaround: latch_workaround(NULL)
      __init___device_dts_ord_40: clk_init(__device_dts_ord_40)
      __init___device_dts_ord_74: uarte_20_init(__device_dts_ord_74)
      __init_uart_console_init: uart_console_init(NULL)
    PRE_KERNEL_2
      __init_grtc_post_init: grtc_post_init(NULL)
    POST_KERNEL
      __init_malloc_prepare: malloc_prepare(NULL)
      __init___device_dts_ord_87: nrf_rram_init(__device_dts_ord_87)
      __init__psa_crypto_init: _psa_crypto_init(NULL)
      __init_mbedtls_heap_init: mbedtls_heap_init(NULL)
    APPLICATION
    SMP

    Best regards

    Stefan

  • Hi Stefan,

     

    What is the intention behind this snippet? Is it to clear it and use it exclusively for debouncing in the application space?

    This code will help with debouncing, but only if you want to read it again in the application:

        uint32_t p0_latch = NRF_P0->LATCH;
    
        NRF_P0->LATCH = p0_latch;

    Writing '1' to the source bit will clear the corresponding source:

    https://docs.nordicsemi.com/bundle/ps_nrf54LS05A/page/gpio.html#ariaid-title17

    meaning that your code snippet, ie. NRF_P0->LATCH = NRF_P0->LATCH; will clear the register as a whole.

     

    Kind regards,

    Håkon

Reply Children
Related