BeagleBone Black w/ libgpiod's gpio-manager / gpiocli

I’ve used quite a few different Beagle boards in various projects over the years, but was recently asked to update a BBB to run on a modern image (Debian 13.5 w/ v6.18 kernel). Figured no big deal… but quickly came across the GPIO change from sysfs to libgpiod, and the non-persistent state of I/Os when using libgpiod. Did some searching on these forums, and found discussion of building custom overlays, using gpio-led/gpio-keys, etc.

While doable, that seemed excessive to just set/read a couple GPIOs. Since gpioset and gpioget worked (only) while the process was running, I thought maybe I should write a daemon that’s always running, to handle all GPIO. But I figured I wasn’t the first to think of this - and it turns out libgpiod has the gpio-manager daemon, and a gpiocli utility to use it ( D-Bus interface — libgpiod 2.3+devel documentation ).

Unfortunately, it looks like the default BBB image doesn’t have libgpiod built with gpio-manager enabled. But it was very simple to rebuild from source, with (I think) --enable-dbus and --enable-systemd build options.

Anyway, from the testing that I’ve done so far, this seems to do the basic GPIO stuff I need. In all the GPIO discussion I saw on these forums, I didn’t see gpio-manager mentioned at all. So I guess the point of this post is:

  1. Mention that gpio-manager exists, in case it’s also helpful to anyone else.

  2. Discuss advantages / disadvantages of gpio-manager vs. other solutions. I haven’t used it extensively yet, so I’m no expert - definitely interested to hear what others have to say.
    Advantages: Easy to use. Allows reconfiguration from userspace.
    Disadvantages: Probably slower to set or read pins than direct register access.
    Anything I’m missing?

  3. Suggest / request that libgpiod gets built in the default image with gpio-manager support enabled (even if the service is disabled by default).

Thanks,
Pat

1 Like

Hi there!

I can’t help thinking that gpio-manager could just be a package, waiting to be installed.

Further, most of the time, what you see isn’t gpios as such being read or written,
it is the manipulation of the pinmux system that governs what the pins do in reality.

libgpio has absolutely no say in what function gets control of the physical balls on the package.

That being said, I had no personal knowledge of gpio-manager, so that’s interesting.

Thank you for chiming in!

Maybe a little more background -

Using libgpiod command line tools already built into the standard image, I’m able to use commands like gpioget and gpioset:

Those utilities can set a pin as an output, input, etc. But they only control the pin while the process is active. I.e. gpioset "P9_27"=1 sets pin P9_27 as an output, and logic high. The gpioset program continues to run, maintaining control of the pin. As soon as you Ctrl+C the program, control of the pin is released, and it goes back to whatever the default pin state is. Similarly, if you run gpioget “P9_27” it’ll set the pin as an input and output “P9_27”=inactive (or active) and then release control of the pin.

If you only need to set the pin once, I guess you could run gpioset “P9_27”=1 & to kick it off as a background process, or you could have something track the processes and kill / start a new one every time you want to change… but that’s really hacky.

What gpio-manager does is runs as a daemon that you can request control of pins from. So, you start by doing gpiocli request --input “P9_27” to take control of the pin as an input. This returns a request number (e.g. request0). Then you can do gpiocli get “P9_27” and it’ll respond with “P9_27”=inactive (or active). You can then release the pin by using gpiocli release request0 .

Similarly, you can set it as an output with gpiocli request --output “P9_27” . Then gpiocli set “P9_27”=1 will output logic high. Unlike gpioset - using gpiocli with gpio-manager doesn’t require keeping that process open to maintain control of the pin. So you can then simply call gpiocli set “P9_27”=0 to toggle it low.

At least for basic tasks, it seems easy to use and “just works”. And gpio-manager actually has a D-Bus interface, so you can also control it from Python, C++, etc… gpiocli just provides a simple command line control over the D-Bus interface.

Since the 6.x kernel seems to have “chosen” libgpiod, gpio-manager seems like a good choice for managing GPIO, since I’d expect that to have more support and longevity than a one-off project that someone throws together to solve whatever current problem they’re working on.

