A DMA transfer can be continuous or noncontinuous:
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.
Applications that perform continuous transfers typically include the following elements:
#include "edtinc.h"
Example
#include "edtinc.h" main() { EdtDev *edt_p = edt_open("edt", 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:
#include "edtinc.h"
Assuming that a multichannel Xilinx firmware 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("edt", 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("edt", 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.
The EDT driver is thread-safe, with the following constraints:
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. | |
1.5.1