Hi all,
I'm looking for some advice or any technique I can use to debug this problem:
We have a 5505 pulling data from codec into RAM across I2S0 using channels 0 and 1. The testing of this took place primarily when debugging the target with an XDS100 emulator connected to the board (i.e. running from RAM). When the code is written into EEPROM and the built-in bootloader loads the code, the image runs but DMA does not behave in the same way - we never get our DMA interrupt. In my reading of the documentation it states that SPI transfers do not (can not) use the DMA controller, so it's not the bootloader somehow leaving the DMA in a bad state. In any case, we are re-initializing the DMA subsystem with the appropriate CSL_DMA calls (DMA_init).
Thanks in advance,
Rich
Some more update if anyone is still thinking about this problem:
· It doesn’t appear that the problems we’ve seen have anything to do with the actual copying of the image
o I am able to reproduce the problem in the debugger. The steps to do this are:
§ Load the program (or if you’d like, use what’s already in eeprom by just connecting to the target)
§ Reset the CPU (do not use ‘restart’)
§ Hit F8 or RUN when you see that the CPU reset puts the program counter in the bootloader area (0xFF6ADC)
§ The code will run, completely executing the DMA initialization routines (I tested with GPIO). But no DMA interrupts will occur.
§ Now HALT and RUN and dma interrupts appear as does audio moments later.
o The key to this is that the problem occurs when there is no interruption of the CPU between the bootloader and the application image running. For some reason halting anywhere (be it ‘main’ or anywhere after) and continuing allows DMA to suddenly kick in.
· It doesn’t appear that the problems have to do with registers being set improperly by the bootloader and/or not reset properly by the application. I did some register dumps when paused right before the dma starts working and after it starts working and noticed nothing in particular – mostly differences in timer counts, the dma destination address (makes sense, since it auto-increments), real-time clock counts, etc. The key here is that there were no differences in DMA registers or PLL/clock registers.
With all that said, I just noticed that where I break affects whether or not the audio gets detected. I have no idea if this means anything, but if I break at the entry point of the application image (_c_int00), we never get a “StreamIsOn” to evaluate true, and therefore get no xmit or i2s line activity. If I break at main (or later) and continue from there, we do.
Here are a few thoughts:
---------------------------------------------------------------------------------------------------------
Please click the Verify Answer button on this post if it answers your question.---------------------------------------------------------------------------------------------------------
I moved the DMA init above the i2s and codec init but still see the same issues.
I also tried closing the memory window so that a read of the i2srx register when halting wouldn't kick off something unknowingly. The issue was still there.
I probably wasn't very clear when I was mentioning the memory window. I was able to get the memory window to display everything just fine. But I originally had tried to dump register contents using the register view. Unfortunately, it took a little while to realize that the register view window does not provide accurate results for peripheral registers because it is looking in program memory space instead of i/o space.
Have you done any further looking into where you need to halt in order for things to work properly? Have you tried putting a long spin loop in the code (as a substitute for halting)? For example:
volatile unsigned long dummy_loop;
for (dummy_loop=0; dummy_loop<100000000; dummy_loop++);
Don't forget to make the variable volatile or the compiler might get rid of it!
Also, to be clear I don't expect the dummy_loop to be a final solution, just a means of trying to narrow down the issue, i.e. is it timing related, etc.
Can I ask a basic question or two?
When I use the debugger and reset the CPU, the PC points to bootloader code in ROM. If ROM executes, it's going to use what's in EEPROM every time, isn't it? How does the debugger determine when you want the bootloader to pull code from it's nonvolatile source and when it should execute what has just been loaded into RAM?
I feel like I'm missing some information.
If you do a reset and execute from the boot ROM it will always do the exact same thing, i.e. run through the list of boot sources trying to find an image.
if you do not want to execute the boot ROM code you can do a reset followed by a restart which will point the CPU to whatever has been designated the "entry point" to your program, generally _c_int00.
I gave this a try right at the beginning of 'main'. I noticed the delay on the scope (several seconds in my case), but the end result was the same. That seems to indicate that it is still something the debugger is altering somehow when the system is halted and continued.
Solution:
Add this to top of 'main':
--------------------------------------------------------------
*((volatile ioport unsigned *)(0x0001)) = 0x000E; // Enable periph clocks in idle control register
asm("\tnop_16"); // flush the pipeline
asm("\tnop_16");
asm("\tidle"); // execute IDLE instr to apply changes
Glad to hear you fixed it! How did you figure that one out? Brute force comparison of registers? Did you ever figure out how connecting with CCS made a difference, i.e. did you miss a gel file or something?
In any case, I'm glad to hear you fixed it. Also, thank you for reporting back your solution.
Best regards,Brad
Sorry, the fix was found in the user's guide for the DSP (sprufp0a.pdf) section 5.5, clock management. It describes how to set the Idle control register. I had read about the ICR a days or two ago, but didn't realize that the CSL didn't take care of that task when calling the _init routines of the various peripherals. I don't know how feasible it would be to provide feedback in the return status when calling DMA_init that the DMA isn't getting a clock. I sort of assumed when I got CSL_SOK back from all of those configuration routines that things were set up properly.
I'm glad Richard got his application running. I have been 3/4 successful – part of my application runs automatically upon power-up (via boot-loading from NOR Flash on the C5515 ezDSP); part requires a restart via the emulator, but then does run OK.
Here's my situation:
Source data is input from I2S via continuously running (auto-reload) ping-pong DMA, initiated at startup. I2S Input DMA interrupts trigger bursts of processing.
Accumulated processing results are output to the UART via sporadically initiated (not auto-reload) DMA, pending the interrupt that occurred when the preceding UART output DMA transfer completed.
This all runs as soon as the board is powered up and the application is loaded from NOR Flash by the boot loader and started.
Input data is also copied to another buffer and sent back to I2S via continuously running (auto-reload) ping-pong DMA. Each copy operation is initiated by the I2S Input DMA interrupt, pending the interrupt that occurred when the preceding I2S Output DMA transfer completed. Outward-bound DMA is initiated when both banks of the copy buffer have been filled from input buffer. (The two initial copy operations do not pend on the I2S Output DMA interrupt.)
I2S Output does not work at power-up. (There is a brief burst of noise at the output.) After Target->Connect Target, with a GEL file doctored to take no action, followed by Target->Run, it still fails, because it merely resumes execution where it was suspended upon connection.
If symbols have been loaded from the corresponding .out file and Target->Connect is followed by Target->Restart (again, with no GEL activity), returning the PC to the entry point for my application, Target->Run results in fully functional operation.
Similarly, if Target->Connect is followed by Target->Reset->CPU Reset, returning the PC to the boot loader in ROM, Target->Run causes boot loader to reload the application from Flash and start fresh, again with full functionality.
Since my initialization code resets all peripherals, I’m puzzled as to why having run the code once, without success, would somehow set the stage to run it successfully the next time. Does power-up reset involve a race condition with power supplies that leaves the DMA controller or the peripherals in an odd state?
I have included the ICR + NOP + idle operations Richard cites in my initialization C code, along with clock generator and peripheral initialization, modeled after InitSystem() in USB_Stick_Sample\src\main.c (similar to Peripheral_Reset() and ProgramPLL_100MHz() in usbstk5515.gel). I have also incorporated a customized version of csl_init\c5515_init.asm *, modified by me to run before _c_int00 in same manner as reset_isr in USB_Stick_Sample\asm\vector.asm. (This duplicates some of the initialization procedures that occur later in my C code.)
Any clues?
Dan
* See Hyun Kim’s posting in: C5515 CSL - Is the Idle Control (ICR) and Idle Status (ISTR) defined in LOWPOWER CSL
http://e2e.ti.com/support/dsp/tms320c5000_power-efficient_dsps/f/109/p/59334/212336.aspx#212336
D E Ungar,
Here's a strategy to help you track down the dependency:
An update:
If I connect to target after power-up, when I hear no I2S audio out, and set breakpoints, I find that I am getting interrupts for I2S inbound and outbound DMA and my code is executing the copy to the outbound I2S buffer. BUT, when the output is "silent," both the input and copy-buffer data differ from what I see when I hear proper audio via the I2S output. I have not examined the UART output recently, since the wire I had tacked onto the PCB to pick up its output broke loose, but it appears that my problem is with the initialization of the codec or the I2S port configuration and, in the "silent" case I would surmise that I am also processing "silent" data and outputting its processed version through the UART.
Since the data coming from the codec via I2S appears to be garabage, does anyone have any ideas why it would clean up upon re-executing my startup code via Target->Restart, Target->Run?
Brad,
Thanks for the spin-loop trick. I will give it a try in the near future. In the meantime, my resources have been redirected, much as I'd like to keep poking at this. (Since I have to re-flash about 100KB via the XDS100 everytime I try this, it's a slow process.)
OK, I'm getting clues, but still no joy.
If I power up the 'C5515 ezDSP and allow my application to load from Flash and run, I get only a brief burst of noise out.
I therefore thought that perhaps the hot DSP was configuring the codec (via I2C) during main() before it was ready, so I added an arbitrary USBSTK5515_waitusec( 100000 ) from the usbstk5515 BSL (~100 mS wait loop) before doing so, but to no avail.
I then also re-executed the codec configuration routine in my main DSP/BIOS task, immediately before entering my primary processing loop, but still got no recognizable sound.
Then, I noticed that in the Digital Spectrum sample code the codec is initialized before the I2S peripheral. I tried a single codec initialization early in the program (during main() ), followed by I2S configuration some operations later, but still no good. Finally, I added the ~100 mS wait back in before codec initialization; still no good.
I was still able to get each of these configurations to work by breaking in and re-running codec configuration via the emulator.
Any thoughts?