Poll() для отслеживания булавки на BeagleBone Black. Непрерывный вывод, даже если контакт не подключен.

Я хочу инициировать событие всякий раз, когда на одном из контактов Beaglebone Black появляется нарастающий фронт. Проблема в том, что хотя я ни к чему не подключал этот контакт, вывод просто продолжает печатать, произошло прерывание, произошло прерывание. Я наткнулся на вопрос Прерывания в Beaglebone в stackoverflow и попытался выполнить шаги. Была ссылка на Программу, реализующую функциональность. Я читал о poll() и внес небольшие изменения в программу, так как хочу контролировать только один пин. Измененный код:

int main(int argc, char **argv, char **envp)
{
struct pollfd fdset[1];  // fdset[2] changed to fdset[1] since I will monitor just 1 pin
int nfds = 1;            // nfds changed from 2 to 1
int gpio_fd, timeout, rc;
char *buf[MAX_BUF];
unsigned int gpio;
int len;



if (argc < 2) {
    printf("Usage: gpio-int <gpio-pin>\n\n");
    printf("Waits for a change in the GPIO pin voltage level or input on stdin\n");
    exit(-1);
}

gpio = atoi(argv[1]);

gpio_export(gpio);
gpio_set_dir(gpio, 0);
gpio_set_edge(gpio, "rising");
gpio_fd = gpio_fd_open(gpio);

timeout = POLL_TIMEOUT;

while (1) {
    memset((void*)fdset, 0, sizeof(fdset));

    fdset[0].fd = gpio_fd;                 // This is the pin to be monitored
    fdset[0].events = POLLIN;

    //fdset[1].fd = gpio_fd;               // commented since I do not need this
    //fdset[1].events = POLLPRI;

    rc = poll(fdset, nfds, timeout);      

    if (rc < 0) {
        printf("\npoll() failed!\n");
        return -1;
    }

    if (rc == 0) {
        printf(".");
    }

    if (fdset[0].revents & POLLIN) {
        len = read(fdset[0].fd, buf, MAX_BUF);
        printf("\npoll() GPIO %d interrupt occurred\n", gpio);
    }

            // ****Commented block****
    //if (fdset[0].revents & POLLIN) {
    //  (void)read(fdset[0].fd, buf, 1);
    //  printf("\npoll() stdin read 0x%2.2X\n", (unsigned int) buf[0]);
    //}

    fflush(stdout);
}

gpio_fd_close(gpio_fd);
return 0;
}

Запуск Angstrom на Beaglebone black.


person sudhir vyasaraja    schedule 17.10.2013    source источник


Ответы (2)


https://www.kernel.org/doc/Documentation/gpio/sysfs.txt

Если контакт может быть сконфигурирован как прерывание, генерирующее прерывание, и если он был сконфигурирован для генерации прерываний (см. описание «края»), вы можете выполнить опрос (2) в этом файле, и опрос (2) будет возвращаться всякий раз, когда прерывание было сработал. Если вы используете poll(2), установите события POLLPRI и POLLERR. Если вы используете select(2), установите дескриптор файла в excludefds. После того, как poll(2) вернется, либо выполните lseek(2) в начало файла sysfs и прочитайте новое значение, либо закройте файл и снова откройте его, чтобы прочитать значение.

Вы не установили события POLLPRI и POLLERR.

struct pollfd fdset[1];
memset((void*)fdset, 0, sizeof(fdset));
fdset[0].fd = fd;
fdset[0].events = POLLPRI | POLLERR;
...
poll()
...
lseek(fdset[0].fd, 0, SEEK_SET);
const ssize_t rc = read(fdset[0].fd, buf, MAX_BUF);

Вышеописанное работает на BeagleBone Black Rev. C под управлением Debian с linux 3.8.13-bone47.

person tweej    schedule 17.08.2014

Поскольку вы «ни к чему не подключали этот контакт», если он не привязан внутренне к низкому или высокому уровню, то это просто плавающий вход, который может вызвать очевидные прерывания, которые вы видите.

person RG_    schedule 28.02.2014
comment
Кроме того, в приведенном вами примере используется POLPRI как при определении pollfd.events, так и при маскировании полученных сообщений для GPIO. - person RG_; 01.03.2014