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

Reply
  • 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

Children
No Data
Related