This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RTOS/TMDSEVM6670: EDMA Transfer Completion Interrupt

Part Number: TMDSEVM6670

Tool/software: TI-RTOS

Hello team,

I am trying trying to generate an interrupt at the end of each EDMA transfer, unfortunately with no success - the interrupt doesn't occur.

What I have already done is an EDMA transfer implementation which has been tested. It seems to copy data properly.

I was trying to use CSL libraries:

#include <ti/csl/csl_cpIntc.h>
#include <ti/csl/csl_cpIntcAux.h>
#include <ti/csl/src/intc/csl_intc.h>
#include <ti/csl/csl_edma3.h>
#include <ti/csl/csl_edma3Aux.h>
#include <ti/csl/soc.h>

that are included within the pdk_c667x_2_0_4 .

Moreover to operate with CSL IntC libraries I added following lines to my .cfg file in my project:

var Csl = xdc.useModule('ti.csl.Settings');
Csl.deviceType = devType;
Csl.useCSLIntcLib=true

Project is in C++ and it is based on SRIO_LpbkDioIsr_evmc6678_C66BiosExampleProject but greatly modified.

The only interrupt I am currently using is a doorbell-generated interrupt from the FPGA. It has been done via Event Combiner on event #20.

Uint32      				passStatus = 1;

CSL_Status					status;
CSL_Edma3Context 			Edmacontext;
CSL_Edma3ModuleBaseAddress	baseAddress;
CSL_Edma3CfgInfo			cfgInfo;
CSL_Edma3Obj            	edmaObj;
CSL_Edma3HwDmaChannelSetup  dmahwSetup;
CSL_Edma3HwSetup            hwSetup;
CSL_Edma3CmdDrae            regionAccess;
CSL_Edma3ChannelHandle  	hChannel;
CSL_Edma3Handle				hModule; //This is a pointer to the object CSL_Edma3Obj, it is passed to all EDMA module level CSL APIs.
CSL_Edma3ChannelObj	   		chObj;
CSL_Edma3ChannelAttr    	chAttr;
Int32 						instNum = 0;
CSL_Edma3ParamHandle		hParamBasic;
CSL_Edma3ParamSetup    		myParamSetup;

CSL_Edma3CmdIntr			regionIntr;
// Get the EDMA CC Instance 0 Information
status = CSL_edma3ccGetModuleBaseAddr(0, NULL, &baseAddress, &cfgInfo);
if (status != CSL_SOK) {
	System_printf("Edma Get Module Base Address failed\n");
	return;
}

// Initialize the EDMA3 Module.
status = CSL_edma3Init(&Edmacontext);
if (status != CSL_SOK) {
	System_printf("Edma module initialization failed\n");
	return;
}

//Open EDMA3 handle, module level open
hModule = CSL_edma3Open(&edmaObj, instNum, NULL, &status);
if ( (hModule == NULL) || (status != CSL_SOK)) {
	System_printf("Edma module open failed\n");
	return;
}

/* Module setup */
dmahwSetup.paramNum = 0;
dmahwSetup.que      = CSL_EDMA3_QUE_0;
hwSetup.dmaChaSetup = &dmahwSetup;
hwSetup.qdmaChaSetup = NULL;
status = CSL_edma3HwSetup(hModule,&hwSetup);
if (status != CSL_SOK) {
	 System_printf("Hardware setup failed\n");
	 CSL_edma3Close(hModule);
	 return;
}

/* DRAE enable(Bits 0-15) for the shadow region 5 */
regionAccess.region = CSL_EDMA3_REGION_5 ;
regionAccess.drae =   0xFFFF ;
regionAccess.draeh =  0x0000 ;
status = CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_DMAREGION_ENABLE, &regionAccess);
if (status != CSL_SOK) {
	System_printf("Edma region enable command failed\n");
	return;
}

// Open DMA Channel 1 in context of shadow region 5.
chAttr.regionNum = CSL_EDMA3_REGION_5;
chAttr.chaNum    = 1;
hChannel = CSL_edma3ChannelOpen(&chObj, instNum, &chAttr, &status);
if ((hChannel == NULL) || (status != CSL_SOK))
{
	System_printf("Error: Unable to open EDMA Channel:%d\n", 0);
	return;
}

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

