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.

Edma + INTC + CPINTC : Proper ISR

Hi everyone,

I have successfully implemented a simple block transfer using EDMA with an interruption.

However I think that my ISR isn't complete. Can anyone help me figure out what is missing ?

Here's a stripped down version of the code.

By the way what does GEM mean ?

Global variables

CSL_IntcHandle	  hIntc;
CSL_CPINTC_Handle hnd;

Main

void main(void) {

...

gem_intc_config();

cp_intc_config();

Edma_block_transfer(block_src,block_dst);

...

}


gem_intc_config


void gem_intc_config( void ){

CSL_IntcContext intcContext;
CSL_IntcGlobalEnableState state;
CSL_IntcObj intcObj;
CSL_IntcParam vectId;
CSL_IntcEventHandlerRecord EventRecord;
CSL_IntcEventHandlerRecord EventHandler[30];

intcContext.eventhandlerRecord = EventHandler;
intcContext.numEvtEntries = 10;

/* Initiate INTC module */
CSL_intcInit(&intcContext)

/* Enable NMIs : Non Maskable Interrups*/
CSL_intcGlobalNmiEnable()

/* Enable global interrupts */
CSL_intcGlobalEnable(&state)

/* Open the INTC Module for Vector ID: 4 and Event ID: 29 (C6678) */
/* Instance 1 (EDMACC1), Core 0 */

vectId = CSL_INTC_VECTID_4;
hIntc = CSL_intcOpen (&intcObj, 29, &vectId , NULL);

/* Register an call-back handler which is invoked when the event occurs. */
EventRecord.handler = &edma_isr_handler;
EventRecord.arg = 0;
 CSL_intcPlugEventHandler(hIntc,&EventRecord)

/* Enabling the events. */
CSL_intcHwControl(hIntc,CSL_INTC_CMD_EVTENABLE, NULL)
}

cp_intc_config


void cp_intc_config( void ){

// chip-level INTC0 is for CorePac0~3
hnd = CSL_CPINTC_open(CSL_CP_INTC_0); // edma3 events are mapped to CPINTC0

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

/* Configure no nesting support in the CPINTC Module. */
CSL_CPINTC_setNestingMode (hnd, CPINTC_NO_NESTING);

/* Map System Interrupt 6 (EDMACC GINT) to channel 40 */
CSL_CPINTC_mapSystemIntrToChannel (hnd, 6, 40);

/* Map channel 40 to host interrupt 40 */
CSL_CPINTC_mapChannelToHostInterrupt (hnd, 40 , 40);

/* Enable system interrupt 6 */
CSL_CPINTC_enableSysInterrupt (hnd, 6);

/* We enable host interrupts. */
CSL_CPINTC_enableHostInterrupt (hnd, 40);

/* Enable all host interrupts also. */
CSL_CPINTC_enableAllHostInterrupt(hnd);

}


edma_isr_handler 

static void edma_isr_handler (void* handle)
{

CSL_CPINTCHostInterrupt hostIntr;
CSL_CPINTCSystemInterrupt sysIntr;


/* Disable CPINTC0 Host interrupt (CPINTC output) */
CSL_CPINTC_disableHostInterrupt(hnd, hostIntr);

/* Clear the CPINTC0 Interrupt */
CSL_CPINTC_clearSysInterrupt(hnd, sysIntr);

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

/* ISR EVENTUAL TASKS */



/* ****************** */

/* Enable CPINTC0 Host interrupt (CPINTC output) */
CSL_CPINTC_enableHostInterrupt(hnd, hostIntr);

}


Edma_block_transfer

