/************************************************************************************ * eventHandler.c * synopsis: Contains initialization routines for DMA engine and the 6701 ISRs for * DMAing data frames from the router FPGA in the event of an external * interrupt from the router. * * in this file: setupDmaParams, loadDmaRegs, initiateTrapping, stopTrapping, * triggerRouter, haltRouter, setPin4Mask, rstPin4Mask, pin4Isr, * frameDmaDoneIsr, addFrameQueue, setDmaRegs, initEventManager, * initEvtMgrStructs, flushEvents, eventManager, advanceEventQueue, getNextEvent, * copyEvent, getFramePtr, getNextFrame, processEvent. * * related files: initSlaveMcbsp.c (open & initialize the serial ports) * * Damon Fasching, UW Madison fasching@wisconsin.cern.ch * Douglas Ferguson, UW Madison (510) 486-5230 dpferguson@lbl.gov ************************************************************************************/ #include #include #include #include #if ( (defined(REV_B))||(defined(REV_C)) ) #include #elif (defined(REV_E)) #include #endif #include "resources.h" #include "peripheralMap.h" #include "memoryPartitions.h" #include "comRegDfns.h" #pragma CODE_SECTION(setupDmaParams, "xcode"); #pragma CODE_SECTION(loadDmaRegs, "xcode"); #pragma CODE_SECTION(initiateTrapping, "xcode"); #pragma CODE_SECTION(stopTrapping, "xcode"); #pragma CODE_SECTION(triggerRouter, "xcode"); #pragma CODE_SECTION(haltRouter, "xcode"); #pragma CODE_SECTION(setPin4Mask, "icode"); #pragma CODE_SECTION(rstPin4Mask, "icode"); #pragma CODE_SECTION(pin4Isr, "icode"); #pragma CODE_SECTION(frameDmaDoneIsr, "icode"); #pragma CODE_SECTION(initEventManager, "xcode"); #pragma CODE_SECTION(initEvtMgrStructs, "xcode"); #pragma CODE_SECTION(flushEvents, "icode"); #pragma CODE_SECTION(eventManager, "icode"); #pragma CODE_SECTION(advanceEventQueue, "xcode"); #pragma CODE_SECTION(getNextEvent, "icode"); #pragma CODE_SECTION(copyEvent, "xcode"); #pragma CODE_SECTION(getFramePtr, "icode"); #pragma CODE_SECTION(getNextFrame, "icode"); #pragma CODE_SECTION(processEvent, "icode"); extern char genStr[]; extern TIMER_Handle timer1; /* general purpose timer, started in main() */ typedef struct { UINT32 code, loopCnt, timeStamp, procTime; UINT32 trapStat[3], isrState; UINT32 nEvents, nHistoEvents, p4MaskStat, maskFlag; } GenEventInfo; extern GenEventInfo *genEventInfo; /* file level variables */ #if (defined(REV_B)||defined(REV_C)) DMA_Handle hBurstDataDmaCh; /* handle for data burst DMA channel */ UINT32 burstDataDmaChEvtId; /* interrupt event ID for data burst DMA channel */ UINT32 reloadCountRegID; /* global DMA registers to reload the DMA engine */ UINT32 burstGblAddrRegID; /* variables for loading DMA registers */ UINT32 cntReload = 0, burstGblRegInit= 0; DMA_Config burstDmaConfig= {0,0,0,0,0}, DmaReset= {0,0,0,0,0}; #elif (defined(REV_E)) EDMA_Handle hBurstDataDmaCh; /* handle for data burst DMA channel */ UINT32 burstDataDmaChEvtId; /* interrupt event ID for data burst DMA channel */ //UINT32 reloadCountRegID; /* global DMA registers to reload the DMA engine */ //UINT32 burstGblAddrRegID; /* variables for loading DMA registers */ //UINT32 cntReload = 0, burstGblRegInit= 0; EDMA_Config burstDmaConfig= {0,0,0,0,0,0}, DmaReset= {0,0,0,0,0,0}; #endif #include "eventHandler.h" /* event manager variables */ #pragma DATA_SECTION(evtMgrCtrl, "idata"); struct EvtMgrCtrl evtMgrCtrl; /* #pragma DATA_SECTION(eventQueue, "xpdata"); */ struct EventQueue eventQueue; /* file level routines */ void setupDmaParams(void); void loadDmaRegs(void); void triggerRouter(void); void haltRouter(void); void setPin4Mask(void); void rstPin4Mask(void); void pin4Isr(void); void frameDmaDoneIsr(void); int isrOverflow(void); unsigned char allocEventId(void); unsigned char addFrameQueue(void); //void setDmaRegs(unsigned char); void advanceEventQueue(unsigned char); /************************************************************************************ * setupDmaParams() * * synopsis: Sets up the paramters to be loaded into registers of the * DMA channel set aside for bursting data from the router. * * author: Damon Fasching * * modifications/bugs * - Added autoinit start field into primary DMA control 5/18/01 LT * - since data is now event driven, switched the DMA ISR to be called * at the end of each frame, so that it can do a search for event * trailers, and other preps for sending the event to analysis. 12.05.02 dpsf ************************************************************************************/ void setupDmaParams() { #if (defined(REV_B)||defined(REV_C)) cntReload = DMA_GBLCNT_RMK(FRAMES_PER_BLOCK, FRAME_SIZE); /* Secondary control register */ burstDmaConfig.secctl= DMA_SECCTL_RMK(DMA_SECCTL_DMACEN_LOW, DMA_SECCTL_WSYNCCLR_CLEAR, DMA_SECCTL_WSYNCSTAT_CLEAR, DMA_SECCTL_RSYNCCLR_CLEAR, DMA_SECCTL_RSYNCSTAT_CLEAR, DMA_SECCTL_WDROPIE_DISABLE, DMA_SECCTL_WDROPCOND_CLEAR, DMA_SECCTL_RDROPIE_DISABLE, DMA_SECCTL_RDROPCOND_CLEAR, DMA_SECCTL_BLOCKIE_DISABLE, DMA_SECCTL_BLOCKCOND_CLEAR, DMA_SECCTL_LASTIE_DISABLE, DMA_SECCTL_LASTCOND_CLEAR, DMA_SECCTL_FRAMEIE_ENABLE, DMA_SECCTL_FRAMECOND_CLEAR, /* <= frame IE */ DMA_SECCTL_SXIE_DISABLE, DMA_SECCTL_SXCOND_CLEAR); /* Transfer counter: number of frames and number of elements per frame */ burstDmaConfig.xfrcnt= DMA_XFRCNT_RMK(FRAMES_PER_BLOCK, FRAME_SIZE); burstDmaConfig.src= ROUTER_FIFO_ADDR; burstDmaConfig.dst= BURST_BFR_BASE; #elif (defined(REV_E)) burstDmaConfig.opt= EDMA_OPT_RMK(EDMA_OPT_PRI_HIGH, EDMA_OPT_ESIZE_32BIT, EDMA_OPT_2DS_NO, EDMA_OPT_SUM_NONE, EDMA_OPT_2DD_NO, EDMA_OPT_DUM_IDX, EDMA_OPT_TCINT_YES, EDMA_OPT_TCC_OF(EDMA_BURST_ID), EDMA_OPT_LINK_NO, EDMA_OPT_FS_YES); //burstDmaConfig.cnt= EDMA_CNT_RMK(FRAMES_PER_BLOCK, FRAME_SIZE); burstDmaConfig.cnt= EDMA_CNT_RMK(0, FRAME_SIZE); burstDmaConfig.idx= EDMA_IDX_RMK(0,4); burstDmaConfig.rld= EDMA_RLD_RMK(FRAME_SIZE,0); burstDmaConfig.src= ROUTER_FIFO_ADDR; burstDmaConfig.dst= BURST_BFR_BASE; #endif return; } /************************************************************************************ * loadDmaRegs * * synopsis: Loads the dma registers with the values calculated the last time * setupDmaParams() was executed. * * author: Damon Fasching * * modifications/bugs: * - use DMA configuration structures. 13.03.02 dpsf ************************************************************************************/ void loadDmaRegs() { /* Even though the code would be more clear and more efficient if we set dmaPriCtrl * in setupDmaParams(), we are forced to move it here because of TI's 'improved' * but completely stupid new csl which requires allocation and deallocation of * global DMA registers. */ #if (defined(REV_B)||defined(REV_C)) burstDmaConfig.prictl= DMA_PRICTL_RMK( burstGblAddrRegID, /* reload the destination address at end of block */ DMA_PRICTL_SRCRLD_NONE, /* src doesn't change, so doesn't need reload */ DMA_PRICTL_EMOD_NOHALT, /* don't care */ DMA_PRICTL_FS_RSYNC, /* enable frame synch; starts with router interrupt */ DMA_PRICTL_TCINT_ENABLE, /* enable interrupt out */ DMA_PRICTL_PRI_DMA, /* give DMA priority over CPU */ DMA_PRICTL_WSYNC_NONE, /* must be disabled if FS enabled */ DMA_PRICTL_RSYNC_EXTINT4, /* set rsynch evnt: becomes fsynch evt if FS enabled */ DMA_PRICTL_INDEX_NA, /* don't care */ reloadCountRegID, /* reload register for element and frame counters */ DMA_PRICTL_SPLIT_DISABLE, /* split channel mode is not used */ DMA_PRICTL_ESIZE_32BIT, /* element size is words */ DMA_PRICTL_DSTDIR_INC, /* increment destination address by element size */ DMA_PRICTL_SRCDIR_NONE, /* no increment of source address (router FIFO output) */ DMA_PRICTL_START_AUTOINIT /* starts immediately upon configuration (then waits for pin 4 interrupts). Subsequent block transfers do not need re-starting. */ ); /* load the global registers and channel specific registers */ DMA_config(hBurstDataDmaCh, &burstDmaConfig); #elif (defined(REV_E)) /* load the global registers and channel specific registers */ EDMA_config(hBurstDataDmaCh, &burstDmaConfig); #endif } /************************************************************************************ * initiateTrapping - Sets up the DMA channel for bursting data from the router FPGA * to the DSP. The router interrupts the DSP to start a frame * transfer each time its internal FIFO has the requested number of words. At the * end of the frame the DMA channel interrupts the CPU to call the end of frame ISR; * the DMA engine automatically resets itself to the beginning of the burst buffer * when the end of the entire block is reached. This routine is called from the * startEventTrapping() primitive. * * author: Damon Fasching * * modifications/bugs: * - Interrupt service routines are now defined & linked to the different interrupt * types from within the BIOS configuration database file (.cdb), so the code * to hook the isr to the burst DMA has been commented out. 11.03.02 dpsf * - allocate a global address register to reload the burst buffer address at the * end of a block transfer. Burst DMA now is auto-initialized, so DMA_Start is * superfluous. Also added configuration for 2 more interrupts: an ISR for a DMA * transfer which moves the data out of internal memory at the end of the block * transfer (preliminary), and a 2nd interrupt triggered by the pin 4 from the * router, to count frames within the block tramsfer. 13.03.02 dpsf * - Removed the block transfer ISR as block transfers are now handled * entirely by the event manager routines. 14.06.02 dpsf ************************************************************************************/ INT32 initiateTrapping() { INT32 returnCode = SUCCESS; /* get global registers and set their values */ #if (defined(REV_B)||defined(REV_C)) reloadCountRegID = DMA_allocGlobalReg(DMA_GBL_CNTRLD, cntReload); burstGblAddrRegID= DMA_allocGlobalReg(DMA_GBL_ADDRRLD, BURST_BFR_BASE); if (reloadCountRegID == 0) { newError(&returnCode, NO_CNT_RLD_REG_AVAIL, FATAL_ERR, "initiateTrapping", "DMA count reload register not available", __FILE__, __LINE__); return returnCode; } else if (burstGblAddrRegID == 0) { newError(&returnCode, NO_GBL_ADDR_REG_AVAIL, FATAL_ERR, "initiateTrapping", "DMA global address register not available", __FILE__, __LINE__); return returnCode; } #endif /* open DMA channel & set up end of frame interrupt */ #if (defined(REV_B)||defined(REV_C)) hBurstDataDmaCh= DMA_open(DMA_CHA0, DMA_OPEN_RESET); burstDataDmaChEvtId= DMA_getEventId(hBurstDataDmaCh); #elif (defined(REV_E)) hBurstDataDmaCh= EDMA_open(EDMA_CHA_EXTINT4, EDMA_OPEN_RESET); EDMA_enableChannel(hBurstDataDmaCh); /* EDMA channels arrive on the CPU_INT8 vector (hooked to DMA ch. 0 in the IRQ). The ISR must then use the EDMA event ID to see which EDMA channel it is dealing with. */ burstDataDmaChEvtId= IRQ_EVT_DMAINT0; EDMA_intClear(EDMA_BURST_ID); EDMA_intEnable(EDMA_BURST_ID); #endif IRQ_clear(burstDataDmaChEvtId); IRQ_enable(burstDataDmaChEvtId); #ifndef TI_EVM /* EVM is handled separately */ /* enable external pin 4 to trigger interrupt on frame ready */ IRQ_clear(IRQ_EVT_EXTINT4); IRQ_enable(IRQ_EVT_EXTINT4); #endif /* load the DMA registers, transfers will be initiated by router with interrupts on pin 4 (DMA autostarts) for each frame transfer */ loadDmaRegs(); /* trigger the router FPGA to start collecting data */ triggerRouter(); rstPin4Mask(); return returnCode; } /************************************************************************************ * stopTrapping - releases the DMA channel used for data taking and disables the end * of block interrupt. Stops data collection in the router and makes * sure halt output is not set. This function is called from the * stopEventTrapping() primitive and also from analysisInterface() if * the user analysis routine has indicated that no more data is * required. * * author: Damon Fasching * * modifications/bugs: * - reset all DMA registers before closing; must also close and disable the * additional DMA channel, and disable the pin 4 interrupt. 15.03.02 dpsf ************************************************************************************/ void stopTrapping() { #if (defined(REV_B)||defined(REV_C)) DMA_config(hBurstDataDmaCh, &DmaReset); DMA_close(hBurstDataDmaCh); /* free the global registers */ DMA_setGlobalReg(reloadCountRegID, 0); DMA_setGlobalReg(burstGblAddrRegID, 0); DMA_freeGlobalReg(reloadCountRegID); DMA_freeGlobalReg(burstGblAddrRegID); /* disable interrupts */ IRQ_disable(burstDataDmaChEvtId); IRQ_disable(IRQ_EVT_EXTINT4); #elif (defined(REV_E)) EDMA_config(hBurstDataDmaCh, &DmaReset); EDMA_disableChannel(hBurstDataDmaCh); EDMA_close(hBurstDataDmaCh); /* disable interrupts */ EDMA_intEnable(EDMA_BURST_ID); IRQ_disable(burstDataDmaChEvtId); IRQ_disable(IRQ_EVT_EXTINT4); #endif /* signal the router to stop collecting data */ setPin4Mask(); haltRouter(); return; } /************************************************************************************ * triggerRouter: Signals router to start filling the output FIFO which feeds this * DSP. It will start filling the FIFO at the beginning of the next * event fragment which matches a trapping condition. The router autoclears the * FIFO when it is triggered to start taking data. The router is triggered using the * CLKXP bit in the MCBSP 0 register, which is configured for general purpose i/o. * * Similarly, the haltRouter routine signals router to stop filling the output FIFO * which feeds this DSP. This is a separate routine in case it is needed in other * places and the method of disabling trapping changes. ************************************************************************************/ void triggerRouter() {MCBSP_FSET(PCR0, CLKXP, 1); } void haltRouter() {MCBSP_FSET(PCR0, CLKXP, 0); } /************************************************************************************ * set and rst Pin4Mask: prevents the router from issuing any more pin4 interrupts; * it continues to collect data however. This is used to give * the DSP time to DMA over the event, trigger & execute the ISR (frameDmaDoneIsr). * Without this, it would be possible for a short event following on the heels of * another event to trigger a DMA while the DSP was still in the ISR. The router * must see the pin4 mask go high and then low again in order to issue any more * triggers. ************************************************************************************/ void setPin4Mask() {MCBSP_FSET(PCR1, DXSTAT, 1); } void rstPin4Mask() {MCBSP_FSET(PCR1, DXSTAT, 0); } /************************************************************************************ * pin4Isr: Hardware interrupt service routine, for the external pin #4; this will * be called at the beginning of every DMA data transfer from the router. * (The DMA autostarts). The yellow LED is toggled for every frame received. The * pin4 mask itself is raised by the DMA ISR (frameDmaDoneIsr). The mask could be * set here, but then the possibility of a race condition exists between this * routine and frameDmaDoneIsr (even though that will not arrive until three micro- * seconds after the pin4 interrupt- function calls are not quick!). * * author: Douglas Ferguson * * modifications: * - toggle the yellow LED using MCBSP port 1/CLKXP. 15.03.02 dpsf * - pin4 masking is now done in frameDmaDoneIsr. 02.07.02 dpsf * - despite moving the LED to its own dedicated register (Ext. pin 7, used * - as a gen. purpose output) in the 6713s, one or more of the SDSP LEDs * - still sometimes get out of sync(!) Instead of simply toggling the LED, * - it is set using the event manager control structure's frame count. To * - ensure the register latches the value, it is set twice. 21.08.03 dpsf * - removed the double latching. 29.06.04 dpsf ************************************************************************************/ interrupt void pin4Isr() { if (evtMgrCtrl.frameCount & 1) {yellowLed_off; } else {yellowLed_on; } } /************************************************************************************ * pin5Isr: Hardware interrupt service routine, for the external pin #5. * * author: Douglas Ferguson ************************************************************************************/ interrupt void pin5Isr() { register UINT32 a= 0, b; if (GET_RBIT(COMMAND_REG_0, CR_RST_ATTN_IFRAME_CNT)) rstMdspAttention(ATTN_IFRAME_CNT); if (GET_RBIT(COMMAND_REG_0, CR_RST_ATTN_SLOW_DATA)) rstMdspAttention(ATTN_SLOW_DATA); if (GET_RBIT(COMMAND_REG_0, CR_RST_ATTN_ERR_EVT)) rstMdspAttention(ATTN_ERR_EVT); if (GET_RBIT(COMMAND_REG_0, CR_RST_ATTN_BUFF_OVF)) rstMdspAttention(ATTN_BUFF_OVF); } /************************************************************************************ * Event Manager routines: The Event Manager organizes all the event data * collected from the router via DMA transfer, and * presents it to the analysis routines in queues. When frameDmaDoneIsr receives * a new frame, it sends the frame on to a specialized event manager routine * before returning; the event manager then (according to the frame's contents) * either a) begins a new event, or b) links the frame to the current event. When * the end-of-event tag is found, it pushes the event onto the approriate event * queue. ************************************************************************************/ /************************************************************************************ * frameDmaDoneIsr * * synopsis: This interrupt service routine is called when a DMA frame transfer from * the router is finished; it searches for headers and trailers, sets * several other parameters (such as trap ID & event length) that will be needed * by the event manager, and updates the event queue. When done, it clears the * interrupt flag, and, if possible, lowers the pin 4 mask. If lowering the pin 4 * mask is *not* possible, the event manager will handle it. * * modifications/bugs * - The new 6713 SDSPs use enhanced DMA (EDMA) in place of DMA. The two are * very different & require different approaches to setting up & monitoring the * DMA progress. For the 6701, the memory setting & copying routines in * utilities.c were independent of the event handling routines, since they used * another DMA channel, and then waited for completion using the CSL DMA_Wait * routine. For the 6713, DMA_Wait does not exist; the only way to monitor it * is to issue an interrupt & then check here to see which EDMA channel prompted * the DMA ISR. (All EDMA channels give an interrupt on CPU INT8). 05.08.03 dpsf * - 6713 EDMA supports interrupts at the end of the entire transfer only, and * does not automatically increment the destination address. Transfers have * been made into single frame transfers, and the increment/wrap check is done * manually. 06.08.03 dpsf * * author: Douglas Ferguson ************************************************************************************/ #define NEWEVENT 0 #define DATA 1 #define SLOWDATA 2 #define TRAILER 3 interrupt void frameDmaDoneIsr() { register UINT32 lw, *ptr, totLen, nEvt, nErr; register UINT32 data1, data2, data3; register int a, b, c; //temp variables. register UINT8 cf, wPtr, isrState; /************************************* ISR setup ************************************/ MCBSP_FSET(PCR1, DXSTAT, 1); SET_RBIT(TRAPSTAT_REG1_0, TSR0_ISR_ACTIVE); wPtr= eventQueue.writePtr; cf= evtMgrCtrl.cf; data1= eventQueue.eventData[wPtr].data1; data2= eventQueue.eventData[wPtr].data2; data3= eventQueue.eventData[wPtr].data3; lw= *(evtMgrCtrl.lastFrameWordPtr); isrState= evtMgrCtrl.isrState; evtMgrCtrl.frameCount++; evtMgrCtrl.eventFrameCount++; evtMgrCtrl.iFrameCnt++; evtMgrCtrl.pin4MaskDown= TRUE; /***************************** ISR overflow handling ********************************/ //An small section & associated c routine handle overflow conditions: if (GET_RBIT(TRAPSTAT_REG1_0, TSR0_OVERFLOW_ARM)) { //If in SLOWDATA, the frame must go to ext. buff, so increment count: if (evtMgrCtrl.isrState == SLOWDATA) evtMgrCtrl.xFrameCnt++; a= (evtMgrCtrl.iFrameCnt == evtMgrCtrl.iFrameMax); b= (evtMgrCtrl.xFrameCnt == evtMgrCtrl.xFrameMax); /* If the ISR state != SLOWDATA then check both buffers, otherwise can only place frames in external memory: */ c= ((isrState == SLOWDATA)? (b):(a && b)); /* If we're allowed to apply back-pressure using the router, simply don't lower the pin-4 mask at the end of the routine, and instead lower it in once at least one current frame has been processed. Otherwise, lower the mask at the end of the routine & allow the router to continue sending events; the DSP will count them & report error events. */ if (!evtMgrCtrl.permitBackPressure) { evtMgrCtrl.overflow= c; if (evtMgrCtrl.overflow) { a= isrOverflow(); if (a) return; //The overflow handler decides when it has ended. } } else {evtMgrCtrl.pin4MaskDown= (evtMgrCtrl.intOnly? (!a):(!c)); } } /******************************* ISR state: NEWEVENT ********************************/ if (evtMgrCtrl.isrState == NEWEVENT) { ptr= (UINT32 *) (BURST_BFR_BASE +cf*0x400); /* event headers begin with a 0xb0f00000 followed by 0xee1234ee. */ evtMgrCtrl.eventFrameCount= 1; if ((*ptr == 0xb0f00000) && (*(ptr+1) == 0xee1234ee)) { evtMgrCtrl.headerError= FALSE; } else { evtMgrCtrl.headerError= TRUE; } eventQueue.eventData[wPtr].startFrame= cf; eventQueue.eventData[wPtr].iStartFrame= cf; eventQueue.eventData[wPtr].iFrameCnt= 0; eventQueue.eventData[wPtr].xFrameCnt= 0; eventQueue.eventData[wPtr].error= FALSE; data1= cf< 16, (b != a) => 32 ASGN_RFLD(TRAPSTAT_REG1_0, 0, b, c); evtMgrCtrl.isrState= DATA; } /************************** Decide the frame destination **************************/ /* If we're using back-pressure (calibrating) and placing frames only into the internal buffers then there is no decision needed beyond that. Note that if the routine has decided not to lower the pin4 mask, the current frame just filled up the internal buffer, but that does not matter since we're not going to receive any more until we're ready for them (by lowering the pin4 mask when a frame has been processed). If both buffers are being used, then if the internal buffers are now full, the newly arrived frame must be moved to make room for the next frame. Once we begin filling external frames, all frames must go there until the event ends. If all buffers are now full, the routine will have gone into overflow & will never arrive here. */ if (evtMgrCtrl.intOnly) evtMgrCtrl.isrState= DATA; else if ( (evtMgrCtrl.isrState == DATA) &&(evtMgrCtrl.iFrameCnt < evtMgrCtrl.iFrameMax)) evtMgrCtrl.isrState= DATA; else evtMgrCtrl.isrState= SLOWDATA; /******************************* ISR state: DATA ********************************/ if (evtMgrCtrl.isrState == DATA) { ++eventQueue.eventData[wPtr].iFrameCnt; data1+= 1<>8) +(cf< evtMgrCtrl.iFrameMax) cf= 0; //Wrap beyond frame #(nFrames -1) evtMgrCtrl.cf= cf; ASGN_RFLD(TRAPSTAT_REG1_2, TSR2_IFRAME_TAIL,TSR2_IFRAME_TAIL_W, cf); evtMgrCtrl.lastFrameWordPtr+= 0x100; if ( ((UINT32) evtMgrCtrl.lastFrameWordPtr) > (BURST_BFR_BASE +BURST_SZ)) evtMgrCtrl.lastFrameWordPtr-= (BURST_SZ>>2); // >>2 => words for ptr. /* 6713 EDMA will not automatically advance the source pointer like the 6701 DMA does, so we do it manually. The element count does reload at the end of each frame (0x100 words). */ #if (defined(REV_E)) setDmaRegs(evtMgrCtrl.cf); #endif if (evtMgrCtrl.iFrameCnt >= evtMgrCtrl.iFrameThres) { setMdspAttention(ATTN_IFRAME_CNT); } //Arm the overflow handler if about to reach or at the maximum: if (evtMgrCtrl.intOnly) { if (evtMgrCtrl.iFrameCnt >= (evtMgrCtrl.iFrameMax -1)) SET_RBIT(TRAPSTAT_REG1_0, TSR0_OVERFLOW_ARM); } } /******************************* ISR state: SLOWDATA ********************************/ else { if (eventQueue.eventData[wPtr].xFrameCnt == 0) { //init. ext. buffs. eventQueue.eventData[wPtr].xStartFrame= evtMgrCtrl.xcf; data1|= evtMgrCtrl.xcf<>8) +(evtMgrCtrl.xcf< evtMgrCtrl.xMaxIdx) evtMgrCtrl.xcf= evtMgrCtrl.xMinIdx; ASGN_RFLD(TRAPSTAT_REG1_2, TSR2_XFRAME_TAIL,TSR2_XFRAME_TAIL_W, evtMgrCtrl.xcf); setMdspAttention(ATTN_SLOW_DATA); //Warn MDSP. //Arm the overflow handler if about to reach or at the maximum: if (evtMgrCtrl.xFrameCnt >= (evtMgrCtrl.xFrameMax -1)) SET_RBIT(TRAPSTAT_REG1_0, TSR0_OVERFLOW_ARM); } /****************************** header error handling *******************************/ /* If the ISR executes this section there has most likely been some sort of problem inside the FPGAs. Since the header wasn't recognized, there's a substantial chance that the trailer won't be either, so chop the event up into a series of single frame fragments. */ if (evtMgrCtrl.headerError) { ++evtMgrCtrl.nEventsTot; eventQueue.eventData[wPtr].length= 0x100; /* single frame */ data2|= 0x100 << EVT_MGR_EVTLEN_O; eventQueue.eventData[wPtr].error= TRUE; data2|= (1< wrap at 256: however the subtraction still works as before 0 (write ptr) -250 (read ptr) = 6 */ ++eventQueue.writePtr; evtMgrCtrl.isrState= NEWEVENT; } /****************************** ISR trailer checking ********************************/ else if ((lw & 0xffce0000) == 0x400e0000) { ++evtMgrCtrl.nEventsTot; eventQueue.eventData[wPtr].length= (UINT16) (lw & 0xffff); data2|= (lw & 0xffff) << EVT_MGR_EVTLEN_O; eventQueue.eventData[wPtr].nFrames= evtMgrCtrl.eventFrameCount; //dpsf get current router codes from john; differentiate between data & link //errors & set bits appropriately. if ((lw & 0xffcf0000) != 0x400f0000) { eventQueue.eventData[wPtr].error= TRUE; data2|= (1<>20].function)< wrap at 256: however the subtraction still works as before 0 (write ptr) -250 (read ptr) = 6 */ ++eventQueue.writePtr; evtMgrCtrl.isrState= NEWEVENT; } /******************************* ISR storage & exit ********************************/ /* for all states: write the updated values of the event record's words wPtr is still correct even if event is finished & on queue */ eventQueue.eventData[wPtr].data1= data1; eventQueue.eventData[wPtr].data2= data2; eventQueue.eventData[wPtr].data3= data3; /* Clear the condition which generated the interrupt, reset the bit which indicates that the ISR is active (for the master DSP) and unmask pin4. If an overflow condition exists, any remaining frames in the event will be dropped and the event subsequently marked as an error event. Once pin 4 is unmasked, the routine has ample time to return control to the interrupted routine, since when the pin 4 mask is dropped, a register inside the router prevents further pin 4 interrupts until a small delay has passed. This is set inside eventTrapSetup (master), by writing to the router's internal delay register (1 cnt= 25 ns= 4 cpu cycles) */ #if (defined(REV_B)||defined(REV_C)) DMA_CLEAR_CONDITION(hBurstDataDmaCh, DMA_SECCTL_FRAMECOND); #elif (defined(REV_E)) EDMA_intClear(EDMA_BURST_ID); #endif RST_RBIT(TRAPSTAT_REG1_0, TSR0_ISR_ACTIVE); if (evtMgrCtrl.pin4MaskDown) MCBSP_FSET(PCR1, DXSTAT, 0); eventInfo4M; } /************************************************************************************ * isrOverflow * * synopsis: This function is called by the DMA ISR when an overflow condition is * encountered. It will return SUCCESS when the condition is cleared (if * not forcibly cleared by the MDSP w/o sending any more events). * * If a data frame arrives on the DSP and the next frame would force the DSP into * overflow (because there is no place to store it) the overflow-arming flag is * asserted. Any subsequent frames arriving while the flag is asserted will cause * an overflow if no frames have been released meanwhile. Once in overflow, the * routine will continue in it until: 1) The MDSP flushes the buffers, or 2) all * internal & external frames are processed by any running tasks. While it's in * overflow, the routine simply counts the number of events & frames which have * been lost. * * Can imagine a more sophisticated treatment where we look for headers & data * frames as well, mimicking the ISR's actions while remaining in overflow. The * MDSP (if it is watching) will have noted the overflow condition though and so * will be simply waiting for the current event flow to end; therefore there's * little point. If the MDSP is not watching, don't care about anything but * counting in any case. Note though that the MDSP should not change the event * series (done during a scan-- see the DMA ISR for details) blindly while the * SDSP is in overflow, since we're not treating that here. * * The overflow events are simply discarded (not put on queue) -- they will not * be especially legible since they're missing frames. We could optionally put * them on the queue & just note error types etc. Note though that the overflow * summarizing routines in the main code cannot rely upon the frames data staying * put- it may already have been over-written by another overflow evt. by the * time they see it! All they have are the 3 event-summary words in the event * queue. * * author: Douglas Ferguson ************************************************************************************/ int isrOverflow(void) { int ovf; UINT32 lw, nErr, a, b; UINT8 cf; cf= evtMgrCtrl.cf; evtMgrCtrl.isrState= NEWEVENT; //When done ISR will always be ready for new event. a= (evtMgrCtrl.xFrameCnt == evtMgrCtrl.xFrameMax); b= (evtMgrCtrl.iFrameCnt == evtMgrCtrl.iFrameMax); ovf= ((a > 0) || (b > 0)); if (ovf) { --evtMgrCtrl.iFrameCnt; //Drop the frame. setDmaRegs(cf); setMdspAttention(ATTN_BUFF_OVF); //Signal to the MDSP that something is amiss. ++evtMgrCtrl.nOverflowFrames; lw= *(evtMgrCtrl.lastFrameWordPtr); if ((lw & 0xffce0000) == 0x400e0000) { //trailer found. ++evtMgrCtrl.nOverflowEvents; SET_RBIT(TRAPSTAT_REG1_0, TSR0_OVERFLOW); SET_RBIT(TRAPSTAT_REG1_0, TSR0_ERROR); nErr= GET_RFLD(TRAPSTAT_REG1_1, TSR1_ERR_COUNT, TSR1_ERR_COUNT_W) +1; ASGN_RFLD(TRAPSTAT_REG1_1, TSR1_ERR_COUNT, TSR1_ERR_COUNT_W, nErr); } } else { //All buffers free => exit overflow. RST_RBIT(TRAPSTAT_REG1_0, TSR0_OVERFLOW); RST_RBIT(TRAPSTAT_REG1_0, TSR0_OVERFLOW_ARM); evtMgrCtrl.overflow= FALSE; } /* If no longer in overflow, the ISR will take over from here. Otherwise, once this routine returns, the ISR will exit, so we handle flag setting here. */ if (ovf) { RST_RBIT(TRAPSTAT_REG1_0, TSR0_ISR_ACTIVE); MCBSP_FSET(PCR1, DXSTAT, 0); } return ovf; } /************************************************************************************ * initEventManager * * synopsis: Initializes all the variables & structures associated with * the event manager; called by eventTrapSetup. * * author: Douglas Ferguson ************************************************************************************/ INT32 initEventManager(UINT32 numberOfEvents, UINT32 releaseFrames, UINT32 permitBackPressure, UINT32 dataMode, UINT32 sLink, UINT32 format, UINT32 trapStray, RouterTrapParams traps[2]) { INT32 returnCode= SUCCESS, errorCode; int i; errorCode= initEvtMgrStructs(); if (errorCode != SUCCESS) { addError(&returnCode, errorCode, "initEventManager", "initEvtMgrStructs", __FILE__, __LINE__); return returnCode; } setupDmaParams(); evtMgrCtrl.isrState= NEWEVENT; evtMgrCtrl.cf= 0; evtMgrCtrl.xcf= 0x20; //dpsf ASGN_RFLD(TRAPSTAT_REG1_2, TSR2_IFRAME_TAIL,TSR2_IFRAME_TAIL_W, evtMgrCtrl.cf); ASGN_RFLD(TRAPSTAT_REG1_2, TSR2_IFRAME_HEAD,TSR2_IFRAME_HEAD_W, evtMgrCtrl.cf); ASGN_RFLD(TRAPSTAT_REG1_2, TSR2_XFRAME_TAIL,TSR2_XFRAME_TAIL_W, evtMgrCtrl.xcf); ASGN_RFLD(TRAPSTAT_REG1_2, TSR2_XFRAME_HEAD,TSR2_XFRAME_HEAD_W, evtMgrCtrl.xcf); evtMgrCtrl.lastFrameWordPtr= (UINT32 *) (BURST_BFR_BASE +evtMgrCtrl.cf*0x400 +0x3fc); evtMgrCtrl.eventLimit= numberOfEvents; evtMgrCtrl.releaseFrames= (char) releaseFrames; evtMgrCtrl.permitBackPressure= (char) permitBackPressure; evtMgrCtrl.dataMode= (char) dataMode; evtMgrCtrl.sLink= (char) sLink; evtMgrCtrl.format= (char) format; evtMgrCtrl.trapStray= (char) trapStray; evtMgrCtrl.asmGuard= 0xc0ffee; evtMgrCtrl.buffPtr[0]= (UINT32 *) BURST_BFR_BASE; evtMgrCtrl.buffPtr[1]= (UINT32 *) XBURST_BFR_BASE; evtMgrCtrl.buffLen[0]= BURST_SZ; evtMgrCtrl.buffLen[1]= XBURST_BFR_SZ; /* The buffer maxima are one less than the # frames since the dsp needs to distinguish between empty (head == tail) & full (if max= buffLen/frameSize then when it's full head == tail too, since they wrap). */ evtMgrCtrl.iFrameMax= (evtMgrCtrl.buffLen[0]>>10) -1; evtMgrCtrl.xFrameMax= (evtMgrCtrl.buffLen[1]>>10) -1; evtMgrCtrl.xMinIdx= evtMgrCtrl.iFrameMax +1; evtMgrCtrl.xMaxIdx= evtMgrCtrl.xMinIdx +evtMgrCtrl.xFrameMax; //If the internal frame threshold is exceeded, the ISR signals the MDSP: evtMgrCtrl.iFrameThres= evtMgrCtrl.iFrameMax -4; if (permitBackPressure) evtMgrCtrl.intOnly= TRUE; evtMgrCtrl.queuePtr= (UINT32 *) &eventQueue; if (evtMgrCtrl.format == TRAP_FMT_NORMAL) evtMgrCtrl.nTrailerWords= 6; else if (evtMgrCtrl.format == TRAP_FMT_ERROR) evtMgrCtrl.nTrailerWords= 9; for (i=0; i<2; ++i) { evtMgrCtrl.trapParams[i].config= (char) traps[i].config; evtMgrCtrl.trapParams[i].match= (char) traps[i].match; evtMgrCtrl.trapParams[i].exclusionFlag= (char) traps[i].exclusionFlag; evtMgrCtrl.trapParams[i].function= (char) traps[i].function; evtMgrCtrl.trapParams[i].modulus= (char) traps[i].modulus; evtMgrCtrl.trapParams[i].remainder= (char) traps[i].remainder; } evtMgrCtrl.running= TRUE; evtMgrCtrl.autoFlush= TRUE; SET_RBIT(STATUS_REG_0, SR_EVM); return returnCode; } /************************************************************************************ * initEvtMgrStructs * * synopsis: Zeros out all the variables & structures associated with * the event manager. * * author: Douglas Ferguson ************************************************************************************/ INT32 initEvtMgrStructs() { INT32 returnCode= SUCCESS; setMem((UINT32 *) &evtMgrCtrl, SIZEOF(struct EvtMgrCtrl), 0); setMem((UINT32 *) &eventQueue, SIZEOF(struct EventQueue), 0); return returnCode; } void flushEvents() { } void advanceEventQueue(unsigned char stray) { } /************************************************************************************ * getNextEvent: Returns a pointer to the event data structure from the first event * on the event queue. If no events are found, returns NULL. ************************************************************************************/ struct EventData *getNextEvent(void) { if (eventQueue.nEvents > 0) return &eventQueue.eventData[eventQueue.readPtr]; else return NULL; } /************************************************************************************ * copyEvent: Given a pointer to an event data structure, copies an event to the * indicated spot in memory. ************************************************************************************/ void copyEvent(struct EventData *data, UINT32 *dest) { UINT8 niFrames, nFrames, startFrame, i, frame; UINT32 *start, xlen= 0; UINT16 len; niFrames= GET_VFLD(data->data1, EVT_MGR_IFCNT_O, 8); if (niFrames > 0) startFrame= GET_VFLD(data->data1, EVT_MGR_IFRAME_O, 8); else startFrame= GET_VFLD(data->data1, EVT_MGR_XFRAME_O, 8); len= GET_VFLD(data->data2, EVT_MGR_EVTLEN_O, 16); nFrames= (len>>8) +1; for (i=0, frame=startFrame; istartFrame) {fCnt= 1;} else {++fCnt; } if (fCnt == (data->iFrameCnt +data->xFrameCnt)) return cf; if (fCnt < data->iFrameCnt) { nf= (cf+1) & 0x1f; //wrap to 0 after frame 31 } else if (fCnt == data->iFrameCnt) { nf= data->xStartFrame; //dpsf } else { nf= cf+1; if (nf == 0) nf= 32; /* will wrap after 255 back to 0; this is labelled the 32nd frame (external frames range from 32 to 255 */ } return nf; } void processEvent(struct EventData *data, unsigned char queue) { } #ifdef COMMENTED /************************************************************************************ * flushEvents: * * synopsis: Resets the event queues, DMA engine and frame registers. * * author: Douglas Ferguson ************************************************************************************/ void flushEvents() { evtMgrCtrl.currentFrame= 0xc; setDmaRegs(evtMgrCtrl.currentFrame); setMem((UINT32 *) &frameInfo, SIZEOF(struct FrameInfo), 0); setMem((UINT32 *) &eventQueue, SIZEOF(struct EventQueue), 0); evtMgrCtrl.currentEventId= 0xff; /* will wrap to 0 at 1st event */ evtMgrCtrl.checkForHeader= 1; evtMgrCtrl.lastFrameWordPtr= (UINT32 *) (BURST_BFR_BASE +evtMgrCtrl.currentFrame*0x400 +0x3fc); evtMgrCtrl.overflow= evtMgrCtrl.nOverflowSets= evtMgrCtrl.overflowSet= 0; evtMgrCtrl.overflowFrame[0]= evtMgrCtrl.overflowFrame[1]= 0; evtMgrCtrl.headerFound= evtMgrCtrl.trailerFound= 0; evtMgrCtrl.headerError= 0; } #endif