myParamSetup.option = CSL_EDMA3_OPT_MAKE (CSL_EDMA3_ITCCH_EN, \
										   CSL_EDMA3_TCCH_DIS, \
										   CSL_EDMA3_ITCINT_EN, \
										   CSL_EDMA3_TCINT_EN,\
										   0, CSL_EDMA3_TCC_NORMAL,\
										   CSL_EDMA3_FIFOWIDTH_NONE, \
										   CSL_EDMA3_STATIC_DIS, \
										   CSL_EDMA3_SYNC_A, \
										   CSL_EDMA3_ADDRMODE_INCR, \
										   CSL_EDMA3_ADDRMODE_INCR
										  );
myParamSetup.srcAddr     = (Uint32)srcDataBuffer[0];
myParamSetup.aCntbCnt    = CSL_EDMA3_CNT_MAKE(32, 128);
myParamSetup.dstAddr     = (Uint32)dstDataBuffer[0];
myParamSetup.srcDstBidx  = CSL_EDMA3_BIDX_MAKE(32, 32);
myParamSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAKE(CSL_EDMA3_LINK_NULL,0);
myParamSetup.srcDstCidx  = CSL_EDMA3_CIDX_MAKE(1,1);
myParamSetup.cCnt        = 1;

// Configure the PARAM Entry with the setup information.
status = CSL_edma3ParamSetup(hParamBasic, &myParamSetup);
if (status != CSL_SOK) {
	System_printf("Edma parameter entry setup is failed\n");
	return;
}

/* Enable channel */
status = CSL_edma3HwChannelControl(hChannel,CSL_EDMA3_CMD_CHANNEL_ENABLE, \
								   NULL);
if (status != CSL_SOK) {
	System_printf("Edma channel enable command is failed\n");
	return;
}

//########################################################################################

/* Intc module initialization */
CSL_IntcContext				context;
CSL_IntcEventHandlerRecord	record;
CSL_IntcGlobalEnableState	state;
CSL_IntcParam				vectId;
CSL_IntcHandle				hIntc;
CSL_IntcObj                 intcObj;
CSL_IntcEventId				eventId;

CSL_Status					intStat;

CSL_CPINTC_Handle			cphnd;
CSL_CPINTCSystemInterrupt	sys_event = 43;
CSL_CPINTCHostInterrupt		host_event = 0;
CSL_CPINTCChannel			channel = 0;


context.numEvtEntries = 1;
context.eventhandlerRecord = &record;

if (CSL_intcInit(&context) != CSL_SOK)
{
	System_printf("Error: Unable to init INTC\n");
}

/* Enable NMIs */
CSL_intcGlobalNmiEnable();

/* Enable Global Interrupts */
intStat = CSL_intcGlobalEnable(&state);

/* Initialize the chip level CIC CSL handle */
cphnd = CSL_CPINTC_open(0);
if (cphnd == 0)
{
	System_printf("Error: Unable to initialize CPINTC-0\n");
}

/* Map the CIC input event to the CorePac input event, which is 56 */

/* Disable all host interrupts. */
CSL_CPINTC_disableAllHostInterrupt(cphnd);

CSL_CPINTC_setNestingMode(cphnd, CPINTC_NO_NESTING);

/* Map the input system event to a channel. Note, the
 * mapping from channel to Host event is fixed.*/
CSL_CPINTC_mapSystemIntrToChannel(cphnd, sys_event, channel);

/* Enable the system interrupt */
CSL_CPINTC_enableSysInterrupt(cphnd, sys_event);

/* Enable the channel (output). */
CSL_CPINTC_enableHostInterrupt(cphnd, host_event);

/* Enable all host interrupts. */
CSL_CPINTC_enableAllHostInterrupt(cphnd);

/*  Hook an ISR to the CorePac input event
 *
 */

/* Get the event id associated with the host interrupt. */
eventId = CpIntc_getEventId(host_event); // = 56

vectId = CSL_INTC_VECTID_4; //4 through 15 are available
hIntc = CSL_intcOpen (&intcObj, eventId, &vectId , &intStat);
if (intStat != CSL_SOK)
{
	System_printf("Error: Unable to open INTC\n");
}

/* Hook the ISR */
record.handler = (CSL_IntcEventHandler)isrEdmaHandler;
record.arg = hModule; 						//hIntc or hModule ???
CSL_intcPlugEventHandler(hIntc, &record);