Sure, but ultimately you’d want to control those GPIO’s from Python, C, C++ anyway,
so why introduce the intermediary?
Anything you can ask gpio-manager to do, you can do by talking to libgpiod directly;
that is what gpioget/set does. Am I missing something here?

Sure, you can use d-bus, if that’s your thing. It just sounds like a detour,
when you can include gpiod, either dynamically or statically and be done.

This is all great to know, and useful for testing and tinkering. But I think I have tried this, and unfortunately found it didn’t let me do everything I needed it to. I’d be interested to know the results of testing out your approach on all 73/4 pins(*) .

In my experience it’s not just a case of claiming a GPIO pin, it can also be a case of disabling something else that’s already claimed it.

DeviceTree and DTBO files definitely require a time investment, and the Beagle community would benefit greatly from a nicer, friendlier, config tool for it IMHO (have those GSoC projects been finalised already?).

But one issue that confused me at first, was that by default, in the main images, other things on the board may have already grabbed certain pins, and a DTBO lets you manage the clashes a lot more explicitly.

E.g. the eMMC and hdmi take up a lot of P8 pins and may need disabling, in /boot/uEnv.txt at least. Also, via a DTBO, certain pins can be configured for OneWire, the PWM pins, the I2C buses, and from there work natively with Linux device drivers. Other Linux devices too, that have nothing to do with GPIO, simply must be configured in a dtbo anyway.

(*) (2 * 46 minus the 10 power/ ground etc., minus the 9 analogue ones, optionally plus the dual purpose P9_42)

Anything you can ask gpio-manager to do, you can do by talking to libgpiod directly;
that is what gpioget/set does. Am I missing something here?

Only sorta… that’s the whole point of gpio-manager. If you try using gpioset, you’ll see that it sets the pin as an output and sets the state… then gpioset continues to run. When you kill that process, the GPIO pin reverts to its default state. The same thing happens if you have your own program that writes the GPIO - once your program exits, the GPIO state reverts (ridiculous, but someone up the chain decided that makes sense).

Unlike the old sysfs where you could write the GPIO to a state and it’d hold until re-written (i.e. you’re actually writing the hardware register), now there’s a GPIO character device, which is only controlled while the process has it open. So gpio-manager is a process that continuously holds the GPIO character device… that way every one of your processes that wants GPIO access doesn’t have to run indefinitely to keep it open.

Here’s a video that the creator of gpio-manager did, discussing some of this. But basically, the title “Give Me Back My GPIO Persistence!” is a pretty good summary.

In my experience it’s not just a case of claiming a GPIO pin, it can also be a case of disabling something else that’s already claimed it.

Yes, that’s always been a thing, and still is - but IMO, it’s pretty simple to modify uEnv.txt to disable overlays. Making your own device tree overlay, hard-coding your GPIOs as inputs or outputs, then shoehorning it into gpio-leds or gpio-keys (common solution) isn’t user friendly, isn’t flexible, and IMO is a hack.

And to clarify, by using v6.xx kernel, we’re basically stuck with libgpiod. Using gpio-manager doesn’t change that - using libgpiod, you need to disable any conflicting overlays, you need to claim a pin, etc. You can see every pin and its status by running gpioinfo. E.g.

Unused input:
line 19: “P9_27” input

Input that I’m using:
line 21: “P9_25” input consumer=“gpio-manager”

BBB User LED:
line 24: “[usr3 led]” output consumer=“beaglebone:green:usr3”

Using gpio-manager just simplifies keeping the pins persistent (making it more like a hardware register that you can set and forget).

as far as i’m aware this is only in the 2.3 development branch… Right now 2.2.4 is the latest tagged version.. we have ci runners if we want to package it, but 2.3.0 has had a ton of changes since 2.2.x that we’d all love to use..

Regards,

There has been quite a bit of discussion of persistent pinmux settings on boot via device tree overlay and custom kernels. Do you know if gpio-manager has the ability to change pinmux settings dynamically from user space?

https://forum.beagleboard.org/t/problem-setting-pin-modes-and-configurations-using-a-device-tree-overlay/43978/10

https://forum.beagleboard.org/t/compiling-custom-linux-kernel-for-beaglebone-black-industrial-6-18-16-bone23/43852

