如何实现数据采集硬件的Linux设备驱动程序



我正在开发一个需要DMA操作才能将大数据帧传输到主存的采集设备。现在,我假设目标是一个连续的内存区域,所以我按照ldd2-ch13的"自己动手分配"一节中的描述,在引导时分配它(比如1 MB)。然后驱动程序可以通过调用ioremap()来访问该区域。

当前系统的工作方式如下:

  1. 内存映射控制寄存器允许用户空间应用程序启动/停止设备

  2. 启动时,设备开始以~8MB/s的速度连续(循环)地将采集到的数据传输到指定的内存区域。

  3. 为了采用双缓冲技术,预留内存区域的大小为两帧。
  4. 一旦传输了一个完整的帧,设备就会触发中断。

我开发了一个简单的char驱动程序,它提供了一个阻塞read()函数,以便每次收到中断时用户空间都可以读取一个新的数据帧。

在运行了几个测试之后,我意识到用户空间应用程序在运行以下代码时遗漏了一些帧:
    for(i=0;i<NUM_FRAMES;i++) {
       read(dev_d,buf,FRAME_SIZE);/*Read frame*/
       for(j=0;j<FRAME_SIZE;j++) /*File dump*/
          fprintf(fp,"%d",buf[j]);
        fprintf(fp,"n");
    }

我怀疑应用程序的进程在两次后续读取之间被置于睡眠状态,允许设备重写应该已经读取的内存位置。

由于我没有内核开发经验,我想知道如何为这样的设备实现驱动程序以确保同步。基本上,我正在尝试为实时采集设备实现一个简单的共享内存通信,我需要保证操作系统能够读取所有采集的数据帧。

你在读一本非常非常古老的书。这里是这本书的最后一个版本的链接(它只是很旧):Linux设备驱动程序3 -内存映射。您也可以从内核文档中读取DMA-API。

要进行一种同步,请阅读时间、延迟和延迟工作章节。您可以使用a waitqueue。你在read()时等待,当有新的帧可用时*wake_up*。

关于你的代码,理解你的问题是不够的。但是,如果您认为您需要睡眠/等待,您可以在驱动程序中实现poll file_operation,并在用户空间中使用select()来询问是否有东西要读。

最新更新