Open elhennig opened 5 months ago
I think a systemd service was always a bit overkill for poweroff, and no doubt has been hopelessly broken by bookworm- if not due to be shortly, since it uses sysfs GPIO.
Might be worth trying to add:
dtoverlay=gpio-poweroff,gpiopin=17,active_low=0
To /boot/firmware/config.txt
uh... I can't remember if it needs to be active low or not 😬
Strange is, that is was working before the OS and kernel update. I will check /boot/firmware/config.txt anyway.
But I guess it is active_low. If I check the pin manually with
# while true; do pinctrl get 17; sleep 1 ;done
I get
17: ip pu | hi // GPIO17 = input 17: ip pu | hi // GPIO17 = input 17: ip pu | hi // GPIO17 = input 17: ip pu | hi // GPIO17 = input 17: ip pu | lo // GPIO17 = input 17: ip pu | lo // GPIO17 = input 17: ip pu | lo // GPIO17 = input 17: ip pu | lo // GPIO17 = input 17: ip pu | hi // GPIO17 = input 17: ip pu | hi // GPIO17 = input 17: ip pu | hi // GPIO17 = input 17: ip pu | hi // GPIO17 = input 17: ip pu | hi // GPIO17 = input 17: ip pu | hi // GPIO17 = input
with the lo values while pressing the button.
I did some more testing: Shutdown works if I set the PIN 4 explicitly on the shell: raspi-gpio set 4 op dl
The clean shutdown daemon confiuration look slike this:
trigger_pin=17 led_pin=17 poweroff_pin=4 hold_time=1 shutdown_delay=0 polling_rate=1
However if I press the switch the PIN 4 is not changed, only 17.
What is the correct setup: PIN 4 for shutdown and 17 for the restart trigger?
That looks right-
trigger_pin
is the external switchpoweroff_pin
is the IO pin that's asserted at the very end of a shutdown to cut the powerIf raspi-gpio set 4 op dl
immediately cuts power, then you'll need to add dtoverlay=gpio-poweroff,gpiopin=4,active_low=1
to /boot/firmware/config.txt
.
There's also a straight dtoverlay approach for the shutdown button, but it doesn't have any long-press or LED indicator functionality: https://github.com/raspberrypi/linux/blob/rpi-6.1.y/arch/arm/boot/dts/overlays/gpio-shutdown-overlay.dts
And from the docs:
Name: gpio-shutdown
Info: Initiates a shutdown when GPIO pin changes. The given GPIO pin
is configured as an input key that generates KEY_POWER events.
This event is handled by systemd-logind by initiating a
shutdown. Systemd versions older than 225 need an udev rule
enable listening to the input device:
ACTION!="REMOVE", SUBSYSTEM=="input", KERNEL=="event*", \
SUBSYSTEMS=="platform", DRIVERS=="gpio-keys", \
ATTRS{keys}=="116", TAG+="power-switch"
Alternatively this event can be handled also on systems without
systemd, just by traditional SysV init daemon. KEY_POWER event
(keycode 116) needs to be mapped to KeyboardSignal on console
and then kb::kbrequest inittab action which is triggered by
KeyboardSignal from console can be configured to issue system
shutdown. Steps for this configuration are:
Add following lines to the /etc/console-setup/remap.inc file:
# Key Power as special keypress
keycode 116 = KeyboardSignal
Then add following lines to /etc/inittab file:
# Action on special keypress (Key Power)
kb::kbrequest:/sbin/shutdown -t1 -a -h -P now
And finally reload configuration by calling following commands:
# dpkg-reconfigure console-setup
# service console-setup reload
# init q
This overlay only handles shutdown. After shutdown, the system
can be powered up again by driving GPIO3 low. The default
configuration uses GPIO3 with a pullup, so if you connect a
button between GPIO3 and GND (pin 5 and 6 on the 40-pin header),
you get a shutdown and power-up button. Please note that
Raspberry Pi 1 Model B rev 1 uses GPIO1 instead of GPIO3.
Load: dtoverlay=gpio-shutdown,<param>=<val>
Params: gpio_pin GPIO pin to trigger on (default 3)
For Raspberry Pi 1 Model B rev 1 set this
explicitly to value 1, e.g.:
dtoverlay=gpio-shutdown,gpio_pin=1
active_low When this is 1 (active low), a falling
edge generates a key down event and a
rising edge generates a key up event.
When this is 0 (active high), this is
reversed. The default is 1 (active low).
gpio_pull Desired pull-up/down state (off, down, up)
Default is "up".
Note that the default pin (GPIO3) has an
external pullup. Same applies for GPIO1
on Raspberry Pi 1 Model B rev 1.
debounce Specify the debounce interval in milliseconds
(default 100)
Name: gpio-poweroff
Info: Drives a GPIO high or low on poweroff (including halt). Using this
overlay interferes with the normal power-down sequence, preventing the
kernel from resetting the SoC (a necessary step in a normal power-off
or reboot). This also disables the ability to trigger a boot by driving
GPIO3 low.
The GPIO starts in an inactive state. At poweroff time it is driven
active for 100ms, then inactive for 100ms, then active again. It is
safe to remove the power at any point after the initial activation of
the GPIO.
Users of this overlay are required to provide an external mechanism to
switch off the power supply when signalled - failure to do so results
in a kernel BUG, increased power consumption and undefined behaviour.
Load: dtoverlay=gpio-poweroff,<param>=<val>
Params: gpiopin GPIO for signalling (default 26)
active_low Set if the power control device requires a
high->low transition to trigger a power-down.
Note that this will require the support of a
custom dt-blob.bin to prevent a power-down
during the boot process, and that a reboot
will also cause the pin to go low.
input Set if the gpio pin should be configured as
an input.
export Set to export the configured pin to sysfs
active_delay_ms Initial GPIO active period (default 100)
inactive_delay_ms Subsequent GPIO inactive period (default 100)
timeout_ms Specify (in ms) how long the kernel waits for
power-down before issuing a WARN (default 3000).
The straight power off is not really what I want. The question is then, why the shutdown daemon does not react on the PIN 17 lo signal. How can I debug the daemon script?
I found several problems with the bash script itself, with the outputs of raspi-gpio, that seem to have changed and some number comparison errors in if statements. Still I do have an error after fixing the script: The systems shuts down but comes up again immediately (at least for the bootloader, the red LED is on, the OS not available
with the outputs of raspi-gpio
Yup Bookworm has broken a whole lot, and I'm nearly 5 months in to trying to fix it all with no end in sight. The lack of sysfs GPIO (needed IIRC for the GPIO to do anything from bash after the system has torn everything else down) means this script probably isn't (easily) fixable. (Note: I haven't touched this code for ~5 years.)
The systems shuts down but comes up again immediately (at least for the bootloader, the red LED is on, the OS not available
Which on/off / power control board are you using?
The straight power off is not really what I want
Not sure what you mean- the mentioned dtoverlays - gpio-shutdown and gpio-poweroff, respectively:
Combined, they pretty much make this script obsolete. And it seems if you set a high debounce it'll give you a push-and-hold-to-shutdown to avoid any accidental triggers. The only thing missing is fancy LED wrangling, which there's probably a proper driver for too.
I am using the OnOffShim.
Do I understand right, that the dtoverlay triggers a real shutdown like the command "shutdown -h". What is the better overlay gpio-shutdown or gpio-poweroff in my case? In bullseye the pi completely shut down (red LED off). Can this be done with the overlay config?
What am I doing wrong if the pi immediately stops again after booting? Is this caused by active_low=0?
I use
dtoverlay=gpio-shutdown,gpio_pin=17,active_low=1,gpio_pull=up
and it works sufficiently good. Is it right, that I cannot trigger a startup without having cycled the power before?
You need to use both gpio-shutdown
which- and I may mangle terminology here- just acts like a real ACPI power button and gpio-poweroff
which toggles a pin to - hopefully - trigger your external board to cut the power completely.
OnOffShim, IIRC, then can latch the power back on when you press the button again.
So maybe:
dtoverlay=gpio-shutdown,gpio_pin=17,active_low=1,gpio_pull=up
dtoverlay=gpio-poweroff,gpiopin=4,active_low=1
Then OnOffShim will cycle the power for you. (Though only if you have the power connected via OnOffShim, if you use the Pi's power connector it can't work)
OK, will try the proposed config. Of course I use the power connector of the OnOffShim as I did before with bulleseye, too
EDIT: Works perfectly fine, now! Thanks a lot for your support.
@elhennig could you share the working config you ended up with?
EDIT:
Ok, so I read back a bit and adding the following from @Gadgetoid
dtoverlay=gpio-shutdown,gpio_pin=17,active_low=1,gpio_pull=up
dtoverlay=gpio-poweroff,gpiopin=4,active_low=1
... works, but it causes the pi to shutdown immediately. One super nice thing about the original implementation was the use of systemd's shutdown hooks to cause a clean shutdown. In my case a clean shutdown is definitely necessary.
Execing pinctrl set 4 op dl
causes power to be cut right away, so we just need to modify the scripts accordingly.
Here's my modification to the scripts to make a clean shutdown work with bookworm
/usr/lib/systemd/system-shutdown/gpio-shutoff
Don't forget to make it executable (I use 0750)
#!/usr/bin/bash
set -e
poweroff_pin="4"
if [ "$1" = "poweroff" ]; then
/usr/bin/pinctrl set "$poweroff_pin" op dl
fi
/usr/local/bin/onoff-shim-trigger
Don't forget to make it executable (I use 0750)
#!/usr/bin/bash
set -e
trigger_pin="17"
led_pin="17"
/usr/bin/pinctrl set "$trigger_pin" ip
power=$(/usr/bin/pinctrl get "$trigger_pin" | awk '{print $5}')
if [ "$power" = "hi" ]; then
switchtype="lo" # Momentary button
elif [ "$power" = "lo" ]; then
switchtype="hi" # Not a momentary button
else
echo "Failed getting trigger_pin=$trigger_pin value (got: '$power')"
exit 1
fi
until [ "$power" = "$switchtype" ]; do
power=$(/usr/bin/pinctrl get "$trigger_pin" | awk '{print $5}')
sleep 1
done
/usr/bin/pinctrl set "$led_pin" op
# Blink the LED
for iteration in 1 2 3 5 6 7 8; do
/usr/bin/pinctrl set "$led_pin" dl
sleep 0.2
/usr/bin/pinctrl set "$led_pin" dh
sleep 0.2
done
echo "Powering Off!"
/usr/bin/systemctl poweroff
/etc/systemd/system/onoff-trigger.service
[Unit]
Description=OnOff SHIM daemon
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/onoff-shim-trigger
Restart=on-failure
[Install]
WantedBy=multi-user.target
Then:
systemctl daemon-reload
systemctl enable --now onoff-shim-trigger
I moved the blinking to the trigger script because in my usecase a clean shutdown can take awhile as systemd stops services, and I wanted to give feedback to the button-pusher sooner.
Hello, excuse my abrupt writing. I had a similar problem on my Pi3 and OnOff-SHIM.
I think one of the causes of the trouble is that the number given to /sys/class/gpio was changed by bookwarm, and the other is that the format of the return value of raspi-gpio get was changed. So, it seems that the following two modifications in the code avoided the trouble.
/lib/systemd/system-shutdown/gpio-poweroff
poweroff_pin=516
led_pin=529
/user/bin/cleanshutd trigger_pin_low() {
raspi-gpio get $trigger_pin | grep -q "level=0 func=INPUT"
}
Please refer to the following.
Hi, I upgraded my raspberry pi 4 to bookworm and kernel 6.6 and even if the GPIO pin 17 is triggered the clean shutdown down does not respond or shutdown the raspberry pi anymore. I also changed the command from raspi-gpio to pinctrl as messages lead to the info the the command raspi-gpio is deprecated. Any idea how to debug this more or even better solve the issue?