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.

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

  • Hello,

    Yes it is expected for the VSYS voltage drop slowly when the capacitors get discharged. But it seems something is keeping the VSYS voltage up in your system in ship mode, that is definitely not normal. And why hibernate mode works, but ship mode does not that is strange as well..

  • At this point, the only things I can think of are:

    1. Maybe there's a bug in Zephyr's driver, and it's not entering hibernate properly? I will check if there are any differences between the driver in Zephyr 4.1, mainline Zephyr, and the Nordic SDK later.
    2. I assumed that ship mode was effectively just hibernate but without the wake timer. Is that correct, or are there other differences between them at the hardware level? If there are any differences, that could point to where to look for hardware issues in my design, since hibernate works (mostly) correctly but ship mode doesn't.

    (It is odd that hibernate only sleeps for 10 seconds when I asked for 30,000 ms. I still need to debug that.)

  • Hi,

    Yes the hibernate mode is essentially the same as ship mode, but the wakeup is with timer instead of button. We will also check the hibernate timer issue you mentioned, is there something in our driver that needs to be updated. 10s would be the same as the boot timer.

  • Hi,

    There has been a fix to the hibernate mode entry which will effect the time you set. This has been fixed upstream, but it's not in the SDK yet. You can see the patch here:

    https://github.com/zephyrproject-rtos/zephyr/pull/98654/files

Reply Children
  • I found the issue. Setting a "regulator-always-on" property on BUCK2 seems to force that regulator to remain on, even when the PMIC itself is in ship mode, which then seems to break waking from ship mode. After removing that property, everything works as expected.

    I had set this because I wanted the regulator to always be on provided the PMIC was on, and I had assumed that the PMIC being off would override that. I'm not sure why this affects ship mode but not hibernate mode.

    I discovered this after testing on an npm1300 EK with an nrf5340 DK, using Zephyr's npm1300_ek sample application which I had modified to function similarly to my application. Everything worked as expected there, so I compared my setup to npm1300_ek.overlay and started removing differences between them until it worked on my hardware.

    Thanks for all the help!

    Edit: not actually the solution. See below.

  • I spoke too soon. I had accidentally left in code to test hibernate mode, so it was triggering hibernate instead of ship mode. Ship mode still does not work.

    I did notice a new, interesting behavior which seems to have started after removing "regulator-always-on". If I remove USB power, enter ship mode, and then plug USB back in, it wakes up. However, now if I unplug USB again, it seems to immediately return to ship mode, with the BUCK2 output disabled, VSYS at 4 V again, and average current draw of ~0.4 uA. Holding the button for 10 seconds gets it back out of this state until the next time I enter ship mode.

  • I think I have actually figured it out this time.

    regulator_parent_ship_mode() does not take a regulator device, look up its parent, and call ship mode on the parent. regulator_parent_ship_mode() wants a regulator's parent device to be passed to it. 

    I expect that calling regulator_parent_ship_mode() on the BUCK2 device did something that actually sent a command to the PMIC, but which it disliked enough to disable BUCK2 and get stuck in a bad state which looked a lot like ship mode, and where only a hard reset could recover it.

    Calling regulator_parent_ship_mode() on the nordic,npm1300-regulator device works as expected. Hibernate mode was working before because that uses mfd_npm1300_hibernate(), which is called on the nordic,npm1300 device.

Related