https://forum.beagleboard.org/t/am335xussetpm-user-space-device-driver/43877

it should be in v2.2… https://static.sched.com/hosted_files/osseu2024/02/Introducing%20the%20gpio-manager.pdf

gpiodetect --version
gpiodetect (libgpiod) v2.2.1

Seem I tried this with gpiod_line_settings_set_direction with no luck. This is what started the whole pinmux hacking journey. The functions to change the pinmux mode are there but do not work. ???

Will be very interesting to see, once 2.3 moves from devel to stable.

Altho, I don’t really consider setting direction == setting pinmux function.

Will definitely save some small animals, once we can move from
fixed overlays to dynamic control ..:wink:..

Good point, this is the function gpiod_line_settings_set_bias(settings, GPIOD_LINE_BIAS_PULL_UP);

I built it from the 2.2.4 tar: https://www.kernel.org/pub/software/libs/libgpiod/libgpiod-2.2.4.tar.xz , and it’s also discussed in the 2.2.4 documentation: D-Bus interface — libgpiod documentation .

Just looked back at the log, and it looks like this is the configure command I ran (probably didn’t need all the bindings, but wasn’t sure what I wanted yet):

./configure --enable-tools --enable-bindings-python --enable-bindings-cxx --enable-bindings-glib --enable-gpioset-interactive --enable-dbus --enable-systemd

Then I think it was just make and make install .

It certainly lets you change input/output dynamically from userspace… I haven’t messed with other settings - documentation says you can change pullup/down. I’d imagine it won’t remap a pin to a different function (e.g. remapping GPIO to UART or whatever other functions that pin has).

backport added… libgpiod (2.2.3-1bbbio0) · beagleboard/repos-armhf@a8011e1 · GitHub next lets try enabling the new options…

and pushed: libgpiod (2.2.3-1bbbio5) install gpiocli/gpio-manager under gpiod · beagleboard/repos-armhf@b199e17 · GitHub

voodoo@21-am335x-bbb:~$ sudo systemctl status gpio-manager.service
× gpio-manager.service - Centralized GPIO manager daemon
     Loaded: loaded (/usr/lib/systemd/system/gpio-manager.service; enabled; preset: enabled)
     Active: failed (Result: exit-code) since Mon 2026-06-08 13:27:57 CDT; 19s ago
 Invocation: d8072be4b00642c29bcf16a6bcd36eac
    Process: 5099 ExecStart=/usr/bin/gpio-manager (code=exited, status=217/USER)
   Main PID: 5099 (code=exited, status=217/USER)

Jun 08 13:27:57 21-am335x-bbb systemd[1]: gpio-manager.service: Scheduled restart job, restart counter is at 5.
Jun 08 13:27:57 21-am335x-bbb systemd[1]: gpio-manager.service: Start request repeated too quickly.
Jun 08 13:27:57 21-am335x-bbb systemd[1]: gpio-manager.service: Failed with result 'exit-code'.
Jun 08 13:27:57 21-am335x-bbb systemd[1]: Failed to start gpio-manager.service - Centralized GPIO manager daemon.
voodoo@21-am335x-bbb:~$ uname -r
6.12.92-bone61

Okay, lets’ look at it:

sudo cat /usr/lib/systemd/system/gpio-manager.service
# SPDX-License-Identifier: CC0-1.0
# SPDX-FileCopyrightText: 2023-2024 Bartosz Golaszewski <bartosz.golaszewski@linaro.org>

[Unit]
Description=Centralized GPIO manager daemon

[Service]
Type=dbus
BusName=io.gpiod1
ExecStart=/usr/bin/gpio-manager
Restart=always
User=gpio-manager

CapabilityBoundingSet=
ReadOnlyDirectories=/
NoNewPrivileges=yes
RemoveIPC=yes
PrivateTmp=yes
PrivateUsers=yes
ProtectControlGroups=yes
ProtectHome=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
ProtectSystem=strict
ProtectClock=yes
Delegate=no
IPAddressDeny=any
KeyringMode=private
LockPersonality=yes
MemoryDenyWriteExecute=yes
NotifyAccess=main
PrivateMounts=no
PrivateNetwork=no
ProtectHostname=yes
RestrictNamespaces=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
SystemCallFilter=~@clock
SystemCallFilter=~@cpu-emulation
SystemCallFilter=~@debug
SystemCallFilter=~@module
SystemCallFilter=~@mount
SystemCallFilter=~@obsolete
SystemCallFilter=~@privileged
SystemCallFilter=~@raw-io
SystemCallFilter=~@reboot
SystemCallFilter=~@swap

[Install]
WantedBy=multi-user.target
Jun 08 13:29:53 21-am335x-bbb systemd[1]: Starting gpio-manager.service - Centralized GPIO manager daemon...
Jun 08 13:29:54 21-am335x-bbb (-manager)[614]: gpio-manager.service: Failed to determine user credentials: No such process
Jun 08 13:29:54 21-am335x-bbb (-manager)[614]: gpio-manager.service: Failed at step USER spawning /usr/bin/gpio-manager: No such process
Jun 08 13:29:54 21-am335x-bbb systemd[1]: gpio-manager.service: Main process exited, code=exited, status=217/USER
Jun 08 13:29:54 21-am335x-bbb systemd[1]: gpio-manager.service: Failed with result 'exit-code'.
Jun 08 13:29:54 21-am335x-bbb systemd[1]: Failed to start gpio-manager.service - Centralized GPIO manager daemon.
Jun 08 13:29:55 21-am335x-bbb systemd[1]: gpio-manager.service: Scheduled restart job, restart counter is at 5.
Jun 08 13:29:55 21-am335x-bbb systemd[1]: gpio-manager.service: Start request repeated too quickly.
Jun 08 13:29:55 21-am335x-bbb systemd[1]: gpio-manager.service: Failed with result 'exit-code'.

Should we stay with upstream with teh User=gpio-manager or map to User=gpio

Closer…

sudo useradd --system -M -s /usr/sbin/nologin -g gpio gpio-manager

Closer:

voodoo@21-am335x-bbb:~$ sudo systemctl status gpio-manager.service
● gpio-manager.service - Centralized GPIO manager daemon
     Loaded: loaded (/usr/lib/systemd/system/gpio-manager.service; enabled; preset: enabled)
     Active: active (running) since Mon 2026-06-08 15:54:05 CDT; 2min 50s ago
 Invocation: b095657bbdf345688b5e207a8556b42a
   Main PID: 477 (gpio-manager)
      Tasks: 4 (limit: 1012)
     Memory: 4.2M (peak: 4.5M)
        CPU: 808ms
     CGroup: /system.slice/gpio-manager.service
             └─477 /usr/bin/gpio-manager

Jun 08 15:53:58 21-am335x-bbb systemd[1]: Starting gpio-manager.service - Centralized GPIO manager daemon...
Jun 08 15:54:03 21-am335x-bbb gpio-manager[477]: initializing gpio-manager
Jun 08 15:54:03 21-am335x-bbb gpio-manager[477]: gpio-manager started
Jun 08 15:54:04 21-am335x-bbb gpio-manager[477]: failed to open GPIO chip /dev/gpiochip0: unable to open GPIO chip '/dev/gpiochip0': Permission denied
Jun 08 15:54:04 21-am335x-bbb gpio-manager[477]: failed to open GPIO chip /dev/gpiochip1: unable to open GPIO chip '/dev/gpiochip1': Permission denied
Jun 08 15:54:04 21-am335x-bbb gpio-manager[477]: failed to open GPIO chip /dev/gpiochip2: unable to open GPIO chip '/dev/gpiochip2': Permission denied
Jun 08 15:54:05 21-am335x-bbb systemd[1]: Started gpio-manager.service - Centralized GPIO manager daemon.
voodoo@21-am335x-bbb:~$ sudo udevadm info /dev/gpiochip0 
P: /devices/platform/ocp/48000000.interconnect/48000000.interconnect:segment@0/4804c000.target-module/4804c000.gpio/gpiochip0
M: gpiochip0
R: 0
J: c254:0
U: gpio
T: gpio_chip
D: c 254:0
N: gpiochip0
L: 0
E: DEVPATH=/devices/platform/ocp/48000000.interconnect/48000000.interconnect:segment@0/4804c000.target-module/4804c000.gpio/gpiochip0
E: DEVNAME=/dev/gpiochip0
E: DEVTYPE=gpio_chip
E: OF_NAME=gpio
E: OF_FULLNAME=/ocp/interconnect@48000000/segment@0/target-module@4c000/gpio@0
E: OF_COMPATIBLE_0=ti,omap4-gpio
E: OF_COMPATIBLE_N=1
E: MAJOR=254
E: MINOR=0
E: SUBSYSTEM=gpio

