cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
giorgio.lopez
Observer
Observer
7,960 Views
Registered: ‎02-02-2012

How to use custom IPs in Embedded Linux

Hello,

 

I have designed and implemented two IP cores in Vivado.

 

The first is a HLS implemented block (realized with the Vivado HLS video libraries(, with AXI interfaces and connected with a Video DMA. I should send cv::Mat objects to it somehow.

 

The second one is a custom designed block which also uses streaming AXI interfaces which is connected with a normal AXI DMA.

 

In both cases, I know how to interact with those units on a bare-metal application, using the BSP provided drivers. But, when it comes to Linux/Petalinux? Where do I find headers and functions like the one provided automatically by the standalone (bare-metal) os?

 

Thanks a lot for your help.

 

Giorgio

0 Kudos
5 Replies
guillaumebres
Scholar
Scholar
7,956 Views
Registered: ‎03-27-2014


@giorgio.lopez wrote:
The first is a HLS implemented block (realized with the Vivado HLS video libraries(, with AXI interfaces and connected with a Video DMA. I should send cv::Mat objects to it somehow.

Compile the VDMA kernel module, which you can find right there

https://github.com/Xilinx/linux-xlnx/tree/master/drivers/dma/xilinx

 

then you need to write your own module to map to this new dma channel, this has been mentionned on several topics.

Finally you write a userspace program which opens this channel and send some data over it.

 


@giorgio.lopez wrote:

The second one is a custom designed block which also uses streaming AXI interfaces which is connected with a normal AXI DMA.


basically the same thing, I have never used VDMA but I think it handles 2D data compared to regular DMA module.

 


@giorgio.lopez wrote:

In both cases, I know how to interact with those units on a bare-metal application, using the BSP provided drivers.


If you are not familiar with kernel modules, you need the hardware address to address the DMA module.

In bare-metal you accessed those addresses directly, in Linux you address them through virtual addresses mapped to physical addresses.

A DMA transaction is a little different than regular bus transactions in the sense it allows you not to address each word, the CPU sets the destination address, waits for an end of transfer interrupt, the DMA controller handles the transfer.

 


@giorgio.lopez wrote:
Where do I find headers and functions like the one provided automatically by the standalone (bare-metal) os?

you need to use the Linux kernel APIs, in this project you will need the DMA API basically

 

#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>

plus learn how to memory map and handle interrupts.

 

Relevant Docs:

The Bible - heavy but I seriously recommend reading it a couple of times to understand key chapters

Linux DMA API

Might be of some interests

DMA from user space (Xilinx) - great

DMA in kernel space (Xilinx) - great

 

gw.
Embedded Systems, DSP, cyber
0 Kudos
giorgio.lopez
Observer
Observer
7,798 Views
Registered: ‎02-02-2012

Ok, so, basically in the two situation my "interaction points" with the IP are three:

 

1 input port (AXI STREAM - connected to a DMA/VDMA)

2 output port (as above)

3 "control" port (AXILITE SLAVE control and status registers and ap_start ap_ready etc signals)

 

Am I correctly assuming that I can interact (at least with ports 1 and 2) without getting into kernel space programming, using the mmap method?

 

What about exposing to a userspace programs the physical addresses to which are mapped the status and control registers of my IP (which correspond to a very small addressing space, like 4 or 8 words)? Should I use the mmap method here, too?

 

Thanks a lot

0 Kudos
guillaumebres
Scholar
Scholar
7,791 Views
Registered: ‎03-27-2014

 

@giorgio.lopez,

yes that is correct. Actually the minimum requiere is controlling(HDL) the input 1/ AXI stream that goes the AXI DMA IP. The AXI-DMA IP then handles the AXI 'DMA' flow going to the SoC (AXI output).

 

I don't know what you mean with this 3rd port, if that is additional control from the user over the streamer based on AXI-Lite, then yes you have to address these registers. I would use MMAP for data buffers instead of simple registers addressing.

 

For addressing, in kernel space you have to:

 

    // old fashion 
sdev->regs = ioremap(mem_res->start, resource_size(mem_res));
// new API
sdev->regs = devm_ioremap_resource(&pdev->dev, res);

which gives you a virtual pointer sdev->pointer to address these registers from the kernel space.

Then I would use the IOCTL File system entry to quicly access these registers:

 

static long driver_ioctl(struct file *filep, unsigned int cmd,
    unsigned long arg){
    switch(cmd){
        case SET_RDY_CMD:
            fpga_set_ready_bit();
            break;
[..]

You can use the /dev/mem driver directly from a userspace main.c program. This drivers allows you mmap whatever address you want directly from userspace,  see reading physical mapped memory /dev/mem. Could be used for quick tests.

 

gw.
Embedded Systems, DSP, cyber
0 Kudos
giorgio.lopez
Observer
Observer
7,758 Views
Registered: ‎02-02-2012

Oh ok, I got the AXILite interface on my IP working, it actually was very easy.

 

Now what I should do is allocating two buffers for the DMA transfers (the Mem->Dev buffer and the Dev->Mem buffer) and be able to start the DMA transaction. Should I do it from Kernel space by layering a driver over the DMA engine? I am currently looking at the axidmatest.c example but it looks fairly complicated.

 

Moreover, while it's clear to me that to begin the transfer to my IP I should just start the  MEM->DEV DMA transaction, I'm not sure about what should I do to get my results back: from a logical point of view the IP should initiate the transfer on the DEV->MEM channel. Probably the best way is to use an interrupt triggered by some sort of "output_valid" signal from my IP, is that correct?

 

But (this would be an interesting option) can I also just tell the DEV->MEM DMA to start its transfer as well, assuming it will then just wait for incoming data from its S2MM AXIS interface?

 

Thanks a lot

 

 

 

0 Kudos
giorgio.lopez
Observer
Observer
7,731 Views
Registered: ‎02-02-2012

@guillaumebres

 

I'm now trying to understand how to use the DMA.

 

 

I'm trying the approach shown in the video from Xilinx Video Lounge "Linux DMA in Device Drivers": what is unclear to me is, after I've compiled a "channel-specific" DMA driver as a module, which will use the DMA engine (layered with the Xilinx DMA / VDMA driver, depending on the channel I'm looking for), how do I access the kernel module? Does it export some system calls? It's my first time working with kernel modules so thank you for your patience. I have read part of the Linux Device Drivers guide's 15th chapter but what I really would find precious in this moment would be a complete example (I mean, both the kernel-space proxy driver and the user-space application)

 

Thanks

0 Kudos