c - 即使 GPIO FD 发生变化,轮询也不会返回

标签 c linux embedded-linux file-descriptor poll-syscall

我正在尝试读取一个 GPIO 值,只要它改变状态。

/sys/class/gpio/gpio499/value

我已经将 /sys/class/gpio/gpio499/edge 设置为 both

我正在尝试在一个单独的线程中使用 poll 命令来监视值的变化。这是代码片段:

void PIN_gpio_poll(size_t gpio)     //GPIO 499
{
        char path[30];
        char cValue;
        int fd;
        int ret_poll;
        int ret_read;
        struct pollfd pollfd;
        int i;

        pollfd.events = POLLPRI | POLLERR; /* look for GPIO status change. */


        snprintf(path, 30, PHDRIVER_LINUX_CFG_DIR "/gpio%u/value", gpio);
        fd = open(path, O_RDONLY);
        if (fd == -1)
        {
                printf("Gpio_poll _ERROR\r\n");
        }

        pollfd.fd = fd;

        ret_read = read(pollfd.fd, &cValue, 1);    // Dummy Read to clear

        while (1)
        {
                lseek(fd, 0, SEEK_SET);
                ret_read = read(fd, &cValue, 1);
                printf("Value=%c, RET READ=%d\n",cValue,ret_read);
//              ret_poll = poll( &pollfd, 1, -1 );
                ret_poll = poll( &pollfd, 1, 10000 );  //10sec timeout

                printf("******REVENTS=%x\n",pollfd.revents);
                if( ret_poll == -1 )
                {
                        printf("Gpio_poll poll failed\r\n");
                        close(fd);
                }else{
//                      if (pollfd.revents & POLLPRI )
                        {
                                lseek(fd, 0, SEEK_SET);
                                ret_read = read(pollfd.fd, &cValue, 1);
                                if(ret_read > 0)
                                {
                                    printf("Cvalue = %c\n",cValue);
                                }
                        }

                }
        }
}

我面临的问题是,如果我将事件设置为POLLIN,轮询会立即返回。这是可以理解的,因为 value(0 或 1)GPIO 中始终有要读取的数据。我提到了https://www.kernel.org/doc/Documentation/gpio/sysfs.txt并将事件设置为 POLLPRI |波勒尔。但在此方法中,轮询仅在超时后返回。当 GPIO 的值改变时它不会返回。有什么我想念这里的把戏吗?我还将 /sys/class/gpio/gpio499/edge 设置为上升、下降,但似乎没有任何效果。

编辑: 这是 grep -r 的输出。/sys/class/gpio/gpio499

/sys/class/gpio/gpio499/edge:both
/sys/class/gpio/gpio499/power/control:auto
/sys/class/gpio/gpio499/power/runtime_active_time:0
grep: /sys/class/gpio/gpio499/power/autosuspend_delay_ms: Input/output error
/sys/class/gpio/gpio499/power/runtime_status:unsupported
/sys/class/gpio/gpio499/power/runtime_suspended_time:0
/sys/class/gpio/gpio499/value:1
/sys/class/gpio/gpio499/active_low:0
/sys/class/gpio/gpio499/direction:in

注意:我要检测从1到0的值。

最佳答案

函数:poll() 不能像发布的代码预期的那样工作。

建议:1)读取文件获取当前输入值。 2) 执行自旋循环,读取值,直到值发生变化,类似于:

readbytes = read( fd, &cValue, 1 );  
while( readbytes > 0 )
{  
    if( (off_t)-1 == lseek(fd, 0, SEEK_SET) )
    { // then lseek failed
        perror( "lseek failed" );
        exit( EXIT_FAILURE );
    }

    // implied else, lseek successful

    readbytes = read(fd, &new_cValue, 1);
    if( 0 >= readbytes )
    { 
        perror( "read failed" );
        exit( EXIT_FAILURE );
    }

    // implied else, read successful

    if( cValue != new_cValue )
    { // then state changed
        cValue = new_cValue;
        break;
    }
}

这个循环确实消耗了更多的 CPU 周期,但应该可以工作

关于c - 即使 GPIO FD 发生变化,轮询也不会返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46825208/

相关文章:

c - 了解声明、malloc 和这行 C 代码的其他部分

c - 为什么显示帧指针超出 3GB 地址空间?

linux-kernel - Linux 用户空间中通过/dev/mem 与 PCIe 设备进行双向通信?

c - C 中 == 的确切含义

c - c程序中的浮点异常

Ubuntu Linux 中的 Java RMI 连接被拒绝

linux - 找不到 LIBBFD(缺少 : LIBBFD_BFD_LIBRARY LIBBFD_IBERTY_LIBRARY LIBBFD_OPCODES_LIBRARY LIBBFD_INCLUDE_DIRS)

regex - Grep/Sed 每次出现换行符后跟 bash 中的字符串

linux - 嵌入式设备为何以及何时会同时具有 NAND 和 NOR?

linux - 我如何知道我的系统是否启用了 ARM 的 XN(永不执行)位支持?