HI:
我们最近想要在DM8127上的M3核上用EDMA实现1080p的YUV422转成YUV420SP的格式转换,我参考了How to Use the EDMA3 Driver on a TMS320DM643x
Device 这个文档,在IPNCRDK3.5里发现并没有现成的EDMA的API函数可以调用,我的想法是这样的把YUV422 分拆成 Y 和UV分两次搬运EDMA一步完成420SP的数据转换 实现的函数如下:
void DM81XX_EDMA3_setParams_test(int chId,
int dmaQueue,
unsigned int srcAddr,
unsigned int dstAddr,
int acnt,int bcnt,int ccnt,
int srcBIdx,int destBIdx,
int srcCIdx,int destCIdx,
unsigned int bCntReload)
{
volatile unsigned int PaRAMEntryAddr =
DM81XX_EDMA3_PARAM_BASE + (chId * 0x20);
volatile unsigned int dchmapChId = DM81XX_EDMA3_DCHMAP0 + (chId * 4);
volatile unsigned int dmaQnum = DM81XX_EDMA3_DMAQNUM0 + ((chId / 8) * 4);
/* PaRAM entry setup */
*((volatile unsigned int *) (PaRAMEntryAddr + OPT)) = ((0) | // SAM -> // // INCR
// mode
(0 << 1) | // DAM // // -> // INCR // mode
(1 << 2) | // SYNCDIM // // -> // AB // synchronized
(0 << 3) | // STATIC // // -> // non-static // mode
(4 << 8) | // FWID // // -> // FIFO // width // is // 128 // bits
(0 << 11) | // TCCMODE // // -> // Normal // completion
(chId << 12) | // TCC // // -> // Transfer // Completion // Code
(1 << 20) | // TCINTEN // // -> // Transfer // Complete // Interrupt // is // enabled
(0 << 21) | // ITCINTEN // // -> // Intermediate // transfer // complete // interrupt // is // disabled
(0 << 22) | // TCCHEN // // -> // Transfer // Complete // Chaining // is // disabled
(0 << 23) | // ITCCHEN // // -> // Intermediate // transfer // complete // chaining // is // disabled
(0 << 24)); // PRIVID // // -> // Privilege // identification // for // the // external // host/CPU/DMA // that
*((volatile unsigned int *) (PaRAMEntryAddr + SRC)) = srcAddr;
*((volatile unsigned int *) (PaRAMEntryAddr + A_B_CNT)) =
(bcnt << 16) | (acnt);
*((volatile unsigned int *) (PaRAMEntryAddr + DST)) = dstAddr;
*((volatile unsigned int *) (PaRAMEntryAddr + SRC_DST_BIDX)) =
(destBIdx << 16) | (srcBIdx);
*((volatile unsigned int *) (PaRAMEntryAddr + LINK_BCNTRLD)) =
(bCntReload << 16) | 0xFFFF;
*((volatile unsigned int *) (PaRAMEntryAddr + SRC_DST_CIDX)) =
(destCIdx << 16) | srcCIdx;
*((volatile unsigned int *) (PaRAMEntryAddr + CCNT)) = ccnt;
if (chId < 32)
{
/* Set Shadow region for the channel */
*((volatile unsigned int *) DM81XX_EDMA3_DRAE3) |= (1 << chId);
/* Enable interrupt */
*((volatile unsigned int *) DM81XX_EDMA3_IESR) |= (1 << chId);
}
else
{
/* Set Shadow region for the channel */
*((volatile unsigned int *) DM81XX_EDMA3_DRAE3H) |= (1 << (chId – 32));
/* Enable interrupt */
*((volatile unsigned int *) DM81XX_EDMA3_IESRH) |= (1 << (chId – 32));
}
/* channel to PaRAM entry mapping */
*((volatile unsigned int *) dchmapChId) = (chId << 5); // maintainig one
// to one mapping
// between channel // and PaRAM entry
/* channel to queue mapping */
*((volatile unsigned int *) dmaQnum) |= (dmaQueue << ((chId % 8) * 4));
}
我的参数是这样配置的(搬运Y数据的配置):chId = 0; dmaQueue =0.acnt = 1 ,bcnt=1920,ccnt =1080,dstbidx =2,dstcidx=1,srccidx=1920*2,dstcidx=1920,bCntReload = 1920;
发现调配置完EDMA后,调用DM81XX_EDMA3_triggerTransfer ,M3核就卡死了。
同样的EDMA通道 queue id 调用了RDK自带的EDMA的API 函数DM81XX_EDMA3_setParams copy 422的数据则没有这个问题。
我觉得那个文档给的思路没问题是不是我的EDMA参数配置有问题?还是在DM8127的RDK不支持EDMA的link重载的功能?有没有类似How to Use the EDMA3 Driver on a TMS320DM643x
Device 这样类似的文档可以参考?
Louis:
Hi,
请参考一下的帖子《About the useage of EDMA in DM8127》,看是否能帮助到你:
http://e2e.ti.com/support/dsp/davinci_digital_media_processors/f/716/p/287739/1004065.aspx#1004065
Aen Jone:
回复 Louis:
HI:
感谢回复 ~~~,那个帖子我看了测试调用rdk的API 实现数据的copy是OK的,我现在要实现每次copy 一个像素,用了EDMA的reload功能,YUV422->420SP的算法需要copy的时候去掉一半的UV数据。不用EDMA 的数据转换我测试了差不多耗时1秒这个太慢了。我改动了rdk的API就发现卡住这问题了。大神有好的建议吗?
rhodesn:
回复 Louis:
Louis,您好!
根据您的意见,使用了cache的一致性命令,使用DM8127自带的EDMA函数,我想测试下EDMA是否成功运行。如下的执行过程是:首先把DDR上图像的数据WIDTH*32拷贝到DDR的另外一个空间(静态数组),然后把原始地址的数据清空,再拷贝回去,看图像显示是否正常。结果,图像数据没有拷贝成功,图像是黑色的。
//UInt8 pImgY[WIDTH*HEIGHT];
//pVideo.pY = (UInt8*)pOrgFrame->addr[0][0]; //Y plane;
Cache_inv((void*)pVideo.pY,WIDTH*32, Cache_Type_ALL, TRUE);DM81XX_EDMA3_setParams(6, 0, (unsigned int)pVideo.pY,(unsigned int)pImgY,WIDTH, 32,WIDTH,WIDTH);DM81XX_EDMA3_triggerTransfer(6);// RCache_wb((void *)pImgY,WIDTH*32, Cache_Type_ALL, TRUE); memset((void *)pVideo.pY, 0, WIDTH*32);DM81XX_EDMA3_memset(7, 0, 0, (unsigned int)pVideo.pY,WIDTH, 32,WIDTH);Cache_inv((void*)pImgY, WIDTH*32, Cache_Type_ALL, TRUE);DM81XX_EDMA3_setParams(5, 0, (unsigned int)pImgY,(unsigned int)pVideo.pY,WIDTH, 32,WIDTH,WIDTH);DM81XX_EDMA3_triggerTransfer(5);// RCache_wb((void *)pVideo.pY,WIDTH*32, Cache_Type_ALL, TRUE);
另外,DM81XX_EDMA3_setParams函数的前两个参数有没有限制,因为我要把WIDTH*32的数据多次的在片内和片外之间拷贝,以提高CPU的执行速度。上述的例子仅仅是DDR与DDR之间的拷贝。我也用相同的办法在DDR和L2之间拷贝,也未成功。另外,已经开启了DDR的CACHE功能,DDR大小为1G(在FC_RMAN_IRES_c6xdsp.cfg中):
/* cache settings for 1st 512MB DDR */Cache.MAR128_159 = 0x00FF0000;//Cache.MAR128_159 = 0x0000FF00;/* cache settings for 2nd 512MB DDR */Cache.MAR160_191 = 0x0F000000;
我在IPNC_RDK看到在函数Int32 FdLink_copyFrames(FdLink_Obj * pObj)中,用到了EDMA函数,并且经过测试,人脸检测确实成功运行,就是说EDMA成功。
麻烦您给诊断下,我的EDMA没有成功可能是哪个地方的问题。谢谢!