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:
A memory-mapped control register enables a user-space application to Start/Stop the device
Upon start, the device begins to transfer the acquired data to the assigned memory region continuously (and circularly) at ~8MB/s.
- The reserved memory region has the size of two frames in order to employ a double-buffering technique.
- 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.