EDT PCD SDK Documentation 6.0.0
EDT DMA Library
Collaboration diagram for EDT DMA Library:

Modules

 Open / Close
 
 DMA Initialization
 
 FIFO Flushing
 
 Input/Output
 
 Register Access
 
 Utility
 

Detailed Description

The DMA library provides a set of consistent routines across many of the EDT products, with simple yet powerful ring-buffered DMA (Direct Memory Access) capabilities.

A DMA transfer can be continuous or noncontinuous:

Note
Always use the library calls edt_reg_read(), edt_reg_write(), edt_reg_or(), or edt_reg_and() to read or write hardware registers, rather than using ioctls.

Elements of EDT Interface Applications

Applications that perform continuous transfers typically include the following elements:

  1. The include statement:
    #include "edtinc.h"
  2. A call to edt_open() to open the device. This returns a handle which represents the EDT board in software. All subsequent calls will use this handle to access the board.
  3. Optionally, setup for writing a file or some other target for the data to be acquired.
  4. A call to edt_configure_ring_buffers() to configure the ring buffers.
  5. A call to start the DMA, such as edt_start_buffers().
  6. In a loop, a call to edt_wait_for_buffers()
    1. Data processing calls in the loop, as required.
  7. A call to edt_stop_buffers() followed by edt_close() to close the device.
  8. Appropriate settings in your Makefile or C workspace to link to the libpcd library.

Example:

#include "edtinc.h"
#include <fcntl.h>
#include <unistd.h>
int main(void)
{
EdtDev edt_p = edt_open("pcd", 0);
char *buf_ptr = NULL;
int outfd = open("outfile", 1) ;
// Configure a ring buffer with four 1 MB buffers
edt_configure_ring_buffers(edt_p, 1024*1024, 4, EDT_READ);
// Count of 0 for continuous DMA transfer ("free running" mode).
edt_start_buffers(edt_p, 0);
// This loop will capture data indefinitely, but the write() or
// other data processing must be able to keep up.
while ((buf_ptr = edt_wait_for_buffers(edt_p, 1)) != NULL)
{
write(outfd, buf_ptr, 1024*1024) ;
}
close(outfd);
edt_close(edt_p);
return 0;
}

Applications that perform noncontinuous transfers typically include the following elements:

  1. The include statement:
    #include "edtinc.h"
  2. A call to edt_open() to open the device. This returns a handle which represents the EDT board in software. All subsequent calls will use this handle to access the board.
  3. Optionally, setup for writing a file or some other target for the data to be acquired..
  4. A call to edt_read() or edt_write() to cause one DMA transfer.
  5. Data processing calls, as required.
  6. A call to edt_close() to close the device.
  7. Appropriate settings in your Makefile or C workspace to link to the libpcd library.

Assuming that a multichannel FPGA configuration file has been loaded, this example opens a specific DMA channel with edt_open_channel():

#include "edtinc.h"
#include <fcntl.h>
#include <unistd.h>
int main(void)
{
EdtDev edt_p = edt_open_channel("pcd", 1, 2);
char buf[1024] = {0};
int numbytes = 0;
int outfd = open("outfile", 1);
// Because edt_read()s are noncontinuous, without hardware
// handshaking the data will have gaps between each edt_read().
while ((numbytes = edt_read(edt_p, buf, sizeof(buf))) > 0)
write(outfd, buf, numbytes);
close(outfd);
edt_close(edt_p);
return 0;
}

You can use ring buffers for real-time data capture using a small number of buffers (typically 1 MB) configured in a round-robin data FIFO. During capture, the application must be able to transfer or process the data before data acquisition wraps around and overwrites the buffer currently being processed (an "overrun" condition). The example below shows real-time data capture using ring buffers, although it includes no error-checking. In this example, process_data(bufptr) must execute in the same or less amount of time it takes DMA to fill a single buffer.

#include "edtinc.h"
int main(void)
{
EdtDev edt_p = edt_open("pcd", 0);
// Configure four 1 MB buffers
edt_configure_ring_buffers(edt_p, 0x100000, 4, EDT_READ);
// Count of 0 for continuous DMA transfer ("free running" mode).
edt_start_buffers(edt_p, 0);
for (;;)
{
// Wait for each buffer to complete, then process it.
// The driver continues data transfer concurrently with userspace processing.
uint8_t *bufptr = edt_wait_for_buffers(edt_p, 1);
process_data(bufptr);
}
}

Multithreaded Programming

The EDT driver is thread-safe, with the following constraints: