// Called from ISR context void SeqManager::doEndOfSequence(unsigned i) { assert(i<hw.size()); SeqHW* HW = hw[i]; HW->running = false; SoftSequence *seq = HW->loaded; if(!seq) return; if(seq->committed.mode==Single) { seq->is_enabled = false; } seq->numEnd++; scanIoRequest(seq->onEnd); if(!seq->is_insync) seq->sync(); if(seq->committed.mode==Single) scanIoRequest(seq->changed); }
int drvACQ196_set_data_parsing(ST_STD_device *pSTDdev) { ST_MASTER *pMaster = pSTDdev->pST_parentAdmin; pSTDdev->StatusDev &= ~TASK_SYSTEM_IDLE; pSTDdev->StatusDev |= TASK_POST_PROCESS; scanIoRequest(pSTDdev->ioScanPvt_status); printf("%s: start data parsing!\n", pSTDdev->taskName ); if( !proc_dataChannelization( pSTDdev ) ) { epicsPrintf("\n>>> drvACQ196_set_data_parsing(%s) : proc_dataChannelization() ... fail\n", pSTDdev->taskName); pSTDdev->StatusDev &= ~TASK_POST_PROCESS; pSTDdev->StatusDev |= DEV_CHANNELIZATION_FAIL; scanIoRequest(pSTDdev->ioScanPvt_status); pMaster->ErrorAdmin |= ERROR_AFTER_SHOT_PROCESS; scanIoRequest(pMaster->ioScanPvt_status); return WR_ERROR; } pSTDdev->StatusDev &= ~TASK_POST_PROCESS; pSTDdev->StatusDev |= TASK_SYSTEM_IDLE; scanIoRequest(pSTDdev->ioScanPvt_status); pSTDdev->StatusDev |= DEV_READY_TO_SAVE; /* if save PV put, then it cleared! */ return WR_OK; }
void evgSoftSeq::abort(bool callBack) { if(!isLoaded() && !isEnabled()) return; // Prevent re-trigger m_seqRam->setRunMode(Single); m_seqRam->setTrigSrc(None); m_seqRam->reset(); m_isEnabled = false; if(mrmEVGSeqDebug) fprintf(stderr, "SS%u: Abort!\n",m_id); scanIoRequest(ioscanpvt); if(callBack) { /* * Satisfy any callback request pending on irqStop0 or irqStop1 * recList. As no 'End of sequence' Intrrupt will be generated. */ if(m_seqRam->getId() == 0) callbackRequest(&m_owner->irqStop0_cb); else callbackRequest(&m_owner->irqStop1_cb); } }
void evgSoftSeq::load() { if(isLoaded()) return; /* * Assign the first avialable(unallocated) hardware sequenceRam to this soft * sequence if none is currently assingned. */ for(unsigned int i = 0; i < m_seqRamMgr->numOfRams(); i++) { evgSeqRam* seqRamIter = m_seqRamMgr->getSeqRam(i); if( seqRamIter->alloc(this) ) break; } if(isLoaded()) { // always need sync after loading m_isSynced = false; if(mrmEVGSeqDebug) fprintf(stderr, "SS%u: Load\n",m_id); sync(); scanIoRequest(ioscanpvt); } else { char err[80]; sprintf(err, "No SeqRam to load SoftSeq %d", getId()); std::string strErr(err); throw std::runtime_error(strErr); } }
LOCAL void drvTPG262_timeoutCallback(asynUser* pasynTPG262User) { asynTPG262UserData* pasynTPG262UserData = (asynTPG262UserData*) pasynTPG262User->userPvt; drvTPG262Config* pdrvTPG262Config = (drvTPG262Config*) pasynTPG262UserData->pdrvTPG262Config; TPG262_read* pTPG262_read = (TPG262_read*) pdrvTPG262Config->pTPG262_read; pdrvTPG262Config->status |= TPG262STATUS_SETUNIT_MASK; pdrvTPG262Config->status |= TPG262STATUS_TIMEOUT_MASK; pdrvTPG262Config->status |= TPG262STATUS_GETGID_MASK; pdrvTPG262Config->status |= TPG262STATUS_GETPROGVER_MASK; epicsMutexLock(pdrvTPG262Config->lock); pdrvTPG262Config->cbCount =0; pdrvTPG262Config->timeoutCount++; pTPG262_read->gst0 = TPG262GST_TIMEOUT; pTPG262_read->gst1 = TPG262GST_TIMEOUT; pTPG262_read->gst_str0 = tSenStList[vSenStList[pTPG262_read->gst0]]; pTPG262_read->gst_str1 = tSenStList[vSenStList[pTPG262_read->gst1]]; strcpy(pTPG262_read->gid_str0, TPG262GID_UNKNOWN_STR); strcpy(pTPG262_read->gid_str1, TPG262GID_UNKNOWN_STR); strcpy(pTPG262_read->progver_str, TPG262PROGVER_UNKNOWN_STR); epicsMutexUnlock(pdrvTPG262Config->lock); scanIoRequest(pdrvTPG262Config->ioScanPvt); return; }
static void devNI6123_AO_DAQ_MAX_VOLT(ST_execParam *pParam) { ST_MASTER *pMaster = get_master(); ST_STD_device *pSTDdev = (ST_STD_device*) ellFirst(pMaster->pList_DeviceTask); ST_NI6123 *pNI6123 = NULL; kLog (K_DATA,"[devNI6123_AO_DAQ_MAX_VOLT] minVolt(%f)\n", pParam->setValue); while(pSTDdev) { if (pSTDdev->StatusDev & TASK_ARM_ENABLED) { kLog (K_DATA,"[devNI6123_AO_DAQ_MAX_VOLT] %s: System is armed! \n", pSTDdev->taskName); notify_error (1, "System is armed!", pSTDdev->taskName ); } else { pNI6123 = pSTDdev->pUser; pNI6123->maxVal = pParam->setValue; scanIoRequest(pSTDdev->ioScanPvt_userCall); kLog (K_DATA,"[devNI6123_AO_DAQ_MAX_VOLT] task(%s) maxVolt(%.f)\n", pSTDdev->taskName, pNI6123->maxVal); } pSTDdev = (ST_STD_device*) ellNext(&pSTDdev->node); } }
static void checkMySync( ) { /* we use channel 0 on board 0 to check */ MY_BOARD_SOFTWARE *pBoardSoft = myBoard_getSoftwareBoard( 0 ); MY_RING_BUFFER *pRingBuffer = &(pBoardSoft->channel_buffer[0]); int resetting = 0; if (getWriteIndexOfMyRingBuffer( pRingBuffer ) == 0) { resetting = 1; } int i; for (i = 0; i < mySyncTagGetNumberUsed(); ++i) { MY_SYNC_T *pMySync = mySyncTagGetSync( i ); if (resetting) { pMySync->indexRead = 0; pMySync->indexNextRead = 0; } else { pMySync->indexRead = pMySync->indexNextRead; /* this will change indexNextRead if enough data */ if (readDataFromMyRingBuffer( pRingBuffer, pMySync->indexRead, &(pMySync->indexNextRead), pMySync->numNewNeed, NULL, 0, &(pMySync->numNewAvailable), &(pMySync->numWaiting) )) { scanIoRequest( pMySync->ioScanPvt ); } } } }
static void devNI6123_AO_DAQ_SAMPLEING_RATE(ST_execParam *pParam) { ST_MASTER *pMaster = get_master(); ST_STD_device *pSTDdev = (ST_STD_device*) ellFirst(pMaster->pList_DeviceTask); ST_NI6123 *pNI6123 = NULL; kLog (K_DATA,"[devNI6123_AO_DAQ_SAMPLEING_RATE] sampleRate(%f)\n", pParam->setValue); while(pSTDdev) { if (pSTDdev->StatusDev & TASK_ARM_ENABLED) { kLog (K_DATA,"[devNI6123_AO_DAQ_SAMPLEING_RATE] %s: System is armed! \n", pSTDdev->taskName); notify_error (1, "System is armed!", pSTDdev->taskName ); } else { pNI6123 = pSTDdev->pUser; if(pParam->setValue > pNI6123->sample_rateLimit){ /* Device Sampling Rate Limit Cut if User is over Sampling Rate Setting. */ pParam->setValue = pNI6123->sample_rateLimit; } else if(pParam->setValue <= 0){ pParam->setValue = 1; } pNI6123->sample_rate = pParam->setValue; scanIoRequest(pSTDdev->ioScanPvt_userCall); kLog (K_DATA,"[devNI6123_AO_DAQ_SAMPLEING_RATE] task(%s) sampleRate(%.f)\n", pSTDdev->taskName, pNI6123->sample_rate); } pSTDdev = (ST_STD_device*) ellNext(&pSTDdev->node); } }
/* auto Run function */ static void devNI6123_BO_AUTO_RUN(ST_execParam *pParam) { ST_MASTER *pMaster = get_master(); ST_STD_device *pSTDdev = (ST_STD_device*) ellFirst(pMaster->pList_DeviceTask); ST_NI6123 *pNI6123 = NULL; kLog (K_TRACE, "[devNI6123_BO_AUTO_RUN] auto_run(%f)\n", pParam->setValue); if( pMaster->StatusAdmin & TASK_WAIT_FOR_TRIGGER || pMaster->StatusAdmin & TASK_IN_PROGRESS ) { kLog (K_ERR, "System is running! (0x%x)\n", pMaster->StatusAdmin); notify_error (1, "System is running! (0x%x)\n", pMaster->StatusAdmin); return; } if(pParam->setValue) { if( !(pMaster->StatusAdmin & TASK_SYSTEM_IDLE) ) { kLog (K_ERR, "System is busy! (0x%x)\n", pMaster->StatusAdmin); notify_error (1, "System is busy! (0x%x)\n", pMaster->StatusAdmin); return; } #if 0 char strBuf[24]; float stopT1; /* remove this function because ECH has not LTU, so We donot use the DBproc_get function */ if( pSTDdev->ST_Base.opMode == OPMODE_REMOTE ){ DBproc_get (PV_LTU_TIG_T0_STR, strBuf); //Get T0 from LTU DBproc_put (PV_START_TIG_T0_STR, strBuf); //Set T0 from LTU sscanf(strBuf, "%f", &stopT1); stopT1 = pNI6123->sample_time - stopT1; sprintf(strBuf,"%f",stopT1); DBproc_put (PV_STOP_TIG_T1_STR, strBuf); //Set T0 from LTU } #endif while(pSTDdev) { pSTDdev->StatusDev |= TASK_STANDBY; pNI6123 = pSTDdev->pUser; pNI6123->auto_run_flag = 1; pSTDdev = (ST_STD_device*) ellNext(&pSTDdev->node); } } else if(!pParam->setValue) { while(pSTDdev) { pNI6123 = pSTDdev->pUser; pNI6123->auto_run_flag = 0; pSTDdev = (ST_STD_device*) ellNext(&pSTDdev->node); } pMaster->n8EscapeWhile = 0; epicsThreadSleep(3.0); pMaster->n8EscapeWhile = 1; admin_all_taskStatus_reset(); scanIoRequest(pMaster->ioScanPvt_status); } notify_refresh_master_status(); }
void Sim::run() { Guard G(lock); while(!stop) { if(!doSim) { UnGuard U(G); event.wait(); continue; } doSim = false; epicsTimeStamp start; epicsTimeGetCurrent(&start); try { std::auto_ptr<StateBase> state(machine->allocState()); machine->propagate(state.get()); valid = true; }catch(std::exception& e){ last_msg = e.what(); valid = false; } epicsTimeGetCurrent(&last_run); last_duration = epicsTimeDiffInSeconds(&last_run, &start); scanIoRequest(aftersim); } }
void func_acq196_OP_MODE(void *pArg, double arg1, double arg2) { ST_STD_device* pSTDdev = (ST_STD_device *)pArg; drvACQ196_status_reset(pSTDdev); scanIoRequest(pSTDdev->ioScanPvt_status); }
static void devNI6250_AO_DAQ_GAIN(ST_execParam *pParam) { ST_MASTER *pMaster = get_master(); ST_STD_device *pSTDdev = (ST_STD_device*) ellFirst(pMaster->pList_DeviceTask); ST_NI6250 *pNI6250 = NULL; kLog (K_MON, "[devNI6250_AO_DAQ_GAIN] gain(%f)\n", pParam->setValue); while(pSTDdev) { if (pSTDdev->StatusDev & TASK_ARM_ENABLED) { kLog (K_ERR, "[devNI6250_AO_DAQ_GAIN] %s: System is armed! \n", pSTDdev->taskName); notify_error (1, "System is armed!", pSTDdev->taskName ); } else { pNI6250 = pSTDdev->pUser; pNI6250->gain = pParam->setValue; scanIoRequest(pSTDdev->ioScanPvt_userCall); kLog (K_DEBUG, "[devNI6250_AO_DAQ_GAIN] task(%s) gain(%.f)\n", pSTDdev->taskName, pNI6250->gain); } pSTDdev = (ST_STD_device*) ellNext(&pSTDdev->node); } }
/** * @brief Thread function that periodically reads the scaler values * @param arg ignore. does not take arguments * @return nothing. */ void *thread_measure( void* arg) { int i; while( 1 ) { // Clear Counters for( i=0; i<n_vuproms; ++i) { start_measurement( &(vu[i]) ); } usleep( sleep_time ); // Save Counters for( i=0; i<n_vuproms; ++i) { stop_measurement( &(vu[i]) ); } // copy values for( i=0; i<n_vuproms; ++i) { save_values( &(vu[i]) ); } if( _iointr ) scanIoRequest( ioinfo ); } return NULL; }
int drvACQ196_notify_InitCondition(ST_STD_device *pSTDdev) { ST_ACQ196 *pAcq196 = (ST_ACQ196*)pSTDdev->pUser; if( (pAcq196->boardConfigure & ACQ196_SET_CLOCK_RATE) && (pAcq196->boardConfigure & ACQ196_SET_R_BITMASK) && (pAcq196->boardConfigure & ACQ196_SET_M_BITMASK) && (pAcq196->boardConfigure & ACQ196_SET_L_BITMASK) && (pAcq196->boardConfigure & ACQ196_SET_T0) && (pAcq196->boardConfigure & ACQ196_SET_T1) && (pAcq196->boardConfigure & ACQ196_SET_TAG) ) /* (pAcq196->boardConfigure & ACQ196_SET_SHOT_NUM) ) */ { if( pSTDdev->ST_Base.opMode == OPMODE_REMOTE ) pSTDdev->StatusDev |= TASK_STANDBY; else { if( pAcq196->boardConfigure & ACQ196_SET_SHOT_NUM) { pSTDdev->StatusDev |= TASK_STANDBY; /* printf(" %s: ready, %x\n", pSTDdev->taskName, pSTDdev->StatusDev ); */ } else { pSTDdev->StatusDev &= ~TASK_STANDBY; /* printf(" %s: not ready, %x\n", pSTDdev->taskName, pSTDdev->StatusDev ); */ } } } else{ pSTDdev->StatusDev &= ~TASK_STANDBY; } scanIoRequest(pSTDdev->ioScanPvt_status); /* notify_sys_ready(); */ notify_refresh_master_status(); return WR_OK; }
void simRegDevCallback(void* arg) { simRegDevMessage* msg = arg; regDevice *device = msg->device; regDevTransferComplete callback = msg->callback; int status; if (simRegDevDebug & (msg->isOutput ? DBG_OUT : DBG_IN)) printf ("simRegDevCallback %s %s: copy %u bytes * %"Z"u elements\n", msg->user, device->name, msg->dlen, msg->nelem); epicsMutexLock(device->lock); if (device->connected == 0) { status = S_dev_noDevice; } else { regDevCopy(msg->dlen, msg->nelem, msg->src, msg->dest, msg->pmask, device->swap); status = S_dev_success; } msg->next = device->msgFreelist[msg->prio]; device->msgFreelist[msg->prio] = msg; if (msg->isOutput) { /* We got new data: trigger all interested input records */ if (simRegDevDebug & DBG_OUT) printf ("simRegDevCallback %s %s: trigger input records\n", msg->user, device->name); scanIoRequest(device->ioscanpvt); } epicsMutexUnlock(device->lock); if (simRegDevDebug & (msg->isOutput ? DBG_OUT : DBG_IN)) printf ("simRegDevCallback %s %s: call back status=%d\n", msg->user, device->name, status); callback(msg->user, status); }
int simRegDevSetStatus( const char* name, int connected) { regDevice* device; if (!name) { printf ("usage: simRegDevSetStatus name, 0|1\n"); return S_dev_badArgument; } device = regDevFind(name); if (!device) { errlogSevPrintf(errlogFatal, "simRegDevSetStatus: %s not found\n", name); return S_dev_noDevice; } if (device->magic != MAGIC) { errlogSevPrintf(errlogFatal, "simRegDevSetStatus: %s is not a simRegDev\n", name); return S_dev_wrongDevice; } device->connected = connected; if (simRegDevDebug >= 1) printf ("simRegDevSetStatus %s: trigger input records\n", device->name); scanIoRequest(device->ioscanpvt); return S_dev_success; }
void setTimestamp(const double *arr, epicsUInt32 count) { const double tmult = getTimeScale(); times_t times(count); // check for monotonic // TODO: not handling overflow (HW supports controlled rollover w/ special 0xffffffff times) for(epicsUInt32 i=0; i<count; i++) { if(!finite(arr[i]) || arr[i]<0.0) throw std::runtime_error("times must be finite >=0"); times[i] = (arr[i]*tmult)+0.5; if(i>0 && times[i]<=times[i-1]) throw std::runtime_error("Non-monotonic timestamp array"); else if(times[i]==0xffffffff) throw std::runtime_error("Time overflow, rollover not supported"); } { SCOPED_LOCK(mutex); scratch.times.swap(times); is_committed = false; } DEBUG(4, ("Set times\n")); scanIoRequest(changed); }
static void devNI6123_AO_BEAM_PLUSE(ST_execParam *pParam) { ST_MASTER *pMaster = get_master(); ST_STD_device *pSTDdev = (ST_STD_device*) ellFirst(pMaster->pList_DeviceTask); ST_NI6123 *pNI6123 = NULL; kLog (K_TRACE, "[devNI6123_AO_BEAM_PLUSE] beam_pulse(%f)\n", pParam->setValue); while(pSTDdev) { if (pSTDdev->StatusDev & TASK_ARM_ENABLED) { kLog (K_ERR, "[devNI6123_AO_BEAM_PLUSE] %s: System is armed! \n", pSTDdev->taskName); notify_error (1, "System is armed!", pSTDdev->taskName ); } else { pNI6123 = pSTDdev->pUser; pNI6123->beam_pulse = pParam->setValue; scanIoRequest(pSTDdev->ioScanPvt_userCall); kLog (K_DEBUG, "[devNI6123_AO_BEAM_PLUSE] task(%s) pulse(%.f)\n", pSTDdev->taskName, pNI6123->beam_pulse); } pSTDdev = (ST_STD_device*) ellNext(&pSTDdev->node); } }
LOCAL void devCallback(void * drvPvt) { devPvt *pdevPvt; pdevPvt = (devPvt *)(*pabDrv->getUserPvt)(drvPvt); if(!pdevPvt) return; scanIoRequest(pdevPvt->ioscanpvt); }
/* Callback, registered with drvEtherIP, for input records. * Used _IF_ scan="I/O Event": * Driver has new value (or no value because of error), process record */ static void scan_callback(void *arg) { dbCommon *rec = (dbCommon *) arg; DevicePrivate *pvt = (DevicePrivate *)rec->dpvt; if (rec->tpro) printf("EIP scan_callback('%s')\n", rec->name); scanIoRequest(pvt->ioscanpvt); }
int simRegDevWrite( regDevice *device, size_t offset, unsigned int dlen, size_t nelem, void* pdata, void* pmask, int prio, regDevTransferComplete callback, const char* user) { if (!device || device->magic != MAGIC) { errlogSevPrintf(errlogMajor, "simRegDevWrite: illegal device handle\n"); return S_dev_wrongDevice; } if (device->connected == 0) { return S_dev_noDevice; } if (simRegDevDebug & DBG_OUT) { size_t n; printf ("simRegDevWrite %s %s:%"Z"u: %u bytes * %"Z"u elements, prio=%d\n", user, device->name, offset, dlen, nelem, prio); for (n=0; n<nelem && n<10; n++) { switch (dlen) { case 1: printf (" %02x",((epicsUInt8*)pdata)[n*dlen]); break; case 2: printf (" %04x",((epicsUInt16*)pdata)[n*dlen]); break; case 4: printf (" %08x",((epicsUInt32*)pdata)[n*dlen]); break; case 8: printf (" %08llx",((unsigned long long*)pdata)[n*dlen]); break; } } printf ("\n"); } if (nelem > 1 && device->lock) return simRegDevAsynTransfer(device, dlen, nelem, pdata, device->buffer+offset, pmask, prio, callback, user, TRUE); regDevCopy(dlen, nelem, pdata, device->buffer+offset, pmask, device->swap); /* We got new data: trigger all interested input records */ if (simRegDevDebug & DBG_OUT) printf ("simRegDevWrite %s: trigger input records\n", device->name); scanIoRequest(device->ioscanpvt); return S_dev_success; }
static void interruptCallbackAverage(void *drvPvt, asynUser *pasynUser, epicsFloat64 value) { devPvt *pPvt = (devPvt *)drvPvt; dbCommon *pr = pPvt->pr; aiRecord *pai = (aiRecord *)pr; ringBufferElement *rp; int numToAverage; static const char *functionName="interruptCallbackAverage"; asynPrint(pPvt->pasynUser, ASYN_TRACEIO_DEVICE, "%s %s::%s new value=%f\n", pr->name, driverName, functionName,value); if (!interruptAccept) return; epicsMutexLock(pPvt->devPvtLock); pPvt->numAverage++; pPvt->sum += value; /* We use the SVAL field to hold the number of values to average when SCAN=I/O Intr * We should be calling dbScanLock when accessing pPvt->isIOIntrScan and pai->sval but that leads to deadlocks * because we have the asynPortDriver lock in the driver, and we would be taking the scan lock * after the asynPortDriver lock, which is the opposite of normal record processing. * pPvt->isIOIntrScan is an int, so should be OK to read because write to it is atomic? * pai->sval is a double so it may not be completely safe to read without the lock? */ if ((pPvt->isIOIntrScan)) { numToAverage = (int)(pai->sval + 0.5); if (numToAverage < 1) numToAverage = 1; if (pPvt->numAverage >= numToAverage) { rp = &pPvt->ringBuffer[pPvt->ringHead]; rp->value = pPvt->sum/pPvt->numAverage; pPvt->numAverage = 0; pPvt->sum = 0.; rp->time = pasynUser->timestamp; rp->status = pasynUser->auxStatus; rp->alarmStatus = pasynUser->alarmStatus; rp->alarmSeverity = pasynUser->alarmSeverity; pPvt->ringHead = (pPvt->ringHead==pPvt->ringSize) ? 0 : pPvt->ringHead+1; if (pPvt->ringHead == pPvt->ringTail) { /* There was no room in the ring buffer. In the past we just threw away * the new value. However, it is better to remove the oldest value from the * ring buffer and add the new one. That way the final value the record receives * is guaranteed to be the most recent value */ pPvt->ringTail = (pPvt->ringTail==pPvt->ringSize) ? 0 : pPvt->ringTail+1; pPvt->ringBufferOverflows++; } /* End ring buffer full */ else { /* We only need to request the record to process if we added a new * element to the ring buffer, not if we just replaced an element. */ scanIoRequest(pPvt->ioScanPvt); } } /* End numAverage=SVAL, so time to compute average */ } /* End SCAN=I/O Intr */ else { pPvt->result.status |= pasynUser->auxStatus; pPvt->result.alarmStatus = pasynUser->alarmStatus; pPvt->result.alarmSeverity = pasynUser->alarmSeverity; } epicsMutexUnlock(pPvt->devPvtLock); }
void setTimestampResolution(epicsUInt32 val) { { SCOPED_LOCK(mutex); timeScale = val; } DEBUG(4, ("Set time scale\n")); scanIoRequest(changed); }
void evgSoftSeq::setRunMode(SeqRunMode runMode) { if(runMode != m_runMode) { m_runMode = runMode; m_isCommited = false; if(mrmEVGSeqDebug>1) fprintf(stderr, "SS%u: Update Mode\n",m_id); scanIoRequest(ioscanpvt); } }
void evgSoftSeq::pause() { if( m_seqRam && m_seqRam->isEnabled() ) { m_seqRam->disable(); m_isEnabled = false; if(mrmEVGSeqDebug) fprintf(stderr, "SS%u: Pause\n",m_id); scanIoRequest(ioscanpvt); } }
void evgSoftSeq::setTrigSrc(SeqTrigSrc trigSrc) { if(trigSrc != m_trigSrc) { m_trigSrc = trigSrc; m_isCommited = false; if(mrmEVGSeqDebug>1) fprintf(stderr, "SS%u: Update Trig\n",m_id); scanIoRequest(ioscanpvt); } }
static void interruptCallbackInput(void *drvPvt, asynUser *pasynUser, epicsInt32 value) { devInt32Pvt *pPvt = (devInt32Pvt *)drvPvt; dbCommon *pr = pPvt->pr; int count, size = sizeof(epicsInt32); if (pPvt->bipolar && (value & pPvt->signBit)) value |= ~pPvt->mask; asynPrint(pPvt->pasynUser, ASYN_TRACEIO_DEVICE, "%s devAsynInt32::interruptCallbackInput new value=%d\n", pr->name, value); /* There is a problem. A driver could be calling us with a value after * this record has registered for callbacks but before EPICS has set interruptAccept, * which means that scanIoRequest will return immediately. * This is very bad, because if we have pushed a value into the ring buffer * it won't get popped off because the record won't process. The values * read the next time the record processes would then be stale. * We previously worked around this problem by waiting here for interruptAccept. * But that does not work if the callback is coming from the thread that is executing * iocInit, which can happen with synchronous drivers (ASYN_CANBLOCK=0) that do callbacks * when a value is written to them, which can happen in initRecord for an output record. * Instead we just return. There will then be nothing in the ring buffer, so the first * read will do a read from the driver, which should be OK. */ if (!interruptAccept) return; /* Note that we put a lock around epicsRingBytesPut and Get because we potentially have * more than one reader, since the reader is whatever thread is processing the record */ epicsMutexLock(pPvt->mutexId); count = epicsRingBytesPut(pPvt->ringBuffer, (char *)&value, size); if (count != size) { /* There was no room in the ring buffer. In the past we just threw away * the new value. However, it is better to remove the oldest value from the * ring buffer and add the new one. That way the final value the record receives * is guaranteed to be the most recent value */ epicsInt32 dummy; count = epicsRingBytesGet(pPvt->ringBuffer, (char *)&dummy, size); if (count != size) { asynPrint(pPvt->pasynUser, ASYN_TRACE_ERROR, "%s devAsynInt32 interruptCallbackInput error, ring read failed\n", pPvt->pr->name); } count = epicsRingBytesPut(pPvt->ringBuffer, (char *)&value, size); if (count != size) { asynPrint(pPvt->pasynUser, ASYN_TRACE_ERROR, "%s devAsynInt32 interruptCallbackInput error, ring put failed\n", pPvt->pr->name); } pPvt->ringBufferOverflows++; } else { /* We only need to request the record to process if we added a * new element to the ring buffer, not if we just replaced an element. */ scanIoRequest(pPvt->ioScanPvt); } epicsMutexUnlock(pPvt->mutexId); }
void setTrigSrc(epicsUInt32 src) { DEBUG(4, ("Setting trig src %x\n", (unsigned)src)); { SCOPED_LOCK(mutex); scratch.src = src; is_committed = false; } DEBUG(4, ("Set trig src %x\n", (unsigned)src)); scanIoRequest(changed); }
static void xycom566isrcb(CALLBACK *cb) { xy566 *card; epicsUInt16 csr; epicsUInt16 datacnt[32]; epicsUInt16 dcnt; size_t i, ch; callbackGetUser(card,cb); epicsMutexMustLock(card->guard); /* clear number of data points */ memset(datacnt,0,sizeof(datacnt)); /* number of samples taken */ dcnt=READ16(card->base, XY566_RAM); if(dcnt>256){ /* Somehow the sequence was restart w/o resetting * the pointer, or changed by an outside program */ dcnt=256; printf("Data longer then expected\n"); } for(i=0;i<dcnt;i++){ ch=card->seq[i]&0x1f; card->data[ch][datacnt[ch]]=READ16(card->data_base, XY566_DOFF(i)); datacnt[ch]++; if( card->seq[i]&SEQ_END ) break; } /* reset pointers */ WRITE16(card->base, XY566_RAM, 0); WRITE8(card->base, XY566_SEQ, 0); csr=READ16(card->base, XY566_CSR); /* enable sequence controller */ csr|=XY566_CSR_SEQ; WRITE16(card->base, XY566_CSR, csr); scanIoRequest(card->seq_irq); epicsMutexUnlock(card->guard); }
void SoftSequence::load() { SCOPED_LOCK(mutex); DEBUG(3, ("Loading %c\n", hw ? 'L' : 'U') ); if(hw) {DEBUG(3, ("Skip\n")); return;} // find unused SeqHW { interruptLock L; is_insync = false; // paranoia for(size_t i=0, N=owner->hw.size(); i<N; i++) { SeqHW *temp = owner->hw[i]; if(temp && !temp->loaded) { temp->loaded = this; hw = temp; break; } } if(hw) { // paranoia: disable any external trigger mappings owner->mapTriggerSrc(hw->idx, 0x02000000); if(!hw->disarm()) sync(); } } if(!hw) { last_err = "All HW Seq. in use"; scanIoRequest(onErr); throw alarm_exception(MAJOR_ALARM, WRITE_ALARM); } scanIoRequest(changed); DEBUG(1, ("Loaded\n") ); }