Kontroluj piny GPIO od C

9

Większość bibliotek, w wielu językach, interakcję z pinów GPIO poprzez /sys/class/gpio/export, /sys/class/gpio/import, /sys/class/gpio/gpio10/value, itd. Jednak jądro Linux docs jasno stwierdzić , że jest to sposób spuścizna robi rzeczy.

Jaki jest nieoczywisty sposób robienia rzeczy?

Jeśli dobrze rozumiem w przestrzeni jądra, użyłbym tych funkcji lub standardowych sterowników jądra do typowych zadań GPIO.

Czego miałbym użyć do przestrzeni użytkownika? Czy istnieje interfejs Sysfs dla nie-dziedzictwa?

PS: Wiem, że dokumenty jądra stwierdzają, że starszy interfejs oparty na liczbach całkowitych, choć uważany za przestarzały, jest nadal użyteczny ze względu na kompatybilność. Jednak nie jestem zainteresowany użyciem tego starszego kodu.

Simão Martins
źródło
1
Większość bibliotek NIE wchodzi w interakcje ze stykami GPIO, /sys/class/gpio/exportponieważ mają bezpośredni dostęp do sprzętu, chociaż MOGĄ korzystać z usług jądra. Z pewnością okres przejściowy WiringPi i AFAIK ma bezpośredni dostęp do rejestrów SoC.
Milliways,

Odpowiedzi:

0

Jak dotąd rozumiem, że (jak już wspomniano) interfejs sysfs jest przestarzały. Istnieją co najmniej dwa stosunkowo nowe interfejsy API C w przestrzeni użytkownika (przepraszam WiringPi i PiGpio). Wydaje się, że jeden lub oba mają etykietę libgpiod

Można je zainstalować na buster (ale nie jessie) za pomocą:

apt-get install gpiod libgpiod-dev libgpiod-doc

Nie jestem pewien co do rozciągania. Nie jestem również pewien, który interfejs API wymaga instalacji.

1) Pierwszy C API opiera się na /usr/include/linux/gpio.h, który przechowuje struktury danych i definiuje używane z wywołaniami systemowymi do interakcji z gpios. To jest napisane przez Linusa Walleij. Przykład tego interfejsu API pokazano poniżej i pochodzi on z wykładu Linusa Walleija wskazanego w komentarzach do kodu. Programy używające tego interfejsu API muszą mieć #include pokazane w poniższym przykładzie, ale nie muszą być kompilowane z żadnymi bibliotekami (AFAIK).

2) Drugi interfejs API języka C opiera się na /usr/include/gpiod.h, który zapewnia uproszczony interfejs, który streszcza konfigurację i obsługuje oraz umożliwia bez kontekstowe odczyty, zapisy i inne funkcje. Utrzymuje to Bartosz Golaszewski. Wprowadzenie do API znajduje się w niektórych slajdach Bartosz, które można znaleźć na:

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

Kilka dobrych przykładów używania tego interfejsu API można znaleźć na stronie:

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

Pamiętaj, że programy korzystające z tego interfejsu API muszą:

#include <gpiod.h>

i zostanie skompilowany z biblioteką -lgpiod (na przykład):

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

Udało mi się skompilować i uruchomić kilka przykładów.

** Istnieje interfejs API C ++ również dostarczony przez Bartosza Golaszewskiego, który zależy od /usr/include/gpiod.hpp. Jest to opakowanie C ++ oparte na C API i zależy od standardu C ++ 11.

Programy korzystające z tego interfejsu API muszą:

#include <gpiod.hpp>

Przykład użycia tego interfejsu API znajduje się na tych samych slajdach co interfejs API C.

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

Nie udało mi się jeszcze skompilować tych przykładów, ale podejrzewam, że jest jeszcze biblioteka, którą muszę odkryć.


Poniżej znajduje się przykładowy program do odczytu gpio wykorzystujący C API numer 1 z góry (ten autorstwa Linusa Walleij). Wielokrotnie czyta gpio 4 na / dev / gpiochip0 i wypisuje jego wartość.

/****
* 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;
}

Połącz z

gcc -o gpio-read gpio-read.c

Wykonać:

./gpio-read

To pokaże wartość określonego przesunięcia gpio co 0,25 sekundy.

użytkownik297954
źródło
Więc jaki jest interfejs API? Czy jest zainstalowany za pomocą apt-get install gpiod? Czy w środku są prototypy funkcji <linux/gpio.h>? Czy istnieje plik biblioteki, z którym można się połączyć?
Dmitrij Grigoriew