seamusdemora / PiFormulae

A collection of "How-To" guides or "Recipes" for the Raspberry Pi
58 stars 9 forks source link

Simplifying 4B startup/shutdown button #6

Open matthijskooijman opened 3 years ago

matthijskooijman commented 3 years ago

Hi! First off, thanks for sharing your solution. I'll add a link to my own blogpost later, but first wanted to respond a bit (and frankly, github is a lot easier than my own blog's comments :-p).

I'm actually quite surprised at the high current draw for the sleep mode, but also even for the PMIC-disabled mode. Working a lot with MCUs where sleep currents are measured in microamps, 370mA sleep current seems excessive (though I also know that getting low sleep currents takes a lot of careful board design and concessions). I do wonder what the sleep currents for earlier pi models are, since if they're similarly high, I should probably add a big disclaimer to my blogpost about this (should probably make it more explicit that the goal is primarily safe shutdown before cutting power, not power saving directly).

I tried looking up sleep currents for earlier models, but didn't quickly find anything. I did find this post, which suggests that the 4B should be able to poweroff with PMIC disabled for either 3mA or 20mA (maybe the 20mA is with PMIC enabled?), which is a lot less than your figures. It does seem these figures are with earlier bootcode versions, but still, I wonder if your figures are not way too high?

Then, regarding the circuit: I see how it works and it seems neat. I do wonder, though, do you really need that much complexity? In particular, when the system is running, do you really need to prevent pulses on GLOBAL_EN? If not, couldn't you just wire a single pushbutton directly to both GLOBAL_EN and GPIO3 (maybe with some series resistance for short-circuit protection), so it activates both when you press the button? When powered-up, GPIO3 will cause a shutdown, when powered off, GLOBAL_EN will cause a power-on?

matthijskooijman commented 3 years ago

Hm, it seems that this post says that GLOBAL_EN works like a reset when already powered on, so that would indeed not work. Still, I wonder if you couldn't make this simpler using just one or maybe two transistors to cut the GLOBAL_EN signal when the 3V3 is active? AFAICS there is no harm in pulling down GPIO3 when not running (or when already shutting down) in any case.

seamusdemora commented 3 years ago

Thanks for the feedback! The 370mA figure was measured some time ago - in this post from July 2020, and using ver 2020-06-15 of the EEPROM bootcode. IIRC, at least one of the participants in the forum thread you linked to also reported measuring 370 mA. AFAIA it was a reasonably accurate figure at the time - at least it was not rebutted. Of course it's certainly possible that subsequent changes to the bootloader have improved that. I'm curious now, because of something I've seen on my USB meter with this LP-OBSS, and I will re-test after I'm able to restore my RPI 4B to the configuration I had then.

Wrt complexity: I'd be surprised if there's not a simpler circuit to do the job. :) Please let me know if you work something out. I tried to "cover all the bases" from my flawed knowledge of how they work, and some makeshift experiments. I found GLOBAL_EN to be a bit slippery: If the RPi is running, and GLOBAL_EN is pulled low, the RPi is immediately shutdown (no "safe" shutdown - it just quits), and remains shutdown until it's allowed to return to its pulled-up default state. At that point - when it transitions to HIGH - the RPi starts up again (reboots). I wasn't sure what an unnecessary HI-LO-HI transition on GPIO 3 would do to a RPi 4 in LP mode, and so I played it safe. Also, the 3V3 bus from the RPi had to be inverted to inhibit an extraneous transition on GLOBAL_EN, so the "cost" was small. And the transistors provide an open-drain interface to the RPi, which seems correct to me - and they were less than 2 cents each, so fit the budget. :)

But I'm so glad you brought this up... I had wondered if it might be possible to change the behavior of GLOBAL_EN with an overlay? What do you think? The best solution would be one that required only a single button & 2 wires - as in your post. That would be very cool!

seamusdemora commented 3 years ago

@matthijskooijman : You're correct - my 370mA figure was off - it's decreased 100mA since last year. I have measured it just now as 270mA using the default bootloader configuration. I currently have no idea what has been changed over the past year (since my earlier measurement of 370mA) to drop the figure to 270 mA. However, the 40mA figure using the modified bootloader config remains the same as last year. I've revised the file to reflect this, and done some "word-smithing" as it was clumsily worded in several spots.

matthijskooijman commented 3 years ago

You're correct - my 370mA figure was off - it's decreased 100mA since last year. I have measured it just now as 270mA using the default bootloader configuration.

I'm still highly surprised that it is that much, given that essentially all that needs to be left running is some CPU/MCU that wakes up when a pin becomes low, but I guess that means a lot of auxiliary components and power rails also need to keep running, raising the power usage that high...

