UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Participant a.gamez
Participant
683 Views
Registered: ‎05-12-2016

AXI DMA Interrupt on complete

Jump to solution

Hi,

 

I'm having trouble with this core when trying to use interrupts. I don't understand the documentation and I've been tinkering a lot with the buffer descriptions without any luck, so I'd really appreciate some insight on this.

I'm doing a very easy test that looks like this:

        bzero(&bd[0], sizeof(*bd));
        bd[0].next_desc = 0x8fe40000 + sizeof(struct buffer_descriptor);
        bd[0].buffer_address = 0x8f800000;
        bd[0].control = TRANSFER_SIZE;

        bzero(&bd[1], sizeof(*bd));
        bd[1].next_desc = bd[0].next_desc + sizeof(struct buffer_descriptor);
        bd[1].buffer_address = bd[0].buffer_address + TRANSFER_SIZE;
        bd[1].control = TRANSFER_SIZE;

        _write32(dma_handler, axi_dma, S2MM_DMACR, S2MM_DMACR_RESET);
        _write32(dma_handler, axi_dma, S2MM_CURDESC, 0x8fe40000);
        _write32(dma_handler, axi_dma, S2MM_DMACR, S2MM_DMACR_RS | S2MM_DMACR_IOC_IrqEn | S2MM_DMACR_Err_IrqEn);
        _write32(dma_handler, axi_dma, S2MM_TAILDESC, bd[0].next_desc);

 

What I expect of this is for two transfers to happen of size TRANSFER_SIZE and it does in fact transfer the amount of data I request to the positions I request, but there's not even a single interrupt! I'd like to receive one interrupt when each buffer descriptor DMA definition has succeeded. However, I'm not even able to get an interrupt at the end of both transfers. IOC is simply not working at all. I've tried different variations of S2MM_CONTROL_RXSOF and S2MM_CONTROL_RXEOF, but I'm not working in microdma mode, so they don't seem to do anything at all.

I've read on some other posts that I need to assert tlast signal in the HDL design, but that is not feasible, among other reasons because I do not know the size of the transfer and tlast doesn't have any meaning at all in a streaming system, I'm just trying to transfer a continuous transfer of ADC data to memory, managed by software. Depending on an external clock, desired sampling frequency and lots of factors, a transfer could be of 512 bytes, 4096, 65536, or even a non power of two number of bytes; so there's no logic at all that can define the use of tlast.

What's the issue here, how do I manage this?

Thank you, best regards!

Tags (4)
0 Kudos
1 Solution

Accepted Solutions
Xilinx Employee
Xilinx Employee
645 Views
Registered: ‎01-09-2019

Re: AXI DMA Interrupt on complete

Jump to solution

Hello @a.gamez 

A couple notes and hopefully helpful resources.  Have you looked at the AXI DMA example code and designs?  This Answer Record provides some example designs to start with if you want to do a few transfers quickly and see how Xilinx has done AXI DMA in the past: https://www.xilinx.com/support/answers/57550.html

As well we have some useful code examples for the bare metal drivers for AXI DMA's various use cases that can be found here: https://gitenterprise.xilinx.com/embeddedsw/embeddedsw/tree/master/XilinxProcessorIPLib/drivers/axidma/examples

The file xaxidma.h has some documentation at the top that shows how our driver is written, and what is going on behind the scenes when using the example code.  There are also a lot of helpful functions to make configuring AXI DMA a little easier.

To your issue at hand, I notice that you have not turned on interrupts in the Control Register (S2MM_DMACR or MM2S_DMACR).  The IRQThreshold must be a value of non-zero and IOC_IRqEn set to 1 at the minimum to receive an interrupt firing on the completion of a transferred descriptor(s).  This also assumes that the processor irq port and AXI DMA IP introut ports are connected properly in hardware.  The example designs above should have most of this configured properly, but may need to be altered to your specific hardware/processor.

