如下所示的程序:
// **************************************************************************************
EDMA3_DRV_Result edmaInitiateXferDoubleChain(const void *dst, const void *src, const int aCnt,
const int bCnt, const int cCnt, const int srcBIdx,
const int destBIdx, const int srcCIdx,
const int destCIdx, const int chCnt)
{
EDMA3_DRV_PaRAMRegs paramSet, *gParamSet;
uint32_t addr;
EDMA3_DRV_Result edmaResult = EDMA3_DRV_SOK;
signed char *srcBuf, *dstBuf;
volatile int coreCnt = determineProcId();
int bIndex; //, cIndex;
if((chCnt<0) || (chCnt>2) || ((chCnt&1) != 0))
{
System_printf("DMA channel (%d) not valid", chCnt);
System_abort("\n");
}
if(bCnt * cCnt > MAX_PARAMS-1)
{
System_printf("Can't handle bCnt(%d)*cCnt(%); max allowed is %d", bCnt, cCnt, MAX_PARAMS-1);
System_abort("\n");
}
srcBuf = (signed char*) getGlobalAddr((signed char *) src);
dstBuf = (signed char*) getGlobalAddr((signed char *) dst);
// set paramSet
paramSet.srcAddr = (unsigned int) srcBuf;
paramSet.destAddr = (unsigned int) dstBuf;
paramSet.aCnt = aCnt;
paramSet.bCnt = 1;
paramSet.cCnt = 1;
paramSet.srcBIdx = 0;
paramSet.destBIdx = 0;
paramSet.srcCIdx = 0;
paramSet.destCIdx = 0;
paramSet.bCntReload = 0;
paramSet.linkAddr = 0xFFFFu;
paramSet.opt = 0x00000000u;
// enable final TCC chaining; only one transfer
paramSet.opt |= (1 << OPT_TCCHEN_SHIFT);
// set TCC to chained channel
paramSet.opt |= ((gEdmaXfer[coreCnt][chCnt+1].tcc << OPT_TCC_SHIFT) & OPT_TCC_MASK);
gParamSet = &globalParamSet[(coreCnt*(EDMA_CHANNELS>>1)+(chCnt>>1))*MAX_PARAMS];
// now write the paramsets to be used by the first of the doubly chained channels
for(bIndex = 0; bIndex <= bCnt; bIndex++)
{
// table of paramSet
gParamSet[bIndex] = paramSet;
// update src and dst address;
paramSet.srcAddr += srcBIdx;
paramSet.destAddr += destBIdx;
if(bIndex == (bCnt-1)) // last in the set
{
// set to be a dummy transfer
paramSet.aCnt = 1;
paramSet.bCnt = 0;
paramSet.cCnt = 0;
// disable chaining
paramSet.opt &= ~(1 << OPT_TCCHEN_SHIFT);
}
}
// ensure gParamSet is written to cache
Cache_wbInv(gParamSet, (bCnt+1)*sizeof(EDMA3_DRV_PaRAMRegs), Cache_Type_ALLD, 1);
// set paramSet; src is global param set; dst is chained PARAMset;
// src increment is size of PARAMset and dst address is always the same
paramSet.srcAddr = (uint32_t) getGlobalAddr((signed char *) &gParamSet[0]);
EDMA3_DRV_getPaRAMPhyAddr(gHEdma[coreCnt/4], gEdmaXfer[coreCnt][chCnt].chId, &addr);
paramSet.destAddr = (uint32_t) getGlobalAddr((signed char *) addr);
paramSet.aCnt = sizeof(EDMA3_DRV_PaRAMRegs);
paramSet.bCnt = bCnt+1;
paramSet.cCnt = 1;
paramSet.srcBIdx = sizeof(EDMA3_DRV_PaRAMRegs);
paramSet.destBIdx = 0;
paramSet.srcCIdx = 0;
paramSet.destCIdx = 0;
paramSet.bCntReload = 0;
paramSet.linkAddr = 0xFFFFu;
paramSet.opt = 0x00000000u;
// both intermediate and final chaining enabled
paramSet.opt |= (1 << OPT_TCCHEN_SHIFT);
paramSet.opt |= (1 << OPT_ITCCHEN_SHIFT);
// final interrupt enabled
paramSet.opt |= (1 << OPT_TCINTEN_SHIFT);
// set TCC to chained channel
paramSet.opt |= ((gEdmaXfer[coreCnt][chCnt].tcc << OPT_TCC_SHIFT) & OPT_TCC_MASK);
/* Now, write the PaRAM Set to the second of the doubly chained channels */
edmaResult = EDMA3_DRV_setPaRAM(gHEdma[coreCnt/4], gEdmaXfer[coreCnt][chCnt+1].chId, (EDMA3_DRV_PaRAMRegs *) ¶mSet);
// start transfer on the second of the doubly chained channels
if(edmaResult == EDMA3_DRV_SOK)
{
edmaResult = EDMA3_DRV_enableTransfer (gHEdma[coreCnt/4],
gEdmaXfer[coreCnt][chCnt+1].chId,
EDMA3_DRV_TRIG_MODE_MANUAL);
}
return(edmaResult);
} // edmaInitiateXferDoubleChain
应该是乒乓模式, 但是我看不懂,希望可以得到解释,困在这里好多天了