I found GLOBAL_EN to be a bit slippery: If the RPi is running, and GLOBAL_EN is pulled low, the RPi is immediately shutdown

Ah, indeed. I was thinking that GLOBAL_EN was maybe a signal to some bootloader somewhere, but it seems this directly controls the PMIC, so also works when the rpi is running.

I wasn't sure what an unnecessary HI-LO-HI transition on GPIO 3 would do to a RPi 4 in LP mode, and so I played it safe.

I suspect that's not a problem, since the CPU is powered down anyway. Even more, if the 3V3 line is down, the GPIO3 is already LO, since it is normally only HI because of a pullup to (I presume) 3V3. So connecting the button directly to GPIO3 would, I think, be fine and also means that the hardware will stay working even with the default POWER_OFF_ON_HALT=0 and WAKE_ON_GPIO=1.

But I'm so glad you brought this up... I had wondered if it might be possible to change the behavior of GLOBAL_EN with an overlay? What do you think? The best solution would be one that required only a single button & 2 wires - as in your post. That would be very cool!

Nope, I don't think that's possible since GLOBAL_EN is hardwired to the PMIC, see also below.

In your formula, you write:

Despite the convenience of OBSS, shutdown is not a "sleep mode".[

Note that technically, AFAIU, it is a sleep mode, at least from the CPU/hardware perspective, in the sense that the bootloader or other low-level firmware puts the CPU (or maybe the GPU) in sleep mode and wakes up again (and continues to start linux) when GPIO3 is pulled low. You are right that from the Linux perspective, this is not a sleep mode, since Linux is fully shutdown rather than in standby/sleep.

You also write:

GLOBAL_EN is not a GPIO, nor can it (at least currently) be assigned to a GPIO. This likely due to the fact that the 3V3 bus is turned off in LPM - thus disabling all GPIO. Regardless of the cause, the net effect is this: OBSS, as currently implemented, does not work when the RPi 4B is configured for Low Power Mode.

Looking at the rpi4 schematic (though incompolete) suggests that the GLOBAL_EN pin is really not connected to any GPIO pin on the CPU at all, but instead connects directly to the GLOBAL_EN pin on the MxL7704 PMIC. This essentially means that if the GLOBAL_EN is low, then the entire PMIC shuts down and (AFICS) all power rails are turned off (except for the "5V" input line, and maybe "5VSYS", which might be powered from 5V directly through a 10Ω R5). So this is just a copper connection, nothing to configure.

I do see in the schematic that there is a transistor that can pull GLOBAL_EN down, which I presume is used by the bootloader to turn off GLOBAL_EN when POWER_OFF_ON_HALT is set. This does imply that there is some component (a microcontroller, or maybe just a flip-flop) that is powered from the 5V line and that stays active to keep that transistor powered on (i.e. the GLOBAL_RESET line high) and the PMIC off. The schematic doesn't show where GLOBAL_RESET is connected (I suspect it's internally connected somewhere and not on a pin header) so I can't tell more than that.

image

You write:

The necessary reboot from LPM shutdown is only possible by either: 1. pulling down the GLOBAL_EN node, or 2. "pulling and re-inserting the plug".

Are you sure this is "pulling down"? I would think that this would be "pulling up", since that enables the PMIC (and then presumably that triggers startup, and then I suspect that the bootloader disables whatever was pulling GLOBAL_EN down). Unless, my analysis above is completely wrong. Looking at your schematic again, you really pull GLOBAL_EN low with an open-drain transistor, so maybe it works differently and the PMIC stays (partly) on when in "shutdown" (i.e. just one of the power outputs, or maybe the PMIC is on, but all outputs are disabled) and then either pulling GLOBAL_EN low disables whatever is still running, or pulling GLOBAL_EN low and then high again resets the PMIC and causes it to power up all its power lines.

If indeed the shutdown works by telling the PMIC to disable all outputs, that would mean there is no need for an additional flip-flop or something to keep the PMIC (GLOBAL_EN) disabled, since the PMIC just remembers its last state already. It does make me wonder what the GLOBAL_RESET signal is, but maybe that's also something triggered by some low-level startup MCU on powerup?

In any case, it seems that the PMIC does not enable any outputs (except maybe 5VSYS) automatically on powerup, it seems that all its outputs need to be configured over I²C before they are enabled. This suggests that there is some component (MCU or a part of the CPU maybe) that runs from the 5V line instead of from the PMIC outputs and that sets up the PMIC, but again, I couldn't find any details. Did you find anything about this maybe? If the bootloader can shut down the PMIC, it must be able to talk to it through I²C (from the GPU, which is where the bootloader runs AFAIU), but maybe both a startup controller and the GPU can access this I²C bus? Or maybe the GPU can start up from 5V with the PMIC disabled?

