9

Most of the libraries, in multiple languages, interact with the GPIO pins via /sys/class/gpio/export, /sys/class/gpio/import, /sys/class/gpio/gpio10/value, etc. However the linux kernel docs clearly state that is the legacy way of doing things.

What is the non legacy way of doing things?

If I understand correctly in kernel space I would use these functions or standard kernel drivers for common GPIO tasks.

What would I use for user space? Is there a Sysfs interface for the non legacy?

PS: I aware the kernel docs state that the legacy integer-based interface although considered deprecated is still usable for compatibility reasons. However I'm not interested in using that legacy code.

  • 1
    Most libraries DO NOT interact with the GPIO pins via /sys/class/gpio/export they access the hardware directly, although they CAN use kernel services. Certainly WiringPi and AFAIK pigpiod directly access SoC registers. – Milliways Aug 19 '19 at 0:58
12

sysfs has been deprecated and has been replaced with libgpiod.

https://www.beyondlogic.org/an-introduction-to-chardev-gpio-and-libgpiod-on-the-raspberry-pi/

The interactions are with /dev/gpiochipx rather than /sys/class/gpio.

The only obvious improvement (to me) is that GPIO events now have a time-stamp.

| improve this answer | |
1

My understanding so far is that (as has been stated) the sysfs interface is deprecated. There are at least two relatively new C APIs in user space (apologies to WiringPi and PiGpio). One or both seem to have the label libgpiod

They can be installed on buster (but not jessie) with:

apt-get install gpiod libgpiod-dev libgpiod-doc

Not sure about stretch. Also not sure which API requires which installs.

1) The first C API relies on /usr/include/linux/gpio.h which holds data structures and defines used with system calls to interact with the gpios. This is written by Linus Walleij. An example of this API is shown below, and is derived from a talk by Linus Walleij indicated in the code comments. Programs using this API must have the #includes shown in the example below but don't need to be compiled with any libraries (AFAIK).

2) The second C API relies on /usr/include/gpiod.h which provides a simplified interface that abstracts setup and handles and allows contextless reads, writes, and other functions. This is maintained by Bartosz Golaszewski. An introduction to the API is given in some slides by Bartosz which can be found at:

https://ostconf.com/system/attachments/files/000/001/532/original/Linux_Piter_2018_-_New_GPIO_interface_for_linux_userspace.pdf?1541021776

Some good examples using this API can be found at:

https://framagit.org/cpb/example-programs-using-libgpiod/-/tree/master/

Note that programs using this API must:

#include <gpiod.h>

and be compiled with the -lgpiod library (for example):

gcc -o read-gpio -lgpiod read-gpio.c

I've successfully compiled and run some of the examples.

** There is a C++ API also provided by Bartosz Golaszewski that depends on /usr/include/gpiod.hpp. It is a C++ a wrapper based on the C API and depends on the C++11 standard.

Programs using this API must:

#include <gpiod.hpp>

An example of using this API is found in the same slides as the C API.

https://ostconf.com/system/attachments/files/000/001/532/original/Linux_Piter_2018_-_New_GPIO_interface_for_linux_userspace.pdf?1541021776

I have yet to get these examples to compile, but suspect there is a library inclusion I have yet to discover.


Below is an example gpio read program using the C API number 1 from above (the one authored by Linus Walleij). It repeatedly reads gpio 4 on /dev/gpiochip0 and prints it's value.

/****
* gpio-read.c -- example program for reading gpio values using the <linux/gpio.h> C API
* The API consists primarily of data structures used as parameters to system calls.
* Adapted from from a youtube video of Linus Walleij at the Embedded Linux Conference Europe
* GPIO for Engineers and Makers: starting at timestamp 44:11
* For simplicity, there is no error checking.
****/

//Need the gpio API and support for the system calls.
#include <linux/gpio.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <string.h>
#include <unistd.h>


int main(){


//Opening device and getting file descriptor.
int fd = open("/dev/gpiochip0",O_RDONLY);

//structure for holding chip information
//This structure is defined in /usr/include/linux/gpio.h
struct gpiochip_info cinfo;

//Getting the chip information via the ioctl system call
//GPIO_GET_CHIPINFO_IOCTL defined also in /usr/include/linux/gpio.h
int ret = ioctl(fd,GPIO_GET_CHIPINFO_IOCTL,&cinfo);

//print out the chip information
fprintf(stdout, "GPIO chip: %s, \"%s\", %u GPIO lines\n",
    cinfo.name, cinfo.label, cinfo.lines);

//structure for holding line information.
//structure defined in /usr/include/linux/gpio.h
struct gpioline_info linfo;

//get generic line information from system call
ret = ioctl(fd,GPIO_GET_LINEINFO_IOCTL, &linfo);

//Not sure what this line_offset is, but we specify the gpio number later.
fprintf(stdout,"line %2d: %s\n",linfo.line_offset,linfo.name);

//Reading lines
//Set up some handles for requests and data
struct gpiohandle_request req;
struct gpiohandle_data data;

//Although req and data can read multiple gpios at a time, we'll use just one
//This reads line offset 4, which corresponds to the BCM value in "gpio readall"
req.lineoffsets[0] = 4;
//have to indicate how many lines we are reading.
req.lines = 1;
//Make this an input request
req.flags = GPIOHANDLE_REQUEST_INPUT;

//Optionally give the line a name
strcpy(req.consumer_label, "First Switch");

//Get a line handle. Note that req.fd is provided a handle for the next ioctl. 
int lhfd = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);

//Loop with some delay that keeps checking the input and displaying the value
for(int ii = 0; ii < 1000; ++ii){

    ret = ioctl(req.fd,  GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);

    printf("line %d is %s\n",req.lineoffsets[0], data.values[0] ? "high" : "low");
    //wait 0.25 seconds
    usleep(250000);
}

return 0;
}

Compile with

gcc -o gpio-read gpio-read.c

Execute:

./gpio-read

This will show the value of the specific gpio offset every 0.25 seconds.

| improve this answer | |
  • So, what's the API? Is it installed using apt-get install gpiod? Are function prototypes inside <linux/gpio.h>? Is there a library file to link against? – Dmitry Grigoryev Apr 26 at 12:53
  • 1
    See my revised answer above. It discusses two C APIs. – gorlux May 20 at 4:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.