2
votes

I am trying to get GPIO based interrupts working on the BeagleBone GPIO using the Poll() function. Below is my code, but in short:

While I have the pin connected to ground, nothing happens (as expected).

When I connect the pin to high, an interrupt is generated. However, it either never clears or is regenerated extremely fast. I implemented a count to be incremented when it went high and in the matter of a few seconds the counter was well over 10,000. Am I missing something in my setup? The issue is probably in my main() function, but I have included the other functions for completeness.

Thanks for any assistance,

Charles

#define SYSFS_GPIO_DIR "/sys/class/gpio"
#define MAX_BUF 64

int gpio_export(unsigned int gpio)
{
    int fd, len;
    char buf[MAX_BUF];

    fd = open(SYSFS_GPIO_DIR "/export", O_WRONLY);
    if (fd < 0) {
        perror("gpio/export");
        return fd;
    }

    len = snprintf(buf, sizeof(buf), "%d", gpio);
    write(fd, buf, len);
    close(fd);

    return 0;
}

int gpio_set_dir(unsigned int gpio, unsigned int direction)
{
    int fd, len;
    char buf[MAX_BUF];

    len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR  "/gpio%d/direction", gpio);

    fd = open(buf, O_WRONLY);
    if (fd < 0) {
        perror("gpio/direction");
        return fd;
    }

    if (direction)
        write(fd, "out", 4);
    else
        write(fd, "in", 3);

    close(fd);
    return 0;
}

int gpio_set_edge(unsigned int gpio, char *edge)
{
    int fd, len;
    char buf[MAX_BUF];

    len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/edge", gpio);

    fd = open(buf, O_WRONLY);
    if (fd < 0) {
        perror("gpio/set-edge");
        return fd;
    }

    write(fd, edge, strlen(edge) + 1);
    close(fd);
    return 0;
}

int gpio_fd_open(unsigned int gpio)
{
    int fd, len;
    char buf[MAX_BUF];

    len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);

    fd = open(buf, O_RDONLY | O_NONBLOCK );
    if (fd < 0) {
        perror("gpio/fd_open");
    }
    return fd;
}

int gpio_fd_close(int fd)
{
    return close(fd);
}

int main()
{
    struct pollfd fdset;
    int nfds = 1;
    int gpio_fd, timeout, rc;
    char *buf[MAX_BUF];
    unsigned int gpio;
    int len;
    char* c;


    gpio = 26;

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

    timeout = 1;

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

        fdset.fd = gpio_fd;
        fdset.events = POLLPRI | POLLERR;

        len = read(fdset.fd, c, 1);

        rc = poll(&fdset, nfds, timeout);

        //printf("POLLPRI is %02x, POLLERR is %02x\r\n", POLLPRI, POLLERR);

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

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

        if (fdset.revents & POLLPRI) {
            if (len==-1)
            {
                printf("Hex of revents is %02x, return code is %02x\r\n", fdset.revents, rc);
            }
            len = read(fdset.fd, buf, MAX_BUF);
        }

        if (fdset.revents & POLLERR)
        {
            printf("errno: %d", errno);
        }
    }

    gpio_fd_close(gpio_fd);
    return 0;
}
1
I did not read your code, but if you "connect" by a mechanical switch or similar (open wire), you have to debounce (just search for the term). - too honest for this site

1 Answers

0
votes

I reinstalled the Debian image on the BeagleBone Black and it works as expected now. I'm not sure why it wasn't working before, but it looks like it was an OS issue.