Wrt complexity: I'd be surprised if there's not a simpler circuit to do the job. :) Please let me know if you work something out.

Thinking about what we'd need, it is minimally a button that:

One caveat is that GLOBAL_EN has a 5V pullup and GPIO3 a 3V3 pullup, so some care should be taken to not get 5V into GPIO3 (though maybe it's ok when through a pullup). The GLOBAL_EN low pulse for startup probably also needs to have some minimal width, but that's probably in the ms range (MxL7704 datasheet doesn't seem to specify, though), so a button press is probably always long enough, especially combined with the 2u2 capacitor on GLOBAL_EN that will probably filter away bouncing anyway.

I haven't figured out the simplest way here yet, I suspect it would be possible with two, or maybe just one transistor. I guess one question that would be relevant if e.g. 3V3 or SYS5V would really go low and be able to sink some current when the PMIC is off (I suspect SYS5V stays high through 10Ω R5, but 3V3 has a 1k8 pulldown that could sink a little current). I'll think on this a bit more, out of time for now.

matthijskooijman commented 3 years ago

Here's one attempt at a simpler schematic:

image

The trick to prevent pulling GLOBAL_ENABLE low when running is that Q2 pulls down GLOBAL_ENABLE to 3V3 rather than GND. When running, 3V3 is still high enough to keep the PMIC enabled (min 2.0V). When not running, the 1k8 pulldown on 3V3 (R52 in the rpi4 schematic) forms a divider with the 100K pullup on GLOBAL_ENABLE (R6 in the rpi schematic), which is more than strong enough to make GLOBAL_ENABLE low. I haven't tested this, though, this is just a theory :-)

If you're using BJT's (as opposed to FETs), the pulldown can probably omitted (a BJT needs base current to conduct). OTOH, adding base series resistors is probably a good idea to prevent excessive base current with the BJTs.

I still think this is a bit complex, I'd hope to make something with just one transistor.

One additional observation is that instead of GPIO3, you could also use another GPIO, add a pulldown and configure it as active-high instead of active-low, that might allow saving one inverting transistor in some circuits. In the above circuit, this could maybe allow omitting Q1, but that would then put 5V on GPIOx, so that would need a resistor divider (so it's exchanging one transistor for two resistors, probably not a good deal...).

An alternative idea would involve a PNP instead of an NPN, but rather than connecting the emitter to a postive voltage (as is customary for PNP), use the emitter as the output and connect the collector to GND. This creates a non-inverting transistor, so the button can remain connected to GND and GPIO3 can then be connected directly without a transistor:

image

There's two caveats here:

  1. Q3 will not be able to pull GLOBAL_ENABLE all the way to GND, since it only conducts as long as its base (GND when button is pressed) is at least 0.7V or so below its collector (GLOBAL_ENABLE). However, the low level threshold for GLOBAL_ENABLE is 0.8V, so I think that should work out (might be worth checking against transistor datasheet, though).
  2. The pullup on GPIO3 might cause Q2 to conduct even when the button is not pressed. This could happen when the rpi is running (because 3V3 is more than 0.7V below the 5V of the GLOBAL_ENABLE pullup), but that can never pull GLOBAL_ENABLE below 4.0V, so that would be harmless. However, when the rpi is shut down, this could pull GE down to 0.7V, just like pressing the button. I added a series base resistor (R2) with the idea that (combined with the GPIO3 pullup) this might prevent this, but I think it would only limit current a bit (which could prevent this problem, but highly depending on transistor amplification / hfe value). I'd have to think about this a bit more, maybe adding another resistor (maybe in the transistor feedback path) could help to fix this. Edit: Or maybe using a PFET with a significantly high gate threshold (combined with some extra resistance here or there) could help ensure that the pullup is not strong enough to turn the transistor on. Or maybe just adding a pullup R3 to 5V on the Q2 base pin would already help enough (picking its value low enough so that the divider formed by R3 and R2 combined with the GPIO3 pullup would not pull the Q2 base low enough, but picking R2 low enough so that pressing the button does still get it low enough, while ideally also ensuring that R2 prevents 5V from ending up at GPIO3 - I suspect this might be a non-solvable puzzle of resistor values....)
matthijskooijman commented 3 years ago

Here's one more (incorrect) attempt, to use a FET a bit like the common level-shifter design, with the gate connected to a voltage supply rather than the signal to be transmitted (but using the 3V3 instead of a fixed supply and a PFET instead of an NFET to ensure the FET does not conduct when the PMIC is still on):

image

Note that this design does not actually work: It needs a FET with a Vgs threshold of at least 1.7V (to prevent conducting when the gate is at 3.3V and the source is pulled up to 5V), but that also means that when the gate is at 0V (PMIC off), the source cannot be pulled below 1.7V, which is too much for GLOBAL_ENABLE.

Also note the diode, which ensures that the button can pull GPIO3 low, but the pullups on GPIO3 cannot pull GLOBAL_ENABLE low when the PMIC is off.

matthijskooijman commented 3 years ago

I just realized that with the second schematic from two posts ago, the second caveat (GPIO3 pulling the Q3 base low) can also easily be fixed by adding a diode:

image

So this seems like an acceptably simple circuit, there might not be anything simpler than this. The first caveat still applies, though, but I suspect that because the collector current only needs to be minimal (±4.3V over a 100k pullup on GLOBAL_ENABLE, so < 50μA), it's ok for the transistor to be just barely turned on, so 0.8V Vbe is probably more than enough (I might double check this intuition against the transistor theory, though). The value of R2 might also influence this, I suspect that keeping it low (so high base current) would help (since then the transistor only needs a very small α/hfe value to produce the required collector current).

Care to try this circuit? :-)

seamusdemora commented 3 years ago

Wow! I've not checked my notifications for a couple of days - you have been busy! :)

I'll try to respond following your order of posting:

I'm still highly surprised that it is that much,

... there is a transistor that can pull GLOBAL_EN down, which I presume is used by the bootloader to turn off GLOBAL_EN when POWER_OFF_ON_HALT is set. This does imply that there is some component (a microcontroller, or maybe just a flip-flop) that is powered from the 5V line and that stays active to keep that transistor powered on (i.e. the GLOBAL_RESET line high) and the PMIC off.

Are you sure this is "pulling down"?

seamusdemora commented 3 years ago

Care to try this circuit? :-)

I think that before I try this, I would simulate it in SPICE. I use a Mac mostly, so that's LTSpice for me.

But just a cursory inspection leads to some questions for me. If Q3 can be turned on with negligible Vce drop, the emitter (GLOBAL_EN) will never be lower than 3.3V. I wonder if that's enough to trigger the PMIC input? Have you found a spec sheet for this?

seamusdemora commented 3 years ago

I've had a run at this in LTSpice. I did not take time to double-check this, so it's entirely possible there's an error. The models/schematics won't make a great deal of sense if you're not familiar w/ LTSpice, but some comments that may help:

I ran 2 cases:

Case 1: GPIO 3 HIGH

Model:

Screen Shot 2021-08-11 at 11 58 49 PM

Result: Screen Shot 2021-08-11 at 11 51 49 PM.

Case 2: GPIO 3 LOW

Model:

Screen Shot 2021-08-11 at 11 56 18 PM

Result:

Screen Shot 2021-08-11 at 11 56 10 PM
matthijskooijman commented 3 years ago

Quick response to your spice model: I think you should also set V2 to 0V in the "GPIO3 low" (== "PMIC off") case. More response later :-)

