nPM1300 does not exit ship hold mode when SHPHLD button pressed or VBUS connected

Hello,

I have custom hardware using an nPM1300 and nRF52840, and I am having trouble getting the nPM1300 to work as described in its documentation. I have a button connected between the SHPHLD pin and ground, and I can tell it is working because I get GPIO events, and a long press does reset the nPM1300. However, if I enable ship hold mode, then it does not exit ship hold mode with either a short press of the button or plugging in USB. I can only get it to exit with a long press.

You can see my hardware at kicanvas.org/?github=https%3A%2F%2Fgithub.com%2Fjoelspadin%2Fmarten_numpad%2Fblob%2Fmain%2Fpcb%2Fnumpad.kicad_pro. The relevant schematics are in usb.kicad_sch and numpad.kicad_sch.

I am using Zephyr 4.1. My devicetree setup for the nPM1300 looks like this:

&i2c0 {
    compatible = "nordic,nrf-twi";
    status = "okay";

    pinctrl-0 = <&i2c0_default>;
    pinctrl-1 = <&i2c0_sleep>;
    pinctrl-names = "default", "sleep";

    npm1300_pmic: pmic@6b {
        compatible = "nordic,npm1300";
        status = "okay";
        reg = <0x6b>;

        host-int-gpios = <&gpio0 30 0>;
        pmic-int-pin = <1>;
        long-press-reset = "one-button";

        npm1300_regulators: regulators {
            compatible = "nordic,npm1300-regulator";

            main_regulator: BUCK2 {
                regulator-min-microvolt = <3300000>;
                regulator-max-microvolt = <3300000>;
                regulator-always-on;
            };
        };

        npm1300_charger: charger {
            compatible = "nordic,npm1300-charger";
            charging-enable;

            term-microvolt = <4150000>;
            term-warm-microvolt = <4000000>;
            current-microamp = <250000>;
            dischg-limit-microamp = <1000000>;
            vbus-limit-microamp = <500000>;

            // No thermistor
            thermistor-ohms = <0>;
            thermistor-beta = <3380>;
        };

        npm1300_leds: leds {
            compatible = "nordic,npm1300-led";
            nordic,led0-mode = "charging";
            nordic,led1-mode = "host";
            nordic,led2-mode = "host";
        };
    };
};

Using

    static struct gpio_callback event_cb;
    gpio_init_callback(&event_cb, power_button_callback, BIT(NPM1300_EVENT_SHIPHOLD_PRESS));
    mfd_npm1300_add_callback(pmic, &event_cb);

I have set up a callback which checks if USB is powered. If not, it blinks an LED a few times, then calls regulator_parent_ship_mode(). With the board powered only from a battery, when I press the button, the LED blinks, then it shuts off and the voltage to the SoC drops to 0 as expected. When I press the button again, nothing happens. (I can tell it is not waking, immediately triggering the GPIO event, and then going back into ship mode, because the LED does not blink.) Similarly, reconnecting USB power does not wake it either.

Is there something else I'm missing that needs to be configured?

Parents
  • I finally took the time to clean up some of the solder blobs on another PCB, and it has the same issue.

    I know the PMIC reset button is being detected, because holding it for 10 seconds does reset the PMIC. However, still neither a short press of the button nor plugging in USB will wake it. Holding the button for 10 seconds is the only thing that wakes it.

    I measure the following voltages in each state:

    Ship hold mode
    Battery only
    Ship hold mode
    Battery + USB 
    After 10s press
    Battery only
    After 10s press
    Battery + USB
    VBUS 0 V 5 V 0 V 5 V
    VBAT 4.1 V 4.1 V 4.1 V 4.1 V
    PMIC VSYS 4.1 V 5 V 4.1 V 5 V
    PMIC VOUT2 < 10 mV < 10 mV 3.2 V 3.2 V
    PMIC SHPHLD 4.1 V 5 V 4.1 V 5 V

    Based on the fact that holding to reset does work, I'm guessing there is either a software issue with the Zephyr driver, or there's a hardware issue that somehow only affects the wake function and not the hard reset function?

  • Hello,

    Have you tried is the behavior the same in hibernate mode? It is strange that plugging in USB does not wake up the device. Note also that if USB is plugged in the device should not enter ship mode.

    To debug this you can also check the event registers that the behavior is correct. You can check that EVENTSVBUSIN0SET shows USB is disconnected before entering ship mode. After wakeup you can check the RSTCAUSE register to see did the reset cause by the ship mode exit.

    It looks like the VSYS stays high on your testing if I read this table correctly. Note that in ship mode the VSYS should go to 0 as well. So it could be that the device has not entered ship mode in the first place. Have you checked the quiescent current of the device in the ship mode? It should be 370nA from the battery.

