1

I am developing an acquisition device which requires DMA operation to transfer large data frames to the main memory. For now I am assuming the destination is a contiguous memory region so I am allocating it (say 1 MB) at boot time as described in section "Do-it-yourself allocation" from ldd2-ch13. The driver can then access that region by calling ioremap().

The current system works as follows:

  1. A memory-mapped control register enables a user-space application to Start/Stop the device

  2. Upon start, the device begins to transfer the acquired data to the assigned memory region continuously (and circularly) at ~8MB/s.

  3. The reserved memory region has the size of two frames in order to employ a double-buffering technique.
  4. Once a complete frame has been transferred, the device triggers an interrupt.

I have developed a simple char driver which provides a blocking read() function so that the user-space can read a new data frame every time an interrupt is received.

After running a few tests, I realized that the user-space application misses some frames when running the following code:

    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");
    }

I suspect that the application's process is being put to sleep between two subsequent reads, allowing the device to rewrite the memory location which should have already been read.

Since I have no experience in kernel development I would like to know how is the correct way to implement a driver for such a device in order to ensure synchronization. Basically I am trying to implement a simple shared memory communication for a real-time acquisition device and I need to guarantee that the OS is able to read all the acquired data frames.

4

1 回答 1

2

你正在读一本非常非常古老的书。这里是本书最新版本的链接(它只是很旧):Linux Device Driver 3 - Memory Mapping。您还可以从内核文档中阅读DMA-API 。

要制作一种同步,请阅读Time、Delays 和 Deferred Work章节。您可以使用waitqueue。当新帧可用时,您等待read() 并 *wake_up*。

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

于 2013-04-03T16:19:00.427 回答