Forum Discussion
SGDMA debug
Hello,
I am trying to learn how to use SGDMA to transfer data to memory. First of all, I am trying to connect SGDMA TX directly to SGDMA RX and check results. You can find the source code ->here<- (http://www.codeupload.com/4051) (I've edited the code found on forum, so thanks the guy who provided it). In order to check what is written to the memory, I've connected the SGDMA modules to ONCHIP memory (size: 32768 bytes) and enabled memory content reader on the on-chip memory options. You can see my connections ->here<- (http://i51.tinypic.com/1zz6fj5.png). The problem is that this dma design doesn't work. The data I get is corrupted. I've tried to disconnect cpu.instruction_master and cpu.data_master from onchip memory, then the memory start address goes to 0x00, but results are the same. If I connect the DMA to the DDR memory, then the data passes correctly, Screenshot is ->here<- (http://i53.tinypic.com/2heak61.png). Now why I get this situation: either I try to read or write from/to onchip memory or DDR memory, the core always tries to read/write from/to address 0x800xxxxx. Obviously when it is connected to DDR ram it works, but when to onchip ram it doesn't. Why is this happening? Nios memory bus bugs? How can I check what is written to the memory? If I use only onchip memory for the whole system and DMA it also works fine, but I want a clear vision without Nios stuff in the memory. Thanks.55 Replies
- Altera_Forum
Honored Contributor
This is the only one I know of: http://www.alterawiki.com/wiki/modular_sgdma_video_frame_buffer
That's my mSGDMA though. The mSGDMA design example is configured for MM-->MM but it supports MM-->ST and ST-->MM as well just like the SGDMA. Complicated descriptor APIs is the price you pay for having the ability to have the SGDMA pre-fetch descriptors. Most don't need that pre-fetching so I excluded it in my implementation and made it a feature on my todo list instead. If you do switch DMAs I recommend sticking to the SGDMA installed with Quartus for ethernet stuff since I haven't heard of anyone bolting my hardware up to the nichestack.... yet. - Altera_Forum
Honored Contributor
Yeah, I've seen here in forums that mSGDMA is Your creation. Great job! I think I will have to dig the INiche source or other already written source, since it is really hard to understand how to make it run from a scratch.
- Altera_Forum
Honored Contributor
Ok I am moving forward.
I've written a code, which successfully takes data from Avalon-ST and writes to the memory. The code is available ->here<- (http://www.codeupload.com/4087). Now when I check the memory contents, I see data written after SOP(Start Of Packet) until EOP(End Of Packet). So SGDMA generates interrupt, status says that EOP is found, descriptor completed and chain is completed. To continue the operation, I thought I had to write do_async_transfer again into SGDMA transfer complete interrupt routine, but that's not working. I suppose I need to set up descriptors again? How can I make the stream-to-memory transfer always continuous? Now it is done once and thats it. - Altera_Forum
Honored Contributor
The easiest way would be to have a second descriptor chain ready to go so that when the interrupt fires from the completion of the first chain you can quickly write the start of the second chain. Unfortunately this means you will have a little bit of dead time between the chains.
Another way to do this is to start building up the second chain which is linked to the first one but make sure the owned by hardware bit isn't set on the beginning of the second chain. Then it becomes a matter of flipping that bit and starting the SGDMA back up. Again this will lead to some dead time between descriptors. Last but not least you could use a polling approach to figure out where the SGDMA is in the chain. Using this same owned by hardware bit flipping approach if you can create the second descriptor chain and flip that bit fast enough then there will be no dead time between the descriptor chains. That said you have to worry about race conditions since you'll have two masters (CPU and SGDMA) accessing the same memory location. This trickiness is why I made it possible to fire an interrupt on the completion of any descriptor in my implementation. - Altera_Forum
Honored Contributor
Take a look at one of the examples on the NEEK board (like the C2H Mandlebrot design). The video support files use the park mode to ensure the owned by hardware bits in each descriptor remain set so that you can loop a descriptor chain back on itself. This might do what you are looking for.... again watch out for race conditions when doing this.
- Altera_Forum
Honored Contributor
--- Quote Start --- The easiest way would be to have a second descriptor chain ready to go so that when the interrupt fires from the completion of the first chain you can quickly write the start of the second chain. Unfortunately this means you will have a little bit of dead time between the chains. Another way to do this is to start building up the second chain which is linked to the first one but make sure the owned by hardware bit isn't set on the beginning of the second chain. Then it becomes a matter of flipping that bit and starting the SGDMA back up. Again this will lead to some dead time between descriptors. Last but not least you could use a polling approach to figure out where the SGDMA is in the chain. Using this same owned by hardware bit flipping approach if you can create the second descriptor chain and flip that bit fast enough then there will be no dead time between the descriptor chains. That said you have to worry about race conditions since you'll have two masters (CPU and SGDMA) accessing the same memory location. This trickiness is why I made it possible to fire an interrupt on the completion of any descriptor in my implementation. --- Quote End --- Hm, well it gives me status result of 0x8e, which says that the chain is complete. Is there a method to start the same chain again? I suppose I have two descriptors prepared in my current chain. I can wait a small period of time since I have to receive a packet and place it to InterNiche packet buffer, which is a small struct with some additional variables. - Altera_Forum
Honored Contributor
In order to re-use the same descriptor chain you'll need to go through the chain and set the owned by hardware bit back on (SGDMA turns those off to let you know it has worked on them). Then you will start up the SGDMA the same way you did the last time.
- Altera_Forum
Honored Contributor
So basically all the allocation procedures & descriptor set up again? Anyway, lets clarify this: in order to continue sgdma to work, I have to do all the set up in sgdma complete interrupt, so it would drop again in the same interrupt and I would set up it again, etc etc forever...?
- Altera_Forum
Honored Contributor
Pretty much. The reason why the SGDMA didn't work on the second time was the the owned by hardware bits were low. So you could reuse those descriptors by just flipping those bits back to being high (like they were for the first time those descriptors were populated in RAM)
- Altera_Forum
Honored Contributor
Ok, thanks, I will try that out.