EDT DMA Library


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:
When developing applications for EDT digital image capture boards such as the PCIe8 DV C-Link, programmers should avoid direct access to the edt library (edt_ subroutines) and instead use the higher level EDT Digital Imaging Library. Some limited use of edtlib calls may be necessary in DV applications, however we can not provide support for applications that directly call edtlib subroutines for data acquisition (e.g. edt_configure_ring_buffers, edt_start_buffers); instead use the pdvlib corollaries (e.g. pdv_multibuf, pdv_start_images).

For portability, use the library calls edt_reg_read, edt_reg_write, edt_reg_or, or edt_reg_and to read or write the hardware registers, rather than using ioctls.

Building and using the Library, Utilities and Example Applications

By default, EDT's pcd installation package is copied into c: (Windows), or /opt/EDTpdv (Linux / Macos). For pdv packages, see the EDT Digital Imaging Library.

Note:
Applications using EDT boards must be linked with the appropriate (32 or 64-bit) for the platform in use. Applications linked with 32-bit EDT libraries will not run correctly on 64-bit systems, or vice-versa.
To rebuild a program or library, you'll need to use a compiler and either the nmake application that comes with Visual Studio, or the Unix make utility, as described below.

1. Do one of the following:

2. Enter

 make file
where file is the name of the example program you wish to build. 3. To rebuild all the libraries, examplees, utilities and diagnostics, run
 make
Alternately, on Windows you can use a Visual Studio. Releases are all built using makefiles; reference includes.mk and makefile.def for lists of the library objects (which all have .c source files), applications, and header files.

Elements of EDT Interface Applications

Applications that perform continuous transfers typically include the following elements:

  1. The preprocessor statement:
     #include "edtinc.h"
    
  2. A call to edt_open to open the device. This returns a pointer to a structure that represents the EDT board in software. All subsequent calls will use this pointer 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. Data processing calls, as required.
  7. A call to edt_close to close the device.
  8. Appropriate settings in your makefile or C workspace to compile and link the library file libedt.c.

Example

 #include "edtinc.h"
 main()
 {
     EdtDev *edt_p = edt_open("pcd", 0) ;
     char *buf_ptr; int outfd = open("outfile", 1) ;
     // Configure a ring buffer with four 1MB buffers
     edt_configure_ring_buffers(edt_p, 1024*1024, 4, EDT_READ, NULL) ;
     edt_start_buffers(edt_p, 0) ; // 0 starts unlimited buffer DMA

     // 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) ;

     edt_close(edt_p) ;
 }

Applications that perform noncontinuous transfers typically include the following elements:

  1. The preprocessor statement:
     #include "edtinc.h"
    
  2. A call to edt_open to open the device. This returns a pointer to a structure that represents the EDT board in software. All subsequent calls will use this pointer to access the board.
  3. Optionally, setup for writing a file or some other target for the data to be acquired.
  4. A system read() or write() call 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 compile and link the library file libedt.c.

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

 #include "edtinc.h"
 main()
 {
     EdtDev *edt_p = edt_open_channel("pcd", 1, 2) ;
     char buf[1024] ;
     int numbytes, outfd = open("outfile", 1) ;

     // Because read()s are noncontinuous, without hardware
     // handshaking, the data will have gaps between each read().
     while ((numbytes = edt_read(edt_p, buf, 1024)) > 0)
         write(outfd, buf, numbytes) ;

     edt_close(edt_p) ;
 }

You can use ring buffer mode 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. 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 amount of time it takes DMA to fill a single buffer, or faster.

 #include "edtinc.h"
 main()
 {
   EdtDev *edt_p = edt_open("pcd", 0) ;

   // Configure four 1 MB buffers:
   // one for DMA
   // one for the second DMA register on most EDT boards
   // one for "process_data(bufptr)" to work on
   // one to keep DMA away from "process_data()"
   //
   edt_configure_ring_buffers(edt_p, 0x100000, 4, EDT_READ, NULL) ;
   edt_start_buffers(edt_p, 0) ; // 0 starts unlimited buffer DMA
   for (;;)
   {
       char *bufptr ;
       // Wait for each buffer to complete, then process it.
       // The driver continues DMA concurrently with processing.
       //
       bufptr = edt_wait_for_buffers(edt_p, 1) ;
       process_data(bufptr) ;
   }
 }

Check compiler options in the EDT-provided makefiles.

Multithreaded Programming

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

  1. Because kernel DMA resources are allocated on a per-thread basis and must be allocated and released in the same thread, perform all DMA operations in the same thread as edt_open and edt_close with respect to each channel. Other threads can open the same channel concurrently with DMA, but must perform no DMA-related operations.
  2. To avoid undefined application or system behavior, or even system crashes, when exiting the program:


Modules

 Startup / Shutdown
 These functions are used to open and close the EDT device.
 Initialization
 FIFO Flushing
 First-in, first-out (FIFO) memory buffers are used to smooth data transmission between different types of data sinks internal to EDT boards.
 Input/Output
 These functions are used to perform and control DMA transfers.
 Register Access
 Register access functions.
 Utility
 Utility functions.


Generated on 19 Jun 2015 by  doxygen 1.4.7