voodoo@21-am335x-bbb:~$ ls -lha /dev/gpiochip*
crw-rw---- 1 root gpio 254, 0 Jun  8 15:54 /dev/gpiochip0
crw-rw---- 1 root gpio 254, 1 Jun  8 15:54 /dev/gpiochip1
crw-rw---- 1 root gpio 254, 2 Jun  8 15:54 /dev/gpiochip2
crw-rw---- 1 root gpio 254, 3 Jun  8 15:53 /dev/gpiochip3
voodoo@21-am335x-bbb:~$ cat /etc/udev/rules.d/
10-of-symlink.rules             81-add-SoftAp0-interface.rules  83-counter-noroot.rules         87-iio-noroot.rules             
61-smsc95xx-mac-address.rules   81-pwm-noroot.rules             85-gpio-noroot.rules            88-leds-noroot.rules            
80-gpio-noroot.rules            82-gpio-config-pin.rules        86-remoteproc-noroot.rules      uio-pruss.rules                 
80-i2c-noroot.rules             82-SoftAp0-start-hostpad.rules  86-rpmsg-noroot.rules           uio.rules                       
voodoo@21-am335x-bbb:~$ cat /etc/udev/rules.d/85-gpio-noroot.rules 
# /etc/udev/rules.d/85-gpio-noroot.rules
#
# Corrects sys GPIO permissions on the BB so non-root users in the gpio group can manipulate bits
#

###needed for gpioinfo and friends...
###Before
###debian@bbb-pwr01-ser09:~$ ls -lha /dev/gpiochip*
###crw-rw---- 1 root root 254, 0 Jul  9 00:01 /dev/gpiochip0
###crw-rw---- 1 root root 254, 1 Jul  9 00:01 /dev/gpiochip1
###crw-rw---- 1 root root 254, 2 Jul  9 00:01 /dev/gpiochip2
###crw-rw---- 1 root root 254, 3 Jul  9 00:01 /dev/gpiochip3
###After
###debian@bbb-pwr01-ser09:~$ ls -lha /dev/gpiochip*
###crw-rw---- 1 root gpio 254, 0 Jul  9 00:01 /dev/gpiochip0
###crw-rw---- 1 root gpio 254, 1 Jul  9 00:01 /dev/gpiochip1
###crw-rw---- 1 root gpio 254, 2 Jul  9 00:01 /dev/gpiochip2
###crw-rw---- 1 root gpio 254, 3 Jul  9 00:01 /dev/gpiochip3

