如何在Linux板上检测GPIO的引脚变化

Ang*_*ngs 9 c linux posix embedded-linux gpio

我在基于ARM的linux板(imx233 CPU)上使用3.12内核.我的目的是检测GPIO的引脚变化(1到0).

我可以不断调用下面的函数读取引脚值(在while(1)循环中)

int GPIO_read_value(int pin){
    int gpio_value = 0;
    char path[35] = {'\0'};
    FILE *fp;
    sprintf(path, "/sys/class/gpio/gpio%d/value", pin);
    if ((fp = fopen(path,"rb+")) == NULL){ //echo in > direction
         //error
    }

    fscanf(fp, "%d", &gpio_value);
    fclose(fp);
    return gpio_value;
}
Run Code Online (Sandbox Code Playgroud)

但它会给CPU带来太多负载.我不使用usleepnanosleep,因为引脚更改发生的时间很短,导致我错过了该事件.

据我所知,它是不可能使用的poll().有没有poll()类似的功能可以用来检测GPIO的引脚变化?

编辑:以防万一,如果我做错了什么,这是我的poll()用法没有检测到引脚更改

struct pollfd pollfds;
    int fd;
    int nread, result;
    pollfds.fd = open("/sys/class/gpio/gpio51/value", O_RDWR);
    int timeout = 20000;           /* Timeout in msec. */
    char buffer[128];

    if( pollfds.fd < 0 ){
        printf(" failed to open gpio \n");
        exit (1);
    }

    pollfds.events = POLLIN;
    printf("fd opens..\n");
    while (1)
    {
            result = poll (&pollfds, 0, timeout);
            switch (result)
            {
                  case 0:
                    printf ("timeout\n");
                    break;
                  case -1:
                    printf ("poll error \n");
                    exit (1);

                   default:
                printf("something is happening..\n");
                    if (pollfds.revents & POLLIN)
                    {
                        nread = read (pollfds.fd, buffer, 8);
                        if (nread == 0) {
                            printf ("result:%d\n", nread);
                            exit (0);
                         } else {
                            buffer[nread] = 0;
                            printf ("read %d from gpio: %s", nread, buffer);
                         }
                     }
              }
     }
     close(fd);
Run Code Online (Sandbox Code Playgroud)

EDIT2:https : //developer.ridgerun.com/wiki/index.php/Gpio-int-test.c上的代码可以正常工作,poll()我需要定义中断的上升沿/下降沿,稍微修改一下定义.它解决了我的问题,然而,对我和其他一些人来说,听听/了解替代方法可能会有好处.

wie*_*iak 2

我以前从未见过这块板,但是我猜想这块板已经完全实现了 PIC(通常是这样),但是您必须在 GPIO 控制器中另外配置中断(通常是这样)。某些部分应该作为内核模块完成,然后您必须将有关中断的信息传递给您的应用程序。

执行此操作的示例方法是将以下内容实现为内核模块:

  • 设置 GPIO 控制器以在特定端口和级别上启用中断(您可以在此处找到如何执行此操作:http ://cache.freescale.com/files/dsp/doc/ref_manual/IMX23RM.pdf 37.2.3.3 输入中断操作)

  • 在PIC中启用GPIO中断(如何做到这一点:http://lwn.net/images/pdf/LDD3/ch10.pdf Chapter10)

  • 实现中断处理例程(我将在下面稍微描述)
  • 为您的模块实现 ioctl 接口。

并在您的应用程序中休息:

  • 一个可以通过中断来辅助操作的函数。

将有关中断的信息从内核传递到应用程序的最简单方法是通过内核端的信号量。在模块中,您可以实现一个 ioctl,它将休眠直到发生中断。因此应用程序将调用此ioctl,并且其线程将被阻塞,直到中断发生。

在模块内部,中断例程应检查应用程序线程现在是否被阻止,如果是,则检查 up() 信号量。

编辑*****

该CPU具有SSP,其工作模式为SPI。为什么不使用它?