/* Clear the Interrupt */
CSL_intcHwControl(hIntc,CSL_INTC_CMD_EVTCLEAR,NULL);

/* Enable the Event & the interrupt */
CSL_intcHwControl(hIntc,CSL_INTC_CMD_EVTENABLE,NULL);

//########################################################################################

/* Manually trigger the channel */
status = CSL_edma3HwChannelControl(hChannel,CSL_EDMA3_CMD_CHANNEL_SET,NULL);
if (status != CSL_SOK) {
	System_printf("Edma channel set command is failed\n");
	return;
}

regionIntr.region = CSL_EDMA3_REGION_5;
regionIntr.intr = 0;
regionIntr.intrh = 0;

do {
	/* Poll on interrupt bit 0 */
	CSL_edma3GetHwStatus(hModule,CSL_EDMA3_QUERY_INTRPEND,&regionIntr);
} while (!(regionIntr.intr & 0x1));


// Here I put a breakpoint to see whether the debugger would come here or to my ISR handler function isrEdmaHandler() where another breakpoint has been put as well.
/* Clear interrupt bit 0 */
status = CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_INTRPEND_CLEAR, \
						   &regionIntr);
if (status != CSL_SOK) {
	System_printf("Edma clear interrupt bit 0 command is failed\n");
	return;
}

/* Close channel */
status = CSL_edma3ChannelClose(hChannel);
if (status != CSL_SOK) {
	System_printf("Edma channel close failed\n");
	return;
}

/* Close edma module */
status = CSL_edma3Close(hModule);
if (status != CSL_SOK) {
	System_printf("Edma module close failed\n");
	return;
}

return;

I would be grateful for any help or suggests in resolving this problem. I am not sure of few arguments so I've enclosed some comments up there but it doesn't mean the rest is good - it doesn't work so there must be something wrong. I've followed this discussion while writing the code: https://e2e.ti.com/support/dsp/c6000_multi-core_dsps/f/639/t/171653 

Thank you in advance,