Unfortunately TLAST is required based on the AXI4-Stream specification in order to tell AXI DMA that there is an end of data.  This will be the way that RXEOF will be set (with RXSOF based on the first address given to DMA), in the Status register.  If TLAST is not set then AXI DMA will not know to end the transaction which will lock up your system.

I describe here a way to do this even if you don't know your data size: https://forums.xilinx.com/t5/AXI-Infrastructure/AXI-DMA-in-S2MM-mode-and-assertion-of-TLAST-question/m-p/939751#M2448 .  You could send TLAST for every x amount of data.  The way AXI DMA is setup, you create a Buffer Descriptor ring and AXI DMA will use the first Buffer Descriptor (BD) to read from that buffer.  If that is all the data you asked for (TLAST was sent), then AXI DMA is done.  If there is more data to be retreived then it goes on to the next BD.  AXI DMA repeats this process until it retrieves all the data you asked for (then sets the RXEOF), or you run out of BDs (error).

Thanks,

Caleb

Thanks,
Caleb
-------------------------------------------------------------------------
Don’t forget to reply, kudo, and accept as solution.
-------------------------------------------------------------------------
6 Replies
Xilinx Employee
Xilinx Employee
646 Views
Registered: ‎01-09-2019

Re: AXI DMA Interrupt on complete

Jump to solution

Hello @a.gamez 

A couple notes and hopefully helpful resources.  Have you looked at the AXI DMA example code and designs?  This Answer Record provides some example designs to start with if you want to do a few transfers quickly and see how Xilinx has done AXI DMA in the past: https://www.xilinx.com/support/answers/57550.html

As well we have some useful code examples for the bare metal drivers for AXI DMA's various use cases that can be found here: https://gitenterprise.xilinx.com/embeddedsw/embeddedsw/tree/master/XilinxProcessorIPLib/drivers/axidma/examples

The file xaxidma.h has some documentation at the top that shows how our driver is written, and what is going on behind the scenes when using the example code.  There are also a lot of helpful functions to make configuring AXI DMA a little easier.

To your issue at hand, I notice that you have not turned on interrupts in the Control Register (S2MM_DMACR or MM2S_DMACR).  The IRQThreshold must be a value of non-zero and IOC_IRqEn set to 1 at the minimum to receive an interrupt firing on the completion of a transferred descriptor(s).  This also assumes that the processor irq port and AXI DMA IP introut ports are connected properly in hardware.  The example designs above should have most of this configured properly, but may need to be altered to your specific hardware/processor.

Unfortunately TLAST is required based on the AXI4-Stream specification in order to tell AXI DMA that there is an end of data.  This will be the way that RXEOF will be set (with RXSOF based on the first address given to DMA), in the Status register.  If TLAST is not set then AXI DMA will not know to end the transaction which will lock up your system.

I describe here a way to do this even if you don't know your data size: https://forums.xilinx.com/t5/AXI-Infrastructure/AXI-DMA-in-S2MM-mode-and-assertion-of-TLAST-question/m-p/939751#M2448 .  You could send TLAST for every x amount of data.  The way AXI DMA is setup, you create a Buffer Descriptor ring and AXI DMA will use the first Buffer Descriptor (BD) to read from that buffer.  If that is all the data you asked for (TLAST was sent), then AXI DMA is done.  If there is more data to be retreived then it goes on to the next BD.  AXI DMA repeats this process until it retrieves all the data you asked for (then sets the RXEOF), or you run out of BDs (error).

Thanks,

Caleb

Thanks,
Caleb
-------------------------------------------------------------------------
Don’t forget to reply, kudo, and accept as solution.
-------------------------------------------------------------------------
Participant a.gamez
Participant
623 Views
Registered: ‎05-12-2016

Re: AXI DMA Interrupt on complete

Jump to solution

Thanks!

 

I was completetly missing the tlast signal. This is not quite documented at all in the datasheet, it would be great if your response were in that document itself.

If I set the DMA to work in cyclic mode I can fill up a circular buffer with a seeming-continuous stream. However, how can I know which is the last buffer written to?

