TI中文支持网
TI专业的中文技术问题搜集分享网站

C6455的EDMA中断问题

问题描述:C6455的EDMA3 TCC中断服务程序只能进入一次,第二次无法进入。

详细描述:

◆  参照DSK6455开发版带的例程dsk_app,设计了EDMA3程序。
◆  采用GPIO5作为EDMA传输触发事件,对应Event编号为 53;
◆  采用AB同步传输方式,PING PONG操作,ACNT = 4,BCNT=64,CCNT = 16; 每个GPIO5 Event触发一个ACNT×BCNT=256Byte大小的EDMA传输。
◆  当EDMA完成传输了16个AB Frame后,将产生EDMA3 TCC中断,进入中断服务程序edmaHwi(),同时LINK到PONG的Param上。
◆  中断服务程序对应的Event为72,因为使用的是REGION1。
◆  在中断服务程序退出前,清除CPU中断事件72(设置EVTCLR2=0x00000100),并清除EDMA事件中断(设置Shadow REGION_1的ICRH=0x00200000)。

目前的现象是第一次能够进入EDMA3 TCC中断服务程序,第二次就无法进入了。
使用单步调试,观察寄存器EVTFLAG2 和 Shadow REGION_1 IPRH的对应位在第一次中断退出前都已经清除。
主要程序如下:(完整工程见附件,需要C64x+的片级支持包)

#define BUFFSIZE 4096
#define PING 0
#define PONG 1

Uint8 gBufferRcvPing[BUFFSIZE] = {0}; // Receive PING buffer
Uint8 gBufferRcvPong[BUFFSIZE] = {0}; // Receive PONG buffer
Uint32 srcBuff[2] = {4, 7};

CSL_Edma3HwDmaChannelSetup dmahwSetup[CSL_EDMA3_NUM_DMACH] = CSL_EDMA3_DMACHANNELSETUP_DEFAULT;

/* ———————- Interrupt Service Routine ——————– */

void edmaHwi(void)
{
Uint32 intrh = 0;
static Uint32 pingOrPong = PING;
static Int16 rcvdone = 0;

/* Check for pending EDMA event interrupts (IPRH) */
intrh = *((volatile Uint32*)0x02a0226C);

if (intrh & 0x00200000)
{
rcvdone = 1;
}

if (rcvdone)
{
if (pingOrPong == PING)
{
pingOrPong = PONG;
}
else
{
pingOrPong = PING;
}

rcvdone = 0;
}

/* Clear CPU interrupt event 72 (EVTCLR2) */
*((volatile Uint32*)0x1800048) = 0x00000100;

/* Clear processed EDMA event interrupts (ICRH) */
*((volatile Uint32*)0x02a02274) = 0x00200000;

}

void gpioInit()
{ CSL_GpioHandle hGpio;
CSL_GpioPinConfig config;
CSL_Status status;
CSL_GpioContext pContext;
CSL_GpioObj gpioObj;
CSL_GpioHwSetup hwSetup;

/* Initialize the GPIO CSL module */
status = CSL_gpioInit(&pContext);
if (status != CSL_SOK) {
printf("GPIO: Initialization error.\n");
return;
}

/* Open the CSL module */
hGpio = CSL_gpioOpen(&gpioObj, CSL_GPIO, NULL, &status);
if ((hGpio == NULL) || (status != CSL_SOK)) {
printf("GPIO: Error opening the instance.\n");
return;
}

/* Setup hardware parameters */
hwSetup.extendSetup = NULL;
/* Setup the General Purpose IO */
status = CSL_gpioHwSetup(hGpio, &hwSetup);

/* Configure pin 5 to generate an interrupt on Rising Edge, and
* configure it as an input. */
config.pinNum = CSL_GPIO_PIN5;
config.trigger = CSL_GPIO_TRIG_RISING_EDGE;
config.direction = CSL_GPIO_DIR_INPUT;
/* Enable the bank interrupt */
status = CSL_gpioHwControl(hGpio, CSL_GPIO_CMD_BANK_INT_ENABLE, NULL);
if (status != CSL_SOK) {
printf("GPIO: Command to enable bank interrupt… Failed.\n");
}

/* configure the gpio pin 5 */
status = CSL_gpioHwControl(hGpio, CSL_GPIO_CMD_CONFIG_BIT, &config);
if (status != CSL_SOK) {
printf("GPIO: GPIO pin configuration error.\n");
return;
}
}