Maciej

  • Hi,

    I've notified the sw team. Their feedback will be posted here.

    Best Regards,
    Yordan
  • Hi,

    Thank you Yordan, looking forward to their reply.

    Regards,
    Maciej
  • I am not an edma expert, but if you can trigger the interrupt manually, then you can tell if the problem is the configuration of the EDMA or the configuration of the various interrupt controllers. Also, you look at the CIC user guide (SPRUGW4A), and the C66x user guide (SPRUGW0), you can look at the registers to see how far the interrupt gets. Trying this with a working example may make it easier to diagnose the non-working example.
  • Ok, I got this.

    The problem was with EDMA but there is still one issue that is needed to be fixed.

    When I set my OPT register to:

        myParamSetup.option = CSL_EDMA3_OPT_MAKE (CSL_EDMA3_ITCCH_DIS, \
                                                   CSL_EDMA3_TCCH_DIS, \
                                                   CSL_EDMA3_ITCINT_DIS, \
                                                   CSL_EDMA3_TCINT_EN,\
                                                   0, CSL_EDMA3_TCC_NORMAL,\
                                                   CSL_EDMA3_FIFOWIDTH_NONE, \
                                                   CSL_EDMA3_STATIC_EN, \
                                                   CSL_EDMA3_SYNC_A, \
    					       CSL_EDMA3_ADDRMODE_CONST, \
    					       CSL_EDMA3_ADDRMODE_CONST
                                                  );
        myParamSetup.srcAddr     = (Uint32)srcDataBuffer[0];
        myParamSetup.aCntbCnt    = CSL_EDMA3_CNT_MAKE(0x100, 0x1);
        myParamSetup.dstAddr     = (Uint32)dstDataBuffer[0];
        myParamSetup.srcDstBidx  = CSL_EDMA3_BIDX_MAKE(0x0, 0x0);
        myParamSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAKE(CSL_EDMA3_LINK_NULL,0);
        myParamSetup.srcDstCidx  = CSL_EDMA3_CIDX_MAKE(0x0,0x0);
        myParamSetup.cCnt        = 0x1;

    It copies the data, and then EDMA3TC sets the IPR[0] bit (I'm using channel 0) and EDMA3CC generates an interrupt (if I understand the idea correctly)

    DRAE 5[0] was previously set to 1 as well as IESR[0]:

    hModule->regs->SHADOW[CSL_EDMA3_REGION_5].TPCC_IESR |= 0x1;
    
    hModule->regs->TPCC_DRA[CSL_EDMA3_REGION_5].DRAE  |= 0x1;

    Then I change the BCNT value in my PaRAM set from 0x1 to 0x2:

        myParamSetup.option = CSL_EDMA3_OPT_MAKE (CSL_EDMA3_ITCCH_DIS, \
                                                   CSL_EDMA3_TCCH_DIS, \
                                                   CSL_EDMA3_ITCINT_DIS, \
                                                   CSL_EDMA3_TCINT_EN,\
                                                   0, CSL_EDMA3_TCC_NORMAL,\
                                                   CSL_EDMA3_FIFOWIDTH_NONE, \
                                                   CSL_EDMA3_STATIC_EN, \
                                                   CSL_EDMA3_SYNC_A, \
    					       CSL_EDMA3_ADDRMODE_CONST, \
    					       CSL_EDMA3_ADDRMODE_CONST
                                                  );
        myParamSetup.srcAddr     = (Uint32)srcDataBuffer[0];
        myParamSetup.aCntbCnt    = CSL_EDMA3_CNT_MAKE(0x100, 0x2);
        myParamSetup.dstAddr     = (Uint32)dstDataBuffer[0];
        myParamSetup.srcDstBidx  = CSL_EDMA3_BIDX_MAKE(0x0, 0x0);
        myParamSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAKE(CSL_EDMA3_LINK_NULL,0);
        myParamSetup.srcDstCidx  = CSL_EDMA3_CIDX_MAKE(0x0,0x0);
        myParamSetup.cCnt        = 0x1;

    to see if any interrupt occur. Unfortunately, nothing happens. I've checked the IPR register but there's no single bit set to 1. All zeros so there is nothing that could even possibly trigger the interrupt.

    What should I do to make IPR bit being set after I trigged the transfer using CSL_edma3HwChannelControl(hChannel,CSL_EDMA3_CMD_CHANNEL_SET,NULL)  while having BCNT in PaRaM > 1?

    Kind Regards,

    Maciej

  • So if I read your post correctly, the transfer and interrupt both occur when BCNT = 1, but neither occur when BCNT = 2.  It sounds like something is preventing the 2D transfer from completing. From the EDMA user guide:

    2nd Dimension or Frame (B): The 2nd dimension in a transfer consists of BCNT arrays of ACNT bytes.
    Each array transfer in the 2nd dimension is separated from each other by an index programmed using
    SRCBIDX or DSTBIDX.

    So I would guess that either the source or destination indexes are not valid, or when applying them, the resulting source or destination address is not valid.

     -dave

  • I looked closer into these indexes and here what I've found:

    I allocate buffers from SRIO:

    UInt8*					srcDataBuffer[16];
    UInt8*					dstDataBuffer[16];
    
    for (unsigned int i = 0; i < 16; i++)
    {
    	dstDataBuffer[i] = (uint8_t*) Osal_srioDataBufferMalloc(BURST_SIZE);
    	if (dstDataBuffer[i] == NULL)
    	{
    	   System_printf("Error: Destination Buffer (%d) Memory Allocation Failed\n", i);
    	}
    }
    for (unsigned int i = 0; i < 16; i++)
    {
    	srcDataBuffer[i] = (uint8_t*) Osal_srioDataBufferMalloc(BURST_SIZE); //TX
    	if (srcDataBuffer[i] == NULL)
    	{
    	   System_printf("Error: Source Buffer (%d) Memory Allocation Failed\n", i);
    	}
    }
    
    myParamSetup.srcAddr = (Uint32)srcDataBuffer[0];
    myParamSetup.dstAddr = (Uint32)dstDataBuffer[0];

    And when I changed it to:

    myParamSetup.srcAddr     = (Uint32)(*(*(&srcDataBuffer)));
    myParamSetup.dstAddr     = (Uint32)(*(*(&dstDataBuffer)));

    to make the EDMA see the buffer as a one integrated block of memory and everything started to work properly.
    Now I see the IPR[0] bit being set and I receive an interrupt with ITCINT disabled and TCINT enabled. :)

    Thank you so much for your hints!

    Kind Regards,

    Maciej

  • Glad I could help!

     -dave