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 |
intermittent EDMA problems on 6211
Started by ●August 5, 2003