seamusdemora commented 3 years ago

I can do that, but your schematic shows the collector of Q3 connected to 3V3

matthijskooijman commented 3 years ago

I can do that, but your schematic shows the collector of Q3 connected to 3V3

Yes, but 3V3 is powered from the PMIC, so that gets powered down when the rpi/PMIC is shut down, right?

seamusdemora commented 3 years ago

Ah - of course, yes it is. Not quite sure that's a ground, but we can assume that for now. I'll do that later today.

matthijskooijman commented 3 years ago

Ah - of course, yes it is. Not quite sure that's a ground, but we can assume that for now. I'll do that later today.

Exactly, but the same thing (not exactly ground) holds for GPIO3, which will have a pull"up" to 3V3 at least, though maybe the GPIO input of the CPU will sink to GND as well, not entirely sure. For 3V3, I suspect that it will not be a solid GND through the PMIC (but I couldn't find any info on disabled outputs in the datasheet when I looked quickly), but 3V3 at least has a pulldown (1k8 IIRC) to GND, so it won't be floating.

seamusdemora commented 3 years ago

3V3 at least has a pulldown (1k8 IIRC) to GND

OK - that will be important for the LTSpice model - models actually, as we'll need one model for LPM when 3V3 is OFF, and another when it's ON/operating mode. So 3V3 will be modeled as a 1.8K R when 3V3 is OFF, and a volt source when it's ON.

... (sound of modeling in background)

Hmmm... this isn't working. It seems that the value of the pullup on GLOBAL_EN (100K) is part of the problem. We really don't have Q1 biased properly. Here's what the model tells me: There's enough leakage current (~150nA) through D1 to pull GLOBAL_EN down to about 2V.

I don't see an easy fix for this, but it's late here now. I'll noodle on it some more tomorrow.


One more thing: Something's been puzzling me about this, but didn't spend enough time thinking on it to formulate a question. Let me try that now: There is some mystery with the OBSS and the "duality" of GPIO3. Something I read, but don't clearly recall now led me to believe that GPIO3 may function differently when in operating mode than it does in halt. If that's the case, pulling GPIO3 low in LPM may do something different & unknown. I do know that from LPM pulling GPIO3 does not cause a boot, but it may have some other effect. Yeah - this sounds flaky, maybe paranoid, but do you have any insight on what GPIO3 does in LPM? Having forced myself to think through this now by writing this question suggests a simple test: connect both GLOBAL_EN and GPIO3 (through a diode) to a PB switch in LPM mode?? Whaddya' think?

matthijskooijman commented 3 years ago

Ok, finally some time to respond in a bit more detail, I'll respond oldest to newest.

Have you confirmed the 270mA measurement I made?

No, TBH I haven't actually powered on the rpi4 at all yet, still a bit too busy with other things (I just freed up some time to think about the schematic, since I needed exactly that kind of puzzle as a distraction from other things :-p). Also, I'll be traveling the coming 2 weeks, so I won't be able to experiment or do measurements, though I'm happy to continue this discussion on my trip :-)

