我正在维护一些通过SPI与FPGA通讯的用户空间代码。现在,它正在轮询以查看是否有数据要处理,对此我并不感到兴奋。 comm线程的(简化后)结构如下所示:

int spi_fd;

void do_transfer(char *buf, int len)
{
    struct spi_ioc_transfer xfer;
    memset(xfer, 0, sizeof(xfer));

    ioctl_tell_some_fpga_register_heads_up();

    xfer[0].len = len;
    xfer[0].tx_buf = NULL;
    xfer[0].rx_buf = buf;
    ioctl(spi_fd, SPI_IOC_MESSAGE(1), xfer);

    ioctl_tell_some_fpga_register_were_done();
}

void *comm_thread(void arg)
{
    uint8_t config = SPI_MODE_3;
    __u32 speed = 4000000;
    char buffer[5120];

    spi_fd = open("/dev/spidev1.0", O_RDWR);
    ioctl(spi_fd, SPI_IOC_WR_MODE, &config);
    ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);

    while(1) {
        sleep(2); //ugh
        if(ioctl_read_some_fpga_register_that_says_if_theres_data())
        {
            do_transfer(buffer, some_small_number_of_bytes());
            do_stuff(buffer); //you get the picture
        }
    }
}

与轮询和 sleep 相比,我真的更喜欢基于事件的解决方案。首先想到的是在spidev文件描述符上执行select(),而不是每隔X秒检查一些寄存器,例如
fd_set myset;

while(1) {
    FD_ZERO(&myset);
    FD_SET(spi_fd, &myset);
    select(spi_fd + 1, &myset, NULL, NULL, NULL);
    do_transfer(buffer, some_small_number_of_bytes());
    do_stuff(buffer);
}

问题是我找不到像这样处理SPI的人员的任何示例,而且我想知道是否有很好的理由。可以以这种方式使用/dev/spidev吗? 它会像永远/永远不会“准备阅读” 那样愚蠢吗?可以使其表现为我想要的方式吗?是否依赖于硬件?如果必要的话,我不反对小小的内核驱动程序黑客攻击,但我不确定是否需要查找。

最佳答案



不。
spidev documentation状态

At this time there is no async I/O support; everything is purely synchronous.

更重要的是,spidev driver不支持轮询文件操作。 select()系统调用要求设备驱动程序支持民意调查。
670 static const struct file_operations spidev_fops = {
671         .owner =        THIS_MODULE,
672         /* REVISIT switch to aio primitives, so that userspace
673          * gets more complete API coverage.  It'll simplify things
674          * too, except for the locking.
675          */
676         .write =        spidev_write,
677         .read =         spidev_read,
678         .unlocked_ioctl = spidev_ioctl,
679         .compat_ioctl = spidev_compat_ioctl,
680         .open =         spidev_open,
681         .release =      spidev_release,
682         .llseek =       no_llseek,
683 };

09-09 18:32