Reply
  • Hello,

    Have you tried is the behavior the same in hibernate mode? It is strange that plugging in USB does not wake up the device. Note also that if USB is plugged in the device should not enter ship mode.

    To debug this you can also check the event registers that the behavior is correct. You can check that EVENTSVBUSIN0SET shows USB is disconnected before entering ship mode. After wakeup you can check the RSTCAUSE register to see did the reset cause by the ship mode exit.

    It looks like the VSYS stays high on your testing if I read this table correctly. Note that in ship mode the VSYS should go to 0 as well. So it could be that the device has not entered ship mode in the first place. Have you checked the quiescent current of the device in the ship mode? It should be 370nA from the battery.

Children
  • I just checked, and the behavior is not the same in hibernate mode. It wakes immediately when pressing the button or plugging in USB when in hibernate mode. Interestingly, I called

    mfd_npm1300_hibernate(pmic, 30 * 1000);

    and it also wakes on its own after 10 seconds, not 30 as I thought I was requesting.

    Measuring the power usage with a PPK2, I'm getting about 55 uA with the device powered from the PPK2, which drops to 0.38 uA as expected after putting it into ship mode. I tried pressing the button a few times to wake it, and each time I pressed the button, it spiked up to ~1 mA a couple of times and then back down to nA range. On the third press, it got stuck drawing a constant 1 mA.

    I've attached two recordings. The first recorded the device being powered for a while, then put into ship mode, then me pressing the reset button a few times and seeing the current draw get stuck at 1 mA. The second recording continues from that state and shows me holding the reset button for 10 seconds to do a hard reset. (The current spikes just before entering ship mode and just after resetting are because I have an LED set to blink 3 times before entering ship mode and twice when it boots.)

     ppk2-20251111T024233 on, ship mode, wake attempt.ppk2ppk2-20251111T024336 ship mode, hard reset.ppk2

    I will see if I can check the status of those registers you mentioned later.

  • I'm not sure what changed to cause this, but now it is waking when I plug in USB as expected. However, it still does not wake with a press of the ship hold button.

    I added some code to log the RSTCAUSE value on init and log a message on the VBUS removed/detected events, but my BLE logging is dropping all the messages from before it reconnects to my PC, and I can't have USB connected when testing this, so I will need to figure out how to set up RTT/SWO logging.

        uint8_t data;
        int err = mfd_npm1300_reg_read(pmic, 0x0e, 0x3, &data);
        if (err) {
            printk("Failed to read RSTCAUSE: %d\n", err);
        } else {
            printk("RSTCAUSE = %02x\n", data);
        }
        
        static struct gpio_callback vbus_cb;
    
        // vbus_event_handler prints a message when called
        gpio_init_callback(&vbus_cb, vbus_event_handler,
                           BIT(NPM1300_EVENT_VBUS_DETECTED) | BIT(NPM1300_EVENT_VBUS_REMOVED));
    
        mfd_npm1300_add_callback(pmic, &vbus_cb);

    Waking when plugging in USB started working right after I added this code, but it also continues to work even if I remove that code, so unless there's some way that it could get stuck persistently in a bad state, and reading these registers gets it unstuck from that state, I have no explanation for this.

    I am also able to reproduce it getting stuck in the 1 mA draw state. Usually, I see a short spike to 1 mA when pressing the button and another when releasing it, but sometimes it doesn't return to ~0.38 uA on release. Plugging in USB now also gets it out of this state.

  • When resetting from ship mode with a long press, RSTCAUSE has LONGPRESSTIMEOUT set, as expected.

    Waking from ship mode by plugging in USB does not seem to modify the register? For a while, RSTCAUSE was 0 when waking by USB, but it switched to 0x8 after waking with a long press, and it stayed 0x8 on subsequent wakes by USB. If I write to TASKCLRERRLOG to clear RSTCAUSE back to 0, then it remains 0 after waking by USB.

    I can also confirm that I am getting VBUS detected and removed events when plugging/unplugging USB.

  • Hi,

    Can you confirm does the VSYS go to 0 when entering the ship mode? If it does not it would indicate the VSYS gets sourced from somewhere outside. And you did not see the same issue with the nPM1300-EK?

  • On the nPM1300 EK, I see VSYS is at 4 V when powered by battery, ~3.5 V and slowly dropping towards 0 in ship/hibernate mode, and 4 V after I press the reset button.

    On my custom hardware,

    VSYS RSTCAUSE on short press RSTCAUSE on long press RSTCAUSE on USB plugged in RSTCAUSE on wake from timer
    Powered on USB 5 V N/A LONGPRESSTIMEOUT N/A N/A
    Powered on battery 4 V N/A N/A N/A
    Hibernate 3.8 V and slowly dropping towards 0 SHIPMODEEXIT Not possible. Wakes immediately when button is pressed. SHIPMODEEXIT SHIPMODEEXIT
    Ship mode 4 V (steady) Does not wake. LONGPRESSTIMEOUT RSTCAUSE is unchanged N/A

    I assume that this behavior with the voltage slowly dropping is just a capacitor discharging, and my multimeter is the only load on the circuit? Regardless, I do see a clear difference between the VSYS behaviors in hibernate and ship modes on my hardware. My hardware in hibernate mode matches the EK in ship and hibernate modes, but my hardware in ship mode has VSYS steady at 4 V.

Related