int Edma_block_transfer(float* block_src, float* block_dst) Uint8 coreNum, Int32 instNum, Uint8 channelNum)
{
(...)

Uint8 coreNum = 0;
Int32 instNum = 1;
Uint8 channelNum = 1;
    // instNum = 1; -> p161/232 data manual EDMACC1_GINT is tied to Event #6

(...)

/* Setup the param set */
myParamSetup.option = CSL_EDMA3_OPT_MAKE( CSL_EDMA3_ITCCH_DIS, \
CSL_EDMA3_TCCH_DIS, \
CSL_EDMA3_ITCINT_DIS, \
CSL_EDMA3_TCINT_EN, \
6, \
CSL_EDMA3_TCC_NORMAL, \
CSL_EDMA3_FIFOWIDTH_NONE, \
CSL_EDMA3_STATIC_EN, \
CSL_EDMA3_SYNC_A, \
CSL_EDMA3_ADDRMODE_INCR, \
CSL_EDMA3_ADDRMODE_INCR
);

(...)

/* Setup the block1 entry */
CSL_edma3ParamSetup(hParamBlock1,&myParamSetup)

/* Interrupt enable for the global region interrupts */
regionIntr.region = CSL_EDMA3_REGION_GLOBAL;
regionIntr.intr = (1<<6);
regionIntr.intrh = 0;
CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_INTR_ENABLE,&regionIntr);

/* *************************************************************************** */
/* Manually trigger the channel 1 */
/* *************************************************************************** */
CSL_edma3HwChannelControl(hChannel,CSL_EDMA3_CMD_CHANNEL_SET,NULL)

/* ISR */

/* Close channel */
CSL_edma3ChannelClose(hChannel)

/* Close EDMA module */
CSL_edma3Close(hModule)
}


