DSPRelated.com
Forums

intermittent EDMA problems on 6211

Started by Calvert, Paul August 5, 2003
All,

I am using the EDMA to output waveforms to a 4 channel D/A. I use Timer 1 to
synchronize the outputs and initiate each transfer. I would NEVER have
gotten this far without the help of my good friend Maur Gaganjot of TI and
he actually came up with the scheme I am trying to use. My thanks to you
Gagan if you are seeing this... I have bothered him so much with this, I
thought perhaps someone on this forum could help and keep me from wearing
out my welcome with Gagan.

My system configuration is: using all of internal RAM as cache, external RAM
is 2MB, 8MB Flash.

My problem: the EDMA will often not make the transfers. I can set breakpoint
in the one line ISR that writes to ESR to cause the transfer and the
interrupt is happening, but no output occurs. Then, after a random and
indetermined amount of time, all of a sudden the output starts functioning.

Once it 'starts up' I have never seen it stop. But my problem is getting it
to 'start up' EVERY time. When it works, it works great, so I don't see an
EDMA setup issue. Since I am only using these 2 EDMA channels and only the
QDMA, I can't see how I can have an EDMA queueing problem. Perhaps someone
can help here?

I thought the problem was originally the errata with partial SRAM/partial
cache configuration and I changed to 100% cache, but the problem persists.

My setup looks like this:
1. Timer interrupt fires EDMA ch2.
2. Channel 2 updates the destination address of the EDMA ch 8.
3. Completion of EDMA ch 2 transfer will fire the EDMA ch 8 transfer.
Also,
EDMA ch 2 param's will be reloaded (linking)
4. EDMA Ch8 will xfer 1 column of my dac[ch][pts] array to DAC address.
5. Keep repeating 1 - 4 for N times. Then the EDMA ch8, after the 4th
step,
would reload the param's (linking).

For ch 2 transfer, even before the transfer updates the destination
memory(channel 8 dest address), CIPR is set. Because of that the Ch8 is
triggered even though the previous transfer is not over. The reason is, EDMA
assumes that a transfer is finished once it is fired, and not when the data
is actually transfered.

So,I set Ch 2 to have ELECNT=2. Because the SUM and DUM are 0, this has no
effect. It is as good as repeating the xsfer. Generate the timer interrupt
at twice the desired rate. At 1st interrupt, ch2 updates the dest addr of
the ch8. But CIPR is not set as 1 element still remains to be transfered. In
the second sync, ch 2 repeats the same xfer, but the difference is, this
time CIPR is set and the ch 8 is triggered. You can look at this fix in this
way: 1st sync to do the actual job, 2nd sync to start the EDMA ch 8.

My setup code is:

void setup_edma_fgen_multichannel(void)
{
Unsign32 i,k;
Unsign32* wave4_org;
k = EER;
k = EER & 0xFFFFF0FB; // disable func gen events
EER = k;

ECR = 0x00000F04; // clr any pending fgen edma events in the event
clr register //0xffffffff;
CIER = 0;

k = CCER;
k = k | 0x00000100; // Enable chaining for the 8th channel
CCER = k;

//----
// 1st clear all existing fgen EDMA setups
//----
for(i= 8; i<12; i++)
set_edma_param_null(i);
set_edma_param_null(2);

// allocate space for a 'packed' contigous array of all 4 waveforms
wave4 = (Unsign32*) realloc(wave4, dac_out[0].num_pts* 4 *
sizeof(Unsign32));
wave4_org = wave4; // save org because re-arrange of wave[] into
wave4 will hose this pointer
wave4_size1= (Unsign32) dac_out[0].num_pts;

for(i=0; i<4; i++){ // copy any enabled waveforms to our custom
contigous 4x waveform array
if( (fgen_enabled_waveforms_ch_mask & ( (Byte)0x01 << i)) ){ //if
this wave is on, include it in the compacted waveform4 array
for(k=0; k< wave4_size1; k++){ // now the src array for edma will
be contiguous between all waveform channels
*wave4 = wave[i][k]; // at every other timer1 occurance,
the nth item in wave[ch] is xferred (for all x: 0-3)
wave4++;
}//endfor k
} //endif
}//endfor i

wave4 = wave4_org; // change ptr back to wave4[0] from wave4[3][end+1] so
that EDMA setup below
// gets the right (starting) address of weave4 instead
of pointing to the end+1
// of wave4.
//----
//program the ch 2 (timer1 initiated EDMA)
//----
// PRI ESIZE 2DS SUM
2DD DUM TCINT TCC RSVD LINK FS
edma_ch_ptr[2]->options = (Unsign32) 0x40180002; // 010 00 0 00
0 00 1 1000 00000000000000 1 0 =0x40180002
edma_ch_ptr[2]->source = (Unsign32) &dac_addr; // must reload dac
addr since now auto-incrementing thru all 4
edma_ch_ptr[2]->count = (Unsign32) 2;
edma_ch_ptr[2]->dest = (Unsign32) &edma_ch_ptr[8]->dest;
edma_ch_ptr[2]->index = (Unsign32) 0;
edma_ch_ptr[2]->reload_lnk = (Unsign32) ((Unsign32)(edma_ch_link_ptr[2])
& 0xffff);

update_link_param(2); // Updating the LINK area: auto reload the dac
address

//---
// Now we will program the channel 8 EDMA
//---
//PRI ESIZE 2DS SUM
2DD DUM TCINT TCC RSVD LINK FS
edma_ch_ptr[8]->options = (Unsign32) 0x43200003; //010 00 0 11 0
01 0 0000 00000000000000 1 1 = 0x43200003
edma_ch_ptr[8]->source = (Unsign32) wave4;
edma_ch_ptr[8]->count = (Unsign32) ( ((wave4_size1 -1) << 16) +
fgen_enabled_waveforms_count);
edma_ch_ptr[8]->dest = (Unsign32) fpga_slowdac;
edma_ch_ptr[8]->index = (Unsign32) (FRAME_IDX + (wave4_size1 *
FOUR_BYTES_PER_WORD)); // The index is in bytes. We want 1 word for FRMIDX
and
edma_ch_ptr[8]->reload_lnk = (Unsign32) ((Unsign32)(edma_ch_link_ptr[8])
& 0xffff); // for the size of one waveform the ELEIDX

update_link_param(8); // Updating the LINK area: auto reload the waveform
array
// for this special case, the timer period needs to be twice as fast to deal
with the edma ch2 complete problem (see header //comments) so we will double
the last set freq rate

DSP_TIMER1_PERIOD = timer1_period >> 1;
flush_cache();
// attempt to get around EDMA missing events errata:
/* this for loop can probably be commented out since we are no longer
mixed SRAM/cache and the errata should no longer apply-- try before
deleting! */
// pre-read waveforms to get them into L1D per errata*/
for(i=0; i< fgen_enabled_waveforms_count; i++){ //
pre-read waveforms to get them into L1D per errata*/
for(k=0; k< wave4_size1; k++){ // workaround 'code modification' on
pg 11 of SPRZ154H
dummy = *wave4; // this seems to help the problem be
less frequent, but
wave4++; // alas, it is still happening.
}//endfor k
}//endfor i
EER = 0x00000004; //re-enable the timer1 trigger for edma ch 2 to
xfer
}

Thanks,

Paul Calvert