/************************************************************************************ * masterTasks.c * * synopsis: This file contains tasks which run on the master DSP. Typically these * coordinate and monitor the slave DSPs as they process data. * * in this file: mirrorTask, trapReqTask * * related files: * taskManager.c: Contains routines for starting, stopping & managing tasks. * slaveTasks.c: Contains the slave DSP tasks. * histogram.h: Contains the definitions for the histogram control structures * on the master & slave DSPs. ************************************************************************************/ #include #include #include #include #include #include #include "resources.h" #include "accessSlave.h" #include "comRegDfns.h" extern char genStr[]; extern TIMER_Handle timer1; /* general purpose timer, started in main() */ extern far struct TaskMgrCtrl taskMgrCtrl; #pragma CODE_SECTION(mirrorTask, "xcode"); #pragma CODE_SECTION(trapReqTask, "xcode"); /* Mirror Task state-machine states: */ #define MIRROR_RUNNING 0x2 #define MIRROR_WAITING 0x3 #define MAX_MIRRORS 6 /************************************************************************************ * mirrorTask * * synopsis: The mirror task takes a snapshot of specified areas of the SDSPs' * memory at a specified frequency. The SDSP memory thus mirrored is * then accessible to the DAQ during normal ROD operations. This could also be * accomplished using repeated primitive sending (rwSlaveMemory); this would * however require constant attemtion & servicing from the DAQ. The task does * the fetching more quickly and autonomously. * struct MIRROR_TASK_IN { UINT32 slvNumber, mirrorFreq, mirrorBase, mirrorSlvBase, mirrorLen; }; * If stopped & restarted- if slvNumber (bits) has high bit set, rest the same, will accumulate the mirrors. later: accum flag. Otherwise will re-init. If accumulating, will stack the mirrors. Output: Gives the base & total length of all mirrors. * author: Douglas Ferguson ************************************************************************************/ INT32 mirrorTask(TaskInput *tsi, TaskOutput *tso, UINT32 opFlags) { INT32 returnCode= REPEAT_TASK, slaveStat, errorCode; static UINT8 state= TASK_INIT, slvBits, nMirrorSlaves, first, warn[4], nMirrors= 0; static UINT32 *mirrorBase= (UINT32 *) (MIRROR_DEFAULT_BASE), mirrorTotLen= 0; static UINT32 mirrorFreq[MAX_MIRRORS], lastUpdate[MAX_MIRRORS], *mirrorSlvBase[MAX_MIRRORS], mirrorLen[MAX_MIRRORS]; UINT32 word, *address, dt, readTime, time; UINT8 i, slv, slv_idx, accum, stateChange; char startStr[40]; /********************* data retrieval & routine reset *********************/ if (opFlags > 0x10) { /* Place the interesting internal variables into the output structure */ tso->genTaskOut.dataPtr= NULL; tso->genTaskOut.dataLength= 0; if (opFlags & TASK_HALT_MASK) { newInformation(__FILE__, __LINE__, "Memory Mirror task halting.\n"); state= TASK_INIT; return TASK_HALTED; } else if (opFlags & TASK_INIT_MASK) { newInformation(__FILE__, __LINE__, "Memory Mirror task re-initing.\n"); /* reset nMirrors, and the default base & length, which are not reset on task stopping to allow accumulation. */ nMirrors= mirrorTotLen= 0; mirrorBase= (UINT32 *) (MIRROR_DEFAULT_BASE); state= TASK_INIT; return TASK_INITIALIZED; } else if (opFlags & TASK_QUERY_MASK) { newInformation(__FILE__, __LINE__, "Memory Mirror task query data output.\n"); return TASK_QUERIED; } } /*************************** routine states:INIT **************************/ else if (state == TASK_INIT) { /* set up any static variables beyond state */ returnCode= REPEAT_TASK; first= TRUE; /* check the mirrored slaves */ if (tsi->mirrorMemoryTaskIn.slvBits == 0) { sprintf(genStr, "%s%s","WARNING: Memory mirroring task running without " "any mirrored slaves.\n"); newInformation(__FILE__, __LINE__, genStr); } accum= ((tsi->mirrorMemoryTaskIn.slvBits & 0x80000000)&&(nMirrors>0)); if (!accum) nMirrors= 0; mirrorSlvBase[nMirrors]= tsi->mirrorMemoryTaskIn.mirrorSlvBase; mirrorLen[nMirrors]= tsi->mirrorMemoryTaskIn.mirrorLen; mirrorFreq[nMirrors]= tsi->mirrorMemoryTaskIn.mirrorFreq; lastUpdate[nMirrors]= TIMER_getCount(timer1); if (accum) { if ( (tsi->mirrorMemoryTaskIn.mirrorBase != mirrorBase) ||((tsi->mirrorMemoryTaskIn.slvBits & 0xff) != slvBits) ) { sprintf(genStr, "%s%s%s"," When accumulating, the bases in memory ", "and the mirrored slaves must match. Stacking on ", "old base and using previous slaves.\n"); newError(&errorCode, ACCUM_ERROR, ERROR_0, "mirrorTask", genStr, __FILE__, __LINE__); } mirrorTotLen+= nMirrorSlaves*mirrorLen[nMirrors]; strcpy(startStr, " Mirror task: accumulating new "); } else { /* need checks on reserved/invalid areas of memory: separate fxn memCheck */ /* errorCode= memCheck(mirrorMemoryTaskIn.mirrorBase); if (errorCode != SUCCESS) ==> bail. + checks on # mirrors, mirror separation*/ slvBits= tsi->mirrorMemoryTaskIn.slvBits; nMirrorSlaves= 0; for (slv= 0; slv< N_SDSP; ++slv) { warn[slv]= FALSE; if (!(slvBits & (1<mirrorMemoryTaskIn.mirrorBase; strcpy(startStr, " Mirror task: starting new "); } ++nMirrors; sprintf(genStr, "%s%s%08x %08x%s%d", startStr, "mirror at slv base, length= ", mirrorSlvBase[nMirrors], mirrorLen[nMirrors], " with frequency ~", mirrorFreq[nMirrors]," x 100 microseconds.\n", "Mirror base, total length= ",mirrorBase, mirrorTotLen,".\n"); newInformation(__FILE__, __LINE__, genStr); state= MIRROR_RUNNING; } /********************* routine states:RUNNING/WAITING ********************* * the task toggles between these two states depending upon whether or not * all slave DSPs are currently configured. */ else if ((state == MIRROR_RUNNING)||(state == MIRROR_WAITING)) { if (first) { first= FALSE; setTaskState(MIRROR_TASK, state); } for (slv= slv_idx= 0; slv< N_SDSP; ++slv) { if (!(slvBits & (1< mirrorFreq[i]) { /* if i== 0, place the slave's # in a sprintf(genStr, " Slave DSP 0x "); (16 bytes) and insert. increment the address & update the lengths to reflect this header. */ readSlvBlock(slv, mirrorSlvBase[i], address, mirrorLen[i]); lastUpdate[i]= TIMER_getCount(timer1); readTime= (lastUpdate[i] -time)/10; if (GET_RBIT(DIAGNOSTIC_REG, DR_DISP_MIRROR_CTIME)) { RST_RBIT(DIAGNOSTIC_REG, DR_DISP_MIRROR_CTIME); sprintf(genStr,"%s%d%s%04x%s%05x%s", "Reading time for mirror[",i,"]: ", readTime, " mic s. deltaT: ", dt,".\n"); newInformation(__FILE__, __LINE__, genStr); } } /* do update */ address+= mirrorLen[i]; } /* loop over mirrors */ } /* memory mirroring block */ } /* loop over slaves */ /* flip the task manager's state indicator if a state change detected. */ if (stateChange) { stateChange= FALSE; if ((warn[0])||(warn[1])||(warn[2])||(warn[3])) { if (state == MIRROR_RUNNING) { first= TRUE; state= MIRROR_WAITING; } } else { if (state == MIRROR_WAITING) { first= TRUE; state= MIRROR_RUNNING; } } } } /***************** end of routine states:RUNNING/WAITING ******************/ return returnCode; } /************************************************************************************ * trapReqTask * * synopsis: Monitoring of the event trap register & handling any pending trap * requests. * * author: Douglas Ferguson ************************************************************************************/ INT32 trapReqTask(TaskInput *tsi, TaskOutput *tso, UINT32 opFlags) { INT32 returnCode= REPEAT_TASK; return returnCode; }