简体   繁体   中英

How to implement a Linux Device Driver for Data Acquisition Hardware?

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.

You are reading a very very old book. Here the link to the last version of the book (it is just very old): Linux Device Driver 3 - Memory Mapping . You can also read the DMA-API from the kernel documentation.

To make a kind of synchronization read Time, Delays and Deferred Work chapter. You can use the a waitqueue . You wait on read() and you *wake_up* when new frames are available.

About your code, it is not enough to understand your problem. But, if you think that you need to sleep/wait, you can implement the poll file_operation in your driver and use select() in user-space to ask if there is something to read.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM