Пытаюсь работать с GPIO на Cubieboard 2. С чтением и записью никаких проблем нет. Но кроме просто чтения хочется ещё и получать уведомления об изменении состояния на вводе без цикла со слипом и чтением. Судя по Documentation/gpio/sysfs.txt, для этого можно использовать poll()/epoll. Попробовал написать на go - не работает. После первого вызова epoll_wait() я сразу же получаю ивент EPOLLPRI и на этом всё. То есть при подаче сигнала на GPIO я внучную (cat /sys/class/gpio/gpioN/value) вижу, что значение меняется, но epoll_wait() висит.
Сначала я решил, что накосячил где-то в коде на go (всё-таки это вообще первая программа, которую я на нём пишу), загуглил примеры работы с GPIO при помощи epoll и нашёл вот этот пример:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <sys/types.h>
int main(int argc, char** argv) {
int n;
int epfd = epoll_create(1);
int fd = open("/sys/class/gpio/gpio99/value", O_RDWR | O_NONBLOCK);
printf("open returned %d: %s\n", fd, strerror(errno));
if(fd > 0) {
char buf = 0;
struct epoll_event ev;
struct epoll_event events;
ev.events = EPOLLPRI;
ev.data.fd = fd;
n = epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev);
printf("epoll_ctl returned %d: %s\n", n, strerror(errno));
while(1) {
n = epoll_wait(epfd, &events, 1, -1);
printf("epoll returned %d: %s\n", n, strerror(errno));
if(n > 0) {
n = lseek(fd, 0, SEEK_SET);
printf("seek %d bytes: %s\n", n, strerror(errno));
n = read(fd, &buf, 1);
printf("read %d bytes: %s\n", n, strerror(errno));
printf("buf = 0x%x\n", buf);
}
}
}
return(0);
}
Вопрос: в чём проблема? У меня только две версии: 1) нужный код для работы poll/epoll на GPIO ещё не портировали в мейнлайновое ядро; 2) A20 это не умеет аппаратно.
Дополнительный вопрос: как настроить встроенные pull-up/pull-down резисторы на GPIO? Судя по содержимому исходников файлов device tree, делать это нужно там. Но там все GPIO привязаны к каким-то конкретным устройствам, я не понял как сделать устройство «просто GPIO».
Версии ядра, на которых я пробовал: 4.1.6 и 4.3.0rc1 из состава fedora 22.