KERNEL=="gpiochip*", SUBSYSTEM=="gpio", MODE="0660", GROUP="gpio"
voodoo@21-am335x-bbb:~$ cat /usr/lib/*/udev/rules.d/90-gpio.rules
# SPDX-License-Identifier: CC0-1.0
# SPDX-FileCopyrightText: 2024 Bartosz Golaszewski <bartosz.golaszewski@linaro.org>

SUBSYSTEM=="gpio", KERNEL=="gpiochip[0-9]*", GROUP="gpio", MODE="0660"

Looks like a delay..

voodoo@21-am335x-bbb:~$ sudo systemctl restart gpio-manager.service
voodoo@21-am335x-bbb:~$ sudo systemctl status gpio-manager.service
● gpio-manager.service - Centralized GPIO manager daemon
     Loaded: loaded (/usr/lib/systemd/system/gpio-manager.service; enabled; preset: enabled)
     Active: active (running) since Mon 2026-06-08 16:00:42 CDT; 2s ago
 Invocation: b7f3da64abb54008a90147f3b920577d
   Main PID: 1122 (gpio-manager)
      Tasks: 5 (limit: 1012)
     Memory: 908K (peak: 1.3M)
        CPU: 667ms
     CGroup: /system.slice/gpio-manager.service
             └─1122 /usr/bin/gpio-manager

Jun 08 16:00:41 21-am335x-bbb systemd[1]: Starting gpio-manager.service - Centralized GPIO manager daemon...
Jun 08 16:00:41 21-am335x-bbb gpio-manager[1122]: initializing gpio-manager
Jun 08 16:00:41 21-am335x-bbb gpio-manager[1122]: gpio-manager started
Jun 08 16:00:42 21-am335x-bbb systemd[1]: Started gpio-manager.service - Centralized GPIO manager daemon.

Amazing!

new user should be added now: libgpiod (2.2.3-1bbbio6) setup gpio-monitor user · beagleboard/repos-armhf@e5e1ff1 · GitHub testing on a fresh board..

voodoo@23-am335x-bbb:~$ sudo apt-get dist-upgrade -y
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Calculating upgrade... Done
The following NEW packages will be installed:
  libgudev-1.0-0
The following packages will be upgraded:
  gpiod libgpiod-dev libgpiod3 python3-libgpiod
4 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 346 kB of archives.
After this operation, 663 kB of additional disk space will be used.
Get:1 http://192.168.1.10/debian trixie/main armhf libgudev-1.0-0 armhf 238-6 [12.7 kB]
Get:2 https://rcn-ee.com/repos/debian-trixie-armhf trixie/main armhf libgpiod-dev armhf 2.2.3-1bbbio6~trixie+20260608 [131 kB]
Get:3 https://rcn-ee.com/repos/debian-trixie-armhf trixie/main armhf python3-libgpiod armhf 2.2.3-1bbbio6~trixie+20260608 [32.0 kB]
Get:4 https://rcn-ee.com/repos/debian-trixie-armhf trixie/main armhf libgpiod3 armhf 2.2.3-1bbbio6~trixie+20260608 [89.3 kB]
Get:5 https://rcn-ee.com/repos/debian-trixie-armhf trixie/main armhf gpiod armhf 2.2.3-1bbbio6~trixie+20260608 [81.7 kB]
Fetched 346 kB in 1s (381 kB/s)
(Reading database ... 39882 files and directories currently installed.)
Preparing to unpack .../libgpiod-dev_2.2.3-1bbbio6~trixie+20260608_armhf.deb ...
Unpacking libgpiod-dev:armhf (2.2.3-1bbbio6~trixie+20260608) over (2.2.1-2+deb13u1) ...
Preparing to unpack .../python3-libgpiod_2.2.3-1bbbio6~trixie+20260608_armhf.deb ...
Unpacking python3-libgpiod (2.2.3-1bbbio6~trixie+20260608) over (2.2.1-2+deb13u1) ...
Preparing to unpack .../libgpiod3_2.2.3-1bbbio6~trixie+20260608_armhf.deb ...
Unpacking libgpiod3:armhf (2.2.3-1bbbio6~trixie+20260608) over (2.2.1-2+deb13u1) ...
Selecting previously unselected package libgudev-1.0-0:armhf.
Preparing to unpack .../libgudev-1.0-0_238-6_armhf.deb ...
Unpacking libgudev-1.0-0:armhf (238-6) ...
Preparing to unpack .../gpiod_2.2.3-1bbbio6~trixie+20260608_armhf.deb ...
Unpacking gpiod (2.2.3-1bbbio6~trixie+20260608) over (2.2.1-2+deb13u1) ...
Setting up libgpiod3:armhf (2.2.3-1bbbio6~trixie+20260608) ...
Setting up libgudev-1.0-0:armhf (238-6) ...
Setting up python3-libgpiod (2.2.3-1bbbio6~trixie+20260608) ...
Setting up libgpiod-dev:armhf (2.2.3-1bbbio6~trixie+20260608) ...
Setting up gpiod (2.2.3-1bbbio6~trixie+20260608) ...
Created symlink '/etc/systemd/system/multi-user.target.wants/gpio-manager.service' → '/usr/lib/systemd/system/gpio-manager.service'.
Could not execute systemctl:  at /usr/bin/deb-systemd-invoke line 148.
Processing triggers for dbus (1.16.2-2) ...
Processing triggers for libc-bin (2.41-12+deb13u3) ...

Check new user:

voodoo@23-am335x-bbb:~$ getent group gpio 
gpio:x:991:voodoo
voodoo@23-am335x-bbb:~$ getent passwd gpio-monitor
gpio-monitor:x:997:991::/home/gpio-monitor:/usr/sbin/nologin

Still broken… time to hit the road..

voodoo@23-am335x-bbb:~$ sudo systemctl status gpio-manager.service
× gpio-manager.service - Centralized GPIO manager daemon
     Loaded: loaded (/usr/lib/systemd/system/gpio-manager.service; enabled; preset: enabled)
     Active: failed (Result: exit-code) since Mon 2026-06-08 16:40:03 CDT; 1min 1s ago
 Invocation: 083f036b5c3c4abe86ffcad8214974ff
    Process: 588 ExecStart=/usr/bin/gpio-manager (code=exited, status=217/USER)
   Main PID: 588 (code=exited, status=217/USER)

Jun 08 16:40:03 23-am335x-bbb systemd[1]: gpio-manager.service: Scheduled restart job, restart counter is at 5.
Jun 08 16:40:03 23-am335x-bbb systemd[1]: gpio-manager.service: Start request repeated too quickly.
Jun 08 16:40:03 23-am335x-bbb systemd[1]: gpio-manager.service: Failed with result 'exit-code'.
Jun 08 16:40:03 23-am335x-bbb systemd[1]: Failed to start gpio-manager.service - Centralized GPIO manager daemon.
Jun 08 16:42:37 23-am335x-bbb (-manager)[1037]: gpio-manager.service: Failed to determine user credentials: No such process
Jun 08 16:42:37 23-am335x-bbb (-manager)[1037]: gpio-manager.service: Failed at step USER spawning /usr/bin/gpio-manager: No such process

Thanks for looking into this… looks like you’re making great progress!

Not sure if that was a typo or intentional, but I see you set up a user gpio-monitor, instead of gpio-manager. Though I personally just used the gpio group.

I think you already mentioned this above, but in mine, I put ExecStartPre=/bin/sleep 5 in my service to give the udev rules some time to work before starting the service. Also, probably specific to my configuration, but my udev rules ended up getting clobbered by openFPGALoader’s udev rules, which gave the gpio subsystem to the plugdev group.

And not sure if they’re helpful to you or anyone else, but I believe I used these links for reference when setting this up.

Pat

Doh, that was me! fixed user… libgpiod (2.2.3-1bbbio7) setup correct gpio-manager user · beagleboard/repos-armhf@bac0410 · GitHub wonder if we need systemd depend on udev on startup..

voodoo@24-am335x-bbb:~$ getent group gpio 
gpio:x:991:voodoo
voodoo@24-am335x-bbb:~$ getent passwd gpio-manager
gpio-manager:x:997:991::/home/gpio-manager:/usr/sbin/nologin
voodoo@24-am335x-bbb:~$ sudo systemctl status gpio-manager.service
● gpio-manager.service - Centralized GPIO manager daemon
     Loaded: loaded (/usr/lib/systemd/system/gpio-manager.service; enabled; preset: enabled)
     Active: active (running) since Tue 2026-06-09 09:29:15 CDT; 1min 46s ago
 Invocation: d50b0ac9a3d84eeaa856417765181010
   Main PID: 479 (gpio-manager)
      Tasks: 4 (limit: 1097)
     Memory: 4M (peak: 4.1M)
        CPU: 877ms
     CGroup: /system.slice/gpio-manager.service
             └─479 /usr/bin/gpio-manager

Jun 09 09:29:09 24-am335x-bbb systemd[1]: Starting gpio-manager.service - Centralized GPIO manager daemon...
Jun 09 09:29:14 24-am335x-bbb gpio-manager[479]: initializing gpio-manager
Jun 09 09:29:14 24-am335x-bbb gpio-manager[479]: gpio-manager started
Jun 09 09:29:15 24-am335x-bbb gpio-manager[479]: failed to open GPIO chip /dev/gpiochip0: unable to open GPIO chip '/dev/gpiochip0': Permission denied
Jun 09 09:29:15 24-am335x-bbb gpio-manager[479]: failed to open GPIO chip /dev/gpiochip1: unable to open GPIO chip '/dev/gpiochip1': Permission denied
Jun 09 09:29:15 24-am335x-bbb gpio-manager[479]: failed to open GPIO chip /dev/gpiochip2: unable to open GPIO chip '/dev/gpiochip2': Permission denied
Jun 09 09:29:15 24-am335x-bbb systemd[1]: Started gpio-manager.service - Centralized GPIO manager daemon.

Tried both of these to “wait”..

[Unit]
Description=Centralized GPIO manager daemon
After=dev-gpiochip*.device
Requires=dev-gpiochip*.device

Actually ^ this failed:

Jun 09 09:36:11 24-am335x-bbb systemd[1]: /usr/lib/systemd/system/gpio-manager.service:6: Failed to add dependency on dev-gpiochip*.device, ignoring: Invalid argument
Jun 09 09:36:11 24-am335x-bbb systemd[1]: /usr/lib/systemd/system/gpio-manager.service:7: Failed to add dependency on dev-gpiochip*.device, ignoring: Invalid argument
Jun 09 09:36:30 24-am335x-bbb systemd[1]: Starting gpio-manager.service - Centralized GPIO manager daemon...
[Unit]
Description=Centralized GPIO manager daemon
After=systemd-udevd.service
Wants=systemd-udevd.service
[Unit]
Description=Centralized GPIO manager daemon
After=dev-gpiochip0.device
Requires=dev-gpiochip0.device

Gives:

Jun 09 10:00:22 24-am335x-bbb kernel: omap_gpio 44e07000.gpio: Could not set line 6 debounce to 200000 microseconds (-22)
Jun 09 10:00:22 24-am335x-bbb systemd[1]: Expecting device dev-gpiochip0.device - /dev/gpiochip0...
Jun 09 10:01:46 24-am335x-bbb systemd[1]: dev-gpiochip0.device: Job dev-gpiochip0.device/start timed out.
Jun 09 10:01:46 24-am335x-bbb systemd[1]: Timed out waiting for device dev-gpiochip0.device - /dev/gpiochip0.
Jun 09 10:01:46 24-am335x-bbb systemd[1]: Dependency failed for gpio-manager.service - Centralized GPIO manager daemon.
Jun 09 10:01:46 24-am335x-bbb systemd[1]: gpio-manager.service: Job gpio-manager.service/start failed with result 'dependency'.
Jun 09 10:01:46 24-am335x-bbb systemd[1]: dev-gpiochip0.device: Job dev-gpiochip0.device/start failed with result 'timeout'.

this seems to work..

[Unit]
Description=Centralized GPIO manager daemon
After=multi-user.target
Wants=multi-user.target

Going to patch it and pull in 2.2.4 and above changes..

So 8th build, test board #5

voodoo@25-am335x-bbb:~$ sudo systemctl status gpio-manager.service 
● gpio-manager.service - Centralized GPIO manager daemon
     Loaded: loaded (/usr/lib/systemd/system/gpio-manager.service; enabled; preset: enabled)
     Active: active (running) since Tue 2026-06-09 14:56:17 CDT; 16s ago
 Invocation: c26ecb987ed04db5be539ba507401560
   Main PID: 876 (gpio-manager)
      Tasks: 4 (limit: 1097)
     Memory: 1.3M (peak: 1.4M)
        CPU: 862ms
     CGroup: /system.slice/gpio-manager.service
             └─876 /usr/bin/gpio-manager

Jun 09 14:56:14 25-am335x-bbb systemd[1]: Starting gpio-manager.service - Centralized GPIO manager daemon...
Jun 09 14:56:15 25-am335x-bbb gpio-manager[876]: initializing gpio-manager
Jun 09 14:56:15 25-am335x-bbb gpio-manager[876]: gpio-manager started
Jun 09 14:56:17 25-am335x-bbb systemd[1]: Started gpio-manager.service - Centralized GPIO manager daemon.

Clean apt install, reboot… working…

1 Like