lau*_*ote 6 c embedded asynchronous spi linux-device-driver
我正在维护一些通过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
}
}
}
Run Code Online (Sandbox Code Playgroud)
我真的很喜欢在轮询和睡眠的基于事件的解决方案.首先想到的是在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);
}
Run Code Online (Sandbox Code Playgroud)
事情是我找不到像这样处理SPI的人的任何例子,我想知道是否有一个很好的理由.可以这样使用/ dev/spidev吗?它会像往常一样愚蠢/永远不会"准备好阅读"吗?是否可以做出的行为就是我想要的?它是硬件依赖的吗?如果有必要的话,我不反对一个小内核驱动程序黑客,但我不确定我是否需要在哪里寻找.
我可以在 /dev/spidev 文件描述符上 select() 吗?
否。
spidev文档指出
At this time there is no async I/O support; everything is purely synchronous.
Run Code Online (Sandbox Code Playgroud)
更重要的是,spidev 驱动程序不支持轮询文件操作。select ()系统调用要求设备驱动程序支持 poll fops。
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 };
Run Code Online (Sandbox Code Playgroud)