Hello, how to configure event trigger edma3 transfer, I have test the intc_example1 in “csl_c64xplus_intc” directory on my 6455 board, and I verified that it is right, the source code is bellow:
#include <std.h>
#include <log.h>
#include <stdio.h>
#include <csl_edma3.h>
#include <csl_intc.h>
#include <soc.h>
/* Pragma to edma tcc handler table */
#pragma DATA_SECTION(TccHandlerTable,".testMem");
/* Global variable to Edma Tcc handler table */
typedef void (* EdmaTccHandler)(void);
EdmaTccHandler TccHandlerTable[64];
/* Macro for tcc handler table */
#define InvokeHandle(num) TccHandlerTable[num]()
/* Funtion forwards, for which registers individual event handlers in a table */
void EdmaEventHook(Uint16 , EdmaTccHandler);
void eventEdmaHandler(void *);
/* Function forwards */
void tcc1Fxn();
void intc_example (void);
/* Intc variable declarartion */
CSL_IntcContext intcContext;
CSL_IntcEventHandlerRecord EventHandler[30];
CSL_IntcObj intcObjEdma;
CSL_IntcHandle hIntcEdma;
CSL_IntcGlobalEnableState state;
CSL_IntcEventHandlerRecord EventRecord;
CSL_IntcParam vectId;
/* Global variable declarations */
Uint8 srcBuff[512];
Uint8 dstBuff[512];
volatile Uint32 intFlag = 0;
CSL_Edma3Handle hModule;
extern LOG_Obj trace;
/*
* ======== main ========
*/
#include <cslr_dev.h>
#include <vpx6455v2.h>
#include <vpx6455v2_pll.h>
#include <vpx6455v2_gpio.h>
Void main()
{
LOG_printf(&trace, "hello world!");
printf ("Running Interrupt Example\n");
vpx6455v2_pll1_init(20);
intc_example ();
/* fall into DSP/BIOS idle loop */
return;
}
/*
* =============================================================================
* @func intc_example
*
* @arg None
*
* @desc
* This is an example of the CSL Interrupt Controller usage.
* A event object is opened and is simply hooked up to a CPU vector.
* An event hnadler is associaed with it.
* 1. Initalizes the intc CSL required with proper ISR
* 2. Intializes and opens EDMA
* 3. Associates EDMA event handler with the INTC routine
* CSL_intcPlugEventHandler ()
* 4. Enables the edma interrupt
* 5. Waits for edma interrupt generate.
* 6. Compares the transferred data
* 7. Closes the edma module and edma channel.
* 8. Closes the Intc module
*
* @return
* None
*
* @eg
* intc_example ();
* =============================================================================
*/
void intc_example (void)
{
CSL_Edma3HwSetup hwSetup;
CSL_Edma3Obj edmaObj;
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;
Uint32 loopIndex;
Uint32 passStatus = 1;
Uint32 evtClr;
CSL_Edma3HwDmaChannelSetup dmahwSetup[CSL_EDMA3_NUM_DMACH] = \
CSL_EDMA3_DMACHANNELSETUP_DEFAULT;
/* Initialize Data Buffers */
for (loopIndex = 0; loopIndex < 512;loopIndex++) {
if(loopIndex<256){
srcBuff[loopIndex] = loopIndex;
}
if(loopIndex>=256){
srcBuff[loopIndex] = 511-loopIndex;
}
dstBuff[loopIndex] = 0;
}
/* Edma CSL initialization */
CSL_edma3Init(&context);
/* Intc module initialization */
intcContext.eventhandlerRecord = EventHandler;
intcContext.numEvtEntries = 10;
status = CSL_intcInit(&intcContext);
if (status != CSL_SOK) {
printf("Intc initialization failed\n");
return;
}
/* Enable NMIs */
status = CSL_intcGlobalNmiEnable();
if (status != CSL_SOK) {
printf("Intc global NMI enable failed\n");
return;
}
/* Enable global interrupts */
status = CSL_intcGlobalEnable(&state);
if (status != CSL_SOK) {
printf ("Intc global enable failed\n");
return;
}
/* Opening intc module */
vectId = CSL_INTC_VECTID_4;
hIntcEdma = CSL_intcOpen (&intcObjEdma, CSL_INTC_EVENTID_EDMA3CC_INT1, \
&vectId , NULL);
if (hIntcEdma == NULL) {
printf("Intc open failed\n");
return;
}
/* Opening a edma module */
hModule = CSL_edma3Open(&edmaObj,CSL_EDMA3,NULL,&status);
/* Edma module setup */
hwSetup.dmaChaSetup = &dmahwSetup[0];
hwSetup.qdmaChaSetup = NULL;
CSL_edma3HwSetup(hModule,&hwSetup);
/* Setup the DRAE Masks
* DRAE Enable(Bits 0-15) for the Shadow Region 1.
*/
regionAccess.region = CSL_EDMA3_REGION_GLOBAL ;
regionAccess.drae = 0xFFFF ;
regionAccess.draeh = 0xFFFF ;
status = CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_DMAREGION_ENABLE, \
®ionAccess);
/* Edma channel open */
chAttr.regionNum = CSL_EDMA3_REGION_GLOBAL;
chAttr.chaNum = CSL_EDMA3_CHA_DSP_EVT;
hChannel = CSL_edma3ChannelOpen(&chObj,CSL_EDMA3,&chAttr,&status);
//CSL_edma3HwChannelSetupQue(hChannel,CSL_EDMA3_QUE_3);
/* Parameter Set Setup */
hParamBasic = CSL_edma3GetParamHandle(hChannel,0,NULL);
myParamSetup.option = CSL_EDMA3_OPT_MAKE(CSL_EDMA3_ITCCH_DIS, \
CSL_EDMA3_TCCH_DIS, \
CSL_EDMA3_ITCINT_DIS, \
CSL_EDMA3_TCINT_EN,\
1,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)srcBuff;
myParamSetup.aCntbCnt = CSL_EDMA3_CNT_MAKE(256,2);
myParamSetup.dstAddr = (Uint32)dstBuff;
myParamSetup.srcDstBidx = CSL_EDMA3_BIDX_MAKE(256,256);
myParamSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAKE(CSL_EDMA3_LINK_NULL,1);
myParamSetup.srcDstCidx = CSL_EDMA3_CIDX_MAKE(0,0);
myParamSetup.cCnt = 1;
CSL_edma3ParamSetup(hParamBasic,&myParamSetup);
/* Association of an EDMA event handler with the INTC routine */
EventRecord.handler = &eventEdmaHandler;
EventRecord.arg = (void*)(hModule);
status = CSL_intcPlugEventHandler(hIntcEdma,&EventRecord);
if (status != CSL_SOK) {
printf("Intc plug event handler failed\n");
return;
}
/* Enabling event edma */
status = CSL_intcHwControl(hIntcEdma,CSL_INTC_CMD_EVTENABLE,NULL);
if (status != CSL_SOK) {
printf("Intc CSL_INTC_CMD_EVTENABLE command failed\n");
return;
}
/* Hook up the EDMA Event with an completion code function handler */
EdmaEventHook(1, tcc1Fxn);
/* Enable Interrupts */
regionIntr.region = CSL_EDMA3_REGION_1 ;
regionIntr.intr = 0x2 ;
regionIntr.intrh = 0x0 ;
CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_INTR_ENABLE,®ionIntr);
/* Enable Channel :- though not required for a manual trigger */
status = CSL_edma3HwChannelControl(hChannel,CSL_EDMA3_CMD_CHANNEL_ENABLE, \
NULL);
/* Clear the all events */
for (loopIndex = 0; loopIndex < 4; loopIndex++) {
evtClr = ((CSL_IntcRegsOvly)CSL_INTC_0_REGS)->EVTFLAG[loopIndex];
((CSL_IntcRegsOvly)CSL_INTC_0_REGS)->EVTCLR[loopIndex] = evtClr;
}
/* Manually trigger the channel */
//status = CSL_edma3HwChannelControl(hChannel,CSL_EDMA3_CMD_CHANNEL_SET,NULL);
for(loopIndex= 0;loopIndex<2000;loopIndex++);
/* Manually trigger the channel */
//status = CSL_edma3HwChannelControl(hChannel,CSL_EDMA3_CMD_CHANNEL_SET,NULL);
/* Wait for generation of interrupt */
while (!intFlag);
/* Verify destination buffer to be equal to the source buffer */
for (loopIndex = 0; loopIndex < 256; loopIndex++)
if (srcBuff[loopIndex] != dstBuff[loopIndex])
passStatus = 0;
if (passStatus != 0) {
printf ("<<Example Passed>>: Interrupt example passed\n");
}
else {
printf ("<<Example Failed>>: Interrupt example failed\n");
return;
}
/* Clear the all events */
for (loopIndex = 0; loopIndex < 4; loopIndex++) {
evtClr = ((CSL_IntcRegsOvly)CSL_INTC_0_REGS)->EVTFLAG[loopIndex];
((CSL_IntcRegsOvly)CSL_INTC_0_REGS)->EVTCLR[loopIndex] = evtClr;
}
/* Close handles */
CSL_edma3ChannelClose(hChannel);
CSL_edma3Close(hModule);
CSL_intcClose (hIntcEdma);
return;
}
/*
* =============================================================================
* @func tcc1Fxn
* @desc
* This is the Interrupt service routine
*
* @arg None
*
* @eg
* tcc1Fxn ();
*
*
* =============================================================================
*/
int intrcnt=0;
void tcc1Fxn(void)
{
intrcnt++;
intFlag = 1;
}
/*
* =============================================================================
* @func EdmaEventHook
*
* @arg
* tcc - Tcc number
* fxn - Pointer to function which points to edma isr
*
* @desc
* This is the interrupt handler routine for edma interrupt
*
* @return
* NONE
*
* =============================================================================
*/
void EdmaEventHook (
Uint16 tcc,
EdmaTccHandler fxn
)
{
TccHandlerTable[tcc] = (fxn);
}
/*
* =============================================================================
* @func eventEdmaHandler
*
* @desc
* This is the event handler for edma
*
* @arg handle
* Pointer to edma handle
*
*
* @eg
* eventEdmaHandler ();
* =============================================================================
*/
void eventEdmaHandler (
void *handle
)
{
CSL_BitMask32 mask;
CSL_BitMask32 maskVal;
CSL_Edma3CmdIntr regionIntr;
Uint32 tcc;
Uint32 intr;
Uint32 intrh;
Int region;
CSL_Edma3Handle hModule = (CSL_Edma3Handle)handle;
regionIntr.region = CSL_EDMA3_REGION_GLOBAL;
CSL_edma3GetHwStatus(hModule,CSL_EDMA3_QUERY_INTRPEND,®ionIntr);
intr = regionIntr.intr;
intrh = regionIntr.intrh;
mask = 1;
tcc = 0;
while (intr) {
maskVal = mask << tcc;
if (regionIntr.intr & maskVal) {
InvokeHandle(tcc);
intr &= ~maskVal;
}
tcc++;
}
mask = 1;
tcc = 0;
while (intrh) {
maskVal = mask << tcc;
if (intrh & maskVal) {
InvokeHandle((tcc+32));
intrh &= ~maskVal;
}
tcc++;
}
CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_INTRPEND_CLEAR,®ionIntr);
CSL_edma3GetHwStatus(hModule,CSL_EDMA3_QUERY_INTRPEND,®ionIntr);
if ((regionIntr.intr !=0)||(regionIntr.intrh !=0)) {
region = CSL_EDMA3_REGION_GLOBAL;
CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_INTR_EVAL,®ion);
}
}
but I want to change it to event trigger (I want to use gpio4 )instead of manual trigger, so I made some change bellow:
-
Add gpio init code in the main function , bellow:
Void main()
{
LOG_printf(&trace, "hello world!");
printf ("Running Interrupt Example\n");
vpx6455v2_pll1_init(20);
vpx6455v2_gpio_init();
vpx6455v2_gpio_set_direction(GPIO_4,GPIO_IN);
vpx6455v2_gpio_set_rising_edge_interrupt(GPIO_4);
vpx6455v2_gpio_enable_global_interrupt();
//vpx6455v2_init();
intc_example ();
/* fall into DSP/BIOS idle loop */
return;
}
-
Change the chaNum of chAttr from CSL_EDMA3_CHA_DSP_EVT; to CSL_EDMA3_CHA_GPINT4
-
Comment the manual trgger code bellow:
/* Manually trigger the channel */
//status = CSL_edma3HwChannelControl(hChannel,CSL_EDMA3_CMD_CHANNEL_SET,NULL);
On my board, a FPGA is connect with GPIO using GPIO, so I generate a period pulse and output to the gpio pin 4, after I configured the fpga, rebuild and reload the DSP code, I found it can’t work(because the dst buffer doesn’t change), what’s wrong with the problem, and I have found the EERH and ERH register the GPIO4 event field has been configured , do I have something unconfigured, .
Another problem, I have a little problem with the edma event, if I want to use event to trigger the edma, should I enable the event interrupt?
Can anyone help me ,or do you have an event trigger edma3 source code using CSL thank you, waiting for your help.