Re: Startup-/Shutdown Button for the Raspberry Pi 4

From: Dr. Rolf Jansen <freebsd-rj_at_cyclaero.com>
Date: Thu, 14 Jul 2022 14:45:24 UTC
> Am 14.07.2022 um 10:26 schrieb Jedi Tek'Unum <freebsd-arm-list-2022-fea3@qoruscant.com>:
> 
> On Jul 13, 2022, at 7:36 PM, Dr. Rolf Jansen - freebsd-rj at cyclaero.com <nxtzmchnyjrirskcrisaafakxcekosgmhdcricnnjyxomsvwpn@simplelogin.co> wrote:
>> 
>>> Am 13.07.2022 um 20:19 schrieb Jedi Tek'Unum <freebsd-arm-list-2022-fea3@qoruscant.com>:
>>> 
>>>> On Jul 12, 2022, at 8:17 PM, Dr. Rolf Jansen - freebsd-rj at cyclaero.com <nxtzmchnyjrirskcrisaafakxcekosgmhdcricnnjyxomsvwpn@simplelogin.co> wrote:
>>>> 
>>>> One week ago I started with exploring the Raspberry Pi 4 B, which might be a substitute for the aging BeagleBone Blacks for my future projects.
>>>> 
>>>> I very much like the built-in power button facility of the BBB, and unfortunately the RPi 4 has nothing comparable - the one button to rule it all.
>>>> 
>>>> I read a lot of howtos and blog posts (mostly for Linux) and nothing was really worth to give it even a try, compared to live without the button. Well, this is not becoming an elaborated question, but here I am going to elaborate my solution for FreeBSD.
>>>> 
>>>> 1. I Prepared a momentary push button for connecting it to the RPi:
>>>>          ___ 
>>>>           | /
>>>>           |/
>>>>           /
>>>>          /
>>>>       +-o      o--------+
>>>>       |        |        |
>>>>       |       [R] 100 Ω |
>>>>       |        |        |
>>>>       o        o        o
>>>>     Pin 5    Pin 6    Pin 13
>>>>    (SCL 1)   (GND)   (GPIO 27)
>>> 
>>> Ok, I’ll bite. I’m not understanding this.
>>> 
>>> I imagine that the resistor is a current limit for the gpio pin and not the pullup.
>>> 
>>> Regardless of how it is wired, why use SCL1 which is pulsing? And how can any of this cause a boot?
>>> 
>>> Is this “magic” dependent on some quirk(s) of RPi? Will it work with others, like Rock64?
>>> 
>>>> 2. I created a shutdown daemon in C for FreeBSD, lurking for push button
>>>> events on a GPIO port: https://github.com/cyclaero/shutdd
>>>> 
>>>> clang -g0 -O3 -fsigned-char -Wno-empty-body -Wno-parentheses shutdd.c -lgpio -s -o /usr/local/bin/shutdd
>>>> 
>>>> shutdd [-p file] [-f] [-n] [-b] [-g] [-h]  
>>>>  -p file    the path to the pid file [default: /var/run/shutdd.pid]  
>>>>  -f         foreground mode, don't fork off as a daemon.  
>>>>  -n         no console, don't fork off as a daemon.  
>>>>  -b         GPIO bank id [default: 0].  
>>>>  -g         GPIO line id [default: 27].  
>>>>  -h         shows these usage instructions.  
>> 
>> The power management of the RPis is quite non-sophisticated, and pin 5 (GPIO 3) of the Pis (3 or 4) happen to be the start-up-only pin when pulled down to ground. Now, the SCL line of the default I2C bus 1 is also routed to pin 5, and that cannot be changed. In case we don't need I2C1 otherwise, then we are done with connecting a simple momentary push button without resistor, and we would start shutdd with the flag -g 3. In this case pushing the button would start up the Pi when it is down, and it would stop the Pi by the way of the daemon when it is up. Only shutdd configures the given GPIO pin for exactly this purpose, and therefore I2C1 could not be used anymore.
>> 
>> In the Linux world it is common sense to simply assume, that you can't have your cake and eat it, and either I2C1 is either abandoned or double-switches or even more complex button assemblies with a n-channel analog multiplexer like the CMOS4053 are used.
>> 
>> The 100 Ω resistor together with the auxiliary GPIO line lets us do this in a more simple way. Pin 5 is internally pulled-up, pin 13 is internally pulled down. Now pushing the button would do a fractional pull-down of pin 3 and a fractional pull up of pin 13. The fraction is determined by the values of the internal pull up/down resisters compared to the 100 Ω resistor. The point is, that shutdd does not depend on accurate logic levels are reached, but instead reacts on rising and/or falling edges on the configured GPIO's.
>> 
>> Now by experiment, for my RPi 4B, the 100 Ω resistor is sufficiently large for the pulled up fraction of the level on GPIO 27 (pin 13) produces edges which can be recognized and yet it is sufficiently low, so that starting up the RPi by pulling down GPIO 3 (= SCL 1, pin 5) does work as well. For example a resistor of 1 kΩ (and above) does not work for starting up, while shutting down does work, and without the 100 Ω resistor, starting up does work but shutting down does not.
>> 
>> I do know nothing about the Rock64, except that it exists. In case the power management is comparable to the one of RPis, this might work as well. In case it is comparable to the sophisticated one of the BeagleBone Black, all this is not needed, you even don't need the shutdown daemon shutdd for that. In case Rock64's power management is completely different, then you would start with reading the specs.
>> 
>> As long as nobody pushes the button, SCL 1 and with it I2C1 does working normally, and once somebody pushes the button, it is not that important anymore, since the RPi goes down anyway.
>> 
>> BTW, right now I am working on implementing a double-push facility into shutdd. This would then restart the RPi instead of shutting it down.
> 
> Clever solution. Thanks for the explanation.
> 
> I should have looked before I typed. The Rock64 has a button. Your solution is likely very specific to the Rpi chip.

In the course of the work on the double-push feature for shutdd, which causes the RPi to restart instead of to shutdown, I figured that heavy bouncing of the button may affect the interval between multiple pushes. I could reduce the bouncing of my button significantly by adding a 1 µF tantalum capacitor in parallel to the 100 Ω resistor. Depending on the mechanics of the button this is not absolutely necessary, though.

I finished the work on shutdd by now and the updated version can be find on GitHub: https://github.com/cyclaero/shutdd

Perhaps in the future I will add triple and quadruple push features, for example to cause the RPi to go into Single User Mode, and/or to start a user defined executable. For now I need to do other things.