I am trying to port code from a c6713 (EDMA2) to c6747 (EDMA3).
I have various audio (McASP) EDMA transfers operating on PARAMSET 0 thru 5 successfully.
I have been trying to make an EDMA transfer to a 220 x 176 x 16bit LCD module but the resulting large EDMA transfer appears to hold off audio DMA transfers and prevent audio interrupts from occurring in a timely fashion. I thought I saw some evidence that the large transfer was preventing any DSP code from running at all but I am not sure of that now.
I have fiddled with the priorities of TC1,TC0 in the SysCfg register as well as the edma3ccRegs->QUEPRI register.
I am not sure I understand how to assign this LCD DMA transfer to TC1 or TC0 so I can separate its priority from the other higher priority transfers.
I Have also fiddled with edma3tc(0and1)Regs->RDRATE hoping to slow down the transfer requests, all to no avail.
I suspect there may be a way to break up the large transfer using a different setup of acnt and bcnt settings but I don’t know if that will help and I have been unsuccessful in getting that strategy to transfer any data whatsoever.
I am having a second problem with not being able to write to the LCD module's single address data register in non-increment mode. I read that the EMIF will not support this mode when used as a destination since it is not a fifo. Is there any way around this so I can use DMA to transfer to the same EMIFA address repeatedly? I am currently getting around this by isolating the EIMFA address bus from my LCD module temporarily with a PLD. This will become a bigger issue when I apply this transfer strategy to my CF card interface however which also uses a single 16bit data register for sector data transfers.
If this does not get resolved I am planning on using the PRU unit to do the transfers instead.
Below is my test code which manually breaks up the transfer in an inefficient way to prevent audio interrupts from failing.
thanks,
-howy
#define QLCD_PARAMSET_7 7 // LCD block xfer
#define QLCD_TC_CODE 7
void QDMAxfer(ushort *DSTaddr, ushort *SRCaddr, int words16)
{
volatile int i=0, j, Words, WordsPerXfer, tmp;
volatile int acnt,bcnt,srcBidx,dstBidx,bcntRLD,srcCidx,dstCidx,ccnt;
volatile uint16 *p16;
edma3ccRegs->QRAE[0] |= 0xFFFFFFFF; // just let them all thru
edma3ccRegs->QRAE[1] |= 0xFFFFFFFF; // just let them all thru
edma3ccRegs->QRAE[2] |= 0xFFFFFFFF; // just let them all thru
edma3ccRegs->QRAE[3] |= 0xFFFFFFFF; // just let them all thru
WordsPerXfer = 220*2;
acnt = WordsPerXfer; // Words * sizeof(int16);
bcnt = 1;
bcntRLD = 1;
srcBidx = 2;
dstBidx = 0;
srcCidx = 0;
dstCidx = 0;
ccnt = 1; // never leave ccnt as zero!
edma3ccRegs->PARAMSET[QLCD_PARAMSET_7].OPT =
CSL_FMKT(EDMA3CC_OPT_ITCCHEN, DISABLE) |
CSL_FMKT(EDMA3CC_OPT_TCCHEN, DISABLE) |
CSL_FMKT(EDMA3CC_OPT_ITCINTEN, DISABLE) |
CSL_FMKT(EDMA3CC_OPT_TCINTEN, ENABLE) | // set bit 7 of IPR when complete
CSL_FMK(EDMA3CC_OPT_TCC, QLCD_TC_CODE) | // transfer complete code = 12 or 8
CSL_FMKT(EDMA3CC_OPT_TCCMOD, NORMAL) |
CSL_FMKT(EDMA3CC_OPT_FWID, 16BIT) | // word width
CSL_FMKT(EDMA3CC_OPT_STATIC, STATIC) | // NORMAL=0 STATIC=1
CSL_FMKT(EDMA3CC_OPT_SYNCDIM, ASYNC) |
CSL_FMKT(EDMA3CC_OPT_DAM, INCR) | //dst CONST or INCR
CSL_FMKT(EDMA3CC_OPT_SAM, INCR); //src CONST or INCR
// NOTE: src addr and dst addr have limits when using CONST addr mode (32byte boundery)
edma3ccRegs->PARAMSET[QLCD_PARAMSET_7].SRC = (uint32)SRCaddr; // srcBOO; // dstBuff;
edma3ccRegs->PARAMSET[QLCD_PARAMSET_7].DST = (uint32)LCD_DATA_ADDR; // &dstBOO; // dstBuff;
edma3ccRegs->PARAMSET[QLCD_PARAMSET_7].A_B_CNT = CSL_FMK(EDMA3CC_A_B_CNT_ACNT, acnt) | CSL_FMK(EDMA3CC_A_B_CNT_BCNT, bcnt);
edma3ccRegs->PARAMSET[QLCD_PARAMSET_7].SRC_DST_BIDX = CSL_FMK(EDMA3CC_SRC_DST_BIDX_SRCBIDX, srcBidx) | CSL_FMK(EDMA3CC_SRC_DST_BIDX_DSTBIDX,dstBidx);
edma3ccRegs->PARAMSET[QLCD_PARAMSET_7].LINK_BCNTRLD = CSL_FMK(EDMA3CC_LINK_BCNTRLD_LINK, 0xFFFF ) | CSL_FMK(EDMA3CC_LINK_BCNTRLD_BCNTRLD,bcntRLD);
edma3ccRegs->PARAMSET[QLCD_PARAMSET_7].SRC_DST_CIDX = CSL_FMK(EDMA3CC_SRC_DST_CIDX_SRCCIDX, srcCidx) | CSL_FMK(EDMA3CC_SRC_DST_CIDX_DSTCIDX,dstCidx);
edma3ccRegs->PARAMSET[QLCD_PARAMSET_7].CCNT = ccnt;
//hdelayMS(10); // wait for cache
BitPLD(baForceLCDA0,1); // force DATA writes to PLD so address bit cannot change (FRONT_A0=1)
p16 = (uint16 *)SRCaddr;
for(j=0;j<(220*176)/(WordsPerXfer/2);j++) // size of LCD is 220x176 16bit words (EMIFA is 16bits wide)
{
edma3ccRegs->PARAMSET[QLCD_PARAMSET_7].SRC = (uint32)SRCaddr;
SRCaddr += WordsPerXfer/2;
edma3ccRegs->ICR = (1<<QLCD_PARAMSET_7); // clear iterrupt pending bit
edma3ccRegs->ESR = (1<<QLCD_PARAMSET_7); // event set reg
for(i=0;i<1e9;i++)
{
tmp = edma3ccRegs->IPR; // wait for EDMA transfer to finish
if(tmp & (1<<QLCD_PARAMSET_7))
break;
}
hdelay(gboodly);
tmp = edma3ccRegs->IPR; // for debug
}
return;
}