Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++

Problem with SGDMA in ISR

Altera_Forum
Honored Contributor II
1,319 Views

I have a custom SOPC component that acquires 512 bytes of sample data and then signals to the Nios processor that the data is ready via its irq_n line. In the Nios ISR I call alt_avalon_sgdma_construct_mem_to_mem_desc() and alt_avalon_sgdma_do_sync_transfer() to DMA the sample data from the custom SOPC component to a USB peripheral.  

 

This works fine most of the time and I can log the sample data over the USB interface to a PC data file. However occasionally the system hangs. This occurs because somewhere in the chain one or more 512 byte data packets are getting lost i.e. the PC application has requested N data packets and has received less than N so is waiting for more packets, the SOPC component has sent N packets and is waiting for another request from the PC. 

 

The packet loss problem is quite rare, approximately 1 in every million packets is getting lost. 

 

To eliminate some possible sources of the problem I ran the system with the Nios processor responding to requests by DMAing dummy data from RAM (i.e. the custom component was removed). This worked fine so I concluded that the problem was with either the hdl of the custom component or the ISR handling.  

 

I then put the SOPC component back in, added an incrementing variable in the ISR and ran the debugger. When the system hung I broke the code and checked the ISR count. This showed that the ISR had been called the expected number of times but somehow the DMA is occasionally failing so the PC application had received less packets than the ISR count.  

 

Is there a problem with calling alt_avalon_sgdma_construct_mem_to_mem_desc() or alt_avalon_sgdma_do_sync_transfer() in an ISR?  

 

Can anyone explain what is going wrong to me?
0 Kudos
4 Replies
Altera_Forum
Honored Contributor II
423 Views

This one will be tricky but when it runs into this stuck case maybe you can get some information back using Nios II or signal tap to see what state the DMA is in. 

 

From the documentation for alt_avalon_sgdma_do_sync_transfer(): Available from ISR: Not recommended.  

 

So I'm guessing you are running into a race condition if you are starting up the SGDMA from within the ISR.  

 

Maybe the programming model of this SGDMA will be easier to handle in your system: http://www.alterawiki.com/wiki/modular_sgdma
0 Kudos
Altera_Forum
Honored Contributor II
423 Views

If I am going to make some extensive changes (such as switching to a different SGDMA implementation), can I check that this is the preferred solution for what I am trying to achieve. 

 

My aim is to move packets of 512 bytes around my system with the minimum possible latency (so I can take data samples at the highest possible frequency). The packets go in two directions: 

 

1) From an external USB fifo avalon MM-slave interface to M9K buffers in other avalon MM-slave data sampling components (these packets hold information about how the sampling should be performed) 

 

2) From M9K buffers in avalon MM-slave data sampling components back to the USB fifo MM-slave interface (these packets hold sampled data) 

 

In my current solution, the slave components signal that they have packets by interrupting a Nios processor.  

 

In the USB component ISR I setup an SGDMA transfer from the component into Nios RAM. In the Nios software main loop, the packet is analysed and sent on to the appropriate data sampling component using another SGDMA transfer.  

 

In the data sampling component ISR I setup an SGDMA transfer either directly to the USB component (if it's buffer isn't full) or to RAM (if the USB component buffer is full).  

 

 

Given what I am trying to achieve, does a direct swap of the standard Altera SGDMA IP block for the modular SGDMA IP block sound like a sensible route to solving the problem? 

 

If so, will it be a problem that I am using Quartus v7.2sp2? (I see that the mSGDMA examples require Quartus v9.1).  

 

I have seen some other posts that recommend building custom avalon MM-masters to perform functionality similar to the SGDMA. Would this be a sensible course of action?
0 Kudos
Altera_Forum
Honored Contributor II
423 Views

Just in case I am using the SGDMA block incorrectly, here is my code that sets up a dma transfer: 

 

void process_dma_transfer( uint16 descriptor_index, alt_u32* source_ptr, alt_u32* destination_ptr, bool fixed_read, bool fixed_write, bool interrupt_protect ) { uint8 result; alt_avalon_sgdma_construct_mem_to_mem_desc( &desc, // Pointer to descriptor being constructed &desc, // Pointer to next descriptor source_ptr, // Source address destination_ptr, // Destination address USB_MESSAGE_LEN, // Bytes to send (512) (int) fixed_read, // fixed read? (int) fixed_write ); // fixed write? // this bit must be set before each transfer desc.control = desc.control | OWNED_BY_HW_BIT; if (interrupt_protect == TRUE) { // disable interrupt during dma transfer because alt_avalon_sgdma_do_sync_transfer() // isn't thread-safe and it gets called inside the ISR disable_fx2_data_ready_interrupt(); } result = (uint8)alt_avalon_sgdma_do_sync_transfer(DMA, &desc); if (interrupt_protect == TRUE) { // re-enable interrupt after dma transfer enable_fx2_data_ready_interrupt(); } }
0 Kudos
Altera_Forum
Honored Contributor II
423 Views

I'm going to refer to the SGDMA on the ACDS as "SGDMA" and the modular SGDMA as "mSGDMA". The main differences are as follows: 

 

- mSGDMA is only 9.1 and beyond while the SGDMA supports 7.1 and up (mSGDMA requires newer .tcl features) 

- SGDMA requires a descriptor linked-list to be present in memory, mSGDMA just requires a host (Nios II) to write descriptors into the hardware directly 

- SGDMA is a single component while the mSGDMA is made up of 2 or 3 components that can be interchanged 

 

By swapping the DMA engines basically you will be able to do the same thing only on the software side it'll become much simpler. If you have ever used the standard DMA in the ACDS then you can think of the mSGDMA as being the same thing only it buffers multiple descriptors internally. With the elimination of the descriptor linked-list it becomes much easier to manage the hardware since you just send descriptors into the DMA engine and wait for it to complete (or shove more descriptors in while the DMA is operating). 

 

Building up custom masters is a sensible approach as well. As a matter of fact the mSGDMA started off as being a mastering frontend for a USB 2.0 interface before I became distracted and glued them together to form a DMA :) Does your host basically ask for samples from a specific interface? If so you might not even need Nios II at all can can have the host select which sampling device directly over USB.
0 Kudos
Reply