Thank you
CM
  • CM,

    I think the majority of your code is fine and you can add some global flag in the ISR to test if the ISR could be entered and exited correctly.

    If  you want to the trigger the same event multiple times, you have to clear the source interrupt (EDMA IPR in  your case) every time before you trigger it again.

    I did some modifications to your code and attached it as follows to show the multiple triggering mechanism and add some EDMA IPR clearing into the ISR. In this way, you may not want to close the EDMA handler too early.

    Hope it helps.

    #include <stdio.h>
    #include <ti/csl/csl.h>
    #include <ti/csl/soc.h>
    #include <ti/csl/csl_edma3.h>
    #include <ti/csl/csl_edma3Aux.h>
    #include <ti/csl/src/intc/csl_intc.h>
    #include <ti/csl/csl_cpintc.h>
    #include <ti/csl/csl_cpintcAux.h>
    
    CSL_IntcHandle	  hIntc;
    CSL_CPINTC_Handle hnd;
    
    CSL_Edma3Handle             hModule;
    CSL_Edma3Obj                edmaObj;
    CSL_Edma3ParamHandle        hParamBlock1;
    CSL_Edma3ChannelObj         chObj;
    CSL_Edma3CmdIntr            regionIntr;
    CSL_Edma3ChannelHandle      hChannel;
    CSL_Edma3ParamSetup         myParamSetup;
    CSL_Edma3Context            context;
    CSL_Edma3ChannelAttr        chAttr;
    CSL_Status                  status;
    
    volatile unsigned int flag = 0;
    
    
    static void edma_isr_handler (void* handle)
    {
    
    	CSL_CPINTCHostInterrupt       hostIntr = 40;
    	CSL_CPINTCSystemInterrupt     sysIntr = 6;
    
    
    	/* Disable CPINTC0 Host interrupt (CPINTC output) */
    	CSL_CPINTC_disableHostInterrupt(hnd, hostIntr);
    
    	/* Clear the CPINTC0 Interrupt */
    	CSL_CPINTC_clearSysInterrupt(hnd, sysIntr);
    
    	/* Clear the CorePac Interrupt */
    	CSL_intcHwControl(hIntc,CSL_INTC_CMD_EVTCLEAR,NULL);
    
    	/* ISR EVENTUAL TASKS */
    
        /* Clear the pending bit */
        CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_INTRPEND_CLEAR,&regionIntr);
    
    	flag++;
    
    	/* ****************** */
    
    	/* Enable CPINTC0 Host interrupt (CPINTC output) */
    	CSL_CPINTC_enableHostInterrupt(hnd, hostIntr);
    
    }
    
    void gem_intc_config( void ){
    
    	CSL_IntcContext             intcContext;
    	CSL_IntcGlobalEnableState   state;
    	CSL_IntcObj                 intcObj;
    	CSL_IntcParam               vectId;
    	CSL_IntcEventHandlerRecord  EventRecord;
    	CSL_IntcEventHandlerRecord  EventHandler[30];
    
    	intcContext.eventhandlerRecord = EventHandler;
    	intcContext.numEvtEntries      = 10;
    
    	/* Initiate INTC module */
    	CSL_intcInit(&intcContext);
    
    	/* Enable NMIs : Non Maskable Interrups*/
            CSL_intcGlobalNmiEnable() ;
    
    	/* Enable global interrupts */
    	CSL_intcGlobalEnable(&state);
    
    	/* Open the INTC Module for Vector ID: 4 and Event ID: 29 (C6678) */
            /* Instance 1 (EDMACC1), Core 0 */
    
    	vectId = CSL_INTC_VECTID_4;
    	hIntc = CSL_intcOpen (&intcObj, 29, &vectId , NULL);
    
    	/* Register an call-back handler which is invoked when the event occurs. */
    	EventRecord.handler = &edma_isr_handler;
    	EventRecord.arg = 0;
    
     CSL_intcPlugEventHandler(hIntc,&EventRecord);
    
    	/* Enabling the events. */
    	CSL_intcHwControl(hIntc,CSL_INTC_CMD_EVTENABLE, NULL);
    }
    
    
    
    
    void cp_intc_config( void ){
    
    	// chip-level INTC0 is for CorePac0~3
    	hnd = CSL_CPINTC_open(CSL_CP_INTC_0); // edma3 events are mapped to CPINTC0
    
    	/* Disable all host interrupts. */
    	CSL_CPINTC_disableAllHostInterrupt(hnd);
    
    	/* Configure no nesting support in the CPINTC Module. */
    	CSL_CPINTC_setNestingMode (hnd, CPINTC_NO_NESTING);
    
    	/* Map System Interrupt 6 (EDMACC GINT) to channel 40 */
    	CSL_CPINTC_mapSystemIntrToChannel (hnd, 6, 40);
    
     	/* Map channel 40 to host interrupt 40 */
    	//CSL_CPINTC_mapChannelToHostInterrupt (hnd, 40 , 40);
    
    	/* Enable system interrupt 6 */
    	CSL_CPINTC_enableSysInterrupt (hnd, 6);
    
    	/* We enable host interrupts. */
    	CSL_CPINTC_enableHostInterrupt (hnd, 40);
    
    	/* Enable all host interrupts also. */
    	CSL_CPINTC_enableAllHostInterrupt(hnd);
    
    }
    
    
    
    
    
    
    
    
    int Edma_block_transfer(float* block_src, float* block_dst)
    {
    
    
    
    
    Uint8 coreNum = 0;
    
    Int32 instNum = 1;
    
    Uint8 channelNum = 1;
    	unsigned int ACNT = 128;
    	unsigned int BCNT = 1;
    	unsigned int CCNT = 1;
    	unsigned int SRCBIDX = 0;
    	unsigned int DSTBIDX = 0;
    
        // instNum = 1; -> p161/232 data manual EDMACC1_GINT is tied to Event #6
    
    	Uint32 L2Offset;
    	L2Offset = 0x10000000 + coreNum*0x01000000;
    
        /* Module initialization 										 */
        CSL_edma3Init(&context) ;
    
        /* Open the EDMA Module using the instance number 				 */
    
        hModule = CSL_edma3Open(&edmaObj, instNum, NULL, &status);
    
        /* Channel Open Global 				 							 */
        chAttr.regionNum = CSL_EDMA3_REGION_GLOBAL;
        chAttr.chaNum    = channelNum;
    
        hChannel = CSL_edma3ChannelOpen(&chObj, instNum, &chAttr, &status);
    
        /* Map the DMA Channel to the appropriate PARAM Block. 				  */
        CSL_edma3HwChannelSetupParam(hChannel, 1) ;
    
        /* Obtain a handle to parameter set 								  */
        hParamBlock1 = CSL_edma3GetParamHandle(hChannel, 1, &status);
    
    
        /* Setup the param set 								  				  */
        myParamSetup.option = CSL_EDMA3_OPT_MAKE( CSL_EDMA3_ITCCH_DIS, \
                                                  CSL_EDMA3_TCCH_DIS, \
                                                  CSL_EDMA3_ITCINT_DIS, \
                                                  CSL_EDMA3_TCINT_EN, \
                                                  6, \
                                                  CSL_EDMA3_TCC_NORMAL, \
                                                  CSL_EDMA3_FIFOWIDTH_NONE, \
                                                  CSL_EDMA3_STATIC_EN, \
                                                  CSL_EDMA3_SYNC_A, \
                                                  CSL_EDMA3_ADDRMODE_INCR, \
                                                  CSL_EDMA3_ADDRMODE_INCR
                                                 );
    
          myParamSetup.srcAddr    = (Uint32)block_src;
          myParamSetup.dstAddr    = (Uint32)block_dst + L2Offset; // Global adress needed
          myParamSetup.aCntbCnt   = CSL_EDMA3_CNT_MAKE(ACNT,BCNT);
          myParamSetup.cCnt       = CCNT;
          myParamSetup.srcDstBidx = CSL_EDMA3_BIDX_MAKE(SRCBIDX,DSTBIDX);
          myParamSetup.linkBcntrld= CSL_EDMA3_LINKBCNTRLD_MAKE(CSL_EDMA3_LINK_NULL,0);
          myParamSetup.srcDstCidx = CSL_EDMA3_CIDX_MAKE(0,0);
    
        /* Setup the block1 entry */
        CSL_edma3ParamSetup(hParamBlock1,&myParamSetup);
    
        /* Interrupt enable for the global region interrupts */
      	regionIntr.region = CSL_EDMA3_REGION_GLOBAL;
      	regionIntr.intr = (1<<6);
      	regionIntr.intrh = 0;
        CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_INTR_ENABLE,&regionIntr);
    
        /* *************************************************************************** */
        /* Manually trigger the channel 1								 			   */
        /* *************************************************************************** */
    	CSL_edma3HwChannelControl(hChannel,CSL_EDMA3_CMD_CHANNEL_SET,NULL);
    
    	/* ISR */
    
    	/* Close channel									 						   */
    	//CSL_edma3ChannelClose(hChannel);
    
    	/* Close EDMA module									 					   */
        //CSL_edma3Close(hModule);
    }
    
    
    void main(void) {
    
    	float * block_src = NULL;
    	float * block_dst = NULL;
    
    	block_src = (float *)0x10840000;
    	block_dst = (float *)0x00850000;
    
    	gem_intc_config();
    
    	cp_intc_config();
    
    	Edma_block_transfer(block_src, block_dst);
    
    	while (flag != 1) {
    		printf("wait for flag = 1\n");
    	}
    
    	printf ("ISR has been completed 1st time\n");
    
    	/* Close channel									 						   */
    	CSL_edma3ChannelClose(hChannel);
    
    	/* Close EDMA module									 					   */
    	CSL_edma3Close(hModule);
    
    	Edma_block_transfer(block_src, block_dst);
    
    
    	while (flag != 2) {
    		printf ("wait for flag = 2\n");
    	}
    	printf ("ISR has been completed 2nd time\n");
    
    	/* Close channel									 						   */
    	CSL_edma3ChannelClose(hChannel);
    
    	/* Close EDMA module									 					   */
    	CSL_edma3Close(hModule);
    
    }
    
    
    
    
    
    
    
    
    

    Sincerely,

    Steven

  • Thanks a lot Steven,

    It is indeed really helpful.

    I'll test that monday but I don't think there will be any problem.

    Regards,

    CM

  • Just for the record in case somebody wants to run the example again.

    The CSL_IntcHandle      hIntc; object is accordingly declared global in the example but the below structures/object are declared local in the gem_intc_config() fct:
        CSL_IntcObj       intcObj;
        CSL_IntcEventHandlerRecord  EventRecord;
    so it will be created on the stack and only exist within the scope of this function. It will be unvalid after. So hIntc will point to an object (intcObj) that is unvalid.
    All the 3 objects should live for the complete scope of the program execution.

    Anthony

  • Anthony,

    Thank you for your input on this old thread.

    It'll be useful when the final implementation will be done.


    Regards,
    Clement

  • Hi Clement,

    GEM : Generalized Embedded Megamodule. As far as I know, its a module combination of all the cores and memory controllers in which the L1 and the L2 memory resides.

    Regards

    Sud