Hello,
I am using 6678 DSP with EDMA and PCIe interfaces included.
In our application project, we are using EDMA(CSL version, not LLD) for fast data transfer over PCIe interface. I am transferring 1 MB of data each time using EDMA.
The EDMA part of software is divided into 3 functions: ConfigureDMA(), PerformDMATransfer(const void *srcBuff, void* dstBuff) and CloseDMA() which are included in EDMA.txt file attached. Please find it. And I am initializing DMA parameters as
instNum= 0;
regionNum= -1;
channelNum = 16;
I am using ConfigureDMA() function once for initializing, and then calling PerformDMATransfer() in a seperate task periodically.
-
My first problem is : I can not achieve data transfer after first time(First 1 MB transfer is achieved but then no transfer could completed). As long as I don't call ConfigureDMA() in PerformDMATransfer() function, the transfer is not achived. Meaning that if I configure DMA everytime I call PerformDMA, then the transfer occurs. Do I have to configure DMA everytime I want to transfer data over it ? What may be the problem about this configuration process ? I think that I shall do it only once during initialization.
Now I am using PerformDMATransfer() funciton with configuration process done every time.
According to the project requirements, I have to enable MSI.
But after enabling MSI, there had occurred a strange situation: EDMA stops working after a while.
I configured a Hardware Interrupt statically for deploying in the MSI mechanism. I had used interrupt vector 11 as input of MSI events and priority of 1 (I had used different interrupt vectors and priorities after I recognized the problem but nothing changed). Please find the attached cfg(edmaCFG.txt) file which includes all the details about my configuration.
2. After a couple of minutes(I am doing 1 MB of data transfer in every 150 ms), EDMA stops transferring data. It remains in the while loop of PerformDMATransfer() function and returns with timeout error. At first I thought that there may be some interrupt configuration error but if it is so, the transfer shouldn't have started at the beginning. Do you have any idea about this problem ?
Regards,
Koray
int CPCIeModule::ConfigureDMA(void) { /* Module initialization */ if (CSL_edma3Init(&context) != CSL_SOK) { return PCIE_DMA_NOT_INITIALIZED; } /* Module level open */ hModule = CSL_edma3Open(&edmaObj,instNum,NULL,&status); if ((hModule == NULL) || (status != CSL_SOK)) { return PCIE_DMA_NOT_INITIALIZED; } /* Is this for GLOBAL or SHADOW Region */ if (regionNum != CSL_EDMA3_REGION_GLOBAL) { /* Shadow Region: Enable DRAE enable(Bits 0-15) it. */ regionAccess.region = regionNum; regionAccess.drae = 0xFFFF; regionAccess.draeh = 0x0000; if (CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_DMAREGION_ENABLE, ®ionAccess) != CSL_SOK) { return PCIE_DMA_NOT_INITIALIZED; } /* Enable access for all QDMA channels in the SHADOW Region. */ qraeSetup.region = regionNum; qraeSetup.qrae = 0xFF; if (CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_QDMAREGION_ENABLE, &qraeSetup) != CSL_SOK) { return PCIE_DMA_NOT_INITIALIZED; } } /* QDMA Channel Open */ chAttr.regionNum = regionNum; chAttr.chaNum = channelNum; hChannel = CSL_edma3ChannelOpen(&chObj, instNum, &chAttr, &status); if ((hChannel == NULL) || (status != CSL_SOK)) { return PCIE_DMA_NOT_INITIALIZED; } /* Map QDMA Channel to the PING Param Block i.e. 1 */ CSL_edma3HwChannelSetupParam (hChannel, 1); /* Setup the trigger word for the QDMA Channel. */ CSL_edma3HwChannelSetupTriggerWord(hChannel, 7); /* PING Parameter Entry Handle */ hParamPing = CSL_edma3GetParamHandle(hChannel, 1, &status); if (hParamPing == NULL) { return PCIE_DMA_NOT_INITIALIZED; } /* Setup param entry */ 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_DIS, \ CSL_EDMA3_SYNC_AB, \ CSL_EDMA3_ADDRMODE_INCR, \ CSL_EDMA3_ADDRMODE_INCR); myParamSetup.srcAddr = (Uint32)NULL; myParamSetup.aCntbCnt = CSL_EDMA3_CNT_MAKE(/*128*/ 128, PCIE_BUFFER_SIZE/128 /*2*/); myParamSetup.dstAddr = (Uint32)NULL; myParamSetup.srcDstBidx = CSL_EDMA3_BIDX_MAKE(128, 128 /*0, 0*/); myParamSetup.linkBcntrld= CSL_EDMA3_LINKBCNTRLD_MAKE(/*hParamPing*/ CSL_EDMA3_LINK_NULL /*NULL*/, 0); myParamSetup.srcDstCidx = CSL_EDMA3_CIDX_MAKE(0,0); myParamSetup.cCnt = 1; /* Enable Channel */ if (CSL_edma3HwChannelControl(hChannel,CSL_EDMA3_CMD_CHANNEL_ENABLE, NULL) != CSL_SOK) { return PCIE_DMA_NOT_INITIALIZED; } return SUCCESS; } int CPCIeModule::PerformDMATransfer(const void *srcBuff, void *dstBuff) { //debug this->ConfigureDMA(); myParamSetup.srcAddr = (Uint32)srcBuff; myParamSetup.dstAddr = (Uint32)dstBuff; /* Setup PING to operate with this PARAM Entry. */ if (CSL_edma3ParamSetup(hParamPing, &myParamSetup) != CSL_SOK) { return PCIE_DMA_TRANSFER_FAIL; } /* Trigger the word by writing to the trigger word... */ if (CSL_edma3ParamWriteWord(hParamPing,7,1) != CSL_SOK) { return PCIE_DMA_TRANSFER_FAIL; } /* Poll IPR bit */ regionIntr.region = regionNum; int iEnd = 0; int iStart = Clock_getTicks(); do { CSL_edma3GetHwStatus(hModule,CSL_EDMA3_QUERY_INTRPEND,®ionIntr); iEnd = Clock_getTicks(); if (PCIE_TIMEOUT_DMA_TRANSFER_CHECK < (iEnd - iStart)) { return PCIE_DMA_TRANSFER_FAIL; } } while (!(regionIntr.intr & /*0x2*/0x1)); /* Clear pending interrupt */ if (CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_INTRPEND_CLEAR, ®ionIntr) != CSL_SOK) { return PCIE_DMA_TRANSFER_FAIL; } return SUCCESS; } int CPCIeModule::CloseDMA(void) { /* Disable the channel */ CSL_edma3HwChannelControl(hChannel,CSL_EDMA3_CMD_CHANNEL_DISABLE, NULL); /* Close channel */ if (CSL_edma3ChannelClose(hChannel) != CSL_SOK) { return PCIE_DMA_NOT_CLOSED; } /* Close EDMA module */ if (CSL_edma3Close(hModule) != CSL_SOK) { return PCIE_DMA_NOT_CLOSED; } return SUCCESS; }
/******************************************************************************************************************** * Specify all needed RTSC Modules and configure them. * ********************************************************************************************************************/ var Memory = xdc.useModule('xdc.runtime.Memory'); var BIOS = xdc.useModule('ti.sysbios.BIOS'); var List = xdc.useModule('ti.sdo.utils.List'); var MessageQ = xdc.useModule('ti.sdo.ipc.MessageQ'); var Main = xdc.useModule('xdc.runtime.Main'); var Idle = xdc.useModule('ti.sysbios.knl.Idle'); var Settings = xdc.useModule('ti.drv.pcie.Settings'); var EDMA3RM = xdc.loadPackage('ti.sdo.edma3.rm'); var EDMA3RMSample = xdc.loadPackage('ti.sdo.edma3.rm.sample'); var EDMA3Driver = xdc.loadPackage('ti.sdo.edma3.drv'); var EDMA3Sample = xdc.loadPackage('ti.sdo.edma3.drv.sample'); var ECM = xdc.useModule ('ti.sysbios.family.c64p.EventCombiner'); var Plib = xdc.loadPackage('ti.platform.evmc6678l'); var TCI66 = xdc.useModule('ti.sysbios.family.c66.tci66xx.CpIntc'); //added for EDMA integration var Defaults = xdc.useModule('xdc.runtime.Defaults'); // var Error = xdc.useModule('xdc.runtime.Error'); // var LoggerBuf = xdc.useModule('xdc.runtime.LoggerBuf'); // var SysMin = xdc.useModule('xdc.runtime.SysMin'); // var Text = xdc.useModule('xdc.runtime.Text'); // var HeapBuf = xdc.useModule('ti.sysbios.heaps.HeapBuf'); // var Event = xdc.useModule('ti.sysbios.knl.Event'); // var Cache = xdc.useModule('ti.sysbios.hal.Cache'); // var loggerBufParams = new LoggerBuf.Params(); // loggerBufParams.numEntries = 32; var logger0 = LoggerBuf.create(loggerBufParams); Defaults.common$.logger = logger0; //Main.common$.diags_INFO = Diags.ALWAYS_ON; //added for EDMA integration-end /* Enable BIOS Task Scheduler */ BIOS.taskEnabled = true; var Task = xdc.useModule('ti.sysbios.knl.Task'); /* ** Allow storing of task names. By default if you name a task with a friendly display name it will not be saved ** to conserve RAM. This must be set to true to allow it. We use friendly names on the Task List display. */ Task.common$.namedInstance = true; var Clock = xdc.useModule ('ti.sysbios.knl.Clock'); /* ** Interface with IPC. Depending on the version of BIOS you are using the ** module name may have changed. */ /* Use this for BIOS 6.30 plus to get the IPC module */ var Sem = xdc.useModule ('ti.sysbios.knl.Semaphore'); /* Hardware Interrupt module */ var Hwi = xdc.useModule ('ti.sysbios.hal.Hwi'); var Ecm = xdc.useModule ('ti.sysbios.family.c64p.EventCombiner'); /* * Enable Event Groups here and registering of ISR for specific GEM INTC is done * using EventCombiner_dispatchPlug() and Hwi_eventMap() APIs */ Ecm.eventGroupHwiNum[0] = 7; Ecm.eventGroupHwiNum[1] = 8; Ecm.eventGroupHwiNum[2] = 9; Ecm.eventGroupHwiNum[3] = 10; /* * Diagnostic Module */ var Diags = xdc.useModule('xdc.runtime.Diags'); var Exc = xdc.useModule('ti.sysbios.family.c64p.Exception'); Exc.enablePrint = true; /* prints exception details to the CCS console */ /* ** Give the Load module it's own LoggerBuf to make sure the ** events are not overwritten. */ /* var loggerBufParams = new LoggerBuf.Params(); loggerBufParams.exitFlush = true; loggerBufParams.numEntries = 64; Load.common$.logger = LoggerBuf.create(loggerBufParams); */ /* ** Use this load to configure NDK 2.2 and above using RTSC. In previous versions of ** the NDK RTSC configuration was not supported and you should comment this out. */ var Global = xdc.useModule('ti.ndk.config.Global'); /* ** This allows the heart beat (poll function) to be created but does not generate the stack threads ** ** Look in the cdoc (help files) to see what CfgAddEntry items can be configured. We tell it NOT ** to create any stack threads (services) as we configure those ourselves in our Main Task ** thread hpdspuaStart. */ Global.enableCodeGeneration = false; /* Define a variable to set the MAR mode for DDR2 as all cacheable */ /*FixUp - changed to C66*/ var Cache = xdc.useModule('ti.sysbios.family.c66.Cache'); /*FixUp*/ /*Cache.MAR224_255 = 0x0000000f;*/ var Startup = xdc.useModule('xdc.runtime.Startup'); var System = xdc.useModule('xdc.runtime.System'); /* Required if using System_printf to output on the console */ SysStd = xdc.useModule('xdc.runtime.SysStd'); System.SupportProxy = SysStd; /* ** Heap Management Module - Create a default Heap. */ var HeapMem = xdc.useModule('ti.sysbios.heaps.HeapMem'); var heapMemParams = new HeapMem.Params(); heapMemParams.size = 4194304; heapMemParams.sectionName = "systemHeap"; Program.global.heap0 = HeapMem.create(heapMemParams); Memory.defaultHeapInstance = Program.global.heap0; /* Load the CSL package - LoadPackage is equivalent to linking the library */ var Csl = xdc.loadPackage('ti.csl'); /* Load the CPPI package - LoadPackage is equivalent to linking the library */ var Cppi = xdc.loadPackage('ti.drv.cppi'); /* Load the QMSS package - LoadPackage is equivalent to linking the library*/ var Qmss = xdc.loadPackage('ti.drv.qmss'); /* Load the PA package - LoadPackage is equivalent to linking the library*/ var Pa = xdc.loadPackage('ti.drv.pa'); /* Load Platform Library - LoadPackage is equivalent to linking the library */ var Plib = xdc.loadPackage('ti.platform.evmc6678l'); /* Load Platform Library - LoadPackage is equivalent to linking the library */ var Nimulib = xdc.loadPackage('ti.transport.ndk'); /******************************************************************************************************************** * Define our Memory Map. We made up the memory names LL2RAM, DDR2 and SL2RAM. They do have special meaning. * * * * DDR - Anyhting destined for DDR always goes into the external RAM on the paltform. * * L2SRAM - This is data that should be placed into the Local L2 of the core. * * MCMSRAM - This is data that should go into the shared L2 (if it exists) or could be placed into LL2 if it doesnt.* * * * These section names are mapped to specific addresses for a paltform using our custom memroy maps which are * * defined using the Platform Wizard. Examples are custom.hpdpsua.evm6678l, etc.,. * ********************************************************************************************************************/ Program.sectMap[".vecs"] = {loadSegment: "L2SRAM", loadAlign:8}; /* CSL per core data structures */ Program.sectMap[".switch"] = {loadSegment: "L2SRAM", loadAlign:8}; /* CSL per core data structures */ Program.sectMap[".cio"] = {loadSegment: "L2SRAM", loadAlign:8}; /* per core data structures */ Program.sectMap[".args"] = {loadSegment: "L2SRAM", loadAlign:8}; /* per core data structures */ Program.sectMap[".cppi"] = {loadSegment: "L2SRAM", loadAlign:16}; /* per core data structures */ Program.sectMap[".far:NDK_OBJMEM"]= {loadSegment: "L2SRAM", loadAlign:16}; /* NDK structures */ Program.sectMap[".nimu_eth_ll2"]= {loadSegment: "L2SRAM", loadAlign:16}; /* per core data structures */ Program.sectMap[".qmss"] = {loadSegment: "L2SRAM", loadAlign:16}; /* per core data structures */ Program.sectMap[".resmgr_memregion"] = {loadSegment: "L2SRAM", loadAlign:128}; /* QMSS descriptors region */ Program.sectMap[".resmgr_handles"] = {loadSegment: "L2SRAM", loadAlign:16}; /* CPPI/QMSS/PA Handles */ Program.sectMap[".resmgr_pa"] = {loadSegment: "L2SRAM", loadAlign:8}; /* PA Memory */ Program.sectMap[".stack"] = "L2SRAM"; Program.sectMap[".bss"] = "DDR3"; /* BSS. .neardata and .rodata are GROUPED */ Program.sectMap[".neardata"] = "DDR3"; Program.sectMap[".rodata"] = "DDR3"; Program.sectMap["systemHeap"] = {loadSegment: "DDR3", loadAlign:128}; /* XDC Heap .. eg Memory_alloc () */ Program.sectMap[".far"] = "DDR3"; Program.sectMap[".cinit"] = "DDR3"; Program.sectMap[".const"] = "DDR3"; Program.sectMap[".text"] = "DDR3"; Program.sectMap[".code"] = "DDR3"; Program.sectMap[".data"] = "DDR3"; /* Program.sectMap[".sysmem"] = "DDR"; /* Malloc memory area */ Program.sectMap["platform_lib"] = "DDR3"; /* Platform Library data structures */ /* Program.sectMap[".gBuffer"] = {loadSegment: "DDR", loadAlign:32}; /* Upload buffer used by the Web Server */ /* Program.sectMap[".far:WEBDATA"] = {loadSegment: "DDR", loadAlign: 32}; /* Web Pages and web server structures */ Program.sectMap[".far:taskStackSection"]= "DDR3"; /* BIOS task stacks */ Program.sectMap[".far:NDK_PACKETMEM"]= {loadSegment: "MSMCSRAM", loadAlign: 128}; /* NDK Buffer Pool */ /******************************************************************************************************************** * Define hooks and static tasks that will always be running. * ********************************************************************************************************************/ /* ** Register an EVM Init handler with BIOS. This will initialize the hardware. BIOS calls before it starts. ** ** If yuo are debugging with CCS, then this function will execute as CCS loads it if the option in your ** Target Configuraiton file (.ccxml) has the option set to execute all code before Main. That is the ** default. */ /* Because NDK is disabled via ethernetTask, no need to initialize EVM */ Startup.firstFxns.$add('&EVM_init'); /* Ethernet task is disable due to testing */ var StartEthernetParams = new Task.Params(); StartEthernetParams.instance.name = "ethernetTask"; StartEthernetParams.priority = 9; Program.global.ethernetTask = Task.create("&StartEthernet", StartEthernetParams); Global.netSchedulerPri = Global.NC_PRIORITY_HIGH; var Log = xdc.useModule('xdc.runtime.Log'); var LogSnapShot = xdc.useModule('ti.uia.runtime.LogSnapshot'); //var Logger = xdc.useModule('ti.uia.runtime.LoggerCircBuf'); var Snapshot = xdc.useModule('ti.uia.events.UIASnapshot'); /* ** Load Module - Configure this to turn on the CPU Load Module for BIOS. ** */ var LoggingSetup = xdc.useModule('ti.uia.sysbios.LoggingSetup'); //LoggingSetup.mainLogging = true; LoggingSetup.mainLoggerSize = 32768; LoggingSetup.sysbiosTaskLogging = true; // Task izlemek icin LoggingSetup.sysbiosSwiLogging = false; LoggingSetup.sysbiosHwiLogging = false; LoggingSetup.sysbiosLoggerSize = 32768; // Set to e.g. 32768 if sysBiosTaskLogging = true LoggingSetup.loadLogging = true; // CPU Load izlemek icin true olmali, default true LoggingSetup.loadLoggerSize = 32768; // set to e.g. 32768 if loadLogging = true LoggingSetup.eventUploadMode = LoggingSetup.UploadMode_JTAGRUNMODE; LoggingSetup.disableMulticoreEventCorrelation = true; var ServiceMgr = xdc.useModule('ti.uia.runtime.ServiceMgr'); ServiceMgr.topology = ServiceMgr.Topology_SINGLECORE; Main.common$.diags_ENTRY = Diags.ALWAYS_ON; Main.common$.diags_USER1 = Diags.ALWAYS_ON; Main.common$.diags_EXIT = Diags.ALWAYS_ON; // Process incoming commands task var Task1Params = new Task.Params(); Task1Params.instance.name = "Task1"; Task1Params.priority = 4; Program.global.Task1 = Task.create("&Task1Commands", Task1Params); var Task2Params = new Task.Params(); Task2Params.instance.name = "Task2"; Task2Params.priority = 2; Task2Params.stackSize = 20480; Program.global.Task2 = Task.create("&Task2Cmds", Task2Params); var Task3Params = new Task.Params(); Task3Params.instance.name = "Task3"; Task3Params.priority = 5; Task3Params.stackSize = 4096; Program.global.Task3 = Task.create("&Task3Cmds", Task3Params); var Task4Params = new Task.Params(); Task4Params.instance.name = "Task4"; Task4Params.priority = 5; Task4Params.stackSize = 4096; Program.global.Task4 = Task.create("&Task4Cmds", Task4Params); // PCIe Task var tskHandle_PCIeModuleManageIQDataParams = new Task.Params(); tskHandle_PCIeModuleManageIQDataParams.instance.name = "tskHandle_PCIeModuleManageIQData"; tskHandle_PCIeModuleManageIQDataParams.stackSize = 4096; tskHandle_PCIeModuleManageIQDataParams.priority = 3; Program.global.tskHandle_PCIeModuleManageIQData = Task.create("&tskPCIeModuleManageIQData", tskHandle_PCIeModuleManageIQDataParams); var Hwi_PCIe_MSIParams = new Hwi.Params(); Hwi_PCIe_MSIParams.instance.name = "Hwi_PCIe_MSI"; Hwi_PCIe_MSIParams.arg = 1; Hwi_PCIe_MSIParams.enableInt = false; Hwi_PCIe_MSIParams.eventId = 17; Hwi_PCIe_MSIParams.priority = 1; Program.global.Hwi_PCIe_MSI = Hwi.create(11, "&isr_Hwi_PCIe_MSI", Hwi_PCIe_MSIParams);