also AIUI, GPIO 3 is one of only 2 (??) GPIOs that has an in-built pullup. This, I think by virtue of its being (half) the default i2c port.

Correct, though "in-built" in this case means "on the board", not "in the chip" AFAIK.

Obviously I am not the authority on these semantics, but I've long understood that the distinguishing feature of "sleep" is that machine "state" is stored, enabling one to "pick up where he left off", and no reboot is required to resume operations. For our discussions, I'm happy to use any definition you like, but we should make it clear between us anyway.

You are correct that sleep should store state, but I think it actually does. AFAIU (because bootloader sources are closed, so I'm going from what I've heard), the hardware goes into a sleep mode, which preserves RAM contents (or maybe not RAM, but then at least hardware registers, such as the "listen to GPIO3 for a falling edge" configuration). So it does not preserve linux state (linux has shut down and freed all its memory by then), but it does preserve hardware and probably also bootloader state.

But indeed, it's just semantics, I wasn't trying to correct you here, but just trying to improve understanding of what happens when the system is in halt mode (not LPM mode, that's different).

For our discussion, I think this is not a really relevant distinction, just using "halt" mode (POWER_OFF_ON_HALT=0) and "LPM" mode (POWER_OFF_ON_HALT=1) is fine.

I don't understand why you've concluded that the transistor driven by GLOBAL_RESET is "always on". If it were, that would mean that GLOBAL_EN be "always LOW", n'est-ce pas ?? Perhaps I have missed something?

I don't think I concluded that, but never mind anyway. That section you were responding to is actually outdated, I was under the impression that that transistor would keep GLOBAL_EN low in LPM mode, but I later realized that LPM mode is done by disabling PMIC outputs through I²C commands, so (I expect) GLOBAL_EN remains high in LPM mode.

The difference seems to be that WAKE_ON_GPIO=1 (default) by itself (i.e. when POWER_OFF_ON_HALT=1 (default) creates a lower power mode, but it must be set =0 (non-default) in conjunction with POWER_OFF_ON_HALT=1 (non-default) for LPM.

I think you have a typo there (POWER_OFF_ON_HALT=0 by default, right), but I'm also not entirely sure what you are saying. In any case, how I think this works (mostly guessing here, based on how I'd implement this):

This gives four combinations, of which POWER_OFF_ON_HALT=1 WAKE_ON_GPIO=1 makes no sense - you cannot wake up from a GPIO if the PMIC is turned off, there's nothing left powered on to check the GPIO. So I think they made an arbitrary choice to ignore POWER_OFF_ON_HALT in this case, and use halt mode with gpio wakup (identical to POWER_OFF_ON_HALT=0, WAKE_ON_GPIO=1).

> At some point shortly after RPi enters LPM, GLOBAL_EN becomes high once again. GLOBAL_RESET may or may not have anything to do with that - I haven't measured it. Let me break for now to make a measurement. I'll record this on my oscilloscope, and post a screen shot of that here - unless you've already confirmed it - I'll continue reading & come back to this if needed.

Hm, interesting, you say "GLOBAL_EN becomes high again", does that mean it does become low momentarily when entering LPM mode? I would not expect so, so it if does, then my hypothesis of how LPM is entered might be wrong. RESOLVED HERE

Did you get around to measuring this on your scope yet?

OK - that will be important for the LTSpice model - models actually, as we'll need one model for LPM when 3V3 is OFF, and another when it's ON/operating mode. So 3V3 will be modeled as a 1.8K R when 3V3 is OFF, and a volt source when it's ON.

Alternatively, you can have a fixed 1.8k pulldown on 3V3, and then power 3V3 through a fixed 3.3V source behind a switch?

Also, note that I'm not sure whether "PMIC off" means "3.3V output floating", it might very well be "3.3V grounded" (or anything in between), but I guess that might be something to test (with the PMIC off, connect 3V3 to 5V (or some other voltage source) through a big (start with 100k or so) resistor, and see what the resulting voltage is to see what the impedance of 3V3 is when the PMIC is off.

Hmmm... this isn't working. It seems that the value of the pullup on GLOBAL_EN (100K) is part of the problem. We really don't have Q1 biased properly. Here's what the model tells me: There's enough leakage current (~150nA) through D1 to pull GLOBAL_EN down to about 2V.

Hm, good point. Maybe increasing the value of R2 would help, since then a little leakage current causes a bigger drop over R2, which could then keep the Q1 base above it's Vbe threshold? Might need a big resistor, though, something like R2 > (5V - 0.7V - 3.3V) / 150nA = 6.6MΩ. That probably prevents the button from working as well (or at least prevent Q1 from pulling its collector all the way below 0.8V when the button is pressed).

Would it help to add a pullup to 5V (between D1 and R2)? That would probably divert the current so that Q1's base doesn't get any significant current (and more importantly, keeps the base voltage above the threshold), while the diode should ensure that GPIO3 does not get 5V (though maybe omitting the diode would also be ok, if GPIO3 has an internal protection diode to VCC that could shunt a little current, provided that the new pullup to 5V is big enough).

One more thing: Something's been puzzling me about this, but didn't spend enough time thinking on it to formulate a question. Let me try that now: There is some mystery with the OBSS and the "duality" of GPIO3. Something I read, but don't clearly recall now led me to believe that GPIO3 may function differently when in operating mode than it does in halt

AFAIU this is just a software thing. While running, the kernel listens to GPIO3 and on falling edge (or whatever you configure), it generates a power button keypress. In halt (which is really the bootloader sleep mode), the bootloader takes over control of the pin, and on a falling edge, it restarts the system.

In LPM, most power rails are turned off, so I think that the CPU (i.e. the chip that GPIO3 is on) is actually powered off. That means that nothing will happen logically when the pin is toggled, there's nothing to listen to the pin. It might mean that some current will leak if you put a voltage on the pin (in general, I/O pins on chips which are powered down tend to have some internal connection to ground, typically with some internal impedance, so they will "leak" some current to ground if you connect a voltage, so in power-saving situations, you must generally be careful with putting a signal on the pins of a powered-down chip).

In this case, though, as I said before, I do not think this is at all relevant: if the PMIC is powered down, 3V3 will be 0V, so pressing the button will not change the GPIO3 voltage (it might change the impedance to GND of GPIO3, but since it's all 0V, no current should be flowing, so nothing should be happening).

Having forced myself to think through this now by writing this question suggests a simple test: connect both GLOBAL_EN and GPIO3 (through a diode) to a PB switch in LPM mode?? Whaddya' think?

Would be interesting to test what happens, but I highly expect that connecting GPIO3 to GND in LPM will do nothing at all :-)

seamusdemora commented 3 years ago

I wanted to throw this into the discussion as a reference schematic for a GPIO pin. Here's the source, but I think it's been posted by others. The clamp diodes are said to be parasitic FETs, which are capable of only very low current.

image

seamusdemora commented 3 years ago

Would be interesting to test what happens, but I highly expect that connecting GPIO3 to GND in LPM will do nothing at all :-)

