Skip to content

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

@geiliwanghaichao

Description

@geiliwanghaichao

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;
}
`

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions