【问题标题】:how to detect a pin change of a GPIO on Linux board如何在 Linux 板上检测 GPIO 的引脚变化
【发布时间】:2014-11-15 17:45:35
【问题描述】:

我在基于 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;
}

但它会导致 CPU 负载过大。我不使用usleep 或nanosleep,因为引脚更改发生的时间很短,会导致我错过活动。

据我所知,无法使用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);

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

【问题讨论】:

  • inotify API 怎么样?
  • 当您说引脚仅在“非常短的时间内”处于活动状态时,您在说什么时间?因为即使像您一样进行主动轮询,从用户空间执行此操作也可能会引入延迟,导致您无论如何都会错过它。
  • 我想使用 GPIO 作为片选来读取 SPI 数据。在空闲状态它是逻辑高。传输开始时变为逻辑低电平。因此,反应越快越好。当我找到合适的方法时,我会以较慢的速度进行测试
  • 这个特定的引脚是否有替代的捕获比较功能?你需要的是产生中断的硬件
  • 对,硬件中断是最好的。但是,我还找不到对我的板(olimex imx233nano)的支持。知道一个可以正常工作的 Linux/posix 函数会很好。正如真实所暗示的那样,我现在正在尝试 inotify。

标签: c linux posix embedded-linux gpio


【解决方案1】:

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

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

在你的应用程序中休息一下:

  • 一个可以与中断协同操作的函数。

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

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

编辑*****

此 CPU 具有具有 SPI 工作模式的 SSP。为什么不用它??

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-26
    • 2018-02-28
    • 2020-09-01
    • 1970-01-01
    • 2011-01-16
    相关资源
    最近更新 更多