Ach, apologies for that gibberish - didn't say what I meant. Yes - in LPM, GPIO3 doesn't trigger a reboot. I've verified this, but GLOBAL_EN was not connected at all - the PB was connected only to GPIO3 and GND. What we are trying to do now is to trigger a boot by somehow connecting both GLOBAL_EN and GPIO3 to the PB, but isolated such that they do not interfere with each other. And so the experiment I had in mind is depicted in the two schematics/models below:

It seems that the diode isolating GPIO3 from GLOBAL_EN does its job when in LPM, but it looks like trouble in RUN mode as the two signals over lap. I don't see this shutting down the RPi - certainly not in a controlled/safe way. And so the problem becomes how do we isolate GLOBAL_EN from the PB action during RUN mode. That's what the PNP transistor was intended to do, but it may not be able to do this as it's not a perfect switch.

That's enough for now. I didn't have any time for this earlier today, but after reading your latest post & re-reading my gibberish, I wanted to try to correct that at least. So this hasn't moved us forward I'm afraid, but I needed to clear my own head :). I'll get back to the other points in your post first chance I get.

Enjoy your travels! I'm trying to plan a trip also - hopefully in about 2 weeks. If that happens I'll be gone for some time - back to Scotland - and have no access to my lab here. ANd so I'll put some priority on getting the measurements done.

