Hello!
I'm trying to catch a Transfer Completion Interrupt from EDMA on the DSP side of OMAP-L138. I'm using channel 10 for my DMA transfer, in its OPT field TCINTEN is set to 1 (INT only on completion). Setting the TCC field is more tricky for me. How should I fill TCC and Scheduling->HWI in Code Composer to attach my function to the interrupt generated by EDMA? Also, should IER be set to (1 << 10) (as the channel number which generates the interrupt), or to the value of (1 << TCC)?
This topic seems similar but it confused me a little bit: http://e2e.ti.com/support/dsp/davinci_digital_media_processors/f/99/p/6711/25716.aspx#25716
RegardsSzymon
Szymon KuklinskiThe interesting thing however is that removing much of the DSPLink code doesn't seem to help. When I comment some time consuming signal processing functions that run in the same Task I do see significant improvement. Such behaviour is odd as Task should not affect ISRs this way.
Are you using the --interrupt_threshold compiler option? If not, that means the compiler is allowed to disable interrupts as long as it wants. There are certain scenarios, generally with very intensive signal processing code, where this can improve performance. So if you are compiling for speed then the compiler will try to "do you a favor" and make the code execute as fast as possible. You should use the --interrupt_threshold to tell the compiler not to disable interrupts for longer than n cycles.
I recommend that you rebuild your entire project adding:
--interrupt_threshold=200
FYI, you don't want to make it TOO small as that can restrict the compiler's ability to generate efficient code. If you make it too big you can run into the issues you're currently experiencing!
One other hint I would recommend for BIOS interrupt prioritization is the following:
Just to be clear, the hardware priority matters little compared to how you configure the interrupt masks in BIOS. The hardware priority only serves as a "tie breaker" in the case where multiple interrupts are pending and the device needs to decide which one to service first. The "interrupt mask" is what decides which interrupts are allowed to interrupt you. When used incorrectly this can often lead to priority inversion.
---------------------------------------------------------------------------------------------------------
Please click the Verify Answer button on this post if it answers your question.---------------------------------------------------------------------------------------------------------
Szymon KuklinskiIs modifying prog.module("TSK").STACKSEG in the TCF file sufficient to acheive what you're suggesting?
I didn't read the whole thread, but the command you mention would cause dynamically created tasks to be allocated wherever you specify. Are you dynamically creating tasks or do you create them statically in the tcf?
Szymon KuklinskiAnd what about moving ISR code to IRAM?
Above the ISR you can do:
#pragma CODE_SECTION(myisr, ".text:fastcode")void myisr(){
}
Then you add your own linker command file and have the following:
SECTIONS{
.text:fastcode > IRAM
Szymon
I recommend trying Brad's suggestion on interrupt_threshold , prior to investigating the memory placement for stack and system stack etc.
Regards
Mukul
Don't forget to verify answers to your forum questions by using the green "Verify Answer" button.
Hi
Here's what I tried:
1) The interrupt_threshold compiler option:
This seemed very promising as what I'm experiencing is relevant to what this option does. I tried several settings of this parameter but even going down to as low as --interrupt_threshold=1 or even omitting the =1 improves my situation only slightly. The interrupts in general do have a lesser delay but still they randomly get shifted so that I'm getting distortions on PCM slots 2 and 3. I recompiled only my project using this option. TI libraries that I'm using I did not recompile.
2) I also tried placing my functions in IRAM in a way Brad suggested. Using the pragma and adding a section in the cmd file did not help however as MAP file still indicates that my functions are in DDR.
3) When I try placing prog.module("TSK").STACKSEG in IRAM like this: prog.module("TSK").STACKSEG = IRAM; I get the following error: js: "./cct_omap_dsp.tcf", line 77: Reference constraint violation: IRAM is an illegal value for TSK.STACKSEG
4) I added the interrupt mask setting as "all" to the TCF file for intrrupts used by EDMA but nothing's changed.
I fear that using EDMA LLD to hook interrupts was not such a good idea considering my time constrains. In your opinion is changing EDMA3 driver that it uses HWIs directly ant not through ECM hard to acomplish?
Also, do you see any pitfalls in using EDMA3 LLD for channel and linking configuration but not for hooking interrupts? I would be doing the latter doing manually.
Which TI libraries were you trying to recompile and what issues did you encounter?
For the new linker command file make sure that you have added it to your project!
Instead of "IRAM" you need to use whatever the name of internal memory is in your tcf file.
If you're asking why I didn't recompile TI's libraries with --interrupt_threshold than the answer is I didn't thought it was necessary. Recompiling DSPLink and EDMA libs should not be a problem. I'm also linking with some DSP/BIOS libs. I'm writing from home and don't have access to my files to check if those DSP/BIOS libs are recompilable or not.
I was wanting to focus on modifying EDMA LLD to use HWIs directly and not through ECM. I'm not quite sure how much effort it would take though but still it's one of the leads to follow.
Syzmon
Yes, that would be the next thing to try. If you attempt it, and run into issues please put them here for the EDMA3LLD experts to review and aid.
EDMA3LLD team is going to work on creating a wiki topic to show how to change the EDMA3LLD code to map to HWI instead of ECM (changes would need to be made in packages\ti\sdo\edma3\drv\sample\src\bios_edma3_drv_sample_init.c file and maybe more places). I am not sure on the time lines yet.
Is this going to be immediate show stopper for you? Is there some local TI support available to you to work through these issues, incase some un-official code snippets needed to be provided to you offline till a formal wiki topic is created?
Also, can you please clarify if you are also making use of DSPLIB for your signal processing functions?
I'm not using DSPLIB. My colleague responsible for signal processing code does make some use of TI's fastrts67x.lib. I recompiled this library yesterday with -mi1 option and built my project against it. Like I mentioned there was only slight improvement.
Unfortunately it is a significant setback for our project, it's been for some time now. We're upgrading our product by switching to a new and faster processor and DSP (OMAP-L138) and the most of our peripherals for our PBX are ready. Having working PCM is crucial for testing and for drawing the final PCB. We already have like a thousand OMAPs in our warehouse waiting for this problem to be sorted out.
I will start modifying the code on my own and see how it goes. At first glance it seems that I need to look into packages\ti\sdo\edma3\drv\sample\src\bios_edma3_drv_sample_init_multi_edma.c (as OMAP-L138 has two EDMA instances) and perhaps packages\ti\sdo\edma3\drv\sample\src\bios_edma3_drv_sample_omapl138_cfg.c.
I have another idea that in my opinion would be quicker to implement. As there are some EDMA LLD specialists helping me with this problem I would like to ask if it is possible to do something like that:
- remove from EDMA LLD all code responsible for registering interrupts and recompiling the library
- in my TCF file doing something like this:bios.HWI.instance("HWI_INT6").interruptSelectNumber = 8; 8 is the EDMA Transfer Completion Interrupt for Shadow Region 1 (DSP)bios.HWI.instance("HWI_INT6").useDispatcher = 1;bios.HWI.instance("HWI_INT6").interruptMask = "all"; so that my ISR doesn't get preemptedbios.HWI.instance("HWI_INT6").fxn = prog.extern("edma_isr");edma_isr would comply to what's written in SPRUGP9A (2.9.2) - checking and clearing IPR etc. because of this interrupt's shared nature
- enabling HWI_INT6 in main():C64_enableIER (C64_EINT6);
- recompiling the whole project against new EDMA LLD and with the changes made
Does this seem as a sensible walkaround do you? My superiors are pushing for a quick fix and not something that would take weeks to implement and test.
Szymon,
This should work theoretically, as you are simply statically connecting the Completion interrupt from EDMA3 IP to the HWI. Though we have not tested any direct static mapping like this, i guess there should be no problem, if you remove all the interrupt registration and handling stuff from the sample library, and then recompile it and use the new library with these changes in your application.
Let us know the development/issues you face in your work with these changes.
Regards,
Sundaram
I was just looking back through the thread and noticed some printf calls in your code. Do you have these sprinkled throughout your code or just a few at startup? FYI, printf will cause MAJOR real-time disruptions. See this wiki page for more details. If that's the case I recommend at least temporarily removing them by either commenting them out or perhaps adding an #ifdef around each of them such that you can selectively turn all the printf statements on or off. Since you're using BIOS a much better option would be to use LOG_printf instead as detailed by this FAQ.
You seem to have had lots of useful technical help here, but glancing through the thread it seems that your software architecture is putting massive pressure on the timing constraints.
Not wanting to wade in to the technical detail here (and assuming I understand your aim correctly) it seems you want to change the source pointer for an EDMA transfer to the McASP after the transfer completes but before the McASP requests a new frame.
This sounds a little crazy...
Surely this is the very purpose the EDMA supports linking (or chaining or ping-pong or whatever the correct TI's terminology is :p).
Assuming you can tolerate a frame's worth of delay through your system you can relax the time to service the interrupt to an entire EDMA transfer (625us, which at 300MHz gives you almost 200K CPU cycles to update this pointer).
When one transfer completes ("ping") the EDMA automatically switches to another transfer context ("pong") which points to the second buffer. You then have all the time in the world to update the source pointer for the first transfer ("ping") before the second transfer completes ("pong") and switches back again.
Again, apologies if I've misunderstood your aim - I hope this helps!