-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Simplifying 4B startup/shutdown button #6
Comments
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. |
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 But I'm so glad you brought this up... I had wondered if it might be possible to change the behavior of |
@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. |
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...
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 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.
Nope, I don't think that's possible since GLOBAL_EN is hardwired to the PMIC, see also below. In your formula, you write:
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:
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. You write:
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?
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. |
Here's one attempt at a simpler schematic: 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: There's two caveats here:
|
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): 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. |
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: 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? :-) |
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 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? |
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 Case 2: GPIO 3 LOW |
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 :-)
|
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? |
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. |
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 |
Ok, finally some time to respond in a bit more detail, I'll respond oldest to newest.
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 :-)
Correct, though "in-built" in this case means "on the board", not "in the chip" AFAIK.
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 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.
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).
Did you get around to measuring this on your scope yet?
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.
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).
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).
Would be interesting to test what happens, but I highly expect that connecting GPIO3 to GND in LPM will do nothing at all :-) |
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. |
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. |
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. 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. |
Yes, agreed (also with the preceding schematics for LPM and RUN mode).
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. :) |
From an earlier post:
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 This does make me wonder what 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. |
Perhaps "sleep" is not relevant, but I guess we should be clear on a
This is from the RPi "official documentation" - though I can't give you a link to it now that the documentation has been totally scrambled like eggs in a skillet! :). It is "claimed" to be the lowest power consumption state available.
Do you agree? - or shall we use different terms to describe these two states? |
Yes, I'm curious if this works well :-)
Ah, thanks. Interesting read, that gives some more insight in how the shutdown process works, nice :-)
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). |
|
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)? |
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. |
@matthijskooijman : 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! |
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 :-) |
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! |
Sounds good, let me know if you want some feedback on something! |
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 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 ![]() |
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?
The text was updated successfully, but these errors were encountered: