Route Multiple DMA Channels
This guide covers subscribing a file descriptor to multiple DMA receive channels and sending data to a specific channel.
Note
For background on how channels work with AXI stream TDEST bits, see AXI Stream Protocol.
Overview
The driver supports up to
DMA_MAX_DEST(4096) channelsEach
open()call creates an independent client with its own channel maskA client only receives frames whose TDEST matches its mask
Subscribe to a Single Channel
#include <DmaDriver.h>
#include <fcntl.h>
int fd = open("/dev/datadev_0", O_RDWR);
dmaSetMask(fd, 0); /* subscribe to channel 0 */
Subscribe to Multiple Channels
Use the byte-mask API to subscribe to more than one channel:
#include <DmaDriver.h>
#include <fcntl.h>
#include <string.h>
int fd = open("/dev/datadev_0", O_RDWR);
uint8_t mask[DMA_MASK_SIZE]; /* DMA_MASK_SIZE = 512 bytes */
dmaInitMaskBytes(mask); /* zero the mask */
dmaAddMaskBytes(mask, 0); /* subscribe to channel 0 */
dmaAddMaskBytes(mask, 1); /* subscribe to channel 1 */
dmaAddMaskBytes(mask, 5); /* subscribe to channel 5 */
dmaSetMaskBytes(fd, mask); /* apply the mask via ioctl */
Send to a Specific Channel
char buf[4096];
uint32_t dest = 3; /* target channel */
ssize_t ret = dmaWrite(fd, buf, sizeof(buf), 0 /* flags */, dest);
Receive and Return Buffers
Warning
Every dmaReadIndex call must be paired with dmaRetIndex. If buffers
are not returned, the receive pool (cfgRxCount buffers) will drain and
all future reads will block permanently.
uint32_t index, flags, error, dest;
ssize_t ret = dmaReadIndex(fd, &index, &flags, &error, &dest);
if (ret > 0) {
/* process data at dmaBuffers[index] */
dmaRetIndex(fd, index); /* MUST call this to return the buffer */
}
Multiple Clients on One Device
Open the same device file multiple times to create independent clients:
int fd_a = open("/dev/datadev_0", O_RDWR);
int fd_b = open("/dev/datadev_0", O_RDWR);
uint8_t mask_a[DMA_MASK_SIZE], mask_b[DMA_MASK_SIZE];
dmaInitMaskBytes(mask_a); dmaAddMaskBytes(mask_a, 0);
dmaInitMaskBytes(mask_b); dmaAddMaskBytes(mask_b, 1);
dmaSetMaskBytes(fd_a, mask_a); /* fd_a receives channel 0 */
dmaSetMaskBytes(fd_b, mask_b); /* fd_b receives channel 1 */
Each open(2) creates an independent DmaDesc with its own channel mask
and receive queue.