For example, let's say I prepare 4 buffers in a circular fashion

A -> B -> C -> D [--> A -> B -> -> C -> D]

If i manage to receive an interrupt either slot by slot or maybe once every few transactions, in the moment of receiving the interrupt, how do I know which is the buffer information was written to last? How do I know if data is ordered ABCD or maybe CDAB, because buffers A and B still have the data that was written to them in the previous iteration of the cyclic transfer?

 

Thanks!

0 Kudos
Xilinx Employee
Xilinx Employee
610 Views
Registered: ‎01-09-2019

Re: AXI DMA Interrupt on complete

Jump to solution

@a.gamez 

That would be what the RXSOF/TXSOF and RXEOF/TXEOF bits are for in the respective Status register (MM2S or S2MM).  The *SOF should indicate which BD was first in the loop, with *EOF being the last in the chain.

With Cyclic mode you have to keep track of a few more things in software, one of which is that order.  As well, you will have to figure out in SW how you will track information, particularly depending on how you are triggering your interrupt.  If you are working with Cyclic mode, have you looked at the example design for Cyclic mode (xaxidma_example_sgcyclic_intr.c)?  That will show how Xilinx handles working with Cyclic mode, and keeping track of information.

Of note, that example does have a known issue that I have described here (towards the bottom): https://forums.xilinx.com/t5/AXI-Infrastructure/AXI-DMA-SG-Cyclic-mode-BD-ring-size-vs-BD-allocated-number/m-p/937073#M2421  .  If you are altering how interrupts are fired, then this will probably pop up as an issue.

Thanks,
Caleb
-------------------------------------------------------------------------
Don’t forget to reply, kudo, and accept as solution.
-------------------------------------------------------------------------
Participant a.gamez
Participant
569 Views
Registered: ‎05-12-2016

Re: AXI DMA Interrupt on complete

Jump to solution

Hi again @calebd 

I have a cyclic transfer going on but I'm facing still a couple of doubts on the behaviour of the DMA core. I read the example xaxidma_example_sgcyclic_intr.c but I just can't grasp what a real use case would look like.

Let's say I have a tlast signal every 512 bytes and I set 4 buffers with a transfer size of 512 each one. So this is the result. As you can see, since the DMA core only modifies the current BD it's processing, there's really no way for me to know which BD has been processed, because once the cycle has gone back to the first descriptor, it reaches a permanent state in which I can't know what's going on and I can't know which is the last BD that was processed, since all descriptors just keep on having exactly the same data.

I guess I can use the interrupt counter I have set in place to just now that one interrupt means one BD increment, but that sounds a bit strange. Shouldn't this be managed by the core someway?

Status: 65544
BD 0. Transferred bytes: 0
BD 1. Transferred bytes: 0
BD 2. Transferred bytes: 0
BD 3. Transferred bytes: 0
Waiting for interrupt

INTERRUPT 146 !!
S2MM_IOC_Irq

Status: 65544
BD 0. Transferred bytes: 512
BD 0. Complete!
BD 0. RXSOF
BD 0. RXEOF
BD 1. Transferred bytes: 0
BD 2. Transferred bytes: 0
BD 3. Transferred bytes: 0
Waiting for interrupt

INTERRUPT  147 !!
S2MM_IOC_Irq

Status: 65544
BD 0. Transferred bytes: 512
BD 0. Complete!
BD 0. RXSOF
BD 0. RXEOF
BD 1. Transferred bytes: 512
BD 1. Complete!
BD 1. RXSOF
BD 1. RXEOF
BD 2. Transferred bytes: 0
BD 3. Transferred bytes: 0
Waiting for interrupt

INTERRUPT  148 !!
S2MM_IOC_Irq

Status: 65544
BD 0. Transferred bytes: 512
BD 0. Complete!
BD 0. RXSOF
BD 0. RXEOF
BD 1. Transferred bytes: 512
BD 1. Complete!
BD 1. RXSOF
BD 1. RXEOF
BD 2. Transferred bytes: 512
BD 2. Complete!
BD 2. RXSOF
BD 2. RXEOF
BD 3. Transferred bytes: 0
Waiting for interrupt