seamusdemora commented 3 years ago

As a variation on your idea for using a transistor, perhaps an analog switch of this configuration would be better suited to this application? I've not been able to find a SPICE model, but it looks promising at first glance. The schematic below shows a different switch to help visualize how this would work. Have a look & let me know what you think.

This first graphic is a schematic of the part in the data sheet linked above (DG2001E). The cost of this part is about US$0.65.

Screen Shot 2021-08-14 at 6 29 55 PM

This graphic shows a similar (not equivalent) analog switch in the schematic. The 3V3 supply acts as the INPUT/CONTROL to select either GPIO3 or GLOBAL_EN. The supply connections on the DG2001E are 5V and GND. If the DG2001E works as it appears, this will isolate GPIO3 from GLOBAL_EN such that only one of them is connected to the PB switch.

Screen Shot 2021-08-14 at 7 12 48 PM
matthijskooijman commented 3 years ago

It seems that the diode isolating GPIO3 from GLOBAL_EN does its job when in LPM, but it looks like trouble in RUN mode as the two signals over lap. I don't see this shutting down the RPi - certainly not in a controlled/safe way. And so the problem becomes how do we isolate GLOBAL_EN from the PB action during RUN mode. That's what the PNP transistor was intended to do, but it may not be able to do this as it's not a perfect switch.

Yes, agreed (also with the preceding schematics for LPM and RUN mode).

As a variation on your idea for using a transistor, perhaps an analog switch of this configuration would be better suited to this application?

Yes, that would indeed be an option as well. It crossed my mind, but somehow using a switch IC where a transistor is sufficient feels a bit like cheating to me, but because you picked a SPDT switch, your schematic neatly cleans up to a single component, which is actually quite nice...

seamusdemora commented 3 years ago

Yes, that would indeed be an option as well. It crossed my mind, but somehow using a switch IC where a transistor is sufficient feels a bit like cheating to me, but because you picked a SPDT switch, your schematic neatly cleans up to a single component, which is actually quite nice...

Yes - I understand the efficiency point, and a single PFET might get the job done. But when considering "all other factors", the efficiency argument just fades away: Arrow Electronics does not stock a single p-ch JFET - the only one they even list is the 2N5460. The engineering that goes into the IC makes for easier integration. The price is about US$0.60 for a qty of 1, etc. I found two parts I think are good candidates from TI, and have ordered several of each: TS5A3153 & TS5A3154. So, we shall see. :)

seamusdemora commented 3 years ago

From an earlier post:

At some point shortly after RPi enters LPM, GLOBAL_EN becomes high once again. GLOBAL_RESET may or may not have anything to do with that - I haven't measured it. Let me break for now to make a measurement. I'll record this on my oscilloscope, and post a screen shot of that here - unless you've already confirmed it - I'll continue reading & come back to this if needed.

Hm, interesting, you say "GLOBAL_EN becomes high again", does that mean it does become low momentarily when entering LPM mode? I would not expect so, so it if does, then my hypothesis of how LPM is entered might be wrong.

I think now I have gotten this confused with something else... when I was working on a circuit for my "solar project" I used a "high-side" switch to remove power from the RPi, and the gpio-poweroff overlay to trigger the shutdown. I ran into an issue where gpio-poweroff did not "play nice" with the LPM configuration. I don't recall all of the details now, but here's part of it icyi.

This does make me wonder what GLOBAL_RESET does exactly - or what causes it to be invoked.

However: I can now confirm by oscilloscope measurement that in this experiment, GLOBAL_EN goes LOW only as long as the button is pressed - releasing the button restores GLOBAL_EN to its HI state - filtered by the R=100K, C=2.2uF.

NOTE: I've struck the comment, and linked it back here.

seamusdemora commented 3 years ago

For our discussion, I think this is not a really relevant distinction, just using "halt" mode (POWER_OFF_ON_HALT=0) and "LPM" mode (POWER_OFF_ON_HALT=1) is fine.

Perhaps "sleep" is not relevant, but I guess we should be clear on a halt mode, and "LPM":

Do you agree? - or shall we use different terms to describe these two states?

matthijskooijman commented 2 years ago

So, we shall see. :)

