Achieving pin retention in nRF54L15 GPIO without hardware pull-up through sys_reboot()

Hi,

I have encountered a challenge with the nRF54L15 that I am hoping someone might know a solution for!

My device has a power enable pin (on GPIO1) that must ideally *always* remain HIGH. Unfortunately, it has no HW pull-up and one cannot be added.

So through software, I would like to keep this pin HIGH through sys_poweroff(), jumping to MCUboot, and resetting out of MCUboot.

My finding so far: The nRF54L15 has automatic pin retention for all GPIOs, but *only* through sys_poweroff() as it appears to be mainly intended as a power-saving feature to mitigate current leakage.

My challenge: Dropping into MCUboot from appcode hits a warm sys_reboot() - which clears the pin for ~5ms, and is problematic in my design.

My solution so far is just to intercept all problematic sys_reboot() calls and instead use a scheduled GRTC wakeup + sys_poweroff() to keep pin retention, but ideally I don't want to have to do this.

TLDR: Is there any way to (without a dedicated HW pull-up) configure a GPIO on nRF54L15 to survive a sys_reboot() call?

Thank you!

Parents
  • Hi,

    Calling sys_reboot()->NVIC_SystemReset() will trigger a "soft" reset of the system, which will reset all GPIO pins back to their default high z state (i.e., input with input buffer disconnected) as the image taken from the datasheet below shows. In other words, it is not possible to retain the GPIO states through this call without patching the SDK source files as you mentioned.

    However, if you can define your own SDK board, you can ensure that the enable pin is asserted early in the boot process for any project built for your board including MCUBoot. Depending on the capacitance and leakage on the line, this may be early enough to avoid causing a glitch on the enable signal. This approach does not require modifications of any files in the SDK tree. It will also work for other reset sources such as watchdog and pinreset. If you want to try this, you can use the thingy53 board as a reference for how you can include custom initialisation code for your board: https://github.com/nrfconnect/sdk-zephyr/blob/main/boards/nordic/thingy53/board.c 

    What layout may look like for an out of tree board:

    boards/<vendor>/<board>/
    ├── board.yml
    ├── Kconfig.<board>
    ├── <board>_defconfig
    ├── <board>.dts  // zephyr,user node
    ├── CMakeLists.txt // zephyr_library_sources(board.c)
    └── board.c // contains custom init code. SYS_INIT(..., EARLY, 0) macro ensures it is run before kernel init.

    custom init code in board.c to drive the enable signal high:

    #include <zephyr/init.h>
    #include <zephyr/devicetree.h>
    #include <soc.h>           
    #include <hal/nrf_gpio.h>
    
    #define EARLY_EN_PSEL  NRF_DT_GPIOS_TO_PSEL(DT_PATH(zephyr_user), early_enable_gpios)
    
    static int regulator_enable(void)
    {
    	/* Control pin configuration directly with HAL as the gpio 
    	 * driver is not initialized yet.
    	 */
    	nrf_gpio_cfg_output(EARLY_EN_PSEL);
    	nrf_gpio_pin_set(EARLY_EN_PSEL);  
    	return 0;
    }
    SYS_INIT(regulator_enable, EARLY, 0);

    And pin assignment for the GPIO pin in the devicetree:

    / {
    	/* Assign the GPIO pin to use for driving the enable signal. This pin could have been
    	 * defined directly in the boards.c file, but then you would not get a warning if there
    	 * were a conflicting pin assignment.
    	 * https://docs.zephyrproject.org/latest/build/dts/zephyr-user-node.html#gpios
    	 */
    	zephyr,user {
    		early-enable-gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
    	};
    	
    };
    

    Best regards,

    Vidar

     

Reply
  • Hi,

    Calling sys_reboot()->NVIC_SystemReset() will trigger a "soft" reset of the system, which will reset all GPIO pins back to their default high z state (i.e., input with input buffer disconnected) as the image taken from the datasheet below shows. In other words, it is not possible to retain the GPIO states through this call without patching the SDK source files as you mentioned.

    However, if you can define your own SDK board, you can ensure that the enable pin is asserted early in the boot process for any project built for your board including MCUBoot. Depending on the capacitance and leakage on the line, this may be early enough to avoid causing a glitch on the enable signal. This approach does not require modifications of any files in the SDK tree. It will also work for other reset sources such as watchdog and pinreset. If you want to try this, you can use the thingy53 board as a reference for how you can include custom initialisation code for your board: https://github.com/nrfconnect/sdk-zephyr/blob/main/boards/nordic/thingy53/board.c 

    What layout may look like for an out of tree board:

    boards/<vendor>/<board>/
    ├── board.yml
    ├── Kconfig.<board>
    ├── <board>_defconfig
    ├── <board>.dts  // zephyr,user node
    ├── CMakeLists.txt // zephyr_library_sources(board.c)
    └── board.c // contains custom init code. SYS_INIT(..., EARLY, 0) macro ensures it is run before kernel init.

    custom init code in board.c to drive the enable signal high:

    #include <zephyr/init.h>
    #include <zephyr/devicetree.h>
    #include <soc.h>           
    #include <hal/nrf_gpio.h>
    
    #define EARLY_EN_PSEL  NRF_DT_GPIOS_TO_PSEL(DT_PATH(zephyr_user), early_enable_gpios)
    
    static int regulator_enable(void)
    {
    	/* Control pin configuration directly with HAL as the gpio 
    	 * driver is not initialized yet.
    	 */
    	nrf_gpio_cfg_output(EARLY_EN_PSEL);
    	nrf_gpio_pin_set(EARLY_EN_PSEL);  
    	return 0;
    }
    SYS_INIT(regulator_enable, EARLY, 0);

    And pin assignment for the GPIO pin in the devicetree:

    / {
    	/* Assign the GPIO pin to use for driving the enable signal. This pin could have been
    	 * defined directly in the boards.c file, but then you would not get a warning if there
    	 * were a conflicting pin assignment.
    	 * https://docs.zephyrproject.org/latest/build/dts/zephyr-user-node.html#gpios
    	 */
    	zephyr,user {
    		early-enable-gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
    	};
    	
    };
    

    Best regards,

    Vidar

     

Children
No Data
Related