INTERRUPT  149 !!
S2MM_IOC_Irq

Status: 65544
BD 0. Transferred bytes: 512
BD 0. Complete!
BD 0. RXSOF
BD 0. RXEOF
BD 1. Transferred bytes: 512
BD 1. Complete!
BD 1. RXSOF
BD 1. RXEOF
BD 2. Transferred bytes: 512
BD 2. Complete!
BD 2. RXSOF
BD 2. RXEOF
BD 3. Transferred bytes: 512
BD 3. Complete!
BD 3. RXSOF
BD 3. RXEOF
Waiting for interrupt

INTERRUPT  150 !!
S2MM_IOC_Irq

Status: 65544
BD 0. Transferred bytes: 512
BD 0. Complete!
BD 0. RXSOF
BD 0. RXEOF
BD 1. Transferred bytes: 512
BD 1. Complete!
BD 1. RXSOF
BD 1. RXEOF
BD 2. Transferred bytes: 512
BD 2. Complete!
BD 2. RXSOF
BD 2. RXEOF
BD 3. Transferred bytes: 512
BD 3. Complete!
BD 3. RXSOF
BD 3. RXEOF
Waiting for interrupt

Another option would be to set DMA transfer to be TOTAL_BYTES_TLAST / NUMBER_OF_DESCRIPTORS i.e. 512/4 bytes, in which case I end up having the following permanent regime:

Status: 65544
BD 0. Transferred bytes: 128
BD 0. Complete!
BD 0. RXSOF
BD 1. Transferred bytes: 128
BD 1. Complete!
BD 2. Transferred bytes: 128
BD 2. Complete!
BD 3. Transferred bytes: 128
BD 3. Complete!
BD 3. RXEOF
Waiting for interrupt

So in this case I will receive only one interrupt per TLAST bytes transferred, and I will always know which is the first block, but this seems to defeat the purpose of a cyclic transfer, because then, why wouldn't I just create a single descriptor with the full size?

Given all this, I just can't comprehend what would be a realistic way of using this functionality: someway the core should be able to tell me what's really been the last transfer.

0 Kudos
Xilinx Employee
Xilinx Employee
552 Views
Registered: ‎01-09-2019

Re: AXI DMA Interrupt on complete

Jump to solution

@a.gamez 

So Cyclic mode is pretty simple in its implementation.  Basically it ignores the Completed bit, and in the example design there is a known bug because that Completed bit is how the example driver is determining if a BD has been transferred.  Could you look at the above forum post I linked (specifically the code block by vlenoir and my subsequent reply)?  That should fix your Completed bit issue, and I think will fix your RXEOF/RXSOF issue as I am guessing that will reset those bits as well since the BD will be processed again since the Completed bit wouldn't be set anymore.

Thanks,
Caleb
-------------------------------------------------------------------------
Don’t forget to reply, kudo, and accept as solution.
-------------------------------------------------------------------------
Participant a.gamez
Participant
522 Views
Registered: ‎05-12-2016

Re: AXI DMA Interrupt on complete

Jump to solution

Hi @calebd 

 

I see that what vlenoir does is to reset via software the complete bit of all descriptors that have it enabled, so next time an interrupt occurs, only those descriptors with the complete bit enabled will need to be read. If I understand it correctly, you're proposing for me to do exactly that and also maybe reset all of the status register, so RXEOF/RXSOF are also cleared in software and next time an interrupt occurs only those  descriptors with the complete, RXEOF, RXSOF bits enabled will be of interest.

I see that for this to work my software needs to react to interrupts at a rate faster than what the DMA core is cycling over the whole set of descriptors, but that's not a problem because anyway it's clear that my software needs to run faster than that, otherwise I would be missing data from the transfer.

I will be testing this throught the day, but I think you've given me a nice solution for every issue I had, so thanks a lot!

0 Kudos