dma_ip_drivers icon indicating copy to clipboard operation
dma_ip_drivers copied to clipboard

Is there an implementation of an event trigger when it is readable?

Open geiliwanghaichao opened this issue 7 months ago • 1 comments

In the ARM application layer, I have the following demo. The purpose is to transfer data from the ARM side to the PCIe EP (FPGA) via PCIe XDMA, and then transfer the data back from the FPGA for data verification and other operations. However, the data is read from the FPGA in a blocking manner, which is very undesirable in the project. I would like to confirm whether the XDMA driver has implemented an event trigger when the kernel confirms that data is available for reading, so that the application layer program can obtain the event through select / poll . Additionally, I would like to confirm whether the kernel driver has implemented the mmap function, so that the application layer program can quickly access the data through memory mapping. If the kernel driver has implemented the above functions,are there any application-layer examples for reference?If not,what are the reasons,and is it supported for users to implement them on their own? Thanks.

`#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <getopt.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <sys/mman.h>

// Transfer size related constants #define MAX_TRANSFER_SIZE (8 * 1024 * 1024) // 8MB #define ALIGNMENT 4096 #define DEFAULT_LOOP_COUNT 10 #define PERFORMANCE_TEST_SIZES {2,4,8,16,32,64,128,256,512,1024,2048,4096,8192} // KB

// Command line options static struct option const long_opts[] = { {"size", required_argument, NULL, 's'}, {"cycle", required_argument, NULL, 'c'}, {0} };

/**

  • @brief Open DMA device file
  • @return File descriptor on success, -1 on failure */ int open_dma_device(const char *filename) { int fd = open(filename, O_RDWR); if (fd < 0) { fprintf(stderr, "Open %s failed: %s\n", filename, strerror(errno)); } return fd; }

/**

  • @brief allocate buffer */ void *allocate_aligned_buffer(size_t size) { void *buf = NULL; return posix_memalign(&buf, ALIGNMENT, size) ? NULL : buf; }

/**

  • @brief Initialize buffer */ void init_buffer(uint32_t *buf, size_t size) { for (size_t i = 0; i < size/4; i++) { buf[i] = (uint32_t)random(); } }

/**

  • @brief verify data consistency
  • @return Number of bit errors */ int verify_buffer(uint32_t *tx_buf, uint32_t *rx_buf, size_t size) { int errors = 0; for (size_t i = 0; i < size/4; i++) { errors += (rx_buf[i] != tx_buf[i]); } return errors; }

/**

  • @brief Execute DMA transfer performance test */ void performance_test(int h2c_fd, int c2h_fd, size_t size, int iterations) { int errors = 0; uint32_t *tx_buf = allocate_aligned_buffer(size); uint32_t *rx_buf = allocate_aligned_buffer(size);

    if (!tx_buf || !rx_buf) { fprintf(stderr, "Buffer allocation failed\n"); goto cleanup; }

    for (int i = 0; i < iterations; i++) { init_buffer(tx_buf, size);

     // H2C Transfer
     if (write(h2c_fd, tx_buf, size) != (ssize_t)size) errors++;
    
     // C2H Transfer
     memset(rx_buf, 0, size);
     if (read(c2h_fd, rx_buf, size) != (ssize_t)size) errors++;
     errors += verify_buffer(tx_buf, rx_buf, size);
    

    }

cleanup: free(tx_buf); free(rx_buf); }

int main(int argc, char **argv) { int opt, cycles = DEFAULT_LOOP_COUNT; size_t size = 0; int perf_mode = 0; int h2c_fd = -1, c2h_fd = -1;

// Parse command line arguments
while ((opt = getopt_long(argc, argv, "c:s:p", long_opts, NULL)) != -1) {
    if (opt == -1) break;
switch (opt) {
        case 'c': cycles = atoi(optarg); break;
        case 's': size = atoi(optarg); break;
        case 'p': perf_mode = 1; break;
        default: 
            printf("Usage: %s [-p] [-c cycles] [-s size_KB]\n", argv[0]);
            return 1;
    }
}

if (argc < 2) {
    printf("Usage: %s [-p] [-c cycles] [-s size_KB]\n", argv[0]);
    return 1;
}

// Open DMA devices
if ((h2c_fd = open_dma_device("/dev/xdma0_h2c_0")) < 0 ||
    (c2h_fd = open_dma_device("/dev/xdma0_c2h_0")) < 0) {
    goto exit;
}

// Execute tests
performance_test(h2c_fd, c2h_fd, size*1024, cycles);

exit: close(h2c_fd); close(c2h_fd); return 0; } `

geiliwanghaichao avatar May 27 '25 02:05 geiliwanghaichao

I don't fully understand the problem. If you need to simultaneously write and read data, just do inside separate threads. XDMA devices don't have mmap becuase it doesn't make sense for them.

Be aware I am not an AMD/Xilinx employee, but just a user like you. However, your application sounds similar to mine.

Prandr avatar May 27 '25 09:05 Prandr