Yes, I'm curious if this works well :-)

I don't recall all of the details now, but here's part of it icyi.

Ah, thanks. Interesting read, that gives some more insight in how the shutdown process works, nice :-)

Do you agree? - or shall we use different terms to describe these two states?

Yes (though as you point out, "halt" is a little ambigous since LPM is also entered through "halt", but as long as we know what we mean, that's ok).

seamusdemora commented 2 years ago
  1. RE TS5A3153 & TS5A3154 switches: These have arrived, but I've done nothing with them yet - and I won't be able to make any progress until I return from travel in mid-October. :( Soldering will be a challenge as the parts are tiny.
matthijskooijman commented 2 years ago

Soldering will be a challenge as the parts are tiny.

Oh indeed, 0.5mm pitch between pins is quite tiny indeed (assuming you didn't take the BGA version, which is even trickier :-p). Maybe you can find a small PCB to break out the pins instead of soldering them directly?

That does mean that as a general purpose solution to recommend, this is a bit less ideal. Did you look for other similar chips that are available in bigger packages (something like 1.27mm pitch, or even 2.54mm DIP would be ideal, since you can then maybe solder directly to pins or so)?

seamusdemora commented 2 years ago

Did you look for other similar chips that are available in bigger packages

I can't say I did an exhaustive search, but I did look. Also, I looked only at TI's website, and it's possible that another manufacturer may produce a part with equivalent function. However, from observation, it seems clear that newer parts are only available in smaller geometries.

seamusdemora commented 2 months ago

@matthijskooijman : Well... I surely dropped the ball on this thread :) That's what a month in the French Alps can do to you!

Anyway - if you're still in the mood to continue this, I'll try to gather up the pieces again?? I've recently been thinking about a change to the design... that one-shot definitely needs to go!

matthijskooijman commented 2 months ago

To be honest, I've quite forgotten what we were doing, but it seems we wrote down a lot of detail so I guess I can figure it out again :-)

I cannot guarantee I'll find time, but I'm still interested in providing some feedback and help with this if you want to pick it up again. I won't have much time though, so initiative will need to be on your side :-)

seamusdemora commented 2 months ago

OK - that's fine. TBH, I don't keep up w/ "Issues" very well on my own site, and was dismayed when I remembered I'd just walked out on this one. Perhaps we could leave it like this?: I've been "noodling" on a different (simpler) solution & think I might have something. I'll get around to testing it in a few days, and if my tests are successful, I'll follow up here. Does that sound OK w/ you?

Other than that, I hope you're doing well!

matthijskooijman commented 2 months ago

Sounds good, let me know if you want some feedback on something!

seamusdemora commented 1 month ago

A "few days" easily turns into a couple of weeks :) Anyway - I did come up with something that I think works. I've not finished testing it completely b/c it seems that the overlay gpio-poweroff does not function on my RPi 0W!?! [Filed issue here]

Anyway - the schematic below is a simplification of the previous; notably it eliminates the 'one-shot'. This one is intended to power the RPi via a 12V battery/solar panel. I guess that it might be simplified still further with a CMOS inverter to replace the two transistors in the RTC #INT output. Any feedback or thoughts are welcome.

Screenshot 2024-06-23 at 4 23 06 PM
seamusdemora commented 1 month ago

@matthijskooijman

I've made minor improvements to the June 23 schematic. Added a Manual pushbutton to allow easier re-starts (need something to cause the Latching relay to change state), improved "snubber" (to limit inductive kick when relay coils turn off), and removed connection to regulator ENable line as superfluous.

I think this is a reasonable "breadboard" prototype for a battery/solar-powered RPi. If I were making it as a PCB I would incorporate a few other changes.

Any feedback or thoughts are welcome!

I have found one idiosyncrasy with the RTC (probably its driver software):

  1. I set the wakealarm (in sysfs) to a value in the future, let's call it Tf, and let's assume it's 24 hours beyond the time at which it is set; i.e. date '+%s' -d '+ 24 hours' | sudo tee /sys/class/rtc/rtc0/wakealarm; IOW: Tf = date '+%s' -d '+ 24 hours'

  2. Now, let's assume that shortly after setting wakealarm as in Step 1, I decide to issue a halt from the command line to make some adjustments to the hardware. Since I have enabled the gpio-poweroff overlay, the relay disconnects power from the RPi. I make the adjustments, and then "power up" again using the "Manual Start PB".

  3. What I expected to happen was that the wakealarm setting (set in the RTC chip's register) would remain set as before the halt was issued. But it does not... the wakealarm setting made prior to the halt is erased, and there is no alarm time set.

Screenshot 2024-07-08 at 7 26 34 PM

That's all for now!