All,
I have a customer that is asking for help on how to set up the DMA on the C6455. He is trying to initiate a DMA from a GPIO pin. He cannot make the tranfer happen. Can someone provide a sample or provide the steps for this?
Regards,
Hector Rivera
Specifically, we have a C6455. We have EMIF connected to an FPGA that acts as a FIFO. A low falling edge on GPIO Pin4 signals us the FIFO is ready to be read.
I'd like to simply do an A-synchronized read of roughly 5000 32 bit values from EMIF into memory. This shouldn't be too hard, but I can't get the transfer to occur.
I followed the c6455-csl_03_00_10_02/csl_c6455/example/edma/edma_interrupt example.
I, however, am using SYS/BIOS 6.33.4.39 and am not using the INTC module from the CSL. So I may be doing something wrong.
But I don't even get the DMA occurring... much less calling my ISR (which I setup through BIOS). I see that the GPIO pin is set to FAL_TRIGGER and as an INPUT. I turned on the BINTEN bank interrupt enable. Maybe I'm missing a step. :(
I can provide code if that would help.
Also, one more piece of data. We had an ISR registered to an interrupt on that pin. We were reading it in a while loop previously. I am attempting to offload that onto the DMA engine. That while loop and ISR all worked fine. In SYS/BIOS in my .cfg file, I disabled that ISR and created a new ISR which I hooked up to the DMA Global Completion Event (Interrupt 24).
That should all affect what happens upon completion of the DMA transfer, but again, I never get a transfer. I initialize my buffer to 0x55. I see the GPIO line go low, and I never see the data change. :(
FF,
There seem to be a variety of issues here, so I may not address them all but this should all be able to work.
One thing I am confused about is the while loop + ISR. Usually, a while loop is polling for a GPIO bit to change, so the ISR would be used instead of that while loop. Can you explain the use of the while loop and the ISR together? If you had an ISR being called based on a transition of the GPIO pin, then that is a good step. But in this case it sounds like you might have been polling instead, and in any case you do not want that ISR anymore because the EDMA3 should cause your interrupt once the actual data transfer is completed.
The GP[4] can be setup to cause an EDMA3 event to trigger DMA channel 52. Using CCS, can you examine the registers DCHMAP52, EMRH, ERH, EERH, SERH, IPRH, IERH, and the PARAM for Channel 52 and any link PARAMs. Please post the hex values for those.
As a test for the EDMA being configured, try writing (1 << (52-32)) to ESRH to manually trigger the DMA channel, then look at memory to see if you are getting data written to the destination.
Regards,RandyP
Search for answers, Ask a question, click Verify when complete, Help others, Learn more.
Randy,
Thanks for the quick reply. I'll rephrase slightly. Before we started doing any DMA work, our FPGA would set GPIO Pin4 low, and we had attached an ISR to that event. Inside the ISR, we would read our data with a while loop. So no, we weren't whiling on the GPIO bit. We were getting an ISR on the GPIO, and then reading the data in a while loop. Now we're trying to DMA it out instead. I'll try that debugging and get right back to you. Thanks!
DCHMAP52 : 0x0000 0680
EMRH : 0x0000 0000
ERH : 0x0010 0000
EERH : 0x0000 0000
SERH : 0x0000 0000
IPRH : 0x0000 0000
IERH : 0x0000 0000
Here's the PARAM for Channel 52 from within CCS
PARAMSET_52_OPT 0x80134201 Option [Memory Mapped] PRIV 1 - SUPERVISOR Privilege level _RESV 000 Reserved PRIVID 0000 Privilege ID for external host/cpu/dma ITCCHEN 0 - DISABLE Intermediate transfer completion chaining enable TCCHEN 0 - DISABLE Transfer completion chaining enable ITCINTEN 0 - DISABLE Intermediate transfer completion interrupt enable TCINTEN 1 - ENABLE Transfer completion interrupt enable _RESV 00 Reserved TCC 110100 Transfer completion code TCCMODE 0 - NORMAL Transfer completion mode FWID 010 - 32 Fifo Width _RESV 0000 Reserved STATIC 0 - NORMAL Static entry SYNCDIM 0 - ASYNC Transfer Synchronization Dimension DAM 0 - INCR Destination address mode SAM 1 - FIFO Source address mode
PARAMSET_52_SRC 0xD0000600 Source Address [Memory Mapped]
SRC 11010000000000000000011000000000 Source Address
PARAMSET_52_A_B_CNT 0x00015000 A Count [Memory Mapped] BCNT 0000000000000001 B Count ACNT 0101000000000000 A Count
PARAMSET_52_DST 0x008A8300 Destination Address [Memory Mapped] DST 00000000100010101000001100000000 Destination Address
PARAMSET_52_SRC_DST_BIDX 0x00000000 SRC B Index, DST B Index [Memory Mapped] DSTBIDX 0000000000000000 Destination B Index SRCBIDX 0000000000000000 Source B Index
PARAMSET_52_LINK_BCNTRLD 0x0001FFFF Link Address [Memory Mapped] BCNTRLD 0000000000000001 B Count Reload LINK 1111111111111111 Link Address
PARAMSET_52_SRC_DST_CIDX 0x00000000 Source C Index [Memory Mapped] DSTCIDX 0000000000000000 Destination C Index SRCCIDX 0000000000000000 Source C Index
PARAMSET_52_CCNT 0x00000001 C Count [Memory Mapped] _RESV 0000000000000000 Reserved CCNT 0000000000000001 C Counter
I just did a manual write of event 52 in the ESRH register in the register view of CCS. It triggered a DMA and filled my buffer! :) That's some good news!
Yes, the fact that the ESRH write filled your buffer means that the DMA PARAM is set somewhat correctly. You need to clear SAM since nothing on the C6455 supports the FIFO/constant addressing mode; use the correct indexing instead with SAM=0; And for my sake, please clear FWID because I never see that field set and I confuse easily.
ERH.bit52=1 means that you are getting an event to the EDMA3 from GP[4], which is good news. But EERH needs to have that same bit set before the event will trigger a transfer. This needs to be added to the program. The IERH bit also must be set before the completion of the transfer (which sets IPRH.bit52) will generate an interrupt; this also needs to be added to the program.
If IPRH gets set and IERH is set, and if you have EDMA3CC_GINT routed to a DSP interrupt and the corresponding bit in [the other] IER is set, you should get your ISR triggered.
RandyP FF, 1.) You need to clear SAM since nothing on the C6455 supports the FIFO/constant addressing mode; use the correct indexing instead with SAM=0; 2.) And for my sake, please clear FWID because I never see that field set and I confuse easily.
1.) You need to clear SAM since nothing on the C6455 supports the FIFO/constant addressing mode; use the correct indexing instead with SAM=0;
2.) And for my sake, please clear FWID because I never see that field set and I confuse easily.
1.) "Use the correct indexing instead of SAM = 0" ??? Happy to. I thought using FIFO mode was what I should be doing to talk to a FIFO. How should I change the indexing to act like FIFO mode? I'm not sure I know what you mean by that.
2.) I was just trying to read 32-bit-width data. Is FWID the wrong way to do that? Our EMIF is 32 bits wide. (Not using the top 32 bits of EMIF data lines.) Does this happen automagically somewhere? (Doubting this is the case.) I just assumed I needed to specify the word transfer width. No?
Also, like I said, I'm using the CSL for this. I see that in the EDMA2.x module there's an "EDMA_enableChannel()" API that sets bits in EER and EERH. But I'm using the CSL_edma3 module, and I don't see an API documented in there which sets these bits. Is there a "Right way" to do this? Or should I just declare a pointer to EERH and set the bit myself? I try to use the APIs when possible, as I feel it's more readable.
FastFourier 1.) "Use the correct indexing instead of SAM = 0" ??? Happy to. I thought using FIFO mode was what I should be doing to talk to a FIFO. How should I change the indexing to act like FIFO mode? I'm not sure I know what you mean by that.
Somewhere in the datasheet or EDMA3 User's Guide, it says FIFO mode is not supported. Or more specifically, it will say that it is supported if you come across an internal peripheral that does support it. This has been discussed on the forum before, so a search on some of the relevant terms should find some other discussions on it.
"use the correct indexing instead with SAM=0" was written poorly. "use the correct indexing with SAM=0" is better. Do not use SAM=1 or DAM=1. If you want all the reads to be from the same address, then use ACNT=4 and SRCBIDX=0 and BCNT=0x5000/4 and OPT.SYMCDIM=ABSYNC.
FastFourier 2.) I was just trying to read 32-bit-width data. Is FWID the wrong way to do that? Our EMIF is 32 bits wide. (Not using the top 32 bits of EMIF data lines.) Does this happen automagically somewhere? (Doubting this is the case.) I just assumed I needed to specify the word transfer width. No?
If you configured the EMIF to be 32-bits wide for the addressing space of the FIFO device, then all accesses will use the defined bits. See the EMIF User's Guide for a more complete explanation and to see which bits are used.
Please describe how you want the FIFO device accesses to run.
RandyP Somewhere in the datasheet or EDMA3 User's Guide, it says FIFO mode is not supported. Or more specifically, it will say that it is supported if you come across an internal peripheral that does support it. This has been discussed on the forum before, so a search on some of the relevant terms should find some other discussions on it. "use the correct indexing instead with SAM=0" was written poorly. "use the correct indexing with SAM=0" is better. Do not use SAM=1 or DAM=1. If you want all the reads to be from the same address, then use ACNT=4 and SRCBIDX=0 and BCNT=0x5000/4 and OPT.SYMCDIM=ABSYNC.
OK. I'll make the changes and see if I can get this up and running this morning.
RandyP If you configured the EMIF to be 32-bits wide for the addressing space of the FIFO device, then all accesses will use the defined bits. See the EMIF User's Guide for a more complete explanation and to see which bits are used.
And that's what we've done, so I'll unset that FWID bit.
The CSL comes with examples that show you how to enable a channel. The CSL_edma3HwChannelControl() function has an argument selection that will enable a channel.
If you search this forum for "c6455_edma" (no quotes) and look at the most recent one with a file attachment, you can use that example, too. It corrects some errors in some of the old C6455 CSL examples, but those may have been fixed. It does not use external events, so it does not enable a channel.
Alright. We're so close here! I'm getting DMAs and they're filling the buffer completely. Great news. Thanks for the help Randy.
The only issue left is that my ISR is not triggering.
In my SYS/BIOS .cfg file, I have hooked the function "EDMA_isr()" to event #24, which should be EDMA global completion event.
It seems like I'm going wrong in my code where I try to enable interrupts from the EDMA CSL module.
regionIntr.region = CSL_EDMA3_REGION_GLOBAL; regionIntr.intr = 1 << 24; regionIntr.intrh = 1 << (20);
status = CSL_edma3HwControl( hModule, CSL_EDMA3_CMD_INTR_ENABLE, ®ionIntr ); if( CSL_SOK != status ) {return -1; }
When I do the following, I get no interrupt
regionIntr.region = CSL_EDMA3_REGION_GLOBAL;regionIntr.intr = 1 << 24;regionIntr.intrh = 0;
I thought regionInt.int = 1<<24; would enable event #24, which would be Global EDMA Complete, but apparently I'm misunderstanding the bit masks in intr and intrh. Is there some documentation on what those bits are/mean that I can use to select the correct bits? Thanks again for all of the help!
There are several things that have to be setup for interrupts to get through. You are confusing a couple of them.
FastFourier It seems like I'm going wrong in my code where I try to enable interrupts from the EDMA CSL module. regionIntr.region = CSL_EDMA3_REGION_GLOBAL;regionIntr.intr = 1 << 24;regionIntr.intrh = 1 << (20); status = CSL_edma3HwControl( hModule, CSL_EDMA3_CMD_INTR_ENABLE, ®ionIntr );if( CSL_SOK != status ){return -1;} When I do the following, I get no interrupt regionIntr.region = CSL_EDMA3_REGION_GLOBAL;regionIntr.intr = 1 << 24;regionIntr.intrh = 0;
regionIntr.region = CSL_EDMA3_REGION_GLOBAL;regionIntr.intr = 1 << 24;regionIntr.intrh = 1 << (20);
status = CSL_edma3HwControl( hModule, CSL_EDMA3_CMD_INTR_ENABLE, ®ionIntr );if( CSL_SOK != status ){return -1;}
Does your comment above the last code snippet imply that you do get an interrupt when you do it right with the intrh set? There is the EDMA3 interrupt generation logic with its IPR & IER, the INTC module with its configuration, and the CPU's IFR & IER registers. You should not have the 1<<24 in the EDMA-register section.
Not knowing what exactly is the status, I will recommend you search the forum for "c6455_edma.zip" (no quotes) to find an example project that uses CSL and interrupts. It also includes a good edmaIntDispatcher.c/.h ISR to poll IPR bits for multiple interrupts. And I prefer the long long method of setting the interrupt bits so you do not have do the -32 for intrh; this is in main.cpp.
Also, In the Training section of TI.com, there is a training video set for the C6474. It may be helpful for you to review all of the modules. In particular, the Megamodule Module for interrupts at the system level and EDMA3/QDMA/IDMA Module may help you understand some of the features and options available within the EDMA3 module. You can find the complete video set here.
I was misunderstanding what intr and intrh meant in the context of edma. I thought I was supposed to enable the bit for the global edma completion interrupt, with is 6455 interrupt 24. But the EDMA intr and intrh refer to edma channels, which upon completion, we want to trigger that global completion interrupt. Now I've got it working. Things are working pretty smoothly now, and I'm on to migrating other code to DMAs. Thanks for the help Randy. I'd mark it as answered, but it's Hector's thread.