cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
guillaumebres
Scholar
Scholar
10,598 Views
Registered: ‎03-27-2014

Writing a Linux driver for AXI-FIFO

Hi,
I am writing a Linux driver for the Xilinx AXI-FIFO IP.

I am very interested in sending 64bit long vectors from the FPGA to the CPU.
if you customize the IP to support AXI4, it can:
  • burst to memory and increase the throughput,
  • send 64 bit long vectors,
  • I think it might be easier to use than the Stream->AXI-DMA->PS flow.

I would like people showing the same interest to work with me, upgrade it (I'm not a Linux GURU),
or just share my work.
You can retrieve the current version with
git clone https://github.com/guillaumeWBres/axi_fifo

just ask me if you wanna work with me, I will add you as administrator within a few days.

I'm basically trying to implement the example presented
in the datasheet
 
Some informations to help you understand what's going on:

MISC device is how I typically register my devices in Linux because
  •  it is easy to do
    sdev->misc.name = sdev->name;
    sdev->misc.minor = MISC_DYNAMIC_MINOR;
    sdev->misc.fops = &fops;

  status = misc_register(&sdev->misc)

 

  •  I love the DYNAMIC_MINOR feature,
  • and I just like finding my devices in /dev.
I use the devicetree blob
    aliases {
  [...]
        axi_fifo0 = "/amba@0/axi_fifo@43C00000";
    };
and
 
    id = of_alias_get_id(node, "axi_fifo");
    if(id < 0){
        printk(KERN_ERR "failed to get an alias-id for %s\n", DRIVER_NAME);
        id = 0;
    }
to create an entry point /dev/axi_fifo_X for each node X.
 
The design is all based on the IRQs coming from the FPGA. Each time the IRQ is triggered,
int32_t sdev->irq_mask stores the current IRQ register. This way I can at least know
if the reading/writing processes are doing well and no under/overflow is happening.

The driver has two file operations: READ/WRITE.

READ: prepares an AXI transfer, reads the FIFO, passes the pointer to userspace.
The first trivial test is to make sure the FIFO was filled by the expected number of words. I also
test the int32_t sdev->irq_mask when I wake up (the completion is completed by the next IRQ),
to make sure the RX_COMPLETE mask has been received, without any over/underflow.
Then copy_to_user();

WRITE: retrives a pointer from userspace with copy_from_user(), checks the current FIFO occupancy,
fills the FIFO and check the new occupancy. Trivial test to make sure the FIFO has been properly filled.
Wait for completion (IRQ triggered) and as I wake up, check the sdev->irq_mask to make sure only TX_COMPLETE
is present.
 
Design flow:
Here is how it is supposed to be used now
int main(int argc, char **argv)
{
[...]

    fpga_buffer = (int*)malloc(len_);
    sprintf(device, "/dev/axi_fifo_0");

    fd = open(device, O_RDWR);
    if (fd < 0)
    {
        printf("error opening %s\n", device);
        return -1;
    }

    /* READ EXAMPLE */
    fpga_slave_stream_set_tdest(fd, 0x00);
    read(fd, fpga_buffer, len_);
    for(i = 0; i < 10; i++)
        printf("%d\n", fpga_buffer[i]);

    /* WRITE EXAMPLE */
    for(i = 0; i < XFER_LEN; i++)
        fpga_buffer[i] = i*i;

    fpga_master_stream_set_tdest(fd, 0x04);
    write(fd, fpga_buffer, len_);

    close(fd);
[...]
}

Questions:
How do you burst to/from memory over AXI4?
How do you handle 64bit long vectors in the Linux kernel space?
 
gwbs,
NIST, Boulder CO.
gw.
Embedded Systems, DSP, cyber
0 Kudos
4 Replies
trenz-al
Scholar
Scholar
10,455 Views
Registered: ‎11-09-2013

Hi

 

how much of your driver works? writes are not implemented right?

 

we are very interested.. will be trying out now the bleeding code

 

br

Antti

0 Kudos
guillaumebres
Scholar
Scholar
10,445 Views
Registered: ‎03-27-2014

Hey there,

I can at least receive valuable data from the FPGA (read),
writing is implemented but not tested, we are only interested in reading the FPGA right now.
Feel free to use it and upgrade it, keep us updated.

gw.
Embedded Systems, DSP, cyber
0 Kudos
trenz-al
Scholar
Scholar
10,436 Views
Registered: ‎11-09-2013

Hi

 

implemented? in the public GIT source the write function is NOT implemented, do have uncommited changes?

 

static struct file_operations fops = {
  .owner = THIS_MODULE,
  .open = axi_fifo_open,
  .release = axi_fifo_release,
  .read = axi_fifo_read,
  .unlocked_ioctl = axi_fifo_ioctl,
  };

 

read function there, write not, we did see function is there but not in the table?

 

we also need read more than write, but I would like to test

 

 

Antti

0 Kudos
trenz-al
Scholar
Scholar
10,318 Views
Registered: ‎11-09-2013

well we try, really!!

 

1 but your demo apps for sure is not working

2 in the driver code INTerrupt is configured rising, but axi_fifo has level high interrupts?

3 if we modprobe all is fine, but well as soon as we manually send a transaction, the system freees and after a minutes or so kernel crash...

 

we try some more..

0 Kudos