void edmaInit()
{
CSL_Edma3Handle hModule; CSL_Edma3Obj edmaObj;
CSL_Edma3ParamHandle hParamPing;
CSL_Edma3ParamHandle hParamPong;
CSL_Edma3ParamHandle hParamBasic;
CSL_Edma3ChannelObj chObj;
CSL_Edma3CmdIntr regionIntr;
CSL_Edma3CmdDrae regionAccess;
CSL_Edma3ChannelHandle hChannel;
CSL_Edma3ParamSetup myParamSetup;
CSL_Edma3Context context;
CSL_Edma3ChannelAttr chAttr;
CSL_Status status;
CSL_Edma3HwSetup hwSetup = {&dmahwSetup[0],NULL};

/* Module initialization */
status = CSL_edma3Init(&context);
if (status != CSL_SOK) {
printf ("Edma module initialization failed\n"); return;
}
/* Edma module open */
hModule = CSL_edma3Open(&edmaObj,CSL_EDMA3,NULL,&status);
if ( (hModule == NULL) || (status != CSL_SOK)) {
printf ("Edma module open failed\n"); return;
}

/* DMA chanel –> PaRAM mapping, queue assignment */
dmahwSetup[53].paramNum = 53; /* GPINT5 -> EDMA chanel 53 */
dmahwSetup[53].que = CSL_EDMA3_QUE_1;
status = CSL_edma3HwSetup(hModule,&hwSetup);
if (status != CSL_SOK) {
printf ("Hardware setup failed\n");
CSL_edma3Close (hModule);
return;
}

/* Setup the DRAE masks
* DRAE enable(Bits 0-63) for the shadow region 1.
*/
regionAccess.region = CSL_EDMA3_REGION_1 ;
regionAccess.drae = 0xFFFFFFFF ; regionAccess.draeh = 0xFFFFFFFF ;
status = CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_DMAREGION_ENABLE, \
&regionAccess); if (status != CSL_SOK) {
printf("Edma region enable command failed\n");
return; }

/* Channel open */
chAttr.regionNum = CSL_EDMA3_REGION_1;
chAttr.chaNum = CSL_EDMA3_CHA_GPINT5;
hChannel = CSL_edma3ChannelOpen(&chObj, CSL_EDMA3, &chAttr, &status); if ( (hChannel == NULL) || (status != CSL_SOK)) {
printf ("Edma channel open failed\n"); return;
}

/* Obtain a handle to parameter set 53 */
hParamBasic = CSL_edma3GetParamHandle(hChannel,53,NULL);
if (hParamBasic == NULL) {
printf ("Edma get param handle for param entry 53 failed\n"); return;
}

/* Obtain a handle to parameter set 69 */
hParamPing = CSL_edma3GetParamHandle(hChannel,69,NULL);
if (hParamPing == NULL) {
printf ("Edma get param handle for param entry 69 failed\n"); return;
}
/* Obtain a handle to parameter set 68 */
hParamPong = CSL_edma3GetParamHandle(hChannel,68,NULL);
if (hParamPong == NULL) {
printf ("Edma get param handle for param entry 68 failed\n"); return;
}

/* Setup the parameter entry parameters (Ping buffer) */
myParamSetup.option = CSL_EDMA3_OPT_MAKE(CSL_EDMA3_ITCCH_DIS, \
CSL_EDMA3_TCCH_DIS, \
CSL_EDMA3_ITCINT_DIS, \
CSL_EDMA3_TCINT_EN, \
53,CSL_EDMA3_TCC_NORMAL,\
CSL_EDMA3_FIFOWIDTH_NONE, \
CSL_EDMA3_STATIC_DIS, \
CSL_EDMA3_SYNC_AB, \
CSL_EDMA3_ADDRMODE_INCR, \
CSL_EDMA3_ADDRMODE_INCR );
myParamSetup.srcAddr = (Uint32)srcBuff/*0xc0100000*/; myParamSetup.aCntbCnt = CSL_EDMA3_CNT_MAKE(4,64); myParamSetup.dstAddr = (Uint32)gBufferRcvPing; myParamSetup.srcDstBidx = CSL_EDMA3_BIDX_MAKE(0,4); myParamSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAKE(hParamPong,0); myParamSetup.srcDstCidx = CSL_EDMA3_CIDX_MAKE(0,256); myParamSetup.cCnt = 16;
status = CSL_edma3ParamSetup(hParamBasic,&myParamSetup);
if (status != CSL_SOK) {
printf("Edma parameter entry setup is failed\n");
return;
}

/* Ping setup */
status = CSL_edma3ParamSetup(hParamPing,&myParamSetup);
if (status != CSL_SOK) {
printf("Edma ping parameter entry setup is failed\n");
return;
}
/* Pong setup */ myParamSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAKE(hParamPing,0); myParamSetup.option = CSL_EDMA3_OPT_MAKE(CSL_EDMA3_ITCCH_DIS, \
CSL_EDMA3_TCCH_DIS, \
CSL_EDMA3_ITCINT_DIS, \
CSL_EDMA3_TCINT_EN,\
53,CSL_EDMA3_TCC_NORMAL,\
CSL_EDMA3_FIFOWIDTH_NONE, \
CSL_EDMA3_STATIC_EN, \
CSL_EDMA3_SYNC_AB, \
CSL_EDMA3_ADDRMODE_INCR, \
CSL_EDMA3_ADDRMODE_INCR );
myParamSetup.srcAddr = (Uint32)srcBuff/*0xc0100000*/;
myParamSetup.dstAddr = (Uint32)gBufferRcvPong; status = CSL_edma3ParamSetup(hParamPong,&myParamSetup);
if (status != CSL_SOK) {
printf("Edma ping parameter entry setup is failed\n");
return;
}

/* Set up channel and queue relationships */
CSL_edma3HwChannelSetupParam(hChannel, 53);
CSL_edma3HwChannelSetupQue(hChannel, CSL_EDMA3_QUE_1);

/* Enable EDMA region interrupts */
regionIntr.region = CSL_EDMA3_REGION_1;
regionIntr.intr = 0x00000000;
regionIntr.intrh = 0x00200000;
status = CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_INTR_ENABLE,&regionIntr); if (status != CSL_SOK) {
printf ("Edma interrupt enable command failed\n");
return;
}

/* Receive event clear and enable */
CSL_edma3HwChannelControl(hChannel,CSL_EDMA3_CMD_CHANNEL_CLEAR,NULL);
CSL_edma3HwChannelControl(hChannel,CSL_EDMA3_CMD_CHANNEL_ENABLE,NULL);

}

void main()
{

memset(gBufferRcvPing, 0, BUFFSIZE);
memset(gBufferRcvPong, 0, BUFFSIZE);

/* Initialize the board support library, must be called first */
DSK6455_init();

/* Disable global interrupts */
HWI_disable();

/* Install HWI handler */
HWI_dispatchPlug(4, &edmaHwi, 0, NULL);
HWI_eventMap(4, 72);
C64_enableIER(0x10);

/* Initialize the GPIO controller */ gpioInit();

/* Initialize the EDMA controller */
edmaInit();

/* Clear CPU interrupt event 72 (EVTCLR2) */
*((Uint32*)0x1800048) = 0x00000100;

/* Enable CPU interrupt event 72 (EVTMASK2) */
*((Uint32*)0x1800088) = 0x00000100;

/* Re-enable global interrupts */
HWI_enable();

}

Hong Lan:

代码看不出问题,请问你说的第一次能进中断,第二次不能进,这是如何判断的?是通过计数器来查看或者传输的结果来判断,还是在中断服务程序中设断点来判断能否进中断的?还有GPIO5的触发信号如何产生,是手动控制,还是其他芯片的输出?我问这些问题主要是想排除在第一次中断处理退出之前,GPIO的第二次启动传输的触发信号就到来了,这样可能导致该触发信号被miss。

建议尝试如下debug手段:

假设你是等待了一段时间以后,没有得到第二次中断,此时暂停程序运行,看一下起始地址为hParamBasic的32个字节,这里是存着控制当前EDMA传输的PaRAM set,如果它的值和起始地址为hParamPong 的32个字节一样的话,说明第二次传输没有启动;如果它的内容中A,B,C 3个cnt都是0,link是0xffff的话,说明传输完成了,错误是发生在TCC引发中断这里。

赞(0)
未经允许不得转载:TI中文支持网 » C6455的EDMA中断问题
分享到: 更多 (0)