Problems migrating a working 1-Wire library in C on Debian Linux from wiringOP to libgpiod

185 Views Asked by At

I managed 1-Wire access to DS18B20 temperature sensors in pure C from userland on a Orange Pi Zero 2, operated by Debian Bullseye.

I learned wiringOP is no more maintained and would like to switch to libgpiod. I managed to address the GPIO lines using libgpiod as expected. Then I replaced in my 1-Wire test program all GPIO calls to the wiringOP lib by the respective calls to the libgpiod like follows:

pinMode(pin, OUTPUT); -> gpiod_line_request_output(gpioline, "gpio");
digitalWrite(pin, LOW); -> gpiod_line_set_value(gpioline, 0);
pinMode(pin, INPUT); -> gpiod_line_request_input(gpioline, "gpio");
bit = digitalRead(pin); -> bit = gpiod_line_get_value(gpioline);

I am aware that the pin/line number scheme of wiringOP is different from libgpiod. In my case the repective wPi pin number is 16 while the GPIO line number is 74. As I said, I verified that mere GPIO access is working either way.

Now 1-Wire does not work with libgpiod while it does work perfectly with wiringOP. I had some troubles to get the timing straight until I ported delayMicroseconds() from wiringOP into my user land program. This works now and is not different from the same program using libgpiod.

What am I missing?

Do calls to libgpiod have a huge overhead, I mean more than a mircosecond until lines become switched - this would spoil any use with 1-Wire, actually any bit-banging would be difficult.

Are there any maintained alternatives to wiringOP?

PS: WiringOP is the fork of WiringPi adapted to the Orange Pi series of SBC's

PPS: In the meantime I checked my very 1-Wire test program on a Raspberry Pi 4B operated by FreeBSD 13.2. Here I simply replaced the calls to the wiringOP library by the respective calls to FreeBSD's GPIO library. It worked out of the box. This lets me conclude that something is seriously flawed with Linux's libgpiod.

1

There are 1 best solutions below

13
On

Any library that accesses hardware via the kernel will be slower than directly accessing the hardware via memory mapped registers, which is what libraries like wiringOP and wiringPi do.

That is also why they are hardware specific, whereas libgpiod is generic.

For libgpiod the hardware is accessed via kernel ioctl calls, which at the very least involve a context switch and are going be to orders of magnitude slower than directly writing to a hardware register.

e.g. on a Pi Zero setting a line with libgpiod takes around 4us. On a Pi4, which you used for your FreeBSD testing, it is less than 1us. Have you tried your libgpiod code on a Pi4?

That doesn't make it useless for bitbanging, I've used it for bitbanging I2C and SPI on the Pi, but it does limit the rate for which it is viable.

If you need to drive lines faster than that then libgpiod is not the tool for you. That doesn't mean libgpiod is flawed, though, it means it has to operate under constraints that make it inappropriate for your application.

Would the 1-wire subsystem be a better fit?

Both libgpiod and the kernel are open source, so if you feel you can improve them then you are welcome to contribute. Or you could always take on supporting wiringOP, if you can't find an alternative.