From 5252df4e86f31c21367e5166cef01e02233f880f Mon Sep 17 00:00:00 2001 From: Rolf Bork <rolf.bork@ligo.org> Date: Thu, 13 Sep 2018 17:42:35 +0000 Subject: [PATCH] Modifications to break up controller code to use common I/O functions added in drv area. git-svn-id: https://redoubt.ligo-wa.caltech.edu/svn/advLigoRTS/trunk@4813 6dcd42c9-f523-4c6d-aada-af552506706e --- src/fe/controllerApp.c | 809 ++++++++------------------ src/fe/controllerAppUser.c | 70 +-- src/fe/controllerIop.c | 1107 +++++++++++------------------------- src/fe/controllerIopUser.c | 60 +- src/fe/moduleLoadApp.c | 22 +- src/fe/moduleLoadCommon.c | 3 +- src/fe/moduleLoadIop.c | 84 +-- src/fe/moduleLoadVirtual.c | 701 ++--------------------- src/fe/rcguser.c | 68 +-- 9 files changed, 754 insertions(+), 2170 deletions(-) diff --git a/src/fe/controllerApp.c b/src/fe/controllerApp.c index 0b9af087a..9f331b520 100644 --- a/src/fe/controllerApp.c +++ b/src/fe/controllerApp.c @@ -33,7 +33,6 @@ #undef printf #include <linux/module.h> #include <linux/kernel.h> -#include <linux/proc_fs.h> #include <linux/kthread.h> #include <asm/delay.h> #include <asm/cacheflush.h> @@ -69,16 +68,14 @@ 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 -#include "drv/fb.h" -#ifdef USE_ZMQ - #include "drv/daqLibZmq.c" // DAQ/GDS connection software -#else + #include "drv/fb.h" #include "drv/daqLib.c" // DAQ/GDS connection software #endif -#endif #include "drv/map.h" // PCI hardware defs #include "drv/epicsXfer.c" // User defined EPICS to/from FE data transfer function @@ -119,9 +116,9 @@ unsigned int odcStateWord = 0xffff; int out_buf_size = 0; // test checking DAC buffer size unsigned int cycle_gps_time = 0; // Time at which ADCs triggered unsigned int cycle_gps_event_time = 0; // Time at which ADCs triggered -unsigned int cycle_gps_ns = 0; -unsigned int cycle_gps_event_ns = 0; -unsigned int gps_receiver_locked = 0; // Lock/unlock flag for GPS time card +unsigned int cycle_gps_ns = 0; +unsigned int cycle_gps_event_ns = 0; +unsigned int gps_receiver_locked = 0; // Lock/unlock flag for GPS time card /// GPS time in GPS seconds unsigned int timeSec = 0; unsigned int timeSecDiag = 0; @@ -146,14 +143,21 @@ int timeHoldWhenHold = 0; ///< Cycle number within last second when maximum rea struct rmIpcStr *daqPtr; int getGpsTime(unsigned int *tsyncSec, unsigned int *tsyncUsec); +int dacOF[MAX_DAC_MODULES]; // Include C code modules #include "moduleLoadApp.c" #include "map.c" +#include <drv/app_adc_read.c> +#include <drv/app_dac_functions.c> +#include <drv/app_dio_routines.c> char daqArea[2*DAQ_DCU_SIZE]; // Space allocation for daqLib buffers int cpuId = 1; +adcInfo_t adcInfo; +dacInfo_t dacInfo; + #ifdef DUAL_DAQ_DC #define MX_OK 15 @@ -197,30 +201,19 @@ void deallocate_dac_channels(void) { /// - void *fe_start(void *arg) { - int ii,jj,kk,ll,mm; // Dummy loop counter variables + int ii,jj,kk,ll; // Dummy loop counter variables static int clock1Min = 0; /// @param clockMin Minute counter (Not Used??) static int cpuClock[CPU_TIMER_CNT]; /// @param cpuClock[] Code timing diag variables - int adcData[MAX_ADC_MODULES][MAX_ADC_CHN_PER_MOD]; /// @param adcData[][] ADC raw data - int adcChanErr[MAX_ADC_MODULES]; - int adcWait = 0; - int adcOF[MAX_ADC_MODULES]; /// @param adcOF[] ADC overrange counters - // int dacChanErr[MAX_DAC_MODULES]; - int dacOF[MAX_DAC_MODULES]; /// @param dacOF[] DAC overrange counters static int dacWriteEnable = 0; /// @param dacWriteEnable No DAC outputs until >4 times through code ///< 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 num_outs = MAX_DAC_CHN_PER_MOD; /// @param num_outs Number of DAC channels variable 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 - int onePpsHi = 0; /// @param onePpsHi One PPS diagnostic check int onePpsTime = 0; /// @param onePpsTime One PPS diagnostic check #ifdef DIAG_TEST float onePpsTest; /// @param onePpsTest Value of 1PPS signal, if used, for diagnostics @@ -239,16 +232,14 @@ void *fe_start(void *arg) int ioClockDac = DAC_PRELOAD_CNT; int ioMemCntr = 0; int ioMemCntrDac = DAC_PRELOAD_CNT; - int memCtr = 0; + // int memCtr = 0; int ioClock = 0; - double dac_in = 0.0; /// @param dac_in DAC value after upsample filtering - int dac_out = 0; /// @param dac_out Integer value sent to DAC FIFO + // double dac_in = 0.0; /// @param dac_in DAC value after upsample filtering + // int dac_out = 0; /// @param dac_out Integer value sent to DAC FIFO int feStatus = 0; - int clk, clk1; // Used only when run on timer enabled (test mode) - int cnt = 0; unsigned long cpc; /// **********************************************************************************************\n @@ -288,9 +279,9 @@ void *fe_start(void *arg) /// - ---- V2.8 and later, code uses EPICS shared memory only. This was done to: \n /// - -------- Allow daqLib.c to retrieve filter module data directly from shared memory. \n /// - -------- Avoid copy of filter module data between to memory locations, which was slow. \n - pDsp[system] = (FILT_MOD *)(&pEpicsComms->dspSpace); - pCoeff[system] = (VME_COEF *)(&pEpicsComms->coeffSpace); - dspPtr[system] = (FILT_MOD *)(&pEpicsComms->dspSpace); + pDsp[system] = (FILT_MOD *)(&pEpicsComms->dspSpace); + pCoeff[system] = (VME_COEF *)(&pEpicsComms->coeffSpace); + dspPtr[system] = (FILT_MOD *)(&pEpicsComms->dspSpace); /// \> Clear the FE reset which comes from Epics pLocalEpics->epicsInput.vmeReset = 0; @@ -300,27 +291,6 @@ void *fe_start(void *arg) pLocalEpics->epicsInput.dacDuoSet_mask = 0; -/// \> Wait for BURT restore.\n -/// - ---- Code will exit if BURT flag not set by EPICS sequencer. - // Do not proceed until EPICS has had a BURT restore ******************************* - printf("Waiting for EPICS BURT Restore = %d\n", pLocalEpics->epicsInput.burtRestore); - cnt = 0; - do{ -#ifndef NO_CPU_SHUTDOWN - udelay(MAX_UDELAY); - udelay(MAX_UDELAY); - udelay(MAX_UDELAY); -#else - msleep(80); -#endif - printf("Waiting for EPICS BURT %d\n", cnt++); - cpu_relax(); - }while(!pLocalEpics->epicsInput.burtRestore); - - printf("BURT Restore Complete\n"); - -// BURT has completed ******************************************************************* - /// < Read in all Filter Module EPICS coeff settings for(ii=0;ii<MAX_MODULES;ii++) { @@ -358,11 +328,12 @@ void *fe_start(void *arg) /// \> Initialize IIR filter bank values if (initVars(pDsp[0], pDsp[0], dspCoeff, MAX_MODULES, pCoeff[0])) { - printf("Filter module init failed, exiting\n"); + // printf("Filter module init failed, exiting\n"); + pLocalEpics->epicsOutput.fe_status = FILT_INIT_ERROR; return 0; } - printf("Initialized servo control parameters.\n"); + // printf("Initialized servo control parameters.\n"); udelay(1000); @@ -385,10 +356,16 @@ udelay(1000); daq.xTpMin = daq.filtTpMax; daq.xTpMax = daq.xTpMin + GDS_MAX_NFM_TP; - printf("DAQ Ex Min/Max = %d %d\n",daq.filtExMin,daq.filtExMax); - printf("DAQ XEx Min/Max = %d %d\n",daq.xExMin,daq.xExMax); - printf("DAQ Tp Min/Max = %d %d\n",daq.filtTpMin,daq.filtTpMax); - printf("DAQ XTp Min/Max = %d %d\n",daq.xTpMin,daq.xTpMax); + /// - ---- Initialize DAQ function + status = daqWrite(0,dcuId,daq,DAQ_RATE,testpoint,dspPtr[0],0, (int *)(pLocalEpics->epicsOutput.gdsMon),xExc,pEpicsDaq); + if(status == -1) + { + // printf("DAQ init failed -- exiting\n"); + pLocalEpics->epicsOutput.fe_status = DAQ_INIT_ERROR; + vmeDone = 1; + return(0); + } +#endif /// - ---- Assign DAC testpoint pointers for (ii = 0; ii < cdsPciModules.dacCount; ii++) @@ -398,84 +375,31 @@ udelay(1000); // Zero out storage memset(floatDacOut, 0, sizeof(floatDacOut)); -#endif pLocalEpics->epicsOutput.ipcStat = 0; pLocalEpics->epicsOutput.fbNetStat = 0; pLocalEpics->epicsOutput.tpCnt = 0; -#if !defined(NO_DAQ) && !defined(IOP_TASK) - /// - ---- Initialize DAQ function - status = daqWrite(0,dcuId,daq,DAQ_RATE,testpoint,dspPtr[0],0, (int *)(pLocalEpics->epicsOutput.gdsMon),xExc,pEpicsDaq); - if(status == -1) - { - printf("DAQ init failed -- exiting\n"); - vmeDone = 1; - return(0); - } -#endif /// \> Read Dio card initial values /// - ---- SLAVE units read/write their own DIO \n /// - ---- MASTER units ignore DIO for speed reasons \n - for(kk=0;kk<cdsPciModules.doCount;kk++) - { - ii = cdsPciModules.doInstance[kk]; - if(cdsPciModules.doType[kk] == ACS_8DIO) - { - rioInputInput[ii] = accesIiro8ReadInputRegister(&cdsPciModules, kk) & 0xff; - rioInputOutput[ii] = accesIiro8ReadOutputRegister(&cdsPciModules, kk) & 0xff; - rioOutputHold[ii] = -1; - } else if(cdsPciModules.doType[kk] == ACS_16DIO) { - rioInput1[ii] = accesIiro16ReadInputRegister(&cdsPciModules, kk) & 0xffff; - rioOutputHold1[ii] = -1; - } else if (cdsPciModules.doType[kk] == CON_32DO) { - CDO32Input[ii] = contec32ReadOutputRegister(&cdsPciModules, kk); - } else if (cdsPciModules.doType[kk] == CON_6464DIO) { - CDIO6464LastOutState[ii] = contec6464ReadOutputRegister(&cdsPciModules, kk); - printf ("Initial state of contec6464 number %d = 0x%x \n",ii,CDIO6464LastOutState[ii]); - } else if (cdsPciModules.doType[kk] == CDI64) { - CDIO6464LastOutState[ii] = contec6464ReadOutputRegister(&cdsPciModules, kk); - printf ("Initial state of contec6464 number %d = 0x%x \n",ii,CDIO6464LastOutState[ii]); - } else if(cdsPciModules.doType[kk] == ACS_24DIO) { - dioInput[ii] = accesDio24ReadInputRegister(&cdsPciModules, kk); - } - } + status = app_dio_init(); // Clear the code exit flag vmeDone = 0; /// \> Call user application software initialization routine. - printf("Calling feCode() to initialize\n"); + // printf("Calling feCode() to initialize\n"); iopDacEnable = feCode(cycleNum,dWord,dacOut,dspPtr[0],&dspCoeff[0], (struct CDS_EPICS *)pLocalEpics,1); -/// \> Verify DAC channels defined for this app are not already in use. \n -/// - ---- User apps are allowed to share DAC modules but not DAC channels. - // See if my DAC channel map overlaps with already running models - for (ii = 0; ii < cdsPciModules.dacCount; ii++) { - int pd = cdsPciModules.dacConfig[ii] - ioMemData->adcCount; // physical DAC number - for (jj = 0; jj < 16; jj++) { - if (dacOutUsed[ii][jj]) { - if (ioMemData->dacOutUsed[pd][jj]) { - vmeDone = 1; - printf("Failed to allocate DAC channel.\n"); - printf("DAC local %d global %d channel %d is already allocated.\n", ii, pd, jj); - } - } - } - } - if (vmeDone == 1) { + + pLocalEpics->epicsOutput.fe_status = INIT_DAC_MODS; + /// \> Initialize DAC channels. + status = app_dac_init(); + if (status) { + pLocalEpics->epicsOutput.fe_status = DAC_INIT_ERROR; return(0); - } else { - for (ii = 0; ii < cdsPciModules.dacCount; ii++) { - int pd = cdsPciModules.dacConfig[ii] - ioMemData->adcCount; // physical DAC number - for (jj = 0; jj < MAX_DAC_CHN_PER_MOD; jj++) { - if (dacOutUsed[ii][jj]) { - ioMemData->dacOutUsed[pd][jj] = 1; - printf("Setting card local=%d global = %d channel=%d dac usage\n", ii, pd, jj); - } - } - } } /// \> Initialize the ADC status @@ -484,40 +408,42 @@ udelay(1000); pLocalEpics->epicsOutput.statAdc[jj] = 1; } - // SLAVE needs to sync with MASTER by looking for cycle 0 count in ipc memory - // Find memory buffer of first ADC to be used in SLAVE application. - ll = cdsPciModules.adcConfig[0]; - printf("waiting to sync %d\n",ioMemData->iodata[ll][0].cycle); - rdtscl(cpuClock[CPU_TIME_CYCLE_START]); + // SLAVE needs to sync with MASTER by looking for cycle 0 count in ipc memory + // Find memory buffer of first ADC to be used in SLAVE application. + ll = cdsPciModules.adcConfig[0]; + // printf("waiting to sync %d\n",ioMemData->iodata[ll][0].cycle); + rdtscl(cpuClock[CPU_TIME_CYCLE_START]); - if (boot_cpu_has(X86_FEATURE_MWAIT)) { + pLocalEpics->epicsOutput.fe_status = INIT_SYNC; + if (boot_cpu_has(X86_FEATURE_MWAIT)) { for(;;) { if (ioMemData->iodata[ll][0].cycle == 0) break; __monitor((void *)&(ioMemData->iodata[ll][0].cycle), 0, 0); if (ioMemData->iodata[ll][0].cycle == 0) break; __mwait(0, 0); } - } else { - // Spin until cycle 0 detected in first ADC buffer location. - do { - udelay(1); - } while(ioMemData->iodata[ll][0].cycle != 0); - } - timeSec = ioMemData->iodata[ll][0].timeSec; - - rdtscl(cpuClock[CPU_TIME_CYCLE_END]); - cycleTime = (cpuClock[CPU_TIME_CYCLE_END] - cpuClock[CPU_TIME_CYCLE_START])/CPURATE; - printf("Synched %d\n",cycleTime); - // Get GPS seconds from MASTER - timeSec = ioMemData->gpsSecond; - pLocalEpics->epicsOutput.timeDiag = timeSec; - // Decrement GPS seconds as it will be incremented on first read cycle. - timeSec --; + } else { + // Spin until cycle 0 detected in first ADC buffer location. + do { + udelay(1); + } while(ioMemData->iodata[ll][0].cycle != 0); + } + pLocalEpics->epicsOutput.fe_status = NORMAL_RUN; + + timeSec = ioMemData->iodata[ll][0].timeSec; + rdtscl(cpuClock[CPU_TIME_CYCLE_END]); + cycleTime = (cpuClock[CPU_TIME_CYCLE_END] - cpuClock[CPU_TIME_CYCLE_START])/CPURATE; + // printf("Synched %d\n",cycleTime); + // Get GPS seconds from MASTER + timeSec = ioMemData->gpsSecond; + pLocalEpics->epicsOutput.timeDiag = timeSec; + // Decrement GPS seconds as it will be incremented on first read cycle. + timeSec --; onePpsTime = cycleNum; #ifdef REMOTE_GPS timeSec = remote_time((struct CDS_EPICS *)pLocalEpics); - printf ("Using remote GPS time %d \n",timeSec); + // printf ("Using remote GPS time %d \n",timeSec); #else timeSec = current_time() -1; #endif @@ -536,11 +462,6 @@ udelay(1000); #endif -#ifdef NO_CPU_SHUTDOWN - while(!kthread_should_stop()){ -#else - while(!vmeDone){ // Run forever until user hits reset -#endif // ********************************************************************************************************** // NORMAL OPERATION -- Wait for ADC data ready // On startup, only want to read one sample such that first cycle @@ -549,256 +470,120 @@ udelay(1000); // code rate eg 32 samples each time thru before proceeding to match 2048 system. // ********************************************************************************************************** +#ifdef NO_CPU_SHUTDOWN + while(!kthread_should_stop()){ +#else + while(!vmeDone){ // Run forever until user hits reset +#endif + /// \> On 1PPS mark \n - if(cycleNum == 0) - { - /// - ---- Check awgtpman status. - //printf("awgtpman gps = %d local = %d\n", pEpicsComms->padSpace.awgtpman_gps, timeSec); - pLocalEpics->epicsOutput.awgStat = (pEpicsComms->padSpace.awgtpman_gps != timeSec); - if(pLocalEpics->epicsOutput.awgStat) feStatus |= FE_ERROR_AWG; - /// - ---- Check if DAC outputs are enabled, report error. - if(!iopDacEnable || dkiTrip) feStatus |= FE_ERROR_DAC_ENABLE; + if(cycleNum == 0) + { + /// - ---- Check awgtpman status. + //printf("awgtpman gps = %d local = %d\n", pEpicsComms->padSpace.awgtpman_gps, timeSec); + pLocalEpics->epicsOutput.awgStat = (pEpicsComms->padSpace.awgtpman_gps != timeSec); + if(pLocalEpics->epicsOutput.awgStat) feStatus |= FE_ERROR_AWG; + /// - ---- Check if DAC outputs are enabled, report error. + if(!iopDacEnable || dkiTrip) feStatus |= FE_ERROR_DAC_ENABLE; } #ifdef NO_CPU_SHUTDOWN - if(vmeDone)usleep_range(2,4); + if(vmeDone)usleep_range(2,4); #endif - for(ll=0;ll<sampleCount;ll++) + for(ll=0;ll<sampleCount;ll++) + { + status = app_adc_read(ioMemCntr,ioClock,&adcInfo,cpuClock); + + // Return of non zero = ADC timeout error. + if(status) { - /// \> SLAVE gets its adc data from MASTER via ipc shared memory\n - /// \> For each ADC defined: - for(jj=0;jj<cdsPciModules.adcCount;jj++) - { - mm = cdsPciModules.adcConfig[jj]; - rdtscl(cpuClock[CPU_TIME_RDY_ADC]); - /// - ---- Wait for proper timestamp in shared memory, indicating data ready. - do{ - rdtscl(cpuClock[CPU_TIME_ADC_WAIT]); - adcWait = (cpuClock[CPU_TIME_ADC_WAIT] - cpuClock[CPU_TIME_RDY_ADC])/CPURATE; - }while((ioMemData->iodata[mm][ioMemCntr].cycle != ioClock) && (adcWait < MAX_ADC_WAIT_SLAVE)); - timeSec = ioMemData->iodata[mm][ioMemCntr].timeSec; - if (cycle_gps_time == 0) { - startGpsTime = timeSec; - pLocalEpics->epicsOutput.startgpstime = startGpsTime; - } - cycle_gps_time = timeSec; - - /// - --------- If data not ready in time, set error, release DAC channel reservation and exit the code. - if(adcWait >= MAX_ADC_WAIT_SLAVE) - { - printf ("ADC TIMEOUT %d %d %d %d\n",mm,ioMemData->iodata[mm][ioMemCntr].cycle, ioMemCntr,ioClock); - pLocalEpics->epicsOutput.stateWord = FE_ERROR_ADC; - pLocalEpics->epicsOutput.diagWord |= ADC_TIMEOUT_ERR; - deallocate_dac_channels(); - return (void *)-1; - } - for(ii=0;ii<MAX_ADC_CHN_PER_MOD;ii++) - { - /// - ---- Read data from shared memory. - adcData[jj][ii] = ioMemData->iodata[mm][ioMemCntr].data[ii]; -#ifdef FLIP_SIGNALS - adcData[jj][ii] *= -1; -#endif - dWord[jj][ii] = adcData[jj][ii]; -#ifdef OVERSAMPLE - /// - ---- Downsample ADC data from 64K to rate of user application - if (dWordUsed[jj][ii]) { - dWord[jj][ii] = iir_filter_biquad(dWord[jj][ii],FE_OVERSAMPLE_COEFF,2,&dHistory[ii+jj*32][0]); - } - /// - ---- Check for ADC data over/under range - if((adcData[jj][ii] > limit) || (adcData[jj][ii] < -limit)) - { - overflowAdc[jj][ii] ++; - pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] ++; - overflowAcc ++; - adcOF[jj] = 1; - odcStateWord |= ODC_ADC_OVF; - } -#endif - } - } + pLocalEpics->epicsOutput.stateWord = FE_ERROR_ADC; + pLocalEpics->epicsOutput.diagWord |= ADC_TIMEOUT_ERR; + deallocate_dac_channels(); + return (void *)-1; + } + /// \> Set counters for next read from ipc memory - ioClock = (ioClock + 1) % IOP_IO_RATE; - ioMemCntr = (ioMemCntr + 1) % IO_MEMORY_SLOTS; - rdtscl(cpuClock[CPU_TIME_CYCLE_START]); + ioClock = (ioClock + 1) % IOP_IO_RATE; + ioMemCntr = (ioMemCntr + 1) % IO_MEMORY_SLOTS; + rdtscl(cpuClock[CPU_TIME_CYCLE_START]); } - // After first synced ADC read, must set to code to read number samples/cycle - sampleCount = OVERSAMPLE_TIMES; -/// End of ADC Read ************************************************************************************** + // After first synced ADC read, must set code to read number samples/cycle + sampleCount = OVERSAMPLE_TIMES; /// \> Call the front end specific application ******************\n /// - -- This is where the user application produced by RCG gets called and executed. \n\n - rdtscl(cpuClock[CPU_TIME_USR_START]); + rdtscl(cpuClock[CPU_TIME_USR_START]); iopDacEnable = feCode(cycleNum,dWord,dacOut,dspPtr[0],&dspCoeff[0],(struct CDS_EPICS *)pLocalEpics,0); - rdtscl(cpuClock[CPU_TIME_USR_END]); - + rdtscl(cpuClock[CPU_TIME_USR_END]); odcStateWord = 0; -/// WRITE DAC OUTPUTS ***************************************** \n -/// Writing of DAC outputs is dependent on code compile option: \n -/// - -- IOP (ADC_MASTER) reads DAC output values from memory shared with user apps and writes to DAC hardware. \n -/// - -- USER APP (ADC_SLAVE) sends output values to memory shared with IOP. \n +// ********************************************************************** /// START OF USER APP DAC WRITE ***************************************** - // Write out data to DAC modules - /// \> Loop thru all DAC modules - for(jj=0;jj<cdsPciModules.dacCount;jj++) - { - /// - -- locate the proper DAC memory block - mm = cdsPciModules.dacConfig[jj]; - /// - -- Set overflow limits, data mask, and chan count based on DAC type - limit = OVERFLOW_LIMIT_16BIT; - mask = GSAO_16BIT_MASK; - num_outs = GSAO_16BIT_CHAN_COUNT; - if (cdsPciModules.dacType[jj] == GSC_18AO8) { - limit = OVERFLOW_LIMIT_18BIT; // 18 bit limit - mask = GSAO_18BIT_MASK; - num_outs = GSAO_18BIT_CHAN_COUNT; - } - if (cdsPciModules.dacType[jj] == GSC_20AO8) { - limit = OVERFLOW_LIMIT_20BIT; // 20 bit limit - mask = GSAO_20BIT_MASK; - num_outs = GSAO_20BIT_CHAN_COUNT; - } - /// - -- If user app < 64k rate (typical), need to upsample from code rate to IOP rate - for (kk=0; kk < OVERSAMPLE_TIMES; kk++) { - /// - -- For each DAC channel - for (ii=0; ii < num_outs; ii++) - { -#ifdef FLIP_SIGNALS - dacOut[jj][ii] *= -1; -#endif - /// - ---- Read in DAC value, if channel is used by the application, and run thru upsample filter\n - if (dacOutUsed[jj][ii]) { -#ifdef OVERSAMPLE_DAC -#ifdef NO_ZERO_PAD - /// - --------- If set to NO_ZERO_PAD (not standard setting), then DAC output value is - /// repeatedly run thru the filter OVERSAMPE_TIMES.\n - dac_in = dacOut[jj][ii]; -#ifdef CORE_BIQUAD - dac_in = iir_filter_biquad(dac_in,FE_OVERSAMPLE_COEFF,2,&dDacHistory[ii+jj*MAX_DAC_CHN_PER_MOD][0]); -#else - dac_in = iir_filter(dac_in,FE_OVERSAMPLE_COEFF,2,&dDacHistory[ii+jj*MAX_DAC_CHN_PER_MOD][0]); -#endif -#else - /// - --------- Otherwise zero padding is used (standard), - /// ie DAC output value is applied to filter on first - /// interation, thereafter zeros are applied. - dac_in = kk == 0? (double)dacOut[jj][ii]: 0.0; -#ifdef CORE_BIQUAD - dac_in = iir_filter_biquad(dac_in,FE_OVERSAMPLE_COEFF,2,&dDacHistory[ii+jj*MAX_DAC_CHN_PER_MOD][0]); -#else - dac_in = iir_filter(dac_in,FE_OVERSAMPLE_COEFF,2,&dDacHistory[ii+jj*MAX_DAC_CHN_PER_MOD][0]); -#endif - dac_in *= OVERSAMPLE_TIMES; -#endif -#else - dac_in = dacOut[jj][ii]; -#endif - } - /// - ---- If channel is not used, then set value to zero. - else - dac_in = 0.0; - /// - ---- Smooth out some of the double > short roundoff errors - if(dac_in > 0.0) dac_in += 0.5; - else dac_in -= 0.5; - dac_out = dac_in; - - /// - ---- Check output values are within range of DAC \n - /// - --------- If overflow, clip at DAC limits and report errors - if(dac_out > limit || dac_out < -limit) - { - overflowDac[jj][ii] ++; - pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] ++; - overflowAcc ++; - dacOF[jj] = 1; - odcStateWord |= ODC_DAC_OVF;; - if(dac_out > limit) dac_out = limit; - else dac_out = -limit; - } - /// - ---- If DAQKILL tripped, set output to zero. - if(!iopDacEnable) dac_out = 0; - /// - ---- Load last values to EPICS channels for monitoring on GDS_TP screen. - dacOutEpics[jj][ii] = dac_out; - - /// - ---- Load DAC testpoints - floatDacOut[16*jj + ii] = dac_out; - /// - ---- Determine shared memory location for new DAC output data - memCtr = (ioMemCntrDac + kk) % IO_MEMORY_SLOTS; - /// - ---- Write DAC output to shared memory. \n - /// - --------- Only write to DAC channels being used to allow two or more - /// slaves to write to same DAC module. - if (dacOutUsed[jj][ii]) - ioMemData->iodata[mm][memCtr].data[ii] = dac_out; - } - /// - ---- Write cycle count to make DAC data complete - if(iopDacEnable) - ioMemData->iodata[mm][memCtr].cycle = (ioClockDac + kk) % IOP_IO_RATE; - } - } - /// \> Increment DAC memory block pointers for next cycle - ioClockDac = (ioClockDac + OVERSAMPLE_TIMES) % IOP_IO_RATE; - ioMemCntrDac = (ioMemCntrDac + OVERSAMPLE_TIMES) % IO_MEMORY_SLOTS; - if(dacWriteEnable < 10) dacWriteEnable ++; + // Write out data to DAC modules +// ********************************************************************** + status = app_dac_write(ioMemCntrDac,ioClockDac, &dacInfo); + /// \> Increment DAC memory block pointers for next cycle + ioClockDac = (ioClockDac + OVERSAMPLE_TIMES) % IOP_IO_RATE; + ioMemCntrDac = (ioMemCntrDac + OVERSAMPLE_TIMES) % IO_MEMORY_SLOTS; + if(dacWriteEnable < 10) dacWriteEnable ++; /// END OF USER APP DAC WRITE ************************************************* -/// END OF DAC WRITE ************************************************* - +// ********************************************************************** /// BEGIN HOUSEKEEPING ************************************************ \n +// ********************************************************************** - pLocalEpics->epicsOutput.cycle = cycleNum; + pLocalEpics->epicsOutput.cycle = cycleNum; /// \> 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)) - { - diagWord |= FE_ADC_HOLD_ERR; - feStatus |= FE_ERROR_TIMING; - - } - if(timeHoldMax > CYCLE_TIME_ALRM) - { - diagWord |= FE_PROC_TIME_ERR; - feStatus |= FE_ERROR_TIMING; - } - pLocalEpics->epicsOutput.stateWord = feStatus; - feStatus = 0; - if(pLocalEpics->epicsInput.diagReset || initialDiagReset) - { - initialDiagReset = 0; - pLocalEpics->epicsInput.diagReset = 0; - pLocalEpics->epicsInput.ipcDiagReset = 1; - // pLocalEpics->epicsOutput.diags[1] = 0; - timeHoldMax = 0; - diagWord = 0; - ipcErrBits = 0; + { + 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)) + { + diagWord |= FE_ADC_HOLD_ERR; + feStatus |= FE_ERROR_TIMING; + } + if(timeHoldMax > CYCLE_TIME_ALRM) + { + diagWord |= FE_PROC_TIME_ERR; + feStatus |= FE_ERROR_TIMING; + } + pLocalEpics->epicsOutput.stateWord = feStatus; + feStatus = 0; + if(pLocalEpics->epicsInput.diagReset || initialDiagReset) + { + initialDiagReset = 0; + pLocalEpics->epicsInput.diagReset = 0; + pLocalEpics->epicsInput.ipcDiagReset = 1; + timeHoldMax = 0; + diagWord = 0; + ipcErrBits = 0; - // feStatus = 0; - } - // Flip the onePPS various once/sec as a watchdog monitor. - // pLocalEpics->epicsOutput.onePps ^= 1; - pLocalEpics->epicsOutput.diagWord = diagWord; - } + } + // 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. @@ -820,211 +605,99 @@ udelay(1000); /// \> Cycle 10 to number of BIO cards:\n /// - ---- Read Dio cards once per second \n - if(cdsPciModules.doCount) - // if((cycleNum < (HKP_READ_DIO + cdsPciModules.doCount)) && (cycleNum >= HKP_READ_DIO)) - { - // kk = cycleNum - HKP_READ_DIO; - kk = cycleNum % cdsPciModules.doCount; - ii = cdsPciModules.doInstance[kk]; - if(cdsPciModules.doType[kk] == ACS_8DIO) - { - rioInputInput[ii] = accesIiro8ReadInputRegister(&cdsPciModules, kk) & 0xff; - rioInputOutput[ii] = accesIiro8ReadOutputRegister(&cdsPciModules, kk) & 0xff; - } - if(cdsPciModules.doType[kk] == ACS_16DIO) - { - rioInput1[ii] = accesIiro16ReadInputRegister(&cdsPciModules, kk) & 0xffff; - } - if(cdsPciModules.doType[kk] == ACS_24DIO) - { - dioInput[ii] = accesDio24ReadInputRegister(&cdsPciModules, kk); - } - if (cdsPciModules.doType[kk] == CON_6464DIO) { - CDIO6464InputInput[ii] = contec6464ReadInputRegister(&cdsPciModules, kk); - } - if (cdsPciModules.doType[kk] == CDI64) { - CDIO6464InputInput[ii] = contec6464ReadInputRegister(&cdsPciModules, kk); - } - } -/// \> Write Dio cards only on change - for(kk=0;kk < cdsPciModules.doCount;kk++) - { - ii = cdsPciModules.doInstance[kk]; - if((cdsPciModules.doType[kk] == ACS_8DIO) && (rioOutput[ii] != rioOutputHold[ii])) - { - accesIiro8WriteOutputRegister(&cdsPciModules, kk, rioOutput[ii]); - rioOutputHold[ii] = rioOutput[ii]; - } else - if((cdsPciModules.doType[kk] == ACS_16DIO) && (rioOutput1[ii] != rioOutputHold1[ii])) - { - accesIiro16WriteOutputRegister(&cdsPciModules, kk, rioOutput1[ii]); - rioOutputHold1[ii] = rioOutput1[ii]; - } else - if(cdsPciModules.doType[kk] == CON_32DO) - { - if (CDO32Input[ii] != CDO32Output[ii]) { - CDO32Input[ii] = contec32WriteOutputRegister(&cdsPciModules, kk, CDO32Output[ii]); - } - } else if (cdsPciModules.doType[kk] == CON_6464DIO) { - if (CDIO6464LastOutState[ii] != CDIO6464Output[ii]) { - CDIO6464LastOutState[ii] = contec6464WriteOutputRegister(&cdsPciModules, kk, CDIO6464Output[ii]); - } - } else if (cdsPciModules.doType[kk] == CDO64) { - if (CDIO6464LastOutState[ii] != CDIO6464Output[ii]) { - CDIO6464LastOutState[ii] = contec6464WriteOutputRegister(&cdsPciModules, kk, CDIO6464Output[ii]); - } - } else - if((cdsPciModules.doType[kk] == ACS_24DIO) && (dioOutputHold[ii] != dioOutput[ii])) - { - accesDio24WriteOutputRegister(&cdsPciModules, kk, dioOutput[ii]); - dioOutputHold[ii] = dioOutput[ii]; - } - } - + status = app_dio_read_write(); /// \> Write data to DAQ. #ifndef NO_DAQ - - // Call daqLib - pLocalEpics->epicsOutput.daqByteCnt = + + // Call daqLib + pLocalEpics->epicsOutput.daqByteCnt = daqWrite(1,dcuId,daq,DAQ_RATE,testpoint,dspPtr[0],myGmError2,(int *)(pLocalEpics->epicsOutput.gdsMon),xExc,pEpicsDaq); - // Send the current DAQ block size to the awgtpman for TP number checking - pEpicsComms->padSpace.feDaqBlockSize = curDaqBlockSize; - pLocalEpics->epicsOutput.tpCnt = tpPtr->count & 0xff; - feStatus |= (FE_ERROR_EXC_SET & tpPtr->count); - if (FE_ERROR_EXC_SET & tpPtr->count) odcStateWord |= ODC_EXC_SET; - else odcStateWord &= ~(ODC_EXC_SET); - if(pLocalEpics->epicsOutput.daqByteCnt > DAQ_DCU_RATE_WARNING) - feStatus |= FE_ERROR_DAQ; + // Send the current DAQ block size to the awgtpman for TP number checking + pEpicsComms->padSpace.feDaqBlockSize = curDaqBlockSize; + pLocalEpics->epicsOutput.tpCnt = tpPtr->count & 0xff; + feStatus |= (FE_ERROR_EXC_SET & tpPtr->count); + if (FE_ERROR_EXC_SET & tpPtr->count) odcStateWord |= ODC_EXC_SET; + else odcStateWord &= ~(ODC_EXC_SET); + if(pLocalEpics->epicsOutput.daqByteCnt > DAQ_DCU_RATE_WARNING) + 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 - mxStat = 0; - mxDiagR = daqPtr->reqAck; - if((mxDiag & 1) != (mxDiagR & 1)) mxStat = 1; - if((mxDiag & 2) != (mxDiagR & 2)) mxStat += 2; + { + pLocalEpics->epicsOutput.userTime = usrHoldTime; + pLocalEpics->epicsOutput.ipcStat = ipcErrBits; + if(ipcErrBits & 0xf) feStatus |= FE_ERROR_IPC; + // Create FB status word for return to EPICS + mxStat = 0; + mxDiagR = daqPtr->reqAck; + if((mxDiag & 1) != (mxDiagR & 1)) mxStat = 1; + if((mxDiag & 2) != (mxDiagR & 2)) mxStat += 2; #ifdef DUAL_DAQ_DC - if((mxDiag & 4) != (mxDiagR & 4)) mxStat += 4; - if((mxDiag & 8) != (mxDiagR & 8)) mxStat += 8; + if((mxDiag & 4) != (mxDiagR & 4)) mxStat += 4; + if((mxDiag & 8) != (mxDiagR & 8)) mxStat += 8; #endif - pLocalEpics->epicsOutput.fbNetStat = mxStat; - 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++) { - overflowAdc[jj][ii] = 0; - overflowAdc[jj][ii + 16] = 0; - pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0; - pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii + 16] = 0; - } - - for (jj = 0; jj < cdsPciModules.dacCount; jj++) { - pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0; - } - } - } - } - if((pLocalEpics->epicsInput.overflowReset) || (overflowAcc > OVERFLOW_CNTR_LIMIT)) - { - pLocalEpics->epicsInput.overflowReset = 0; - pLocalEpics->epicsOutput.ovAccum = 0; - overflowAcc = 0; - } - } + pLocalEpics->epicsOutput.fbNetStat = mxStat; + 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; + pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0; + pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii + 16] = 0; + } + + for (jj = 0; jj < cdsPciModules.dacCount; jj++) { + pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0; + } + } + } + } + if((pLocalEpics->epicsInput.overflowReset) || (overflowAcc > OVERFLOW_CNTR_LIMIT)) + { + pLocalEpics->epicsInput.overflowReset = 0; + pLocalEpics->epicsOutput.ovAccum = 0; + overflowAcc = 0; + } + } - if(cycleNum == 1) + if(cycleNum == 1) { pLocalEpics->epicsOutput.timeDiag = timeSec; } /// \> Cycle 20, Update latest DAC output values to EPICS - if(subcycle == HKP_DAC_EPICS_UPDATES) + if(subcycle == HKP_DAC_EPICS_UPDATES) { - // Send DAC output values at 16Hzfb - for(jj=0;jj<cdsPciModules.dacCount;jj++) - { + // Send DAC output values at 16Hzfb + for(jj=0;jj<cdsPciModules.dacCount;jj++) + { for(ii=0;ii<MAX_DAC_CHN_PER_MOD;ii++) { - pLocalEpics->epicsOutput.dacValue[jj][ii] = dacOutEpics[jj][ii]; - } - } + pLocalEpics->epicsOutput.dacValue[jj][ii] = dacInfo.dacOutEpics[jj][ii]; + } + } } /// \> Cycle 21, Update ADC/DAC status to EPICS. - if(cycleNum == HKP_ADC_DAC_STAT_UPDATES) - { - pLocalEpics->epicsOutput.ovAccum = overflowAcc; - for(jj=0;jj<cdsPciModules.adcCount;jj++) - { - // SET/CLR Channel Hopping Error - if(adcChanErr[jj]) - { - pLocalEpics->epicsOutput.statAdc[jj] &= ~(2); - feStatus |= FE_ERROR_ADC;; - } - else pLocalEpics->epicsOutput.statAdc[jj] |= 2; - adcChanErr[jj] = 0; - // SET/CLR Overflow Error - if(adcOF[jj]) - { - pLocalEpics->epicsOutput.statAdc[jj] &= ~(4); - feStatus |= FE_ERROR_OVERFLOW;; - } - else pLocalEpics->epicsOutput.statAdc[jj] |= 4; - adcOF[jj] = 0; - for(ii=0;ii<32;ii++) - { - - 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; - - } - } - for(jj=0;jj<cdsPciModules.dacCount;jj++) - { - if(dacOF[jj]) - { - pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_OVERFLOW_BIT); - feStatus |= FE_ERROR_OVERFLOW;; - } - else pLocalEpics->epicsOutput.statDac[jj] |= DAC_OVERFLOW_BIT; - dacOF[jj] = 0; - if(dacChanErr[jj]) - { - pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_TIMING_BIT); - } - else pLocalEpics->epicsOutput.statDac[jj] |= DAC_TIMING_BIT; - dacChanErr[jj] = 0; - for(ii=0;ii<MAX_DAC_CHN_PER_MOD;ii++) - { - - if (pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] > OVERFLOW_CNTR_LIMIT) { - pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0; - } - pLocalEpics->epicsOutput.overflowDac[jj][ii] = overflowDac[jj][ii]; - overflowDac[jj][ii] = 0; - - } - } - } + if(cycleNum == HKP_ADC_DAC_STAT_UPDATES) + { + pLocalEpics->epicsOutput.ovAccum = overflowAcc; + feStatus |= app_adc_status_update(&adcInfo); + feStatus |= app_dac_status_update(&dacInfo); + } // Capture end of cycle time. - rdtscl(cpuClock[CPU_TIME_CYCLE_END]); + rdtscl(cpuClock[CPU_TIME_CYCLE_END]); /// \> Compute code cycle time diag information. 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; @@ -1033,6 +706,7 @@ udelay(1000); // 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; @@ -1045,37 +719,36 @@ udelay(1000); usrTime = (cpuClock[CPU_TIME_USR_END] - cpuClock[CPU_TIME_USR_START])/CPURATE; if(usrTime > usrHoldTime) usrHoldTime = usrTime; - /// \> Update internal cycle counters - cycleNum += 1; + /// \> Update internal cycle counters + cycleNum += 1; #ifdef DIAG_TEST - if(pLocalEpics->epicsInput.bumpCycle != 0) { + if(pLocalEpics->epicsInput.bumpCycle != 0) { cycleNum += pLocalEpics->epicsInput.bumpCycle; pLocalEpics->epicsInput.bumpCycle = 0; - } + } #endif - cycleNum %= CYCLE_PER_SECOND; - clock1Min += 1; - clock1Min %= CYCLE_PER_MINUTE; - if(subcycle == DAQ_CYCLE_CHANGE) - { + cycleNum %= CYCLE_PER_SECOND; + clock1Min += 1; + clock1Min %= CYCLE_PER_MINUTE; + if(subcycle == DAQ_CYCLE_CHANGE) + { daqCycle = (daqCycle + 1) % DAQ_NUM_DATA_BLOCKS_PER_SECOND; if(!(daqCycle % 2)) pLocalEpics->epicsOutput.epicsSync = daqCycle; - } - if(subcycle == END_OF_DAQ_BLOCK) /*we have reached the 16Hz second barrier*/ - { - /* Reset the data cycle counter */ - subcycle = 0; - - } - else{ - /* Increment the internal cycle counter */ - subcycle ++; - } + } + if(subcycle == END_OF_DAQ_BLOCK) /*we have reached the 16Hz second barrier*/ + { + /* Reset the data cycle counter */ + subcycle = 0; + } + else{ + /* Increment the internal cycle counter */ + subcycle ++; + } /// \> If not exit request, then continue INFINITE LOOP ******* } - printf("exiting from fe_code()\n"); + // printf("exiting from fe_code()\n"); pLocalEpics->epicsOutput.cpuMeter = 0; deallocate_dac_channels(); diff --git a/src/fe/controllerAppUser.c b/src/fe/controllerAppUser.c index e72979966..97055b09d 100644 --- a/src/fe/controllerAppUser.c +++ b/src/fe/controllerAppUser.c @@ -41,6 +41,7 @@ #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 @@ -184,14 +185,11 @@ int fe_start() static int clock1Min = 0; /// @param clockMin Minute counter (Not Used??) struct timespec tp; static struct timespec cpuClock[CPU_TIMER_CNT]; /// @param cpuClock[] Code timing diag variables +int dacOF[MAX_DAC_MODULES]; - int adcData[MAX_ADC_MODULES][MAX_ADC_CHN_PER_MOD]; /// @param adcData[][] ADC raw data - int adcChanErr[MAX_ADC_MODULES]; - int adcWait = 0; - int adcOF[MAX_ADC_MODULES]; /// @param adcOF[] ADC overrange counters + adcInfo_t adcInfo; + dacInfo_t dacInfo; - // int dacChanErr[MAX_DAC_MODULES]; - int dacOF[MAX_DAC_MODULES]; /// @param dacOF[] DAC overrange counters static int dacWriteEnable = 0; /// @param dacWriteEnable No DAC outputs until >4 times through code ///< Code runs longer for first few cycles on startup as it settles in, ///< so this helps prevent long cycles during that time. @@ -287,20 +285,6 @@ int fe_start() memset(proc_futures, 0, sizeof(proc_futures)); -/// \> Wait for BURT restore.\n -/// - ---- Code will exit if BURT flag not set by EPICS sequencer. - // Do not proceed until EPICS has had a BURT restore ******************************* - printf("Waiting for EPICS BURT Restore = %d\n", pLocalEpics->epicsInput.burtRestore); - cnt = 0; - do{ - usleep(80000); - printf("Waiting for EPICS BURT %d\n", cnt++); - }while(!pLocalEpics->epicsInput.burtRestore); - - printf("BURT Restore Complete\n"); - -// BURT has completed ******************************************************************* - /// < Read in all Filter Module EPICS coeff settings for(ii=0;ii<MAX_MODULES;ii++) { @@ -512,11 +496,11 @@ usleep(1000); do{ // usleep(1); clock_gettime(CLOCK_MONOTONIC, &cpuClock[CPU_TIME_ADC_WAIT]); - adcWait = BILLION * (cpuClock[CPU_TIME_ADC_WAIT].tv_sec - cpuClock[CPU_TIME_RDY_ADC].tv_sec) + + adcInfo.adcWait = BILLION * (cpuClock[CPU_TIME_ADC_WAIT].tv_sec - cpuClock[CPU_TIME_RDY_ADC].tv_sec) + cpuClock[CPU_TIME_ADC_WAIT].tv_nsec - cpuClock[CPU_TIME_RDY_ADC].tv_nsec; - adcWait /= 1000; + adcInfo.adcWait /= 1000; // kk++; - }while((ioMemData->iodata[mm][ioMemCntr].cycle != ioClock) && (adcWait < MAX_ADC_WAIT_SLAVE)); + }while((ioMemData->iodata[mm][ioMemCntr].cycle != ioClock) && (adcInfo.adcWait < MAX_ADC_WAIT_SLAVE)); timeSec = ioMemData->iodata[mm][ioMemCntr].timeSec; if (cycle_gps_time == 0) { startGpsTime = timeSec; @@ -525,7 +509,7 @@ usleep(1000); cycle_gps_time = timeSec; /// - --------- If data not ready in time, set error, release DAC channel reservation and exit the code. - if(adcWait >= MAX_ADC_WAIT_SLAVE) + if(adcInfo.adcWait >= MAX_ADC_WAIT_SLAVE) { printf ("ADC TIMEOUT %d %d %d %d\n",mm,ioMemData->iodata[mm][ioMemCntr].cycle, ioMemCntr,ioClock); pLocalEpics->epicsOutput.stateWord = FE_ERROR_ADC; @@ -536,23 +520,23 @@ usleep(1000); for(ii=0;ii<MAX_ADC_CHN_PER_MOD;ii++) { /// - ---- Read data from shared memory. - adcData[jj][ii] = ioMemData->iodata[mm][ioMemCntr].data[ii]; + adcInfo.adcData[jj][ii] = ioMemData->iodata[mm][ioMemCntr].data[ii]; #ifdef FLIP_SIGNALS - adcData[jj][ii] *= -1; + adcInfo.adcData[jj][ii] *= -1; #endif - dWord[jj][ii] = adcData[jj][ii]; + dWord[jj][ii] = adcInfo.adcData[jj][ii]; #ifdef OVERSAMPLE /// - ---- Downsample ADC data from 64K to rate of user application if (dWordUsed[jj][ii]) { dWord[jj][ii] = iir_filter_biquad(dWord[jj][ii],FE_OVERSAMPLE_COEFF,2,&dHistory[ii+jj*32][0]); } /// - ---- Check for ADC data over/under range - if((adcData[jj][ii] > limit) || (adcData[jj][ii] < -limit)) + if((adcInfo.adcData[jj][ii] > limit) || (adcInfo.adcData[jj][ii] < -limit)) { - overflowAdc[jj][ii] ++; + adcInfo.overflowAdc[jj][ii] ++; pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] ++; overflowAcc ++; - adcOF[jj] = 1; + adcInfo.adcOF[jj] = 1; odcStateWord |= ODC_ADC_OVF; } #endif @@ -651,7 +635,7 @@ usleep(1000); /// - --------- If overflow, clip at DAC limits and report errors if(dac_out > limit || dac_out < -limit) { - overflowDac[jj][ii] ++; + dacInfo.overflowDac[jj][ii] ++; pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] ++; overflowAcc ++; dacOF[jj] = 1; @@ -662,7 +646,7 @@ usleep(1000); /// - ---- If DAQKILL tripped, set output to zero. if(!iopDacEnable) dac_out = 0; /// - ---- Load last values to EPICS channels for monitoring on GDS_TP screen. - dacOutEpics[jj][ii] = dac_out; + dacInfo.dacOutEpics[jj][ii] = dac_out; /// - ---- Load DAC testpoints floatDacOut[16*jj + ii] = dac_out; @@ -796,8 +780,8 @@ usleep(1000); 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; } @@ -828,7 +812,7 @@ usleep(1000); { for(ii=0;ii<MAX_DAC_CHN_PER_MOD;ii++) { - pLocalEpics->epicsOutput.dacValue[jj][ii] = dacOutEpics[jj][ii]; + pLocalEpics->epicsOutput.dacValue[jj][ii] = dacInfo.dacOutEpics[jj][ii]; } } } @@ -840,29 +824,29 @@ usleep(1000); for(jj=0;jj<cdsPciModules.adcCount;jj++) { // SET/CLR Channel Hopping Error - if(adcChanErr[jj]) + if(adcInfo.adcChanErr[jj]) { pLocalEpics->epicsOutput.statAdc[jj] &= ~(2); feStatus |= FE_ERROR_ADC;; } else pLocalEpics->epicsOutput.statAdc[jj] |= 2; - adcChanErr[jj] = 0; + adcInfo.adcChanErr[jj] = 0; // SET/CLR Overflow Error - if(adcOF[jj]) + if(adcInfo.adcOF[jj]) { pLocalEpics->epicsOutput.statAdc[jj] &= ~(4); feStatus |= FE_ERROR_OVERFLOW;; } else pLocalEpics->epicsOutput.statAdc[jj] |= 4; - adcOF[jj] = 0; + adcInfo.adcOF[jj] = 0; for(ii=0;ii<32;ii++) { 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; } } @@ -887,8 +871,8 @@ usleep(1000); if (pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] > OVERFLOW_CNTR_LIMIT) { pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0; } - pLocalEpics->epicsOutput.overflowDac[jj][ii] = overflowDac[jj][ii]; - overflowDac[jj][ii] = 0; + pLocalEpics->epicsOutput.overflowDac[jj][ii] = dacInfo.overflowDac[jj][ii]; + dacInfo.overflowDac[jj][ii] = 0; } } diff --git a/src/fe/controllerIop.c b/src/fe/controllerIop.c index 406570321..4b5d7b895 100644 --- a/src/fe/controllerIop.c +++ b/src/fe/controllerIop.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 @@ -92,11 +93,17 @@ int printk(const char *fmt, ...) { #include "dolphin.c" #endif + #ifdef TIME_MASTER TIMING_SIGNAL *pcieTimer; #endif +adcInfo_t adcinfo; +dacInfo_t dacinfo; +duotone_diag_t dt_diag; +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 @@ -133,39 +140,18 @@ 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; ///< Stores time between code cycles -int adcHoldTimeMax; ///< Stores time between code cycles -int adcHoldTimeEverMax; ///< Maximum cycle time recorded -int adcHoldTimeEverMaxWhen; -int cpuTimeEverMax; ///< Maximum code cycle time recorded -int cpuTimeEverMaxWhen; -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 - -// The following are for timing histograms written to /proc files -#if defined(SERVO64K) || defined(SERVO32K) -unsigned int cycleHist[32]; -unsigned int cycleHistMax[32]; -unsigned int cycleHistWhen[32]; -unsigned int cycleHistWhenHold[32]; -#elif defined(SERVO16K) -unsigned int cycleHist[64]; -unsigned int cycleHistMax[64]; -unsigned int cycleHistWhen[64]; -unsigned int cycleHistWhenHold[64]; -#endif +int ioClockDac = DAC_PRELOAD_CNT; +int ioMemCntr = 0; +int ioMemCntrDac = DAC_PRELOAD_CNT; +int dac_out = 0; /// @param dac_out Integer value sent to DAC FIFO +int dacEnable = 0; +int pBits[9] = {1,2,4,8,16,32,64,128,256}; /// @param pBits[] Lookup table for quick power of 2 calcs +int dacOF[MAX_DAC_MODULES]; /// @param dacOF[] DAC overrange counters +int dacWriteEnable = 0; /// @param dacWriteEnable No DAC outputs until >4 times through code +int dacTimingErrorPending[MAX_DAC_MODULES]; +static int dacTimingError = 0; struct rmIpcStr *daqPtr; int dacWatchDog = 0; @@ -175,6 +161,8 @@ int getGpsTime(unsigned int *tsyncSec, unsigned int *tsyncUsec); // Include C code modules #include "moduleLoadIop.c" #include "map.c" +#include <drv/iop_adc_functions.c> +#include <drv/iop_dac_functions.c> char daqArea[2*DAQ_DCU_SIZE]; // Space allocation for daqLib buffers @@ -212,35 +200,24 @@ int initialDiagReset = 1; /// - void *fe_start(void *arg) { - int longestWrite2 = 0; int tempClock[4]; - int ii,jj,kk,ll,mm; // Dummy loop counter variables + int ii,jj,kk,ll; // Dummy loop counter variables + // int mm; static int clock1Min = 0; /// @param clockMin Minute counter (Not Used??) static int cpuClock[CPU_TIMER_CNT]; /// @param cpuClock[] Code timing diag variables - static int chanHop = 0; /// @param chanHop Adc channel hopping status - int adcData[MAX_ADC_MODULES][MAX_ADC_CHN_PER_MOD]; /// @param adcData[][] ADC raw data - int adcChanErr[MAX_ADC_MODULES]; - int adcWait = 0; - int adcOF[MAX_ADC_MODULES]; /// @param adcOF[] ADC overrange counters - // int dacChanErr[MAX_DAC_MODULES]; - int dacOF[MAX_DAC_MODULES]; /// @param dacOF[] DAC overrange counters - static int dacWriteEnable = 0; /// @param dacWriteEnable No DAC outputs until >4 times through code ///< 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 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 - int wtmin,wtmax; /// @param wtmin Time window for startup on IRIG-B - int dacEnable = 0; - int pBits[9] = {1,2,4,8,16,32,64,128,256}; /// @param pBits[] Lookup table for quick power of 2 calcs + // 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 num_outs = MAX_DAC_CHN_PER_MOD; /// @param num_outs Number of DAC channels variable + // volatile unsigned int *pDacData; /// @param *pDacData Pointer to DAC PCI data space + // int dacEnable = 0; + // int pBits[9] = {1,2,4,8,16,32,64,128,256}; /// @param pBits[] Lookup table for quick power of 2 calcs int sync21ppsCycles = 0; /// @param sync32ppsCycles Number of attempts to sync to 1PPS - int dkiTrip = 0; + // 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 @@ -262,37 +239,35 @@ void *fe_start(void *arg) int mxDiag = 0; int mxDiagR = 0; // ****** Share data +#if 0 int ioClockDac = DAC_PRELOAD_CNT; int ioMemCntr = 0; int ioMemCntrDac = DAC_PRELOAD_CNT; - double dac_in = 0.0; /// @param dac_in DAC value after upsample filtering int dac_out = 0; /// @param dac_out Integer value sent to DAC FIFO +#endif int feStatus = 0; + int dkiTrip = 0; int clk, clk1; // Used only when run on timer enabled (test mode) - static float duotone[IOP_IO_RATE]; // Duotone timing diagnostic variables - static float duotoneDac[IOP_IO_RATE]; - float duotoneTimeDac; - float duotoneTime; - static float duotoneTotal = 0.0; - static float duotoneMean = 0.0; - static float duotoneTotalDac = 0.0; - static float duotoneMeanDac = 0.0; - static int dacDuoEnable = 0; - static int dacTimingError = 0; - static int dacTimingErrorPending[MAX_DAC_MODULES]; - - 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 + + // 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 unsigned int usec = 0; - unsigned int offset = 0; - int cnt = 0; unsigned long cpc; + float duotoneTimeDac; + float duotoneTime; + + // static int dacTimingErrorPending[MAX_DAC_MODULES]; + // static int dacTimingError = 0; + // int dacOF[MAX_DAC_MODULES]; /// @param dacOF[] DAC overrange counters + // static int dacWriteEnable = 0; /// @param dacWriteEnable No DAC outputs until >4 times through code + // int dacChanErr[MAX_DAC_MODULES]; + /// **********************************************************************************************\n /// Start Initialization Process \n @@ -306,40 +281,18 @@ void *fe_start(void *arg) fz_daz(); /// \> Kill the denorms! -// Set memory for cycle time history diagnostics -#if defined(SERVO64K) || defined(SERVO32K) || defined(SERVO16K) - memset(cycleHist, 0, sizeof(cycleHist)); - memset(cycleHistMax, 0, sizeof(cycleHistMax)); - memset(cycleHistWhen, 0, sizeof(cycleHistWhen)); - memset(cycleHistWhenHold, 0, sizeof(cycleHistWhenHold)); -#endif - /// \> Init comms with EPICS processor */ pEpicsComms = (RFM_FE_COMMS *)_epics_shm; pLocalEpics = (CDS_EPICS *)&pEpicsComms->epicsSpace; pEpicsDaq = (char *)&(pLocalEpics->epicsOutput); -// printf("Epics at 0x%x and DAQ at 0x%x size = %d \n",pLocalEpics,pEpicsDaq,sizeof(CDS_EPICS_IN)); +adcInfo_t *padcinfo = (adcInfo_t *)&adcinfo; #ifdef OVERSAMPLE /// \> Zero out filter histories memset(dHistory, 0, sizeof(dHistory)); memset(dDacHistory, 0, sizeof(dDacHistory)); #endif - /// \> Zero out DAC outputs - for (ii = 0; ii < MAX_DAC_MODULES; ii++) - { - dacTimingErrorPending[ii] = 0; - for (jj = 0; jj < 16; jj++) { - dacOut[ii][jj] = 0.0; - dacOutUsed[ii][jj] = 0; - dacOutBufSize[ii] = 0; - // Zero out DAC channel map in the shared memory - // to be used to check on slaves' channel allocation - ioMemData->dacOutUsed[ii][jj] = 0; - } - } - /// \> Set pointers to filter module data buffers. \n /// - ---- Prior to V2.8, separate local/shared memories for FILT_MOD data.\n /// - ---- V2.8 and later, code uses EPICS shared memory only. This was done to: \n @@ -362,35 +315,12 @@ void *fe_start(void *arg) if(cdsPciModules.cDio1616lCount) syncSource = SYNC_SRC_TDS; else syncSource = SYNC_SRC_1PPS; -printf("Sync source = %d\n",syncSource); #ifdef TIME_MASTER pcieTimer = (TIMING_SIGNAL *) ((volatile char *)(cdsPciModules.dolphinWrite[0]) + IPC_PCIE_TIME_OFFSET); -printf("I am a TIMING MASTER **************\n"); +// printf("I am a TIMING MASTER **************\n"); #endif - -/// \> Wait for BURT restore.\n -/// - ---- Code will exit if BURT flag not set by EPICS sequencer. - // Do not proceed until EPICS has had a BURT restore ******************************* - printf("Waiting for EPICS BURT Restore = %d\n", pLocalEpics->epicsInput.burtRestore); - cnt = 0; - do{ -#ifndef NO_CPU_SHUTDOWN - udelay(MAX_UDELAY); - udelay(MAX_UDELAY); - udelay(MAX_UDELAY); -#else - msleep(80); -#endif - printf("Waiting for EPICS BURT %d\n", cnt++); - cpu_relax(); - }while(!pLocalEpics->epicsInput.burtRestore); - - printf("BURT Restore Complete\n"); - -// BURT has completed ******************************************************************* - /// < Read in all Filter Module EPICS coeff settings for(ii=0;ii<MAX_MODULES;ii++) { @@ -428,11 +358,11 @@ printf("I am a TIMING MASTER **************\n"); /// \> Initialize IIR filter bank values if (initVars(pDsp[0], pDsp[0], dspCoeff, MAX_MODULES, pCoeff[0])) { - printf("Filter module init failed, exiting\n"); + // printf("Filter module init failed, exiting\n"); + pLocalEpics->epicsOutput.fe_status = FILT_INIT_ERROR; return 0; } - printf("Initialized servo control parameters.\n"); udelay(1000); @@ -454,11 +384,18 @@ udelay(1000); daq.filtTpSize = MAX_MODULES * 3; daq.xTpMin = daq.filtTpMax; daq.xTpMax = daq.xTpMin + GDS_MAX_NFM_TP; + + /// - ---- Initialize DAQ function + status = daqWrite(0,dcuId,daq,DAQ_RATE,testpoint,dspPtr[0],0, (int *)(pLocalEpics->epicsOutput.gdsMon),xExc,pEpicsDaq); + if(status == -1) + { + // printf("DAQ init failed -- exiting\n"); + pLocalEpics->epicsOutput.fe_status = DAQ_INIT_ERROR; + vmeDone = 1; + return(0); + } - printf("DAQ Ex Min/Max = %d %d\n",daq.filtExMin,daq.filtExMax); - printf("DAQ XEx Min/Max = %d %d\n",daq.xExMin,daq.xExMax); - printf("DAQ Tp Min/Max = %d %d\n",daq.filtTpMin,daq.filtTpMax); - printf("DAQ XTp Min/Max = %d %d\n",daq.xTpMin,daq.xTpMax); +#endif /// - ---- Assign DAC testpoint pointers for (ii = 0; ii < cdsPciModules.dacCount; ii++) @@ -468,83 +405,54 @@ udelay(1000); // Zero out storage memset(floatDacOut, 0, sizeof(floatDacOut)); -#endif pLocalEpics->epicsOutput.ipcStat = 0; pLocalEpics->epicsOutput.fbNetStat = 0; pLocalEpics->epicsOutput.tpCnt = 0; -#if !defined(NO_DAQ) && !defined(IOP_TASK) - /// - ---- Initialize DAQ function - status = daqWrite(0,dcuId,daq,DAQ_RATE,testpoint,dspPtr[0],0, (int *)(pLocalEpics->epicsOutput.gdsMon),xExc,pEpicsDaq); - if(status == -1) - { - printf("DAQ init failed -- exiting\n"); - vmeDone = 1; - return(0); - } -#endif - - // Clear the code exit flag vmeDone = 0; /// \> Call user application software initialization routine. - printf("Calling feCode() to initialize\n"); + // printf("Calling feCode() to initialize\n"); 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; + timeinfo.cpuTimeEverMax = 0; + timeinfo.cpuTimeEverMaxWhen = 0; + timeinfo.startGpsTime = 0; + timeinfo.usrHoldTime = 0; + timeinfo.timeHold = 0; + timeinfo.timeHoldHold = 0; + timeinfo.timeHoldWhen = 0; + timeinfo.timeHoldWhenHold = 0; + timeinfo.usrTime = 0; + timeinfo.cycleTime = 0; missedCycle = 0; - /// \> If IOP, Initialize the ADC modules - for(jj=0;jj<cdsPciModules.adcCount;jj++) - { - // Setup the DMA registers - status = gsc16ai64DmaSetup(jj); - // Preload input memory with dummy variables to test that new ADC data has arrived. - packedData = (int *)cdsPciModules.pci_adc[jj]; - // Write a dummy 0 to first ADC channel location - // This location should never be zero when the ADC writes data as it should always - // have an upper bit set indicating channel 0. - *packedData = 0x0; - if (cdsPciModules.adcType[jj] == GSC_18AISS6C) packedData += 5; - else packedData += 31; - // Write a number into the last channel which the ADC should never write ie no - // upper bits should be set in channel 31. - *packedData = DUMMY_ADC_VAL; - // Set ADC Present Flag - pLocalEpics->epicsOutput.statAdc[jj] = 1; - adcRdTimeErr[jj] = 0; - } - printf("ADC setup complete \n"); - - /// \> If IOP, Initialize the DAC module variables - for(jj = 0; jj < cdsPciModules.dacCount; jj++) { - pLocalEpics->epicsOutput.statDac[jj] = DAC_FOUND_BIT; - pDacData = (unsigned int *) cdsPciModules.pci_dac[jj]; - // Arm DAC DMA for full data size - if(cdsPciModules.dacType[jj] == GSC_16AO16) { - status = gsc16ao16DmaSetup(jj); - } else if (cdsPciModules.dacType[jj] == GSC_20AO8){ - status = gsc20ao8DmaSetup(jj); - } else { - status = gsc18ao8DmaSetup(jj); - } + for(ii=0;ii<IOP_IO_RATE;ii++) { + dt_diag.adc[ii] = 0; + dt_diag.dac[ii] = 0; } - printf("DAC setup complete \n"); + dt_diag.totalAdc = 0.0; + dt_diag.totalDac = 0.0; + dt_diag.meanAdc = 0.0; + dt_diag.meanDac = 0.0; + dt_diag.dacDuoEnable = 0.0; + + /// \> Initialize the ADC modules ************************************* + pLocalEpics->epicsOutput.fe_status = INIT_ADC_MODS; + status = iop_adc_init(padcinfo); + // printf("ADC setup complete \n"); + + pLocalEpics->epicsOutput.fe_status = INIT_DAC_MODS; + /// \> Initialize the DAC module variables ********************************** + status = iop_dac_init(dacTimingErrorPending); + + // printf("DAC setup complete \n"); + pLocalEpics->epicsOutput.fe_status = INIT_SYNC; -/// \> If IOP, find the code syncrhonization source. \n +/// \> Find the code syncrhonization source. \n /// - Standard aLIGO Sync source is the Timing Distribution System (TDS) (SYNC_SRC_TDS). if (!run_on_timer) { switch(syncSource) @@ -554,14 +462,13 @@ udelay(1000); /// - ---- Turn off TDS slave unit timing clocks, in turn removing clocks from ADC/DAC modules. for(ii=0;ii<tdsCount;ii++) { - CDIO1616Output[ii] = TDS_STOP_CLOCKS; - CDIO1616Input[ii] = contec1616WriteOutputRegister(&cdsPciModules, tdsControl[ii], CDIO1616Output[ii]); - printf("writing BIO %d\n",tdsControl[ii]); + CDIO1616Output[ii] = TDS_STOP_CLOCKS; + CDIO1616Input[ii] = contec1616WriteOutputRegister(&cdsPciModules, tdsControl[ii], CDIO1616Output[ii]); } udelay(MAX_UDELAY); udelay(MAX_UDELAY); /// - ---- Arm ADC modules - gsc16ai64Enable(cdsPciModules.adcCount); + gsc16ai64Enable(cdsPciModules.adcCount); /// - ---- Arm DAC outputs gsc18ao8Enable(&cdsPciModules); gsc16ao16Enable(&cdsPciModules); @@ -574,21 +481,7 @@ udelay(1000); /// values not written until a few cycle into run. \n /// - --------- DAC timing diags will later check FIFO sizes to verify synchrounous timing. #ifndef NO_DAC_PRELOAD - for(jj=0;jj<cdsPciModules.dacCount;jj++) - { - if(cdsPciModules.dacType[jj] == GSC_18AO8) - { - dac18bitPtr = (volatile GSA_18BIT_DAC_REG *)(dacPtr[jj]); - for(ii=0;ii<GSAO_18BIT_PRELOAD;ii++) dac18bitPtr->OUTPUT_BUF = 0; - } else if(cdsPciModules.dacType[jj] == GSC_20AO8) { - dac20bitPtr = (volatile GSA_20BIT_DAC_REG *)(dacPtr[jj]); - for(ii=0;ii<GSAO_20BIT_PRELOAD;ii++) dac20bitPtr->OUTPUT_BUF = 0; - }else{ - dac16bitPtr = dacPtr[jj]; - printf("writing DAC %d\n",jj); - for(ii=0;ii<GSAO_16BIT_PRELOAD;ii++) dac16bitPtr->ODB = 0; - } - } + status = iop_dac_preload(dacPtr); #endif /// - ---- Start the timing clocks\n /// - --------- Send start command to TDS slave.\n @@ -596,62 +489,18 @@ udelay(1000); // CDIO1616Output[tdsControl] = 0x7B00000; for(ii=0;ii<tdsCount;ii++) { - // CDIO1616Output[ii] = TDS_START_ADC_NEG_DAC_POS; - CDIO1616Output[ii] = TDS_START_ADC_NEG_DAC_POS | TDS_NO_DAC_DUOTONE; - CDIO1616Input[ii] = contec1616WriteOutputRegister(&cdsPciModules, tdsControl[ii], CDIO1616Output[ii]); + // CDIO1616Output[ii] = TDS_START_ADC_NEG_DAC_POS; + CDIO1616Output[ii] = TDS_START_ADC_NEG_DAC_POS | TDS_NO_DAC_DUOTONE; + CDIO1616Input[ii] = contec1616WriteOutputRegister(&cdsPciModules, tdsControl[ii], CDIO1616Output[ii]); } break; case SYNC_SRC_1PPS: - printf("Sync src is 1PPS\n"); #ifndef NO_DAC_PRELOAD - for(jj=0;jj<cdsPciModules.dacCount;jj++) - { - if(cdsPciModules.dacType[jj] == GSC_18AO8) - { - dac18bitPtr = (volatile GSA_18BIT_DAC_REG *)(dacPtr[jj]); - for(ii=0;ii<GSAO_18BIT_PRELOAD;ii++) dac18bitPtr->OUTPUT_BUF = 0; - } else if(cdsPciModules.dacType[jj] == GSC_20AO8) { - dac20bitPtr = (volatile GSA_20BIT_DAC_REG *)(dacPtr[jj]); - for(ii=0;ii<GSAO_20BIT_PRELOAD;ii++) dac20bitPtr->OUTPUT_BUF = 0; - }else{ - dac16bitPtr = dacPtr[jj]; - printf("writing DAC %d\n",jj); - for(ii=0;ii<GSAO_16BIT_PRELOAD;ii++) dac16bitPtr->ODB = 0; - } - } + status = iop_dac_preload(dacPtr); #endif // Arm ADC modules // This has to be done sequentially, one at a time. - kk = 0; - for(jj=0;jj<cdsPciModules.adcCount;jj++) - { - packedData = (int *)cdsPciModules.pci_adc[0]; - packedData += 31; - gsc16ai64Enable1PPS(jj); - rdtscl(cpuClock[jj]); - status = gsc16ai64WaitDmaDone(0, packedData); - kk ++; - udelay(2); - for(ii=0;ii<kk;ii++) { - gsc16ai64DmaEnable(ii); - } - } - // Need to do some dummy reads here to allow time for last ADC to arm - // as it takes two clock cycles past arm to actually deliver data. - for(ii=0;ii<cdsPciModules.adcCount;ii++) - { - // Want to verify ADC FIFOs are empty to ensure they are in sync. - status = gsc16ai64WaitDmaDone(0, packedData); - cpuClock[ii] = gsc16ai64CheckAdcBuffer(ii); - for(jj=0;jj<cdsPciModules.adcCount;jj++) - { - gsc16ai64DmaEnable(jj); - } - } - // Print out the FIFO info to dmesg to verify sync. - for(jj=0;jj<cdsPciModules.adcCount;jj++) { - printf("ADC buffer %d = %d\n",jj,cpuClock[jj]); - } + status = sync_adc_2_1pps(); break; default: { // IRIG-B card not found, so use CPU time to get close to 1PPS on startup @@ -663,11 +512,13 @@ udelay(1000); if (run_on_timer) { // NOT normal operating mode; used for test systems without I/O cards/chassis - printf("*******************************\n"); - printf("* Running on timer! *\n"); - printf("*******************************\n"); + // printf("*******************************\n"); + // printf("* Running on timer! *\n"); + // printf("*******************************\n"); + pLocalEpics->epicsOutput.fe_status = RUN_ON_TIMER; } else { - printf("Triggered the ADC\n"); + // printf("Triggered the ADC\n"); + pLocalEpics->epicsOutput.fe_status = NORMAL_RUN; } onePpsTime = cycleNum; @@ -678,7 +529,7 @@ udelay(1000); timeSec = current_time() -1; #endif - rdtscl(adcTime); + rdtscl(adcinfo.adcTime); /// ******************************************************************************\n /// Enter the infinite FE control loop ******************************************\n @@ -757,8 +608,8 @@ udelay(1000); #endif /// \> On 1PPS mark \n - if(cycleNum == 0) - { + if(cycleNum == 0) + { /// - ---- Check awgtpman status. //printf("awgtpman gps = %d local = %d\n", pEpicsComms->padSpace.awgtpman_gps, timeSec); pLocalEpics->epicsOutput.awgStat = (pEpicsComms->padSpace.awgtpman_gps != timeSec); @@ -767,19 +618,17 @@ udelay(1000); if(!iopDacEnable || dkiTrip) feStatus |= FE_ERROR_DAC_ENABLE; /// - ---- If IOP, Increment GPS second - timeSec ++; - pLocalEpics->epicsOutput.timeDiag = timeSec; + timeSec ++; + pLocalEpics->epicsOutput.timeDiag = timeSec; if (cycle_gps_time == 0) { - startGpsTime = timeSec; - pLocalEpics->epicsOutput.startgpstime = startGpsTime; + timeinfo.startGpsTime = timeSec; + pLocalEpics->epicsOutput.startgpstime = timeinfo.startGpsTime; } cycle_gps_time = timeSec; } #ifdef NO_CPU_SHUTDOWN if((cycleNum % 2048) == 0) usleep_range(2,4); #endif - for(ll=0;ll<sampleCount;ll++) - { /// IF IOP *************************** \n // Start of ADC Read ************************************************************************************* /// \> IF IOP, Wait for ADC data ready @@ -788,180 +637,20 @@ udelay(1000); /// 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. // Read ADC data - for(jj=0;jj<cdsPciModules.adcCount;jj++) - { - /// - ---- ADC DATA RDY is detected when last channel in memory no longer contains the - /// dummy variable written during initialization and reset after the read. - packedData = (int *)cdsPciModules.pci_adc[jj]; - if (cdsPciModules.adcType[jj] == GSC_18AISS6C) packedData += 5; - else packedData += 31; - - rdtscl(cpuClock[CPU_TIME_RDY_ADC]); - do { - /// - ---- Need to delay if not ready as constant banging of the input register - /// will slow down the ADC DMA. - // if(*packedData == DUMMY_ADC_VAL) { - rdtscl(cpuClock[CPU_TIME_ADC_WAIT]); - adcWait = (cpuClock[CPU_TIME_ADC_WAIT] - cpuClock[CPU_TIME_RDY_ADC])/CPURATE; - // } - /// - ---- Allow 1sec for data to be ready (should never take that long). - }while((*packedData == DUMMY_ADC_VAL) && (adcWait < MAX_ADC_WAIT)); -#ifdef TIME_MASTER - pcieTimer->gps_time = timeSec; - pcieTimer->cycle = cycleNum; -#endif - - /// - ---- 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; - else - adcRdTime[jj] = adcWait; - - if(adcRdTime[jj] > adcRdTimeMax[jj]) adcRdTimeMax[jj] = 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 data not ready in time, abort. - /// Either the clock is missing or code is running too slow and ADC FIFO - /// is overflowing. - if (adcWait >= MAX_ADC_WAIT) { - pLocalEpics->epicsOutput.stateWord = FE_ERROR_ADC; - pLocalEpics->epicsOutput.diagWord |= ADC_TIMEOUT_ERR; - stop_working_threads = 1; - vmeDone = 1; - printf("timeout %d %d \n",jj,adcWait); - continue; - } - if(jj == 0) - { - // Capture cpu clock for cpu meter diagnostics - rdtscl(cpuClock[CPU_TIME_CYCLE_START]); - /// \> If first cycle of a new second, capture IRIG-B time. Standard for aLIGO is - /// TSYNC_RCVR. - if(cycleNum == 0) - { - // if SymCom type, just do write to lock current time and read later - // This save a couple three microseconds here - if(cdsPciModules.gpsType == SYMCOM_RCVR) lockGpsTime(); - if(cdsPciModules.gpsType == TSYNC_RCVR) - { - /// - ---- Reading second info will lock the time register, allowing - /// nanoseconds to be read later (on next cycle). Two step process used to - /// save CPU time here, as each read can take 2usec or more. - timeSec = getGpsSecTsync(); - } - } - - } - -#ifndef RFM_DIRECT_READ -#ifdef FUTURE_RFM_DMA_CHECK - /// \> If RFM cards, verify DMA is complete - if(jj == 0 && (cycleNum % 4) == 0 && cdsPciModules.pci_rfm[0]) - vmic5565DMAdone(0); - if(jj == 0 && (cycleNum % 4) == 0 && cdsPciModules.pci_rfm[1]) - vmic5565DMAdone(1); -#endif -#endif - - /// \> Read adc data - packedData = (int *)cdsPciModules.pci_adc[jj]; - /// - ---- First, and only first, channel should have upper bit marker set. - /// If not, have a channel hopping error. - if(!(*packedData & ADC_1ST_CHAN_MARKER)) - { - adcChanErr[jj] = 1; - chanHop = 1; - pLocalEpics->epicsOutput.stateWord |= FE_ERROR_ADC; - } - - limit = OVERFLOW_LIMIT_16BIT; - if (cdsPciModules.adcType[jj] == GSC_18AISS6C) { - limit = OVERFLOW_LIMIT_18BIT; // 18 bit limit - offset = GSAF_DATA_CODE_OFFSET; // Data coding offset in 18-bit DAC - mask = GSAF_DATA_MASK; - num_outs = GSAF_CHAN_COUNT; - } else { - // Various ADC models have different number of channels/data bits - offset = GSAI_DATA_CODE_OFFSET; - mask = GSAI_DATA_MASK; - num_outs = GSAI_CHAN_COUNT; - } - /// - ---- Determine next ipc memory location to load ADC data - ioMemCntr = (cycleNum % IO_MEMORY_SLOTS); - /// - ---- Read adc data from PCI mapped memory into local variables - for(ii=0;ii<num_outs;ii++) - { - // adcData is the integer representation of the ADC data - adcData[jj][ii] = (*packedData & mask); - adcData[jj][ii] -= offset; -#ifdef DEC_TEST - if(ii==0) - { - adcData[jj][ii] = dspPtr[0]->data[0].exciteInput; - } -#endif - // dWord is the double representation of the ADC data - // This is the value used by the rest of the code calculations. - dWord[jj][ii] = adcData[jj][ii]; - /// - ---- Load ADC value into ipc memory buffer - ioMemData->iodata[jj][ioMemCntr].data[ii] = adcData[jj][ii]; - packedData ++; - } - /// - ---- Write GPS time and cycle count as indicator to slave that adc data is ready - ioMemData->gpsSecond = timeSec;; - ioMemData->iodata[jj][ioMemCntr].timeSec = timeSec;; - ioMemData->iodata[jj][ioMemCntr].cycle = cycleNum; - - /// - ---- Check for ADC overflows - for(ii=0;ii<num_outs;ii++) - { - if((adcData[jj][ii] > limit) || (adcData[jj][ii] < -limit)) - { - overflowAdc[jj][ii] ++; - pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] ++; - overflowAcc ++; - adcOF[jj] = 1; - odcStateWord |= ODC_ADC_OVF; - } - } - - /// - ---- Clear out last ADC data read for test on next cycle - packedData = (int *)cdsPciModules.pci_adc[jj]; - *packedData = 0x0; - - if (cdsPciModules.adcType[jj] == GSC_18AISS6C) packedData += GSAF_CHAN_COUNT_M1; - else packedData += GSAI_CHAN_COUNT_M1; - - *packedData = DUMMY_ADC_VAL; - -#ifdef DIAG_TEST -// For DIAGS ONLY !!!!!!!! -// This will change ADC DMA BYTE count -// -- Greater than normal will result in channel hopping. -// -- Less than normal will result in ADC timeout. -// In both cases, real-time kernel code should exit with errors to dmesg - if(pLocalEpics->epicsInput.bumpAdcRd != 0) { - gsc16ai64DmaBump(jj,pLocalEpics->epicsInput.bumpAdcRd); - pLocalEpics->epicsInput.bumpAdcRd = 0; - } -#endif - } - + for(ll=0;ll<sampleCount;ll++) + { + status = iop_adc_read (padcinfo, cpuClock); - // Try synching to 1PPS on ADC[0][31] if not using IRIG-B or TDS - // Only try for 1 sec. - if(!sync21pps) - { + // Try synching to 1PPS on ADC[0][31] if not using IRIG-B or TDS + // Only try for 1 sec. + if(!sync21pps) + { // 1PPS signal should rise above 4000 ADC counts if present. - if((adcData[0][31] < ONE_PPS_THRESH) && (sync21ppsCycles < (CYCLE_PER_SECOND*OVERSAMPLE_TIMES))) + if((adcinfo.adcData[0][31] < ONE_PPS_THRESH) && (sync21ppsCycles < (CYCLE_PER_SECOND*OVERSAMPLE_TIMES))) { ll = -1; sync21ppsCycles ++; - }else { + }else { // Need to start clocking the DAC outputs. gsc18ao8Enable(&cdsPciModules); gsc16ao16Enable(&cdsPciModules); @@ -970,15 +659,15 @@ udelay(1000); if(sync21ppsCycles >= (CYCLE_PER_SECOND*OVERSAMPLE_TIMES)) { syncSource = SYNC_SRC_NONE; - printf("NO SYNC SOURCE FOUND %d %d\n",sync21ppsCycles,adcData[0][31]); + // printf("NO SYNC SOURCE FOUND %d %d\n",sync21ppsCycles,adcinfo.adcData[0][31]); } else { // 1PPS found and synched to - printf("GPS Trigg %d %d\n",adcData[0][31],sync21pps); + // printf("GPS Trigg %d %d\n",adcinfo.adcData[0][31],sync21pps); syncSource = SYNC_SRC_1PPS; } pLocalEpics->epicsOutput.timeErr = syncSource; - } - } + } + } } /// END IF IOP \n @@ -1001,7 +690,10 @@ udelay(1000); gsc16ai64DmaEnable(jj); odcStateWord = 0; + +// ******************************************************************** /// WRITE DAC OUTPUTS ***************************************** \n +// ******************************************************************** /// Writing of DAC outputs is dependent on code compile option: \n /// - -- IOP (ADC_MASTER) reads DAC output values from memory shared with user apps and writes to DAC hardware. \n @@ -1012,120 +704,17 @@ udelay(1000); /// - -- Code will require restart to clear. // COMMENT OUT NEX LINE FOR TEST STAND w/bad DAC cards. #ifndef DAC_WD_OVERRIDE - if(dacTimingError) iopDacEnable = 0; - // Write out data to DAC modules + if(dacTimingError) iopDacEnable = 0; + // Write out data to DAC modules dkiTrip = 0; - /// \> Loop thru all DAC modules - for(jj=0;jj<cdsPciModules.dacCount;jj++) - { - /// - -- Point to DAC memory buffer - pDacData = (unsigned int *)(cdsPciModules.pci_dac[jj]); - /// - -- locate the proper DAC memory block - mm = cdsPciModules.dacConfig[jj]; - /// - -- Determine if memory block has been set with the correct cycle count by Slave app. - if(ioMemData->iodata[mm][ioMemCntrDac].cycle == ioClockDac) - { - dacEnable |= pBits[jj]; - }else { - dacEnable &= ~(pBits[jj]); - dacChanErr[jj] += 1; - } - /// - -- Set overflow limits, data mask, and chan count based on DAC type - limit = OVERFLOW_LIMIT_16BIT; - mask = GSAO_16BIT_MASK; - num_outs = GSAO_16BIT_CHAN_COUNT; - if (cdsPciModules.dacType[jj] == GSC_18AO8) { - limit = OVERFLOW_LIMIT_18BIT; // 18 bit limit - mask = GSAO_18BIT_MASK; - num_outs = GSAO_18BIT_CHAN_COUNT; - } - if (cdsPciModules.dacType[jj] == GSC_20AO8) { - limit = OVERFLOW_LIMIT_20BIT; // 20 bit limit - mask = GSAO_20BIT_MASK; - num_outs = GSAO_20BIT_CHAN_COUNT; - } - /// - -- For each DAC channel - for (ii=0; ii < num_outs; ii++) - { -#ifdef FLIP_SIGNALS - dacOut[jj][ii] *= -1; -#endif - /// - ---- Read DAC output value from shared memory and reset memory to zero - if((!dacChanErr[jj]) && (iopDacEnable)) { - dac_out = ioMemData->iodata[mm][ioMemCntrDac].data[ii]; - /// - --------- Zero out data in case user app dies by next cycle - /// when two or more apps share same DAC module. - ioMemData->iodata[mm][ioMemCntrDac].data[ii] = 0; - } else { - dac_out = 0; - dkiTrip = 1; - } - /// - ---- Write out ADC duotone signal to first DAC, last channel, - /// if DAC duotone is enabled. - if((dacDuoEnable) && (ii==(num_outs-1)) && (jj == 0)) - { - dac_out = adcData[0][ADC_DUOTONE_CHAN]; - } -// Code below is only for use in DAQ test system. -#ifdef DIAG_TEST - if((ii==0) && (jj == 0)) - { - if(cycleNum < 100) dac_out = limit / 20; - else dac_out = 0; - } - if((ii==0) && (jj == 2)) - { - if(cycleNum < 100) dac_out = limit / 20; - else dac_out = 0; - } -#endif - /// - ---- Check output values are within range of DAC \n - /// - --------- If overflow, clip at DAC limits and report errors - if(dac_out > limit || dac_out < -limit) - { - overflowDac[jj][ii] ++; - pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] ++; - overflowAcc ++; - dacOF[jj] = 1; - odcStateWord |= ODC_DAC_OVF;; - if(dac_out > limit) dac_out = limit; - else dac_out = -limit; - } - /// - ---- If DAQKILL tripped, set output to zero. - if(!iopDacEnable) dac_out = 0; - /// - ---- Load last values to EPICS channels for monitoring on GDS_TP screen. - dacOutEpics[jj][ii] = dac_out; - - /// - ---- Load DAC testpoints - floatDacOut[16*jj + ii] = dac_out; - - /// - ---- Write to DAC local memory area, for later xmit to DAC module - *pDacData = (unsigned int)(dac_out & mask); - pDacData ++; - } - /// - -- Mark cycle count as having been used -1 \n - /// - --------- Forces slaves to mark this cycle or will not be used again by Master - ioMemData->iodata[mm][ioMemCntrDac].cycle = -1; - /// - -- DMA Write data to DAC module - if(dacWriteEnable > 4) { - if(cdsPciModules.dacType[jj] == GSC_16AO16) { - gsc16ao16DmaStart(jj); - } else if(cdsPciModules.dacType[jj] == GSC_20AO8) { - gsc20ao8DmaStart(jj); - } else { - gsc18ao8DmaStart(jj); - } - } - } - /// \> Increment DAC memory block pointers for next cycle - ioClockDac = (ioClockDac + 1) % IOP_IO_RATE; - ioMemCntrDac = (ioMemCntrDac + 1) % IO_MEMORY_SLOTS; - if(dacWriteEnable < 10) dacWriteEnable ++; + dkiTrip = iop_dac_write(); /// END OF IOP DAC WRITE ************************************************* - #endif + +// *********************************************************************** /// BEGIN HOUSEKEEPING ************************************************ \n +// *********************************************************************** pLocalEpics->epicsOutput.cycle = cycleNum; // The following, to endif, is all duotone timing diagnostics. @@ -1145,10 +734,10 @@ udelay(1000); feStatus |= FE_ERROR_TIMING;; } /// - ---- Calc duotone diagnostic mean values for past second and reset. - duotoneMean = duotoneTotal/CYCLE_PER_SECOND; - duotoneTotal = 0.0; - duotoneMeanDac = duotoneTotalDac/CYCLE_PER_SECOND; - duotoneTotalDac = 0.0; + dt_diag.meanAdc = dt_diag.totalAdc/CYCLE_PER_SECOND; + dt_diag.totalAdc = 0.0; + dt_diag.meanDac = dt_diag.totalDac/CYCLE_PER_SECOND; + dt_diag.totalDac = 0.0; } /// \> Cycle 1 and Spectricom IRIGB (standard), get IRIG-B time information. @@ -1168,31 +757,30 @@ udelay(1000); } /// \> Update duotone diag information - duotoneDac[(cycleNum + DT_SAMPLE_OFFSET) % CYCLE_PER_SECOND] = dWord[ADC_DUOTONE_BRD][DAC_DUOTONE_CHAN]; - duotoneTotalDac += dWord[ADC_DUOTONE_BRD][DAC_DUOTONE_CHAN]; - duotone[(cycleNum + DT_SAMPLE_OFFSET) % CYCLE_PER_SECOND] = dWord[ADC_DUOTONE_BRD][ADC_DUOTONE_CHAN]; - duotoneTotal += dWord[ADC_DUOTONE_BRD][ADC_DUOTONE_CHAN]; + dt_diag.dac[(cycleNum + DT_SAMPLE_OFFSET) % CYCLE_PER_SECOND] = dWord[ADC_DUOTONE_BRD][DAC_DUOTONE_CHAN]; + dt_diag.totalDac += dWord[ADC_DUOTONE_BRD][DAC_DUOTONE_CHAN]; + dt_diag.adc[(cycleNum + DT_SAMPLE_OFFSET) % CYCLE_PER_SECOND] = dWord[ADC_DUOTONE_BRD][ADC_DUOTONE_CHAN]; + dt_diag.totalAdc += dWord[ADC_DUOTONE_BRD][ADC_DUOTONE_CHAN]; /// \> Cycle 16, perform duotone diag calcs. if(cycleNum == HKP_DT_CALC) { - duotoneTime = duotime(DT_SAMPLE_CNT, duotoneMean, duotone); + duotoneTime = duotime(DT_SAMPLE_CNT, dt_diag.meanAdc, dt_diag.adc); pLocalEpics->epicsOutput.dtTime = duotoneTime; if(((duotoneTime < MIN_DT_DIAG_VAL) || (duotoneTime > MAX_DT_DIAG_VAL)) && syncSource != SYNC_SRC_1PPS) feStatus |= FE_ERROR_TIMING; - duotoneTimeDac = duotime(DT_SAMPLE_CNT, duotoneMeanDac, duotoneDac); + duotoneTimeDac = duotime(DT_SAMPLE_CNT, dt_diag.meanDac, dt_diag.dac); pLocalEpics->epicsOutput.dacDtTime = duotoneTimeDac; } /// \> Cycle 17, set/reset DAC duotone switch if request has changed. if(cycleNum == HKP_DAC_DT_SWITCH) { - if(dacDuoEnable != pLocalEpics->epicsInput.dacDuoSet) + if(dt_diag.dacDuoEnable != pLocalEpics->epicsInput.dacDuoSet) { - dacDuoEnable = pLocalEpics->epicsInput.dacDuoSet; - // printf("duo set = %d\n",dacDuoEnable); - if(dacDuoEnable) + dt_diag.dacDuoEnable = pLocalEpics->epicsInput.dacDuoSet; + if(dt_diag.dacDuoEnable) CDIO1616Output[0] = TDS_START_ADC_NEG_DAC_POS; else CDIO1616Output[0] = TDS_START_ADC_NEG_DAC_POS | TDS_NO_DAC_DUOTONE; CDIO1616Input[0] = contec1616WriteOutputRegister(&cdsPciModules, tdsControl[0], CDIO1616Output[0]); @@ -1202,36 +790,31 @@ 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.cpuMeter = timeinfo.timeHold; + pLocalEpics->epicsOutput.cpuMeterMax = timeinfo.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; + 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 = adcHoldTimeMax; + pLocalEpics->epicsOutput.adcWaitTime = adcinfo.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)) + 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; feStatus |= FE_ERROR_TIMING; } - if(timeHoldMax > CYCLE_TIME_ALRM) + if(timeinfo.timeHoldMax > CYCLE_TIME_ALRM) { diagWord |= FE_PROC_TIME_ERR; feStatus |= FE_ERROR_TIMING; @@ -1244,20 +827,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; } } @@ -1287,7 +870,7 @@ udelay(1000); { // Assign chan 32 to onePps - onePps = adcData[ADC_DUOTONE_BRD][ADC_DUOTONE_CHAN]; + onePps = adcinfo.adcData[ADC_DUOTONE_BRD][ADC_DUOTONE_CHAN]; if((onePps > ONE_PPS_THRESH) && (onePpsHi == 0)) { onePpsTime = cycleNum; @@ -1302,8 +885,8 @@ udelay(1000); #ifdef DIAG_TEST for(ii=0;ii<10;ii++) { - if(ii<5) onePpsTest = adcData[0][ii]; - else onePpsTest = adcData[1][(ii-5)]; + if(ii<5) onePpsTest = adcinfo.adcData[0][ii]; + else onePpsTest = adcinfo.adcData[1][(ii-5)]; if((onePpsTest > 400) && (onePpsHiTest[ii] == 0)) { onePpsTimeTest[ii] = cycleNum; @@ -1321,148 +904,145 @@ udelay(1000); /// \> Write data to DAQ. #ifndef NO_DAQ - // Call daqLib - pLocalEpics->epicsOutput.daqByteCnt = - daqWrite(1,dcuId,daq,DAQ_RATE,testpoint,dspPtr[0],myGmError2,(int *)(pLocalEpics->epicsOutput.gdsMon),xExc,pEpicsDaq); - // Send the current DAQ block size to the awgtpman for TP number checking - pEpicsComms->padSpace.feDaqBlockSize = curDaqBlockSize; - pLocalEpics->epicsOutput.tpCnt = tpPtr->count & 0xff; - feStatus |= (FE_ERROR_EXC_SET & tpPtr->count); - if (FE_ERROR_EXC_SET & tpPtr->count) odcStateWord |= ODC_EXC_SET; - else odcStateWord &= ~(ODC_EXC_SET); - if(pLocalEpics->epicsOutput.daqByteCnt > DAQ_DCU_RATE_WARNING) - feStatus |= FE_ERROR_DAQ; + // Call daqLib + pLocalEpics->epicsOutput.daqByteCnt = + daqWrite(1,dcuId,daq,DAQ_RATE,testpoint,dspPtr[0],myGmError2,(int *)(pLocalEpics->epicsOutput.gdsMon),xExc,pEpicsDaq); + // Send the current DAQ block size to the awgtpman for TP number checking + pEpicsComms->padSpace.feDaqBlockSize = curDaqBlockSize; + pLocalEpics->epicsOutput.tpCnt = tpPtr->count & 0xff; + feStatus |= (FE_ERROR_EXC_SET & tpPtr->count); + if (FE_ERROR_EXC_SET & tpPtr->count) odcStateWord |= ODC_EXC_SET; + else odcStateWord &= ~(ODC_EXC_SET); + if(pLocalEpics->epicsOutput.daqByteCnt > DAQ_DCU_RATE_WARNING) + 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 - mxStat = 0; - mxDiagR = daqPtr->reqAck; - if((mxDiag & 1) != (mxDiagR & 1)) mxStat = 1; - if((mxDiag & 2) != (mxDiagR & 2)) mxStat += 2; + { + pLocalEpics->epicsOutput.userTime = timeinfo.usrHoldTime; + pLocalEpics->epicsOutput.ipcStat = ipcErrBits; + if(ipcErrBits & 0xf) feStatus |= FE_ERROR_IPC; + // Create FB status word for return to EPICS + mxStat = 0; + mxDiagR = daqPtr->reqAck; + if((mxDiag & 1) != (mxDiagR & 1)) mxStat = 1; + if((mxDiag & 2) != (mxDiagR & 2)) mxStat += 2; #ifdef DUAL_DAQ_DC - if((mxDiag & 4) != (mxDiagR & 4)) mxStat += 4; - if((mxDiag & 8) != (mxDiagR & 8)) mxStat += 8; + if((mxDiag & 4) != (mxDiagR & 4)) mxStat += 4; + if((mxDiag & 8) != (mxDiagR & 8)) mxStat += 8; #endif - pLocalEpics->epicsOutput.fbNetStat = mxStat; - 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++) { - overflowAdc[jj][ii] = 0; - overflowAdc[jj][ii + 16] = 0; - pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0; - pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii + 16] = 0; - } - - for (jj = 0; jj < cdsPciModules.dacCount; jj++) { - pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0; - } - } - } - } - if((pLocalEpics->epicsInput.overflowReset) || (overflowAcc > OVERFLOW_CNTR_LIMIT)) - { - pLocalEpics->epicsInput.overflowReset = 0; - pLocalEpics->epicsOutput.ovAccum = 0; - overflowAcc = 0; - } - } + pLocalEpics->epicsOutput.fbNetStat = mxStat; + mxDiag = mxDiagR; + if(mxStat != MX_OK) + feStatus |= FE_ERROR_DAQ;; + timeinfo.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; + pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0; + pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii + 16] = 0; + } + for (jj = 0; jj < cdsPciModules.dacCount; jj++) { + pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0; + } + } + } + } + if((pLocalEpics->epicsInput.overflowReset) || (overflowAcc > OVERFLOW_CNTR_LIMIT)) + { + pLocalEpics->epicsInput.overflowReset = 0; + pLocalEpics->epicsOutput.ovAccum = 0; + overflowAcc = 0; + } + } /// \> Cycle 20, Update latest DAC output values to EPICS - if(subcycle == HKP_DAC_EPICS_UPDATES) + if(subcycle == HKP_DAC_EPICS_UPDATES) { - // Send DAC output values at 16Hzfb - for(jj=0;jj<cdsPciModules.dacCount;jj++) - { + // Send DAC output values at 16Hzfb + for(jj=0;jj<cdsPciModules.dacCount;jj++) + { for(ii=0;ii<MAX_DAC_CHN_PER_MOD;ii++) { - pLocalEpics->epicsOutput.dacValue[jj][ii] = dacOutEpics[jj][ii]; - } - } + pLocalEpics->epicsOutput.dacValue[jj][ii] = dacOutEpics[jj][ii]; + } + } } /// \> Cycle 21, Update ADC/DAC status to EPICS. - if(cycleNum == HKP_ADC_DAC_STAT_UPDATES) - { - pLocalEpics->epicsOutput.ovAccum = overflowAcc; - for(jj=0;jj<cdsPciModules.adcCount;jj++) - { - // SET/CLR Channel Hopping Error - if(adcChanErr[jj]) - { - pLocalEpics->epicsOutput.statAdc[jj] &= ~(2); - feStatus |= FE_ERROR_ADC;; - } - else pLocalEpics->epicsOutput.statAdc[jj] |= 2; - adcChanErr[jj] = 0; - // SET/CLR Overflow Error - if(adcOF[jj]) - { - pLocalEpics->epicsOutput.statAdc[jj] &= ~(4); - feStatus |= FE_ERROR_OVERFLOW;; - } - else pLocalEpics->epicsOutput.statAdc[jj] |= 4; - adcOF[jj] = 0; - for(ii=0;ii<32;ii++) - { - + if(cycleNum == HKP_ADC_DAC_STAT_UPDATES) + { + pLocalEpics->epicsOutput.ovAccum = overflowAcc; + for(jj=0;jj<cdsPciModules.adcCount;jj++) + { + // SET/CLR Channel Hopping Error + if(adcinfo.adcChanErr[jj]) + { + pLocalEpics->epicsOutput.statAdc[jj] &= ~(2); + feStatus |= FE_ERROR_ADC;; + } + else pLocalEpics->epicsOutput.statAdc[jj] |= 2; + adcinfo.adcChanErr[jj] = 0; + // SET/CLR Overflow Error + if(adcinfo.adcOF[jj]) + { + pLocalEpics->epicsOutput.statAdc[jj] &= ~(4); + feStatus |= FE_ERROR_OVERFLOW;; + } + else pLocalEpics->epicsOutput.statAdc[jj] |= 4; + adcinfo.adcOF[jj] = 0; + for(ii=0;ii<32;ii++) + { 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; - - } - } - // If ADC channels not where they should be, we have no option but to exit - // from the RT code ie loops would be working with wrong input data. - if (chanHop) { - pLocalEpics->epicsOutput.stateWord = FE_ERROR_ADC; - stop_working_threads = 1; - vmeDone = 1; - printf("Channel Hopping Detected on one or more ADC modules !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); - printf("Check GDSTP screen ADC status bits to id affected ADC modules\n"); - printf("Code is exiting ..............\n"); - continue; - } - for(jj=0;jj<cdsPciModules.dacCount;jj++) - { - if(dacOF[jj]) - { - pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_OVERFLOW_BIT); - feStatus |= FE_ERROR_OVERFLOW;; - } - else pLocalEpics->epicsOutput.statDac[jj] |= DAC_OVERFLOW_BIT; - dacOF[jj] = 0; - if(dacChanErr[jj]) - { - pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_TIMING_BIT); - } - else pLocalEpics->epicsOutput.statDac[jj] |= DAC_TIMING_BIT; - dacChanErr[jj] = 0; - for(ii=0;ii<MAX_DAC_CHN_PER_MOD;ii++) - { - - if (pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] > OVERFLOW_CNTR_LIMIT) { - pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0; - } - pLocalEpics->epicsOutput.overflowDac[jj][ii] = overflowDac[jj][ii]; - overflowDac[jj][ii] = 0; + pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0; + } + pLocalEpics->epicsOutput.overflowAdc[jj][ii] = adcinfo.overflowAdc[jj][ii]; + adcinfo.overflowAdc[jj][ii] = 0; - } - } - } + } + } + // If ADC channels not where they should be, we have no option but to exit + // from the RT code ie loops would be working with wrong input data. + if (adcinfo.chanHop) { + pLocalEpics->epicsOutput.stateWord = FE_ERROR_ADC; + stop_working_threads = 1; + vmeDone = 1; + pLocalEpics->epicsOutput.fe_status = CHAN_HOP_ERROR; + // printf("Channel Hopping Detected on one or more ADC modules !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); + // printf("Check GDSTP screen ADC status bits to id affected ADC modules\n"); + // printf("Code is exiting ..............\n"); + continue; + } + for(jj=0;jj<cdsPciModules.dacCount;jj++) + { + if(dacOF[jj]) + { + pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_OVERFLOW_BIT); + feStatus |= FE_ERROR_OVERFLOW;; + } + else pLocalEpics->epicsOutput.statDac[jj] |= DAC_OVERFLOW_BIT; + dacOF[jj] = 0; + if(dacChanErr[jj]) + { + pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_TIMING_BIT); + } + else pLocalEpics->epicsOutput.statDac[jj] |= DAC_TIMING_BIT; + dacChanErr[jj] = 0; + for(ii=0;ii<MAX_DAC_CHN_PER_MOD;ii++) + { + if (pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] > OVERFLOW_CNTR_LIMIT) { + pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0; + } + pLocalEpics->epicsOutput.overflowDac[jj][ii] = dacinfo.overflowDac[jj][ii]; + dacinfo.overflowDac[jj][ii] = 0; + } + } + } /// \> Cycle 300, If IOP and RFM cards, check own data diagnostics // Deal with the own-data bits on the VMIC 5565 rfm cards if (cdsPciModules.rfmCount > 0) { @@ -1625,84 +1205,69 @@ udelay(1000); #endif // Capture end of cycle time. - rdtscl(cpuClock[CPU_TIME_CYCLE_END]); + rdtscl(cpuClock[CPU_TIME_CYCLE_END]); /// \> Compute code cycle time diag information. - 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; + 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; + if(timeinfo.cycleTime > timeinfo.timeHold) { + timeinfo.timeHold = timeinfo.cycleTime; + timeinfo.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; + 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 && (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 (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 (timeHoldMax > cpuTimeEverMax) { - cpuTimeEverMax = timeHoldMax; - cpuTimeEverMaxWhen = cycle_gps_time; + if (timeinfo.timeHoldMax > timeinfo.cpuTimeEverMax) { + timeinfo.cpuTimeEverMax = timeinfo.timeHoldMax; + timeinfo.cpuTimeEverMaxWhen = cycle_gps_time; } } - adcTime = cpuClock[CPU_TIME_CYCLE_START]; + 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; + /// \> Update internal cycle counters + cycleNum += 1; #ifdef DIAG_TEST - if(pLocalEpics->epicsInput.bumpCycle != 0) { + if(pLocalEpics->epicsInput.bumpCycle != 0) { cycleNum += pLocalEpics->epicsInput.bumpCycle; pLocalEpics->epicsInput.bumpCycle = 0; - } + } #endif - cycleNum %= CYCLE_PER_SECOND; - clock1Min += 1; - clock1Min %= CYCLE_PER_MINUTE; - if(subcycle == DAQ_CYCLE_CHANGE) - { + cycleNum %= CYCLE_PER_SECOND; + clock1Min += 1; + clock1Min %= CYCLE_PER_MINUTE; + if(subcycle == DAQ_CYCLE_CHANGE) + { daqCycle = (daqCycle + 1) % DAQ_NUM_DATA_BLOCKS_PER_SECOND; if(!(daqCycle % 2)) pLocalEpics->epicsOutput.epicsSync = daqCycle; - } - if(subcycle == END_OF_DAQ_BLOCK) /*we have reached the 16Hz second barrier*/ - { - /* Reset the data cycle counter */ - subcycle = 0; - - } - else{ - /* Increment the internal cycle counter */ - subcycle ++; - } + } + if(subcycle == END_OF_DAQ_BLOCK) /*we have reached the 16Hz second barrier*/ + { + /* Reset the data cycle counter */ + subcycle = 0; + } else { + /* Increment the internal cycle counter */ + subcycle ++; + } /// \> If not exit request, then continue INFINITE LOOP ******* } - printf("exiting from fe_code()\n"); + // printf("exiting from fe_code()\n"); pLocalEpics->epicsOutput.cpuMeter = 0; diff --git a/src/fe/controllerIopUser.c b/src/fe/controllerIopUser.c index 17b5c46c3..fa64b8951 100644 --- a/src/fe/controllerIopUser.c +++ b/src/fe/controllerIopUser.c @@ -38,6 +38,7 @@ #include "inlineMath.h" +#include "cds_types.h" #include "fm10Gen.h" // CDS filter module defs and C code #include "feComms.h" // Lvea control RFM network defs. #include "daqmap.h" // DAQ network layout @@ -154,7 +155,7 @@ unsigned int getGpsTimeProc() { fclose(timef); return (mytime); } - void initAdcModules(void) { + void initAdcModules(adcInfo_t *adcinfo) { int status; int jj; @@ -162,7 +163,7 @@ unsigned int getGpsTimeProc() { { // Set ADC Present Flag pLocalEpics->epicsOutput.statAdc[jj] = 1; - adcRdTimeErr[jj] = 0; + adcinfo->adcRdTimeErr[jj] = 0; } printf("ADC setup complete \n"); } @@ -198,14 +199,15 @@ int fe_start() struct timespec tp; static struct timespec cpuClock[CPU_TIMER_CNT]; /// @param cpuClock[] Code timing diag variables static int chanHop = 0; /// @param chanHop Adc channel hopping status + int dacOF[MAX_DAC_MODULES]; int adcData[MAX_ADC_MODULES][MAX_ADC_CHN_PER_MOD]; /// @param adcData[][] ADC raw data int adcChanErr[MAX_ADC_MODULES]; - int adcWait = 0; + // int adcWait = 0; + adcInfo_t adcInfo; + dacInfo_t dacInfo; int adcOF[MAX_ADC_MODULES]; /// @param adcOF[] ADC overrange counters - // int dacChanErr[MAX_DAC_MODULES]; - int dacOF[MAX_DAC_MODULES]; /// @param dacOF[] DAC overrange counters static int dacWriteEnable = 0; /// @param dacWriteEnable No DAC outputs until >4 times through code ///< Code runs longer for first few cycles on startup as it settles in, ///< so this helps prevent long cycles during that time. @@ -302,7 +304,7 @@ int fe_start() for (jj = 0; jj < 16; jj++) { dacOut[ii][jj] = 0.0; dacOutUsed[ii][jj] = 0; - dacOutBufSize[ii] = 0; + dacInfo.dacOutBufSize[ii] = 0; // Zero out DAC channel map in the shared memory // to be used to check on slaves' channel allocation ioMemData->dacOutUsed[ii][jj] = 0; @@ -449,6 +451,7 @@ usleep(1000); printf("Calling feCode() to initialize\n"); iopDacEnable = feCode(cycleNum,dWord,dacOut,dspPtr[0],&dspCoeff[0], (struct CDS_EPICS *)pLocalEpics,1); + /// \> Verify DAC channels defined for this app are not already in use. \n /// - ---- User apps are allowed to share DAC modules but not DAC channels. @@ -462,7 +465,7 @@ usleep(1000); missedCycle = 0; /// \> If IOP, Initialize the ADC modules - initAdcModules(); + initAdcModules(&adcInfo); /// \> If IOP, Initialize the DAC module variables initDacModules(); @@ -511,18 +514,18 @@ printf("cycle time = %d\n",cycleTime); ioMemCntr = (cycleNum % IO_MEMORY_SLOTS); // Write GPS time and cycle count as indicator to slave that adc data is ready - for(jj=0;jj<cdsPciModules.adcCount;jj++) + for(jj=0;jj<cdsPciModules.adcCount;jj++) { for(ii=0;ii<IO_MEMORY_SLOT_VALS;ii++) { - ioMemData->iodata[jj][ioMemCntr].data[ii] = ioMemDataIop->iodata[jj][cycleNum].data[ii]; - dWord[jj][ii] = ioMemData->iodata[jj][ioMemCntr].data[ii]; - ioMemDataIop->iodata[jj][cycleNum].data[ii] = 0; + ioMemData->iodata[jj][ioMemCntr].data[ii] = ioMemDataIop->iodata[jj][cycleNum].data[ii]; + dWord[jj][ii] = ioMemData->iodata[jj][ioMemCntr].data[ii]; + ioMemDataIop->iodata[jj][cycleNum].data[ii] = 0; } ioMemData->iodata[jj][ioMemCntr].timeSec = timeSec;; ioMemData->iodata[jj][ioMemCntr].cycle = cycleNum; - ioMemDataIop->gpsSecond = timeSec; - ioMemDataIop->cycleNum = cycleNum; + ioMemDataIop->gpsSecond = timeSec; + ioMemDataIop->cycleNum = cycleNum; } ioMemData->gpsSecond = timeSec; clock_gettime(CLOCK_MONOTONIC, &cpuClock[CPU_TIME_CYCLE_START]); @@ -548,7 +551,8 @@ printf("cycle time = %d\n",cycleTime); /// \> Call the front end specific application ******************\n /// - -- This is where the user application produced by RCG gets called and executed. \n\n clock_gettime(CLOCK_MONOTONIC, &cpuClock[CPU_TIME_USR_START]); - iopDacEnable = feCode(cycleNum,dWord,dacOut,dspPtr[0],&dspCoeff[0],(struct CDS_EPICS *)pLocalEpics,0); + iopDacEnable = feCode(cycleNum,dWord,dacOut,dspPtr[0],&dspCoeff[0], (struct CDS_EPICS *)pLocalEpics,0); + clock_gettime(CLOCK_MONOTONIC, &cpuClock[CPU_TIME_USR_END]); odcStateWord = 0; @@ -632,7 +636,7 @@ printf("cycle time = %d\n",cycleTime); /// - --------- If overflow, clip at DAC limits and report errors if(dac_out > limit || dac_out < -limit) { - overflowDac[jj][ii] ++; + dacInfo.overflowDac[jj][ii] ++; pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] ++; overflowAcc ++; dacOF[jj] = 1; @@ -643,7 +647,7 @@ printf("cycle time = %d\n",cycleTime); /// - ---- If DAQKILL tripped, set output to zero. if(!iopDacEnable) dac_out = 0; /// - ---- Load last values to EPICS channels for monitoring on GDS_TP screen. - dacOutEpics[jj][ii] = dac_out; + dacInfo.dacOutEpics[jj][ii] = dac_out; /// - ---- Load DAC testpoints floatDacOut[16*jj + ii] = dac_out; @@ -714,15 +718,15 @@ printf("cycle time = %d\n",cycleTime); 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; } } @@ -787,8 +791,8 @@ printf("cycle time = %d\n",cycleTime); 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; } @@ -799,7 +803,7 @@ printf("cycle time = %d\n",cycleTime); } } } - if((pLocalEpics->epicsInput.overflowReset) || (overflowAcc > OVERFLOW_CNTR_LIMIT)) + if((pLocalEpics->epicsInput.overflowReset) || (adcInfo.overflowAdc > OVERFLOW_CNTR_LIMIT)) { pLocalEpics->epicsInput.overflowReset = 0; pLocalEpics->epicsOutput.ovAccum = 0; @@ -815,7 +819,7 @@ printf("cycle time = %d\n",cycleTime); { for(ii=0;ii<MAX_DAC_CHN_PER_MOD;ii++) { - pLocalEpics->epicsOutput.dacValue[jj][ii] = dacOutEpics[jj][ii]; + pLocalEpics->epicsOutput.dacValue[jj][ii] = dacInfo.dacOutEpics[jj][ii]; } } } @@ -823,7 +827,7 @@ printf("cycle time = %d\n",cycleTime); /// \> Cycle 21, Update ADC/DAC status to EPICS. if(cycleNum == HKP_ADC_DAC_STAT_UPDATES) { - pLocalEpics->epicsOutput.ovAccum = overflowAcc; + pLocalEpics->epicsOutput.ovAccum = adcInfo.overflowAdc; for(jj=0;jj<cdsPciModules.adcCount;jj++) { // SET/CLR Channel Hopping Error @@ -848,8 +852,8 @@ printf("cycle time = %d\n",cycleTime); 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; } } @@ -885,8 +889,8 @@ printf("cycle time = %d\n",cycleTime); if (pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] > OVERFLOW_CNTR_LIMIT) { pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0; } - pLocalEpics->epicsOutput.overflowDac[jj][ii] = overflowDac[jj][ii]; - overflowDac[jj][ii] = 0; + pLocalEpics->epicsOutput.overflowDac[jj][ii] = dacInfo.overflowDac[jj][ii]; + dacInfo.overflowDac[jj][ii] = 0; } } diff --git a/src/fe/moduleLoadApp.c b/src/fe/moduleLoadApp.c index 750062690..fcc0c9b96 100644 --- a/src/fe/moduleLoadApp.c +++ b/src/fe/moduleLoadApp.c @@ -22,7 +22,7 @@ struct task_struct *sthread; #include "moduleLoadCommon.c" /// Startup function for initialization of kernel module. -int init_module (void) +int rt_fe_init (void) { int status; int ii,jj,kk; /// @param ii,jj,kk default loop counters @@ -61,18 +61,17 @@ int init_module (void) jj = 0; - // Allocate EPICS shmem area ret = mbuf_allocate_area(SYSTEM_NAME_STRING_LOWER, 64*1024*1024, 0); if (ret < 0) { - printf("mbuf_allocate_area() failed; ret = %d\n", ret); + printk("mbuf_allocate_area() failed; ret = %d\n", ret); return -1; } _epics_shm = (unsigned char *)(kmalloc_area[ret]); // Allocate IPC shmem area ret = mbuf_allocate_area("ipc", 4*1024*1024, 0); if (ret < 0) { - printf("mbuf_allocate_area(ipc) failed; ret = %d\n", ret); + printk("mbuf_allocate_area(ipc) failed; ret = %d\n", ret); return -1; } _ipc_shm = (unsigned char *)(kmalloc_area[ret]); @@ -84,7 +83,7 @@ int init_module (void) sprintf(fname, "%s_daq", SYSTEM_NAME_STRING_LOWER); ret = mbuf_allocate_area(fname, 64*1024*1024, 0); if (ret < 0) { - printf("mbuf_allocate_area() failed; ret = %d\n", ret); + printk("mbuf_allocate_area() failed; ret = %d\n", ret); return -1; } _daq_shm = (unsigned char *)(kmalloc_area[ret]); @@ -248,7 +247,7 @@ int init_module (void) // If no ADC cards were found, then SLAVE cannot run if(!cdsPciModules.adcCount) { - printf("No ADC cards found - exiting\n"); + printk("No ADC cards found - exiting\n"); return -1; } // This did not quite work for some reason @@ -256,7 +255,7 @@ int init_module (void) //cdsPciModules.dacCount = ioMemData->dacCount; if(status < cards) { - printf(" ERROR **** Did not find correct number of cards! Expected %d and Found %d\n",cards,status); + printk(" ERROR **** Did not find correct number of cards! Expected %d and Found %d\n",cards,status); cardCountErr = 1; } @@ -293,12 +292,14 @@ int init_module (void) // Set Pointer to EPICS data pLocalEpics = (CDS_EPICS *)&((RFM_FE_COMMS *)_epics_shm)->epicsSpace; + pLocalEpics->epicsOutput.fe_status = WAIT_BURT; // Ensure EPICS is running for (cnt = 0; cnt < 10 && pLocalEpics->epicsInput.burtRestore == 0; cnt++) { msleep(1000); } // If EPICS not running, EXIT if (cnt == 10) { + pLocalEpics->epicsOutput.fe_status = BURT_RESTORE_ERROR; // Cleanup return -1; } @@ -308,13 +309,14 @@ int init_module (void) #ifdef NO_CPU_SHUTDOWN sthread = kthread_create(fe_start, 0, "fe_start/%d", CPUID); if (IS_ERR(sthread)){ - printf("Failed to kthread_create()\n"); + printk("Failed to kthread_create()\n"); return -1; } kthread_bind(sthread, CPUID); wake_up_process(sthread); #endif + pLocalEpics->epicsOutput.fe_status = LOCKING_CORE; #ifndef NO_CPU_SHUTDOWN set_fe_code_idle(fe_start, CPUID); @@ -327,7 +329,7 @@ int init_module (void) return 0; } -void cleanup_module (void) { +void rt_fe_cleanup (void) { int i; int ret; extern int __cpuinit cpu_up(unsigned int cpu); @@ -361,6 +363,8 @@ void cleanup_module (void) { } +module_init(rt_fe_init); +module_exit(rt_fe_cleanup); MODULE_DESCRIPTION("Control system"); MODULE_AUTHOR("LIGO"); MODULE_LICENSE("Dual BSD/GPL"); diff --git a/src/fe/moduleLoadCommon.c b/src/fe/moduleLoadCommon.c index c9b4b29f2..4c00a1a2a 100644 --- a/src/fe/moduleLoadCommon.c +++ b/src/fe/moduleLoadCommon.c @@ -1,8 +1,9 @@ /// @file moduleLoadCommon.c /// @brief File contains common routines for moduleLoadIop.c and moduleLoadApp.c.` -int print_io_info(CDS_HARDWARE *cdsp) { +void print_io_info(CDS_HARDWARE *cdsp) { int ii,jj,kk; + jj = 0; printf("THIS IS A TEST \n"); #ifndef USER_SPACE printf("startup time is %ld\n", current_time()); diff --git a/src/fe/moduleLoadIop.c b/src/fe/moduleLoadIop.c index 9ed1875c7..f6d38d223 100644 --- a/src/fe/moduleLoadIop.c +++ b/src/fe/moduleLoadIop.c @@ -25,7 +25,7 @@ extern void msleep(unsigned int); #include "moduleLoadCommon.c" /// Startup function for initialization of kernel module. -int init_module (void) +int rt_iop_init (void) { int status; int ii,jj,kk; /// @param ii,jj,kk default loop counters @@ -45,7 +45,7 @@ int init_module (void) #ifndef NO_CPU_SHUTDOWN // See if our CPU core is free - if (is_cpu_taken_by_rcg_model(CPUID)) { + if (is_cpu_taken_by_rcg_model(CPUID)) { printk(KERN_ALERT "Error: CPU %d already taken\n", CPUID); return -1; } @@ -63,34 +63,39 @@ int init_module (void) // Allocate EPICS memory area - ret = mbuf_allocate_area(SYSTEM_NAME_STRING_LOWER, 64*1024*1024, 0); - if (ret < 0) { - printf("mbuf_allocate_area() failed; ret = %d\n", ret); - return -1; - } - _epics_shm = (unsigned char *)(kmalloc_area[ret]); -// Allocate IPC memory area - ret = mbuf_allocate_area("ipc", 4*1024*1024, 0); - if (ret < 0) { - printf("mbuf_allocate_area(ipc) failed; ret = %d\n", ret); - return -1; - } - _ipc_shm = (unsigned char *)(kmalloc_area[ret]); + ret = mbuf_allocate_area(SYSTEM_NAME_STRING_LOWER, 64*1024*1024, 0); + if (ret < 0) { + printk("mbuf_allocate_area() failed; ret = %d\n", ret); + return -1; + } + _epics_shm = (unsigned char *)(kmalloc_area[ret]); + // Set pointer to EPICS area + pLocalEpics = (CDS_EPICS *)&((RFM_FE_COMMS *)_epics_shm)->epicsSpace; + pLocalEpics->epicsOutput.fe_status = 0; + + // Allocate IPC memory area + ret = mbuf_allocate_area("ipc", 4*1024*1024, 0); + if (ret < 0) { + printk("mbuf_allocate_area(ipc) failed; ret = %d\n", ret); + return -1; + } + _ipc_shm = (unsigned char *)(kmalloc_area[ret]); // Assign pointer to IOP/USER app comms space ioMemData = (IO_MEM_DATA *)(_ipc_shm+ 0x4000); // Allocate DAQ memory area - sprintf(fname, "%s_daq", SYSTEM_NAME_STRING_LOWER); - ret = mbuf_allocate_area(fname, 64*1024*1024, 0); - if (ret < 0) { - printf("mbuf_allocate_area() failed; ret = %d\n", ret); - return -1; - } - _daq_shm = (unsigned char *)(kmalloc_area[ret]); + sprintf(fname, "%s_daq", SYSTEM_NAME_STRING_LOWER); + ret = mbuf_allocate_area(fname, 64*1024*1024, 0); + if (ret < 0) { + printk("mbuf_allocate_area() failed; ret = %d\n", ret); + return -1; + } + _daq_shm = (unsigned char *)(kmalloc_area[ret]); daqPtr = (struct rmIpcStr *) _daq_shm; + pLocalEpics->epicsOutput.fe_status = 1; // Find and initialize all PCI I/O modules ************************************************** // Following I/O card info is from feCode cards = sizeof(cards_used)/sizeof(cards_used[0]); @@ -105,7 +110,7 @@ int init_module (void) status = mapPciModules(&cdsPciModules); if(status < cards) { - printf(" ERROR **** Did not find correct number of cards! Expected %d and Found %d\n",cards,status); + printk(" ERROR **** Did not find correct number of cards! Expected %d and Found %d\n",cards,status); cardCountErr = 1; } @@ -117,13 +122,13 @@ int init_module (void) // kk will act as ioMem location counter for mapping modules kk = cdsPciModules.adcCount; for(ii=0;ii<cdsPciModules.adcCount;ii++) - { + { // MASTER maps ADC modules first in ipc shm for SLAVES ioMemData->model[ii] = cdsPciModules.adcType[ii]; ioMemData->ipc[ii] = ii; // ioData memory buffer location for SLAVE to use - } + } for(ii=0;ii<cdsPciModules.dacCount;ii++) - { + { // Pass DAC info to SLAVE processes ioMemData->model[kk] = cdsPciModules.dacType[ii]; ioMemData->ipc[kk] = kk; @@ -186,11 +191,10 @@ int init_module (void) if (cdsPciModules.adcCount == 0) run_on_timer = 1; // Initialize buffer for daqLib.c code - // printf("Initializing space for daqLib buffers\n"); daqBuffer = (long)&daqArea[0]; -// Set pointer to EPICS area - pLocalEpics = (CDS_EPICS *)&((RFM_FE_COMMS *)_epics_shm)->epicsSpace; + pLocalEpics->epicsOutput.fe_status = 2; +printk("Waiting for EPICS BURT Restore = %d\n", pLocalEpics->epicsInput.burtRestore); // Ensure EPICS running else exit for (cnt = 0; cnt < 10 && pLocalEpics->epicsInput.burtRestore == 0; cnt++) { msleep(1000); @@ -202,13 +206,14 @@ int init_module (void) #endif return -1; } + printk("BURT Restore Complete\n"); pLocalEpics->epicsInput.vmeReset = 0; #ifdef NO_CPU_SHUTDOWN sthread = kthread_create(fe_start, 0, "fe_start/%d", CPUID); if (IS_ERR(sthread)){ - printf("Failed to kthread_create()\n"); + printk("Failed to kthread_create()\n"); return -1; } kthread_bind(sthread, CPUID); @@ -217,19 +222,18 @@ int init_module (void) #ifndef NO_CPU_SHUTDOWN + pLocalEpics->epicsOutput.fe_status = 3; + printk("Locking CPU core %d\n", CPUID); // The code runs on the disabled CPU - set_fe_code_idle(fe_start, CPUID); - msleep(100); - + set_fe_code_idle(fe_start, CPUID); + msleep(100); cpu_down(CPUID); #endif return 0; } -void cleanup_module (void) { - int i; - int ret; +void rt_iop_cleanup(void) { extern int __cpuinit cpu_up(unsigned int cpu); #ifndef NO_CPU_SHUTDOWN @@ -237,9 +241,10 @@ void cleanup_module (void) { set_fe_code_idle(0, CPUID); #endif - printk("Setting stop_working_threads to 1\n"); + // printk("Setting stop_working_threads to 1\n"); // Stop the code and wait #ifdef NO_CPU_SHUTDOWN + int ret; ret = kthread_stop(sthread); #endif stop_working_threads = 1; @@ -257,13 +262,16 @@ void cleanup_module (void) { msleep(1000); // Bring the CPU back up cpu_up(CPUID); - //msleep(1000); + msleep(1000); printk("Brought the CPU back up\n"); #endif printk("Just before returning from cleanup_module for " SYSTEM_NAME_STRING_LOWER "\n"); } +module_init(rt_iop_init); +module_exit(rt_iop_cleanup); + MODULE_DESCRIPTION("Control system"); MODULE_AUTHOR("LIGO"); MODULE_LICENSE("Dual BSD/GPL"); diff --git a/src/fe/moduleLoadVirtual.c b/src/fe/moduleLoadVirtual.c index 1c068daec..76b8129ac 100644 --- a/src/fe/moduleLoadVirtual.c +++ b/src/fe/moduleLoadVirtual.c @@ -1,485 +1,19 @@ -/// @file moduleLoad.c -/// @brief File contains startup routines for real-time code. +/// @file moduleLoadIop.c +/// @brief File contains startup routines for real-time IOP code. #include <asm/uaccess.h> #include <linux/ctype.h> #include <linux/spinlock_types.h> #include <proc.h> - // These externs and "16" need to go to a header file (mbuf.h) extern void *kmalloc_area[16]; extern int mbuf_allocate_area(char *name, int size, struct file *file); extern void *fe_start(void *arg); extern int run_on_timer; extern char daqArea[2*DAQ_DCU_SIZE]; // Space allocation for daqLib buffers +struct task_struct *sthread; -#include FE_PROC_FILE - -/// /proc filesystem directory entry -struct proc_dir_entry *proc_dir_entry; -/// /proc/{sysname}/status entry -struct proc_dir_entry *proc_entry; -/// /proc/{sysname}/gps entry -struct proc_dir_entry *proc_gps_entry; -/// /proc/{sysname}/epics directory entry -struct proc_dir_entry *proc_epics_dir_entry; -/// /proc/{sysname}/futures entry -struct proc_dir_entry *proc_futures_entry; - -void remove_epics_proc_files(void); -int create_epics_proc_files(void); - -/// Routine to read the /proc/{model}/status file. \n \n -/// We give all of our information in one go, so if the -/// user asks us if we have more information the \n -/// answer should always be no. -/// -/// This is important because the standard read -/// function from the library would continue to issue \n -/// the read system call until the kernel replies -/// that it has no more information, or until its \n -/// buffer is filled. -int -procfile_status_read(char *buffer, - char **buffer_location, - off_t offset, int buffer_length, int *eof, void *data) -{ - int ret, i; - i = 0; - *buffer = 0; - - /* - * We give all of our information in one go, so if the - * user asks us if we have more information the - * answer should always be no. - * - * This is important because the standard read - * function from the library would continue to issue - * the read system call until the kernel replies - * that it has no more information, or until its - * buffer is filled. - */ - if (offset > 0) { - /* we have finished to read, return 0 */ - ret = 0; - } else { -#if defined(SERVO64K) || defined(SERVO32K) || defined(SERVO16K) || defined(COMMDATA_INLINE) - char b[128]; -#if defined(SERVO64K) || defined(SERVO32K) - static const int nb = 32; -#elif defined(SERVO16K) - static const int nb = 64; -#endif -#endif - /* fill the buffer, return the buffer size */ - ret = sprintf(buffer, - - "startGpsTime=%d\n" - "uptime=%d\n" - "cpuTimeEverMax=%d\n" - "cpuTimeEverMaxWhen=%d\n" - "adcHoldTime=%d\n" - "adcHoldTimeEverMax=%d\n" - "adcHoldTimeEverMaxWhen=%d\n" - "adcHoldTimeMax=%d\n" - "adcHoldTimeMin=%d\n" - "adcHoldTimeAvg=%d\n" - "usrTime=%d\n" - "usrHoldTime=%d\n" - "cycle=%d\n" - "gps=%d\n" - "buildDate=%s\n" - "cpuTimeMax(cur,past sec)=%d,%d\n" - "cpuTimeMaxCycle(cur,past sec)=%d,%d\n", - - startGpsTime, - cycle_gps_time - startGpsTime, - cpuTimeEverMax, - cpuTimeEverMaxWhen, - adcHoldTime, - adcHoldTimeEverMax, - adcHoldTimeEverMaxWhen, - adcHoldTimeMax, - adcHoldTimeMin, - adcHoldTimeAvgPerSec, - usrTime, - usrHoldTime, - cycleNum, - cycle_gps_time, - build_date, - cycleTime, timeHoldHold, - timeHoldWhen, timeHoldWhenHold); -#if defined(SERVO64K) || defined(SERVO32K) || defined(SERVO16K) - strcat(buffer, "cycleHist: "); - for (i = 0; i < nb; i++) { - if (!cycleHistMax[i]) continue; - sprintf(b, "%d=%d@%d ", i, cycleHistMax[i], cycleHistWhenHold[i]); - strcat(buffer, b); - } - strcat(buffer, "\n"); -#endif - - /* Output DAC buffer size information */ - for (i = 0; i < cdsPciModules.dacCount; i++) { - if (cdsPciModules.dacType[i] == GSC_18AO8) { - sprintf(b, "DAC #%d 18-bit buf_size=%d\n", i, dacOutBufSize[i]); - } else { - sprintf(b, "DAC #%d 16-bit fifo_status=%d (%s)\n", i, dacOutBufSize[i], - dacOutBufSize[i] & 8? "full": - (dacOutBufSize[i] & 1? "empty": - (dacOutBufSize[i] & 4? "high quarter": "OK"))); - } - strcat(buffer, b); - } - /* Output ADC read time information */ - for (i = 0; i < cdsPciModules.adcCount; i++) { - sprintf(b, "ADC #%d read time MAX=%d Current=%d\n", i, adcRdTimeMax[i],adcRdTime[i]); - strcat(buffer, b); - } -#ifdef COMMDATA_INLINE - // See if we have any IPC with errors and print the numbers out - // - sprintf(b, "ipcErrBits=0x%x\n", ipcErrBits); - strcat(buffer, b); - - // The following loop has a chance to overflow the buffer, - // which is set to PROC_BLOCK_SIZE. (PAGE_SIZE-1024 = 3072 bytes). - // We will simply stop printing at that point. -#define PROC_BLOCK_SIZE (3*1024) - unsigned int byte_cnt = strlen(buffer) + 1; - for (i = 0; i < myIpcCount; i++) { - if (ipcInfo[i].errTotal) { - unsigned int cnt = - sprintf(b, "IPC net=%d num=%d name=%s sender=%s errcnt=%d\n", - ipcInfo[i].netType, ipcInfo[i].ipcNum, - ipcInfo[i].name, ipcInfo[i].senderModelName, - ipcInfo[i].errTotal); - if (byte_cnt + cnt > PROC_BLOCK_SIZE) break; - byte_cnt += cnt; - strcat(buffer, b); - } - } -#endif - ret = strlen(buffer); - } - - return ret; -} - -/// Routine to read the /proc/{model}/gps file. \n \n -/// -int -procfile_gps_read(char *buffer, - char **buffer_location, - off_t offset, int buffer_length, int *eof, void *data) -{ - *buffer = 0; - - if (offset > 0) { - /* we have finished to read, return 0 */ - return 0; - } else { - /* fill the buffer, return the buffer size */ - /* print current GPS time and zero padded fraction */ - return sprintf(buffer, "%d.%02d\n", cycle_gps_time, (cycleNum*100/CYCLE_PER_SECOND)%100); - } - // Never reached -} - -/// Routine to read the /proc/{model}/epics/{chname} files. \n \n -/// -int -procfile_epics_read(char *buffer, - char **buffer_location, - off_t offset, int buffer_length, int *eof, void *data) -{ - *buffer = 0; - - if (offset > 0) { - /* we have finished to read, return 0 */ - return 0; - } else { - /* fill the buffer, return the buffer size */ - struct proc_epics *pe = (struct proc_epics *)data; - unsigned int ncel = pe->nrow * pe->ncol; // Matrix size - switch (pe -> type) { - case 0: /* int */ - return sprintf(buffer, "%s%d\n", - (*((char *)(((void *)pLocalEpics) + pe->mask_idx)))? "\t": "", - *((int *)(((void *)pLocalEpics) + pe->idx))); - // printf("Accessing data at %x\n", (((void *)pLocalEpics) + pe->idx)); - break; - case 1: /* double */ { - char lb[64]; - if (ncel) { /* Print Matrix */ - unsigned int i, j; - unsigned int nrow = pe->nrow; - unsigned int ncol = pe->ncol; - unsigned int s = 0; - unsigned int masked = *((char *)(((void *)pLocalEpics) + pe->mask_idx)); - for (i = 0; i < nrow; i++) { - if (masked) s += sprintf(buffer + s, "\t"); - for (j = 0; j < ncol; j++) { - s += sprintf(buffer + s, "%s ", dtoa_r(lb, ((double *)(((void *)pLocalEpics) + pe->idx))[ncol*i + j])); - } - s += sprintf(buffer + s, "\n"); - } - return s; - } else { /* Print single value */ - return sprintf(buffer, "%s%s\n", - (*((char *)(((void *)pLocalEpics) + pe->mask_idx)))? "\t": "", - dtoa_r(lb, *((double *)(((void *)pLocalEpics) + pe->idx)))); - } - break; - } - } - } - // Never reached -} - -#define PROC_BLOCK_SIZE (3*1024) - -// Scan a double -double -simple_strtod(char *start, char **end) { - int integer; - if (*start != '.') { - integer = simple_strtol(start, end, 10); - if (*end == start) return 0.0; - start = *end; - } else integer = 0; - if (*start != '.') return integer; - else { - start++; - double frac = simple_strtol(start, end, 10); - if (*end == start) return integer; - int i; - for (i = 0; i < (*end - start); i++) frac /= 10.0; - return ((double)integer) + frac; - } - // Never reached -} - - -int -procfile_epics_write(struct file *file, const char __user *buf, - unsigned long count, void *data) -{ - ssize_t ret = -ENOMEM; - char *page; - char *start; - unsigned int future = 0; - - if (count > PROC_BLOCK_SIZE) - return -EOVERFLOW; - - start = page = (char *)__get_free_page(GFP_KERNEL); - if (page) { - ret = -EFAULT; - if (copy_from_user(page, buf, count)) - goto out; - page[count] = 0; - ret = count; - struct proc_epics *pe = (struct proc_epics *)data; - char *end; - for(;isspace(*start);start++); - // See if this a single-character command - switch (*start) { - case 'm': - *((char *)(((void *)pLocalEpics) + pe->mask_idx)) = 1; - start++; - break; - case 'u': - *((char *)(((void *)pLocalEpics) + pe->mask_idx)) = 0; - start++; - break; - case 'f': - future=1; - start++; - break; - } - for(;isspace(*start);start++); - double new_double = 0.0; - int new_int = 0; - switch (pe -> type) { - case 0: /* int */ - new_int = simple_strtol(start, &end, 10); - if (new_int > INT_MAX || new_int < INT_MIN) { - ret = -EFAULT; - goto out; - } - break; - case 1: /* double */ - new_double = simple_strtod(start, &end); - //printf("User wrote %s\n", dtoa1(new_double)); - break; - } - if (end == start) goto out; - // See if this is a matrix - int idx = 0; - int ncel = pe->nrow * pe->ncol; - if (ncel) { - // Expect the cell index number next - start = end; - for(;isspace(*start);start++); - idx = simple_strtol(start, &end, 10); - if (idx >= ncel || idx < 0) { - ret = -EFAULT; - goto out; - } - - } - if (!future) { - switch (pe -> type) { - case 0: /* int */ - *((int *)(((void *)pLocalEpics) + pe->idx)) = new_int; - break; - case 1: /* double */ - ((double *)(((void *)pLocalEpics) + pe->idx))[idx] = new_double; - break; - } - } else if ((*((char *)(((void *)pLocalEpics) + pe->mask_idx)))) { // Allow to setup a future only if masked - unsigned long cycle; - start = end; - for(;isspace(*start);start++); - // check for gps seconds - double gps = simple_strtod(start, &end); - if (end == start) { - gps = cycle_gps_time + 5; - cycle = cycleNum; - } else { - // Convert gps time - unsigned long gps_int = gps; - gps -= gps_int; - cycle = gps * CYCLE_PER_SECOND; - gps = gps_int; - } - // Add new future setpoint - // Find first available slot - int i; - static DEFINE_SPINLOCK(fut_lock); - spin_lock(&fut_lock); - for (i = 0; (i < MAX_PROC_FUTURES) && proc_futures[i].proc_epics; i++); - if (i == MAX_PROC_FUTURES) { - spin_unlock(&fut_lock); - ret = -ENOMEM; - } else { - // Found a slot - proc_futures[i].cycle = cycle; - proc_futures[i].gps = gps; - proc_futures[i].val = pe->type? new_double: new_int; - proc_futures[i].idx = idx; - - // This pointer has to be set last; Indicates a vailid entry for the - // real-time code in controller.c - proc_futures[i].proc_epics = pe; // FE code reads/writes this variable - spin_unlock(&fut_lock); - } - } else ret = -EFAULT; - } -out: - free_page((unsigned long)page); - return ret; -} - -/// Routine to read the /proc/{model}/epics/futures files. \n \n -/// -// :TODO: the function does not check for buffer overflow, Linux kernel catches it though, -// when proc_futures contains too many entries. -int -procfile_futures_read(char *buffer, - char **buffer_location, - off_t offset, int buffer_length, int *eof, void *data) -{ - *buffer = 0; - - if (offset > 0) { - /* we have finished to read, return 0 */ - return 0; - } else { - /* fill the buffer, return the buffer size */ - char b[128]; - int i; - for (i = 0; i < MAX_PROC_FUTURES; i++) { - // Copy the entry to avoid race with the FE code - struct proc_futures pf = proc_futures[i]; - if (pf.proc_epics) { - char s[64]; - char s1[64]; - if (pf.idx) { /* matrix */ - sprintf(b, "%s %s@%s %d %d\n", pf.proc_epics->name, dtoa_r(s, pf.val), dtoa_r(s1, pf.idx), pf.gps, pf.cycle); - } else { - sprintf(b, "%s %s %d %d\n", pf.proc_epics->name, dtoa_r(s, pf.val), pf.gps, pf.cycle); - } - strcat(buffer, b); - } - } - return strlen(buffer); - } - // Never reached -} - - -static const ner = sizeof(proc_epics)/sizeof(struct proc_epics); - -/// Function to create /proc/{model}/epics/* files -/// -int -create_epics_proc_files() { - int i; - - for (i = 0; i < ner; i++) proc_epics_entry[i] = 0; - - for (i = 0; i < ner; i++) { - //printf("%s\n", proc_epics[i].name); - proc_epics_entry[i] = create_proc_entry(proc_epics[i].name, PROC_MODE, proc_epics_dir_entry); - if (proc_epics_entry[i] == NULL) { - remove_epics_proc_files(); - printk(KERN_ALERT "Error: Could not initialize /proc/%s/epics/%s\n", SYSTEM_NAME_STRING_LOWER, proc_epics[i].name); - return 0; - } - proc_epics_entry[i]->mode = S_IFREG | S_IRUGO; - switch (proc_epics[i].in) { - case 0: - proc_epics_entry[i]->write_proc = procfile_epics_write; - proc_epics_entry[i]->mode |= S_IWUGO; - // Fall through - case 1: - proc_epics_entry[i]->read_proc = procfile_epics_read; - break; - } - proc_epics_entry[i]->uid = PROC_UID; - proc_epics_entry[i]->gid = 0; - unsigned int ncel = proc_epics[i].nrow * proc_epics[i].ncol; // Enough space to deal with the matrix - proc_epics_entry[i]->size = ncel? 64 * ncel: 128; - proc_epics_entry[i]->data = proc_epics + i; - } - proc_futures_entry = create_proc_entry("futures", PROC_MODE, proc_epics_dir_entry); - if (proc_futures_entry == NULL) { - remove_epics_proc_files(); - printk(KERN_ALERT "Error: Could not initialize /proc/%s/epics/futures\n", SYSTEM_NAME_STRING_LOWER); - return 0; - } - proc_futures_entry->mode = S_IFREG | S_IRUGO; - proc_futures_entry->uid = PROC_UID; - proc_futures_entry->gid = 0; - proc_futures_entry->size = 10240; - proc_futures_entry->read_proc = procfile_futures_read; - return 1; -} - -/// Function to delete /proc/{model}/epics/* files -/// -void remove_epics_proc_files() { - int i; - for (i = 0; i < ner; i++) - if (proc_epics_entry[i] != NULL) { - remove_proc_entry(proc_epics[i].name, proc_epics_dir_entry); - proc_epics_entry[i] = 0; - } - remove_proc_entry("futures", proc_epics_dir_entry); -} // MAIN routine: Code starting point **************************************************************** int need_to_load_IOP_first; @@ -488,6 +22,8 @@ EXPORT_SYMBOL(need_to_load_IOP_first); extern void set_fe_code_idle(void *(*ptr)(void *), unsigned int cpu); extern void msleep(unsigned int); +#include "moduleLoadCommon.c" + /// Startup function for initialization of kernel module. int init_module (void) { @@ -517,77 +53,23 @@ int init_module (void) #ifdef DOLPHIN_TEST - status = init_dolphin(); + status = init_dolphin(1); if (status != 0) { return -1; } #endif - // Create /proc filesystem tree - proc_dir_entry = proc_mkdir(SYSTEM_NAME_STRING_LOWER, NULL); - if (proc_dir_entry == NULL) { - printk(KERN_ALERT "Error: Could not initialize /proc/%s\n", SYSTEM_NAME_STRING_LOWER); - return -ENOMEM; - } - - proc_entry = create_proc_entry("status", PROC_MODE, proc_dir_entry); - if (proc_entry == NULL) { - remove_proc_entry(SYSTEM_NAME_STRING_LOWER, NULL); - printk(KERN_ALERT "Error: Could not initialize /proc/%s/status\n", SYSTEM_NAME_STRING_LOWER); - return -ENOMEM; - } - - proc_gps_entry = create_proc_entry("gps", PROC_MODE, proc_dir_entry); - if (proc_gps_entry == NULL) { - remove_proc_entry("status", proc_dir_entry); - remove_proc_entry(SYSTEM_NAME_STRING_LOWER, NULL); - printk(KERN_ALERT "Error: Could not initialize /proc/%s/gps\n", SYSTEM_NAME_STRING_LOWER); - return -ENOMEM; - } - - proc_epics_dir_entry = proc_mkdir("epics", proc_dir_entry); - if (proc_epics_dir_entry == NULL) { - remove_proc_entry("gps", proc_dir_entry); - remove_proc_entry("status", proc_dir_entry); - remove_proc_entry(SYSTEM_NAME_STRING_LOWER, NULL); - printk(KERN_ALERT "Error: Could not initialize /proc/%s/epics\n", SYSTEM_NAME_STRING_LOWER); - return -ENOMEM; - } - - proc_entry->read_proc = procfile_status_read; - proc_entry->mode = S_IFREG | S_IRUGO; - proc_entry->uid = PROC_UID; - proc_entry->gid = 0; - proc_entry->size = 10240; - - proc_gps_entry->read_proc = procfile_gps_read; - proc_gps_entry->mode = S_IFREG | S_IRUGO; - proc_gps_entry->uid = PROC_UID; - proc_gps_entry->gid = 0; - proc_gps_entry->size = 128; - proc_gps_entry->data = &cycle_gps_time; - - // Create all /proc/{system}/epics/* files, one file per existing Epics channel - if (create_epics_proc_files() == 0) { - remove_proc_entry("epics", proc_dir_entry); - remove_proc_entry("gps", proc_dir_entry); - remove_proc_entry("status", proc_dir_entry); - remove_proc_entry(SYSTEM_NAME_STRING_LOWER, NULL); - return -ENOMEM; - } - - printf("startup time is %ld\n", current_time()); jj = 0; - printf("cpu clock %u\n",cpu_khz); +// Allocate EPICS memory area ret = mbuf_allocate_area(SYSTEM_NAME_STRING_LOWER, 64*1024*1024, 0); if (ret < 0) { printf("mbuf_allocate_area() failed; ret = %d\n", ret); return -1; } _epics_shm = (unsigned char *)(kmalloc_area[ret]); - printf("EPICSM at 0x%x\n", _epics_shm); +// Allocate IPC memory area ret = mbuf_allocate_area("ipc", 4*1024*1024, 0); if (ret < 0) { printf("mbuf_allocate_area(ipc) failed; ret = %d\n", ret); @@ -595,13 +77,11 @@ int init_module (void) } _ipc_shm = (unsigned char *)(kmalloc_area[ret]); - printf("IPC at 0x%x\n",_ipc_shm); +// Assign pointer to IOP/USER app comms space ioMemData = (IO_MEM_DATA *)(_ipc_shm+ 0x4000); - printf("IOMEM at 0x%x size 0x%x\n",(_ipc_shm + 0x4000),sizeof(IO_MEM_DATA)); -// If DAQ is via shared memory (Framebuilder code running on same machine or MX networking is used) -// attach DAQ shared memory location. +// Allocate DAQ memory area sprintf(fname, "%s_daq", SYSTEM_NAME_STRING_LOWER); ret = mbuf_allocate_area(fname, 64*1024*1024, 0); if (ret < 0) { @@ -609,88 +89,48 @@ int init_module (void) return -1; } _daq_shm = (unsigned char *)(kmalloc_area[ret]); - // printf("Allocated daq shmem; set at 0x%x\n", _daq_shm); - printf("DAQSM at 0x%x\n",_daq_shm); daqPtr = (struct rmIpcStr *) _daq_shm; - // Find and initialize all PCI I/O modules ******************************************************* - // Following I/O card info is from feCode - cards = sizeof(cards_used)/sizeof(cards_used[0]); - printf("configured to use %d cards\n", cards); - cdsPciModules.cards = cards; - cdsPciModules.cards_used = cards_used; - //return -1; - printf("Initializing PCI Modules\n"); - cdsPciModules.adcCount = 5; - for(ii=0;ii<cdsPciModules.adcCount;ii++) - cdsPciModules.adcType[ii] = GSC_16AI64SSA; - cdsPciModules.dacCount = 10; - for(ii=0;ii<cdsPciModules.dacCount;ii++) - cdsPciModules.dacType[ii] = GSC_16AO16; + // Find and initialize all PCI I/O modules ************************************************** + // Following I/O card info is from feCode + cards = sizeof(cards_used)/sizeof(cards_used[0]); + cdsPciModules.cards = cards; + cdsPciModules.cards_used = cards_used; + cdsPciModules.adcCount = 0; + cdsPciModules.dacCount = 0; cdsPciModules.dioCount = 0; cdsPciModules.doCount = 0; - status = 15; - printf("%d PCI cards found \n",status); + // Call PCI initialization routine in map.c file. + status = mapPciModules(&cdsPciModules); if(status < cards) { printf(" ERROR **** Did not find correct number of cards! Expected %d and Found %d\n",cards,status); cardCountErr = 1; } - // Print out all the I/O information - printf("***************************************************************************\n"); - // Master send module counds to SLAVE via ipc shm - ioMemData->totalCards = status; - ioMemData->adcCount = cdsPciModules.adcCount; - ioMemData->dacCount = cdsPciModules.dacCount; - ioMemData->bioCount = cdsPciModules.doCount; - // kk will act as ioMem location counter for mapping modules - kk = cdsPciModules.adcCount; - printf("%d ADC cards found\n",cdsPciModules.adcCount); + // Master send module counds to SLAVE via ipc shm + ioMemData->totalCards = status; + ioMemData->adcCount = cdsPciModules.adcCount; + ioMemData->dacCount = cdsPciModules.dacCount; + ioMemData->bioCount = cdsPciModules.doCount; + // kk will act as ioMem location counter for mapping modules + kk = cdsPciModules.adcCount; for(ii=0;ii<cdsPciModules.adcCount;ii++) { // MASTER maps ADC modules first in ipc shm for SLAVES ioMemData->model[ii] = cdsPciModules.adcType[ii]; ioMemData->ipc[ii] = ii; // ioData memory buffer location for SLAVE to use - if(cdsPciModules.adcType[ii] == GSC_16AI64SSA) - { - printf("\tADC %d is a GSC_16AI64SSA module\n",ii); - jj = 32; - printf("\t\tChannels = %d \n",jj); - } } - printf("***************************************************************************\n"); - printf("%d DAC cards found\n",cdsPciModules.dacCount); for(ii=0;ii<cdsPciModules.dacCount;ii++) { - if(cdsPciModules.dacType[ii] == GSC_18AO8) - { - printf("\tDAC %d is a GSC_18AO8 module\n",ii); - } - if(cdsPciModules.dacType[ii] == GSC_16AO16) - { - printf("\tDAC %d is a GSC_16AO16 module\n",ii); - } // Pass DAC info to SLAVE processes ioMemData->model[kk] = cdsPciModules.dacType[ii]; ioMemData->ipc[kk] = kk; // Following used by MASTER to point to ipc memory for inputting DAC data from SLAVES cdsPciModules.dacConfig[ii] = kk; - printf("MASTER DAC SLOT %d %d\n",ii,cdsPciModules.dacConfig[ii]); kk ++; } - printf("***************************************************************************\n"); - printf("%d DIO cards found\n",cdsPciModules.dioCount); - printf("***************************************************************************\n"); - printf("%d IIRO-8 Isolated DIO cards found\n",cdsPciModules.iiroDioCount); - printf("***************************************************************************\n"); - printf("%d IIRO-16 Isolated DIO cards found\n",cdsPciModules.iiroDio1Count); - printf("***************************************************************************\n"); - printf("%d Contec 32ch PCIe DO cards found\n",cdsPciModules.cDo32lCount); - printf("%d Contec PCIe DIO1616 cards found\n",cdsPciModules.cDio1616lCount); - printf("%d Contec PCIe DIO6464 cards found\n",cdsPciModules.cDio6464lCount); - printf("%d DO cards found\n",cdsPciModules.doCount); // MASTER sends DIO module information to SLAVES // Note that for DIO, SLAVE modules will perform the I/O directly and therefore need to // know the PCIe address of these modules. @@ -701,7 +141,6 @@ int init_module (void) if(cdsPciModules.doType[ii] == CON_1616DIO) { tdsControl[tdsCount] = ii; - printf("TDS controller %d is at %d\n",tdsCount,ii); tdsCount ++; } ioMemData->model[kk] = cdsPciModules.doType[ii]; @@ -710,69 +149,48 @@ int init_module (void) ioMemData->ipc[kk] = cdsPciModules.pci_do[ii]; kk ++; } - printf("Total of %d I/O modules found and mapped\n",kk); - for(ii=0;ii<kk;ii++) { - printf("Model = %d ipc = %d \n",ioMemData->model[ii],ioMemData->ipc[ii]); - } - printf("***************************************************************************\n"); // Following section maps Reflected Memory, both VMIC hardware style and Dolphin PCIe network style. // Slave units will perform I/O transactions with RFM directly ie MASTER does not do RFM I/O. // Master unit only maps the RFM I/O space and passes pointers to SLAVES. - cdsPciModules.rfmCount = 0; - printf("%d RFM cards found\n",cdsPciModules.rfmCount); ioMemData->rfmCount = cdsPciModules.rfmCount; + for(ii=0;ii<cdsPciModules.rfmCount;ii++) + { + // Master sends RFM memory pointers to SLAVES + ioMemData->pci_rfm[ii] = cdsPciModules.pci_rfm[ii]; + ioMemData->pci_rfm_dma[ii] = cdsPciModules.pci_rfm_dma[ii]; + } // ioMemData->dolphinCount = 0; +#ifdef DOLPHIN_TEST + ioMemData->dolphinCount = cdsPciModules.dolphinCount; + ioMemData->dolphinRead[0] = cdsPciModules.dolphinRead[0]; + ioMemData->dolphinWrite[0] = cdsPciModules.dolphinWrite[0]; + +#else // Clear Dolphin pointers so the slave sees NULLs ioMemData->dolphinCount = 0; ioMemData->dolphinRead[0] = 0; - ioMemData->dolphinRead[1] = 0; - ioMemData->dolphinRead[2] = 0; - ioMemData->dolphinRead[3] = 0; ioMemData->dolphinWrite[0] = 0; - ioMemData->dolphinWrite[1] = 0; - ioMemData->dolphinWrite[2] = 0; - ioMemData->dolphinWrite[3] = 0; - printf("***************************************************************************\n"); - if (cdsPciModules.gps) { - printf("IRIG-B card found %d\n",cdsPciModules.gpsType); - printf("***************************************************************************\n"); - } +#endif + // Print out all the I/O information + print_io_info(&cdsPciModules); // Code will run on internal timer if no ADC modules are found - printf("Virtual IOP ******* running on timer\n"); - run_on_timer = 1; + if (cdsPciModules.adcCount == 0) run_on_timer = 1; // Initialize buffer for daqLib.c code - printf("Initializing space for daqLib buffers\n"); + // printf("Initializing space for daqLib buffers\n"); daqBuffer = (long)&daqArea[0]; -#ifndef NO_DAQ -#ifndef SHMEM_DAQ - printf("Initializing Network\n"); - numFb = 1; - if (numFb <= 0) { - printf("Couldn't initialize Myrinet network connection\n"); - return -1; - } - printf("Found %d frameBuilders on network\n",numFb); -#endif -#endif - - +// Set pointer to EPICS area pLocalEpics = (CDS_EPICS *)&((RFM_FE_COMMS *)_epics_shm)->epicsSpace; + // Ensure EPICS running else exit for (cnt = 0; cnt < 10 && pLocalEpics->epicsInput.burtRestore == 0; cnt++) { - printf("Epics burt restore is %d\n", pLocalEpics->epicsInput.burtRestore); msleep(1000); } if (cnt == 10) { // Cleanup - remove_epics_proc_files(); - remove_proc_entry("epics", proc_dir_entry); - remove_proc_entry("gps", proc_dir_entry); - remove_proc_entry("status", proc_dir_entry); - remove_proc_entry(SYSTEM_NAME_STRING_LOWER, NULL); #ifdef DOLPHIN_TEST finish_dolphin(); #endif @@ -782,38 +200,32 @@ int init_module (void) pLocalEpics->epicsInput.vmeReset = 0; #ifdef NO_CPU_SHUTDOWN - struct task_struct *p; - p = kthread_create(fe_start, 0, "fe_start/%d", CPUID); - if (IS_ERR(p)){ + sthread = kthread_create(fe_start, 0, "fe_start/%d", CPUID); + if (IS_ERR(sthread)){ printf("Failed to kthread_create()\n"); return -1; } - kthread_bind(p, CPUID); - wake_up_process(p); + kthread_bind(sthread, CPUID); + wake_up_process(sthread); #endif #ifndef NO_CPU_SHUTDOWN + // The code runs on the disabled CPU set_fe_code_idle(fe_start, CPUID); msleep(100); cpu_down(CPUID); - // The code runs on the disabled CPU #endif return 0; } void cleanup_module (void) { int i; + int ret; extern int __cpuinit cpu_up(unsigned int cpu); - remove_epics_proc_files(); - remove_proc_entry("epics", proc_dir_entry); - remove_proc_entry("gps", proc_dir_entry); - remove_proc_entry("status", proc_dir_entry); - remove_proc_entry(SYSTEM_NAME_STRING_LOWER, NULL); - #ifndef NO_CPU_SHUTDOWN // Unset the code callback set_fe_code_idle(0, CPUID); @@ -821,6 +233,9 @@ void cleanup_module (void) { printk("Setting stop_working_threads to 1\n"); // Stop the code and wait +#ifdef NO_CPU_SHUTDOWN + ret = kthread_stop(sthread); +#endif stop_working_threads = 1; msleep(1000); @@ -832,16 +247,12 @@ void cleanup_module (void) { // Unset the code callback set_fe_code_idle(0, CPUID); - printkl("Will bring back CPU %d\n", CPUID); + // printkl("Will bring back CPU %d\n", CPUID); msleep(1000); - // Unmask all masked epics channels - for (i = 0; i < ner; i++) { - *((char *)(((void *)pLocalEpics) + proc_epics[i].mask_idx)) = 0; - } // Bring the CPU back up cpu_up(CPUID); //msleep(1000); - printkl("Brought the CPU back up\n"); + printk("Brought the CPU back up\n"); #endif printk("Just before returning from cleanup_module for " SYSTEM_NAME_STRING_LOWER "\n"); diff --git a/src/fe/rcguser.c b/src/fe/rcguser.c index 77938c33a..64049a9b9 100644 --- a/src/fe/rcguser.c +++ b/src/fe/rcguser.c @@ -337,73 +337,7 @@ int main (int argc, char **argv) // Print out all the I/O information -#if 0 - printf("***************************************************************************\n"); - printf("%d ADC cards found\n",cdsPciModules.adcCount); - for(ii=0;ii<cdsPciModules.adcCount;ii++) - { - if(cdsPciModules.adcType[ii] == GSC_18AISS6C) - { - printf("\tADC %d is a GSC_18AISS6C module\n",ii); - printf("\t\tChannels = 6 \n"); - printf("\t\tFirmware Rev = %d \n\n",(cdsPciModules.adcConfig[ii] & 0xfff)); - } - if(cdsPciModules.adcType[ii] == GSC_16AI64SSA) - { - printf("\tADC %d is a GSC_16AI64SSA module\n",ii); - if((cdsPciModules.adcConfig[ii] & 0x10000) > 0) jj = 32; - else jj = 64; - printf("\t\tChannels = %d \n",jj); - printf("\t\tFirmware Rev = %d \n\n",(cdsPciModules.adcConfig[ii] & 0xfff)); - } - } - printf("***************************************************************************\n"); - printf("%d DAC cards found\n",cdsPciModules.dacCount); - for(ii=0;ii<cdsPciModules.dacCount;ii++) - { - if(cdsPciModules.dacType[ii] == GSC_18AO8) - { - printf("\tDAC %d is a GSC_18AO8 module\n",ii); - } - if(cdsPciModules.dacType[ii] == GSC_16AO16) - { - printf("\tDAC %d is a GSC_16AO16 module\n",ii); - if((cdsPciModules.dacConfig[ii] & 0x10000) == 0x10000) jj = 8; - if((cdsPciModules.dacConfig[ii] & 0x20000) == 0x20000) jj = 12; - if((cdsPciModules.dacConfig[ii] & 0x30000) == 0x30000) jj = 16; - printf("\t\tChannels = %d \n",jj); - if((cdsPciModules.dacConfig[ii] & 0xC0000) == 0x0000) - { - printf("\t\tFilters = None\n"); - } - if((cdsPciModules.dacConfig[ii] & 0xC0000) == 0x40000) - { - printf("\t\tFilters = 10kHz\n"); - } - if((cdsPciModules.dacConfig[ii] & 0xC0000) == 0x80000) - { - printf("\t\tFilters = 100kHz\n"); - } - if((cdsPciModules.dacConfig[ii] & 0x100000) == 0x100000) - { - printf("\t\tOutput Type = Differential\n"); - } - printf("\t\tFirmware Rev = %d \n\n",(cdsPciModules.dacConfig[ii] & 0xfff)); - } - } - printf("***************************************************************************\n"); - printf("%d DIO cards found\n",cdsPciModules.dioCount); - printf("***************************************************************************\n"); - printf("%d IIRO-8 Isolated DIO cards found\n",cdsPciModules.iiroDioCount); - printf("***************************************************************************\n"); - printf("%d IIRO-16 Isolated DIO cards found\n",cdsPciModules.iiroDio1Count); - printf("***************************************************************************\n"); - printf("%d Contec 32ch PCIe DO cards found\n",cdsPciModules.cDo32lCount); - printf("%d Contec PCIe DIO1616 cards found\n",cdsPciModules.cDio1616lCount); - printf("%d Contec PCIe DIO6464 cards found\n",cdsPciModules.cDio6464lCount); - printf("%d DO cards found\n",cdsPciModules.doCount); - printf("***************************************************************************\n"); -#endif + // Following section maps Reflected Memory, both VMIC hardware style and Dolphin PCIe network style. // Slave units will perform I/O transactions with RFM directly ie MASTER does not do RFM I/O. // Master unit only maps the RFM I/O space and passes pointers to SLAVES. -- GitLab