From af78cc8f3554f495a9767d656ad24c471a9b84d7 Mon Sep 17 00:00:00 2001 From: Rolf Bork <rolf@ligo.caltech.edu> Date: Wed, 29 May 2019 11:20:42 -0500 Subject: [PATCH] Made generic functions to pass FE code timing info to EPICS. --- src/fe/controllerApp.c | 114 +++++++++------------- src/fe/controllerCymac.c | 47 +-------- src/fe/controllerTS.c | 142 +++++++++------------------- src/fe/timing.c | 2 +- src/include/drv/iop_adc_functions.c | 1 + 5 files changed, 93 insertions(+), 213 deletions(-) diff --git a/src/fe/controllerApp.c b/src/fe/controllerApp.c index d7fa6e500..de35cd6af 100644 --- a/src/fe/controllerApp.c +++ b/src/fe/controllerApp.c @@ -124,21 +124,9 @@ unsigned int timeSec = 0; unsigned int timeSecDiag = 0; /* 1 - error occured on shmem; 2 - RFM; 3 - Dolphin */ unsigned int ipcErrBits = 0; -int adcTime; ///< Used in code cycle timing -int adcHoldTime = 0; ///< Stores time between code cycles -int adcHoldTimeMax = 0; ///< Stores time between code cycles int startGpsTime = 0; -int adcHoldTimeMin = 0xffff; -int adcHoldTimeAvg = 0; -int adcHoldTimeAvgPerSec; -int usrTime; ///< Time spent in user app code -int usrHoldTime = 0; ///< Max time spent in user app code int cardCountErr = 0; int cycleTime; ///< Current cycle time -int timeHold = 0; ///< Max code cycle time within 1 sec period -int timeHoldHold = 0; ///< Max code cycle time within 1 sec period; hold for another sec -int timeHoldWhen= 0; ///< Cycle number within last second when maximum reached; running -int timeHoldWhenHold = 0; ///< Cycle number within last second when maximum reached struct rmIpcStr *daqPtr; @@ -155,8 +143,9 @@ int dacOF[MAX_DAC_MODULES]; char daqArea[2*DAQ_DCU_SIZE]; // Space allocation for daqLib buffers int cpuId = 1; -adcInfo_t adcInfo; +adcInfo_t adcinfo; dacInfo_t dacInfo; +timing_diag_t timeinfo; int killipc = 0; @@ -212,7 +201,6 @@ void *fe_start(void *arg) ///< so this helps prevent long cycles during that time. int dkiTrip = 0; RFM_FE_COMMS *pEpicsComms; /// @param *pEpicsComms Pointer to EPICS shared memory space - int timeHoldMax = 0; /// @param timeHoldMax Max code cycle time since last diag reset int myGmError2 = 0; /// @param myGmError2 Myrinet error variable int status; /// @param status Typical function return value int onePpsTime = 0; /// @param onePpsTime One PPS diagnostic check @@ -394,6 +382,8 @@ udelay(1000); // printf("Calling feCode() to initialize\n"); iopDacEnable = feCode(cycleNum,dWord,dacOut,dspPtr[0],&dspCoeff[0], (struct CDS_EPICS *)pLocalEpics,1); +// Initialize timing info variables + initializeTimingDiags(&timeinfo); pLocalEpics->epicsOutput.fe_status = INIT_DAC_MODS; /// \> Initialize DAC channels. @@ -440,7 +430,7 @@ udelay(1000); timeSec = current_time_fe() -1; #endif - rdtscll(adcTime); + rdtscll(adcinfo.adcTime); /// ******************************************************************************\n /// Enter the infinite FE control loop ******************************************\n @@ -454,13 +444,13 @@ udelay(1000); #endif - // ********************************************************************************************************** + // ******************************************************************************* // NORMAL OPERATION -- Wait for ADC data ready // On startup, only want to read one sample such that first cycle // coincides with GPS 1PPS. Thereafter, sampleCount will be // increased to appropriate number of 65536 s/sec to match desired // code rate eg 32 samples each time thru before proceeding to match 2048 system. - // ********************************************************************************************************** + // ******************************************************************************* #ifdef NO_CPU_SHUTDOWN while(!kthread_should_stop()){ @@ -484,7 +474,7 @@ udelay(1000); #endif for(ll=0;ll<sampleCount;ll++) { - status = app_adc_read(ioMemCntr,ioClock,&adcInfo,cpuClock); + status = app_adc_read(ioMemCntr,ioClock,&adcinfo,cpuClock); // Return of non zero = ADC timeout error. if(status) @@ -535,27 +525,14 @@ udelay(1000); /// \> Cycle 18, Send timing info to EPICS at 1Hz if(cycleNum ==HKP_TIMING_UPDATES) { - pLocalEpics->epicsOutput.cpuMeter = timeHold; - pLocalEpics->epicsOutput.cpuMeterMax = timeHoldMax; - timeHoldHold = timeHold; - timeHold = 0; - timeHoldWhenHold = timeHoldWhen; - - if (timeSec % 4 == 0) pLocalEpics->epicsOutput.adcWaitTime = adcHoldTimeMin; - else if (timeSec % 4 == 1) - pLocalEpics->epicsOutput.adcWaitTime = adcHoldTimeMax; - else - pLocalEpics->epicsOutput.adcWaitTime = adcHoldTimeAvg/CYCLE_PER_SECOND; - adcHoldTimeAvgPerSec = adcHoldTimeAvg/CYCLE_PER_SECOND; - adcHoldTimeMax = 0; - adcHoldTimeMin = 0xffff; - adcHoldTimeAvg = 0; - if((adcHoldTime > CYCLE_TIME_ALRM_HI) || (adcHoldTime < CYCLE_TIME_ALRM_LO)) + sendTimingDiags2Epics(pLocalEpics, &timeinfo, &adcinfo); + + if((adcinfo.adcHoldTime > CYCLE_TIME_ALRM_HI) || (adcinfo.adcHoldTime < CYCLE_TIME_ALRM_LO)) { diagWord |= FE_ADC_HOLD_ERR; feStatus |= FE_ERROR_TIMING; } - if(timeHoldMax > CYCLE_TIME_ALRM) + if(timeinfo.timeHoldMax > CYCLE_TIME_ALRM) { diagWord |= FE_PROC_TIME_ERR; feStatus |= FE_ERROR_TIMING; @@ -567,22 +544,21 @@ udelay(1000); initialDiagReset = 0; pLocalEpics->epicsInput.diagReset = 0; pLocalEpics->epicsInput.ipcDiagReset = 1; - timeHoldMax = 0; + timeinfo.timeHoldMax = 0; diagWord = 0; ipcErrBits = 0; } - // Flip the onePPS various once/sec as a watchdog monitor. - // pLocalEpics->epicsOutput.onePps ^= 1; pLocalEpics->epicsOutput.diagWord = diagWord; } - +// ***************************************************************** /// \> Check for requests for filter module clear history requests. This is spread out over a number of cycles. // Spread out filter coeff update, but keep updates at 16 Hz // here we are rounding up: // x/y rounded up equals (x + y - 1) / y // +// ***************************************************************** static const unsigned int mpc = (MAX_MODULES + (FE_RATE / 16) - 1) / (FE_RATE / 16); // Modules per cycle unsigned int smpc = mpc * subcycle; // Start module counter unsigned int empc = smpc + mpc; // End module counter @@ -590,16 +566,22 @@ udelay(1000); for (i = smpc; i < MAX_MODULES && i < empc ; i++) checkFiltReset(i, dspPtr[0], pDsp[0], &dspCoeff[0], MAX_MODULES, pCoeff[0]); +// ***************************************************************** /// \> Check if code exit is requested if(cycleNum == MAX_MODULES) vmeDone = stop_working_threads | checkEpicsReset(cycleNum, (struct CDS_EPICS *)pLocalEpics); +// ***************************************************************** +// ***************************************************************** /// \> Cycle 10 to number of BIO cards:\n /// - ---- Read Dio cards once per second \n +// ***************************************************************** status = app_dio_read_write(); +// ***************************************************************** /// \> Write data to DAQ. +// ***************************************************************** #ifndef NO_DAQ // Call daqLib @@ -615,10 +597,11 @@ udelay(1000); feStatus |= FE_ERROR_DAQ; #endif +// ***************************************************************** /// \> Cycle 19, write updated diag info to EPICS +// ***************************************************************** if(cycleNum == HKP_DIAG_UPDATES) { - pLocalEpics->epicsOutput.userTime = usrHoldTime; pLocalEpics->epicsOutput.ipcStat = ipcErrBits; if(ipcErrBits & 0xf) feStatus |= FE_ERROR_IPC; // Create FB status word for return to EPICS @@ -634,14 +617,13 @@ udelay(1000); mxDiag = mxDiagR; if(mxStat != MX_OK) feStatus |= FE_ERROR_DAQ;; - usrHoldTime = 0; if(pLocalEpics->epicsInput.overflowReset) { if (pLocalEpics->epicsInput.overflowReset) { for (ii = 0; ii < 16; ii++) { for (jj = 0; jj < cdsPciModules.adcCount; jj++) { - adcInfo.overflowAdc[jj][ii] = 0; - adcInfo.overflowAdc[jj][ii + 16] = 0; + adcinfo.overflowAdc[jj][ii] = 0; + adcinfo.overflowAdc[jj][ii + 16] = 0; pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0; pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii + 16] = 0; } @@ -664,7 +646,10 @@ udelay(1000); { pLocalEpics->epicsOutput.timeDiag = timeSec; } + +// ***************************************************************** /// \> Cycle 20, Update latest DAC output values to EPICS +// ***************************************************************** if(subcycle == HKP_DAC_EPICS_UPDATES) { // Send DAC output values at 16Hzfb @@ -677,48 +662,35 @@ udelay(1000); } } +// ***************************************************************** /// \> Cycle 21, Update ADC/DAC status to EPICS. +// ***************************************************************** if(cycleNum == HKP_ADC_DAC_STAT_UPDATES) { pLocalEpics->epicsOutput.ovAccum = overflowAcc; - feStatus |= app_adc_status_update(&adcInfo); + feStatus |= app_adc_status_update(&adcinfo); feStatus |= app_dac_status_update(&dacInfo); } + + // ***************************************************************** + // // Update end of cycle information + // // ***************************************************************** // Capture end of cycle time. rdtscll(cpuClock[CPU_TIME_CYCLE_END]); + captureEocTiming(cycleNum, cycle_gps_time, &timeinfo, &adcinfo); + /// \> Compute code cycle time diag information. - cycleTime = (cpuClock[CPU_TIME_CYCLE_END] - cpuClock[CPU_TIME_CYCLE_START])/CPURATE; + timeinfo.cycleTime = (cpuClock[CPU_TIME_CYCLE_END] - cpuClock[CPU_TIME_CYCLE_START])/CPURATE; - // Hold the max cycle time over the last 1 second - if(cycleTime > timeHold) { - timeHold = cycleTime; - timeHoldWhen = cycleNum; - } - // Hold the max cycle time since last diag reset - if(cycleTime > timeHoldMax) timeHoldMax = cycleTime; - adcHoldTime = (cpuClock[CPU_TIME_CYCLE_START] - adcTime)/CPURATE; - - // Avoid calculating the max hold time for the first few seconds - if (cycleNum != 0 && (startGpsTime+3) < cycle_gps_time) { - if(adcHoldTime > adcHoldTimeMax) adcHoldTimeMax = adcHoldTime; - if(adcHoldTime < adcHoldTimeMin) adcHoldTimeMin = adcHoldTime; - adcHoldTimeAvg += adcHoldTime; - } - adcTime = cpuClock[CPU_TIME_CYCLE_START]; - // Calc the max time of one cycle of the user code - // For IOP, more interested in time to get thru ADC read code and send to slave apps - usrTime = (cpuClock[CPU_TIME_USR_END] - cpuClock[CPU_TIME_USR_START])/CPURATE; - if(usrTime > usrHoldTime) usrHoldTime = usrTime; + adcinfo.adcHoldTime = (cpuClock[CPU_TIME_CYCLE_START] - adcinfo.adcTime)/CPURATE; + adcinfo.adcTime = cpuClock[CPU_TIME_CYCLE_START]; + // Calc the max time of one cycle of the user code + timeinfo.usrTime = (cpuClock[CPU_TIME_USR_END] - cpuClock[CPU_TIME_USR_START])/CPURATE; + if(timeinfo.usrTime > timeinfo.usrHoldTime) timeinfo.usrHoldTime = timeinfo.usrTime; /// \> Update internal cycle counters cycleNum += 1; -#ifdef DIAG_TEST - if(pLocalEpics->epicsInput.bumpCycle != 0) { - cycleNum += pLocalEpics->epicsInput.bumpCycle; - pLocalEpics->epicsInput.bumpCycle = 0; - } -#endif cycleNum %= CYCLE_PER_SECOND; clock1Min += 1; clock1Min %= CYCLE_PER_MINUTE; diff --git a/src/fe/controllerCymac.c b/src/fe/controllerCymac.c index 1d9500423..f05c49a8e 100644 --- a/src/fe/controllerCymac.c +++ b/src/fe/controllerCymac.c @@ -495,7 +495,7 @@ adcInfo_t *padcinfo = (adcInfo_t *)&adcinfo; timeSec = remote_time((struct CDS_EPICS *)pLocalEpics); printf ("Using remote GPS time %d \n",timeSec); #else - timeSec = current_time() -1; + timeSec = current_time_fe() -1; #endif rdtscl(adcinfo.adcTime); @@ -662,24 +662,10 @@ adcInfo_t *padcinfo = (adcInfo_t *)&adcinfo; // ***************************************************************** if(cycleNum ==HKP_TIMING_UPDATES) { - pLocalEpics->epicsOutput.cpuMeter = timeinfo.timeHold; - pLocalEpics->epicsOutput.cpuMeterMax = timeinfo.timeHoldMax; + sendTimingDiags2Epics(pLocalEpics, &timeinfo, &adcinfo); pLocalEpics->epicsOutput.dacEnable = dacEnable; - timeinfo.timeHoldHold = timeinfo.timeHold; - timeinfo.timeHold = 0; - timeinfo.timeHoldWhenHold = timeinfo.timeHoldWhen; - - if (timeSec % 4 == 0) pLocalEpics->epicsOutput.adcWaitTime = - adcinfo.adcHoldTimeMin; - else if (timeSec % 4 == 1) - pLocalEpics->epicsOutput.adcWaitTime = adcinfo.adcHoldTimeMax; - else - pLocalEpics->epicsOutput.adcWaitTime = adcinfo.adcHoldTimeAvg/CYCLE_PER_SECOND; - - adcinfo.adcHoldTimeAvgPerSec = adcinfo.adcHoldTimeAvg/CYCLE_PER_SECOND; - adcinfo.adcHoldTimeMax = 0; - adcinfo.adcHoldTimeMin = 0xffff; - adcinfo.adcHoldTimeAvg = 0; + + if((adcinfo.adcHoldTime > CYCLE_TIME_ALRM_HI) || (adcinfo.adcHoldTime < CYCLE_TIME_ALRM_LO)) { diagWord |= FE_ADC_HOLD_ERR; @@ -697,7 +683,6 @@ adcInfo_t *padcinfo = (adcInfo_t *)&adcinfo; initialDiagReset = 0; pLocalEpics->epicsInput.diagReset = 0; pLocalEpics->epicsInput.ipcDiagReset = 1; - // pLocalEpics->epicsOutput.diags[1] = 0; timeinfo.timeHoldMax = 0; diagWord = 0; ipcErrBits = 0; @@ -970,31 +955,9 @@ adcInfo_t *padcinfo = (adcInfo_t *)&adcinfo; rdtscl(cpuClock[CPU_TIME_CYCLE_END]); /// \> Compute code cycle time diag information. + captureEocTiming(cycleNum, cycle_gps_time, &timeinfo, &adcinfo); timeinfo.cycleTime = (cpuClock[CPU_TIME_CYCLE_END] - cpuClock[CPU_TIME_CYCLE_START])/CPURATE; - // Hold the max cycle time over the last 1 second - if(timeinfo.cycleTime > timeinfo.timeHold) { - timeinfo.timeHold = timeinfo.cycleTime; - timeinfo.timeHoldWhen = cycleNum; - } - // Hold the max cycle time since last diag reset - if(timeinfo.cycleTime > timeinfo.timeHoldMax) timeinfo.timeHoldMax = timeinfo.cycleTime; adcinfo.adcHoldTime = (cpuClock[CPU_TIME_CYCLE_START] - adcinfo.adcTime)/CPURATE; - // Avoid calculating the max hold time for the first few seconds - if (cycleNum != 0 && (timeinfo.startGpsTime+3) < cycle_gps_time) { - if(adcinfo.adcHoldTime > adcinfo.adcHoldTimeMax) - adcinfo.adcHoldTimeMax = adcinfo.adcHoldTime; - if(adcinfo.adcHoldTime < adcinfo.adcHoldTimeMin) - adcinfo.adcHoldTimeMin = adcinfo.adcHoldTime; - adcinfo.adcHoldTimeAvg += adcinfo.adcHoldTime; - if (adcinfo.adcHoldTimeMax > adcinfo.adcHoldTimeEverMax) { - adcinfo.adcHoldTimeEverMax = adcinfo.adcHoldTimeMax; - adcinfo.adcHoldTimeEverMaxWhen = cycle_gps_time; - } - if (timeinfo.timeHoldMax > timeinfo.cpuTimeEverMax) { - timeinfo.cpuTimeEverMax = timeinfo.timeHoldMax; - timeinfo.cpuTimeEverMaxWhen = cycle_gps_time; - } - } adcinfo.adcTime = cpuClock[CPU_TIME_CYCLE_START]; // Calc the max time of one cycle of the user code // For IOP, more interested in time to get thru ADC read code and send to slave apps diff --git a/src/fe/controllerTS.c b/src/fe/controllerTS.c index 6fec66f8f..26295400d 100644 --- a/src/fe/controllerTS.c +++ b/src/fe/controllerTS.c @@ -70,6 +70,7 @@ int printk(const char *fmt, ...) { #include "fm10Gen.h" // CDS filter module defs and C code #include "feComms.h" // Lvea control RFM network defs. #include "daqmap.h" // DAQ network layout +#include "cds_types.h" #include "controller.h" #ifndef NO_DAQ @@ -94,6 +95,10 @@ int printk(const char *fmt, ...) { TIMING_SIGNAL *pcieTimer; +adcInfo_t adcinfo; +dacInfo_t dacinfo; +timing_diag_t timeinfo; + // Contec 64 input bits plus 64 output bits (Standard for aLIGO) /// Contec6464 input register values unsigned int CDIO6464InputInput[MAX_DIO_MODULES]; // Binary input bits @@ -130,6 +135,8 @@ unsigned int timeSec = 0; unsigned int timeSecDiag = 0; /* 1 - error occured on shmem; 2 - RFM; 3 - Dolphin */ unsigned int ipcErrBits = 0; +int cardCountErr = 0; +#if 0 int adcTime; ///< Used in code cycle timing int adcHoldTime; ///< Stores time between code cycles int adcHoldTimeMax; ///< Stores time between code cycles @@ -141,14 +148,13 @@ int startGpsTime; int adcHoldTimeMin; int adcHoldTimeAvg; int adcHoldTimeAvgPerSec; -int usrTime; ///< Time spent in user app code int usrHoldTime; ///< Max time spent in user app code -int cardCountErr = 0; int cycleTime; ///< Current cycle time int timeHold = 0; ///< Max code cycle time within 1 sec period int timeHoldHold = 0; ///< Max code cycle time within 1 sec period; hold for another sec int timeHoldWhen= 0; ///< Cycle number within last second when maximum reached; running int timeHoldWhenHold = 0; ///< Cycle number within last second when maximum reached +#endif // The following are for timing histograms written to /proc files #if defined(SERVO64K) || defined(SERVO32K) @@ -247,7 +253,7 @@ void *fe_start(void *arg) ///< Code runs longer for first few cycles on startup as it settles in, ///< so this helps prevent long cycles during that time. int limit = OVERFLOW_LIMIT_16BIT; /// @param limit ADC/DAC overflow test value - int mask = GSAI_DATA_MASK; /// @param mask Bit mask for ADC/DAC read/writes + // int mask = GSAI_DATA_MASK; /// @param mask Bit mask for ADC/DAC read/writes int num_outs = MAX_DAC_CHN_PER_MOD; /// @param num_outs Number of DAC channels variable volatile int *packedData; /// @param *packedData Pointer to ADC PCI data space volatile unsigned int *pDacData; /// @param *pDacData Pointer to DAC PCI data space @@ -257,7 +263,6 @@ void *fe_start(void *arg) int sync21ppsCycles = 0; /// @param sync32ppsCycles Number of attempts to sync to 1PPS int dkiTrip = 0; RFM_FE_COMMS *pEpicsComms; /// @param *pEpicsComms Pointer to EPICS shared memory space - int timeHoldMax = 0; /// @param timeHoldMax Max code cycle time since last diag reset int myGmError2 = 0; /// @param myGmError2 Myrinet error variable int status; /// @param status Typical function return value float onePps; /// @param onePps Value of 1PPS signal, if used, for diagnostics @@ -296,9 +301,11 @@ void *fe_start(void *arg) static int dacTimingError = 0; static int dacTimingErrorPending[MAX_DAC_MODULES]; +#if 0 volatile GSA_18BIT_DAC_REG *dac18bitPtr; // Pointer to 16bit DAC memory area volatile GSA_20BIT_DAC_REG *dac20bitPtr; // Pointer to 20bit DAC memory area volatile GSC_DAC_REG *dac16bitPtr; // Pointer to 18bit DAC memory area + #endif unsigned int usec = 0; unsigned int offset = 0; @@ -500,16 +507,7 @@ udelay(1000); iopDacEnable = feCode(cycleNum,dWord,dacOut,dspPtr[0],&dspCoeff[0], (struct CDS_EPICS *)pLocalEpics,1); // Clear timing diags. - adcHoldTime = 0; - adcHoldTimeMax = 0; - adcHoldTimeEverMax = 0; - adcHoldTimeEverMaxWhen = 0; - cpuTimeEverMax = 0; - cpuTimeEverMaxWhen = 0; - startGpsTime = 0; - adcHoldTimeMin = 0xffff; - adcHoldTimeAvg = 0; - usrHoldTime = 0; + initializeTimingDiags(&timeinfo); missedCycle = 0; /// \> If IOP, Initialize the ADC modules @@ -527,7 +525,7 @@ udelay(1000); } // Set ADC Present Flag pLocalEpics->epicsOutput.statAdc[jj] = 1; - adcRdTimeErr[jj] = 0; + adcinfo.adcRdTimeErr[jj] = 0; } printf("ADC setup complete \n"); @@ -558,10 +556,10 @@ udelay(1000); timeSec = remote_time((struct CDS_EPICS *)pLocalEpics); printf ("Using remote GPS time %d \n",timeSec); #else - timeSec = current_time() -1; + timeSec = current_time_fe() -1; #endif - rdtscl(adcTime); + rdtscl(adcinfo.adcTime); /// ******************************************************************************\n /// Enter the infinite FE control loop ******************************************\n @@ -594,7 +592,7 @@ udelay(1000); timeSec ++; pLocalEpics->epicsOutput.timeDiag = timeSec; if (cycle_gps_time == 0) { - startGpsTime = timeSec; + timeinfo.startGpsTime = timeSec; } cycle_gps_time = timeSec; } @@ -622,16 +620,16 @@ udelay(1000); /// - ---- Added ADC timing diagnostics to verify timing consistent and all rdy together. if(jj==0) - adcRdTime[jj] = (cpuClock[CPU_TIME_ADC_WAIT] - cpuClock[CPU_TIME_CYCLE_START]) / CPURATE; + adcinfo.adcRdTime[jj] = (cpuClock[CPU_TIME_ADC_WAIT] - cpuClock[CPU_TIME_CYCLE_START]) / CPURATE; else - adcRdTime[jj] = adcWait; + adcinfo.adcRdTime[jj] = adcWait; - if(adcRdTime[jj] > adcRdTimeMax[jj]) adcRdTimeMax[jj] = adcRdTime[jj]; + if(adcinfo.adcRdTime[jj] > adcinfo.adcRdTimeMax[jj]) adcinfo.adcRdTimeMax[jj] = adcinfo.adcRdTime[jj]; - if((jj==0) && (adcRdTimeMax[jj] > MAX_ADC_WAIT_CARD_0)) - adcRdTimeErr[jj] ++; - if((jj!=0) && (adcRdTimeMax[jj] > MAX_ADC_WAIT_CARD_S)) - adcRdTimeErr[jj] ++; + if((jj==0) && (adcinfo.adcRdTimeMax[jj] > MAX_ADC_WAIT_CARD_0)) + adcinfo.adcRdTimeErr[jj] ++; + if((jj!=0) && (adcinfo. adcRdTimeMax[jj] > MAX_ADC_WAIT_CARD_S)) + adcinfo.adcRdTimeErr[jj] ++; /// - --------- If data not ready in time, abort. /// Either the clock is missing or code is running too slow and ADC FIFO @@ -695,7 +693,7 @@ udelay(1000); { if((adcData[jj][ii] > limit) || (adcData[jj][ii] < -limit)) { - overflowAdc[jj][ii] ++; + adcinfo.overflowAdc[jj][ii] ++; pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] ++; overflowAcc ++; adcOF[jj] = 1; @@ -817,35 +815,14 @@ udelay(1000); /// \> Cycle 18, Send timing info to EPICS at 1Hz if(cycleNum ==HKP_TIMING_UPDATES) { - pLocalEpics->epicsOutput.cpuMeter = timeHold; - pLocalEpics->epicsOutput.cpuMeterMax = timeHoldMax; - pLocalEpics->epicsOutput.dacEnable = dacEnable; - timeHoldHold = timeHold; - timeHold = 0; - timeHoldWhenHold = timeHoldWhen; - -#if defined(SERVO64K) || defined(SERVO32K) || defined(SERVO16K) - memcpy(cycleHistMax, cycleHist, sizeof(cycleHist)); - memset(cycleHist, 0, sizeof(cycleHist)); - memcpy(cycleHistWhenHold, cycleHistWhen, sizeof(cycleHistWhen)); - memset(cycleHistWhen, 0, sizeof(cycleHistWhen)); -#endif - if (timeSec % 4 == 0) pLocalEpics->epicsOutput.adcWaitTime = adcHoldTimeMin; - else if (timeSec % 4 == 1) - pLocalEpics->epicsOutput.adcWaitTime = adcHoldTimeMax; - else - pLocalEpics->epicsOutput.adcWaitTime = adcHoldTimeAvg/CYCLE_PER_SECOND; - adcHoldTimeAvgPerSec = adcHoldTimeAvg/CYCLE_PER_SECOND; - adcHoldTimeMax = 0; - adcHoldTimeMin = 0xffff; - adcHoldTimeAvg = 0; - if((adcHoldTime > CYCLE_TIME_ALRM_HI) || (adcHoldTime < CYCLE_TIME_ALRM_LO)) + sendTimingDiags2Epics(pLocalEpics, &timeinfo, &adcinfo); + if((adcinfo.adcHoldTime > CYCLE_TIME_ALRM_HI) || (adcinfo.adcHoldTime < CYCLE_TIME_ALRM_LO)) { diagWord |= FE_ADC_HOLD_ERR; feStatus |= FE_ERROR_TIMING; } - if(timeHoldMax > CYCLE_TIME_ALRM) + if(timeinfo.timeHoldMax > CYCLE_TIME_ALRM) { diagWord |= FE_PROC_TIME_ERR; feStatus |= FE_ERROR_TIMING; @@ -858,20 +835,20 @@ udelay(1000); pLocalEpics->epicsInput.diagReset = 0; pLocalEpics->epicsInput.ipcDiagReset = 1; // pLocalEpics->epicsOutput.diags[1] = 0; - timeHoldMax = 0; + timeinfo.timeHoldMax = 0; diagWord = 0; ipcErrBits = 0; // feStatus = 0; - for(jj=0;jj<cdsPciModules.adcCount;jj++) adcRdTimeMax[jj] = 0; + for(jj=0;jj<cdsPciModules.adcCount;jj++) adcinfo.adcRdTimeMax[jj] = 0; } // Flip the onePPS various once/sec as a watchdog monitor. // pLocalEpics->epicsOutput.onePps ^= 1; pLocalEpics->epicsOutput.diagWord = diagWord; for(jj=0;jj<cdsPciModules.adcCount;jj++) { - if(adcRdTimeErr[jj] > MAX_ADC_WAIT_ERR_SEC) + if(adcinfo.adcRdTimeErr[jj] > MAX_ADC_WAIT_ERR_SEC) pLocalEpics->epicsOutput.stateWord |= FE_ERROR_ADC; - adcRdTimeErr[jj] = 0; + adcinfo.adcRdTimeErr[jj] = 0; } } @@ -914,7 +891,7 @@ udelay(1000); /// \> Cycle 19, write updated diag info to EPICS if(cycleNum == HKP_DIAG_UPDATES) { - pLocalEpics->epicsOutput.userTime = usrHoldTime; + pLocalEpics->epicsOutput.userTime = timeinfo.usrHoldTime; pLocalEpics->epicsOutput.ipcStat = ipcErrBits; if(ipcErrBits & 0xf) feStatus |= FE_ERROR_IPC; // Create FB status word for return to EPICS @@ -930,14 +907,14 @@ udelay(1000); mxDiag = mxDiagR; if(mxStat != MX_OK) feStatus |= FE_ERROR_DAQ;; - usrHoldTime = 0; + timeinfo.usrHoldTime = 0; if(pLocalEpics->epicsInput.overflowReset) { if (pLocalEpics->epicsInput.overflowReset) { for (ii = 0; ii < 16; ii++) { for (jj = 0; jj < cdsPciModules.adcCount; jj++) { - overflowAdc[jj][ii] = 0; - overflowAdc[jj][ii + 16] = 0; + adcinfo.overflowAdc[jj][ii] = 0; + adcinfo.overflowAdc[jj][ii + 16] = 0; pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0; pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii + 16] = 0; } @@ -997,8 +974,8 @@ udelay(1000); if (pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] > OVERFLOW_CNTR_LIMIT) { pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0; } - pLocalEpics->epicsOutput.overflowAdc[jj][ii] = overflowAdc[jj][ii]; - overflowAdc[jj][ii] = 0; + pLocalEpics->epicsOutput.overflowAdc[jj][ii] = adcinfo.overflowAdc[jj][ii]; + adcinfo.overflowAdc[jj][ii] = 0; } } @@ -1045,49 +1022,16 @@ udelay(1000); rdtscl(cpuClock[CPU_TIME_CYCLE_END]); /// \> Compute code cycle time diag information. - cycleTime = (cpuClock[CPU_TIME_CYCLE_END] - cpuClock[CPU_TIME_CYCLE_START])/CPURATE; + captureEocTiming(cycleNum, cycle_gps_time, &timeinfo, &adcinfo); + timeinfo.cycleTime = (cpuClock[CPU_TIME_CYCLE_END] - cpuClock[CPU_TIME_CYCLE_START])/CPURATE; if (longestWrite2 < ((tempClock[3]-tempClock[2])/CPURATE)) longestWrite2 = (tempClock[3]-tempClock[2])/CPURATE; - // Hold the max cycle time over the last 1 second - if(cycleTime > timeHold) { - timeHold = cycleTime; - timeHoldWhen = cycleNum; - } - // Hold the max cycle time since last diag reset - if(cycleTime > timeHoldMax) timeHoldMax = cycleTime; -#if defined(SERVO64K) || defined(SERVO32K) || defined(SERVO16K) -// This produces cycle time histogram in /proc file - { -#if defined(SERVO64K) || defined(SERVO32K) - static const int nb = 31; -#elif defined(SERVO16K) - static const int nb = 63; -#endif - cycleHist[cycleTime<nb?cycleTime:nb]++; - cycleHistWhen[cycleTime<nb?cycleTime:nb] = cycleNum; - } -#endif - adcHoldTime = (cpuClock[CPU_TIME_CYCLE_START] - adcTime)/CPURATE; - // Avoid calculating the max hold time for the first few seconds - if (cycleNum != 0 && (startGpsTime+3) < cycle_gps_time) { - if(adcHoldTime > adcHoldTimeMax) adcHoldTimeMax = adcHoldTime; - if(adcHoldTime < adcHoldTimeMin) adcHoldTimeMin = adcHoldTime; - adcHoldTimeAvg += adcHoldTime; - if (adcHoldTimeMax > adcHoldTimeEverMax) { - adcHoldTimeEverMax = adcHoldTimeMax; - adcHoldTimeEverMaxWhen = cycle_gps_time; - //printf("Maximum adc hold time %d on cycle %d gps %d\n", adcHoldTimeMax, cycleNum, cycle_gps_time); - } - if (timeHoldMax > cpuTimeEverMax) { - cpuTimeEverMax = timeHoldMax; - cpuTimeEverMaxWhen = cycle_gps_time; - } - } - adcTime = cpuClock[CPU_TIME_CYCLE_START]; + adcinfo.adcHoldTime = (cpuClock[CPU_TIME_CYCLE_START] - adcinfo.adcTime)/CPURATE; + adcinfo.adcTime = cpuClock[CPU_TIME_CYCLE_START]; // Calc the max time of one cycle of the user code // For IOP, more interested in time to get thru ADC read code and send to slave apps - usrTime = (cpuClock[CPU_TIME_USR_START] - cpuClock[CPU_TIME_CYCLE_START])/CPURATE; - if(usrTime > usrHoldTime) usrHoldTime = usrTime; + timeinfo.usrTime = (cpuClock[CPU_TIME_USR_START] - cpuClock[CPU_TIME_CYCLE_START])/CPURATE; + if(timeinfo.usrTime > timeinfo.usrHoldTime) timeinfo.usrHoldTime = timeinfo.usrTime; /// \> Update internal cycle counters cycleNum += 1; diff --git a/src/fe/timing.c b/src/fe/timing.c index de8f7e840..65e4ad0cb 100644 --- a/src/fe/timing.c +++ b/src/fe/timing.c @@ -100,6 +100,7 @@ inline void initializeDuotoneDiags(duotone_diag_t *dt_diag) dt_diag->dacDuoEnable = 0.0; } +#endif inline void initializeTimingDiags(timing_diag_t *timeinfo) { @@ -164,4 +165,3 @@ inline void captureEocTiming(int cycle, unsigned int cycle_gps, timing_diag_t *t } } } -#endif diff --git a/src/include/drv/iop_adc_functions.c b/src/include/drv/iop_adc_functions.c index de4c7a278..9bf269856 100644 --- a/src/include/drv/iop_adc_functions.c +++ b/src/include/drv/iop_adc_functions.c @@ -161,6 +161,7 @@ inline int iop_adc_read (adcInfo_t *adcinfo,int cpuClk[]) #ifdef TIME_MASTER pcieTimer->gps_time = timeSec; pcieTimer->cycle = cycleNum; + clflush_cache_range(&pcieTimer->gps_time,16); #endif } else { adcinfo->adcRdTime[jj] = adcinfo->adcWait; -- GitLab