/* This routine can be called from interrupt context */ int callbackRequest(CALLBACK *pcallback) { int priority; int pushOK; cbQueueSet *mySet; if (!pcallback) { epicsInterruptContextMessage("callbackRequest: pcallback was NULL\n"); return S_db_notInit; } priority = pcallback->priority; if (priority < 0 || priority >= NUM_CALLBACK_PRIORITIES) { epicsInterruptContextMessage("callbackRequest: Bad priority\n"); return S_db_badChoice; } mySet = &callbackQueue[priority]; if (mySet->queueOverflow) return S_db_bufFull; pushOK = epicsRingPointerPush(mySet->queue, pcallback); if (!pushOK) { char msg[48] = "callbackRequest: "; strcat(msg, threadNamePrefix[priority]); strcat(msg, " ring buffer full\n"); epicsInterruptContextMessage(msg); mySet->queueOverflow = TRUE; return S_db_bufFull; } epicsEventSignal(mySet->semWakeUp); return 0; }
void omsMAXv::InterruptHandler( void * param ) { omsMAXv* pController = (omsMAXv*) param; volatile struct MAXv_motor *pmotor = (MAXv_motor*) pController->getCardAddress();; STATUS1 status1_flag; static char errmsg[65]; status1_flag.All = pmotor->status1_flag.All; /* Motion done handling */ if (status1_flag.Bits.done != 0) epicsEventSignal(pController->pollEventId_); if (status1_flag.Bits.cmndError) { strcpy(errmsg, "\nomsMAXv::InterruptHandler: command error - Port: "); strncat(errmsg, pController->getPortName(), sizeof(errmsg)-strlen(errmsg)-2); strcat(errmsg,"\n"); epicsInterruptContextMessage(errmsg); } /* unset this bit to not clear the text_response bit */ if (status1_flag.Bits.text_response != 0) status1_flag.Bits.text_response = 0; /* Release IRQ's. Clear bits by writing a 1 */ pmotor->status1_flag.All = status1_flag.All; /* do a dummy read to ensure that all previous writes, which may * have been queued in the VME bridge chip get processed */ status1_flag.All = pmotor->status1_flag.All; }
epicsShareFunc int errlogSevVprintf( const errlogSevEnum severity,const char *pFormat,va_list pvar) { char *pnext; int nchar; int totalChar = 0; int isOkToBlock; if (epicsInterruptIsInterruptContext()) { epicsInterruptContextMessage ("errlogSevVprintf called from interrupt level\n"); return 0; } errlogInit(0); if (pvtData.atExit) return 0; isOkToBlock = epicsThreadIsOkToBlock(); pnext = msgbufGetFree(isOkToBlock); if (!pnext) return 0; nchar = sprintf(pnext, "sevr=%s ", errlogGetSevEnumString(severity)); pnext += nchar; totalChar += nchar; nchar = tvsnPrint(pnext, pvtData.maxMsgSize - totalChar - 1, pFormat, pvar); pnext += nchar; totalChar += nchar; if (pnext[-1] != '\n') { strcpy(pnext,"\n"); totalChar++; } msgbufSetSize(totalChar); return nchar; }
static void writeRegister(niport *pniport,int offset, epicsUInt8 value) { volatile epicsUInt8 *pregister = (epicsUInt8 *) (((char *)pniport->registers)+offset); if(ni1014Debug) { char message[100]; sprintf(message,"writeRegister pregister %p offset %x value %2.2x\n", pregister,offset,value); if(epicsInterruptIsInterruptContext()) { epicsInterruptContextMessage(message); } else { printf("%s",message); } } *pregister = value; /* * Must wait 5 ti9914 clock cycles between AUXMR commands * Documentation is confusing but experiments indicate that 6 microsecod wait * Is required. */ if (offset == AUXMR) microSecondDelay(6); }
epicsShareFunc int errlogSevPrintf( const errlogSevEnum severity,const char *pFormat, ...) { va_list pvar; int nchar; int isOkToBlock; if (epicsInterruptIsInterruptContext()) { epicsInterruptContextMessage ("errlogSevPrintf called from interrupt level\n"); return 0; } errlogInit(0); if (pvtData.sevToLog > severity) return 0; isOkToBlock = epicsThreadIsOkToBlock(); if (pvtData.atExit || (isOkToBlock && pvtData.toConsole)) { fprintf(pvtData.console, "sevr=%s ", errlogGetSevEnumString(severity)); va_start(pvar, pFormat); vfprintf(pvtData.console, pFormat, pvar); va_end(pvar); fflush(pvtData.console); } va_start(pvar, pFormat); nchar = errlogSevVprintf(severity, pFormat, pvar); va_end(pvar); return nchar; }
epicsShareFunc int errlogVprintf( const char *pFormat,va_list pvar) { int nchar; char *pbuffer; int isOkToBlock; if (epicsInterruptIsInterruptContext()) { epicsInterruptContextMessage ("errlogVprintf called from interrupt level\n"); return 0; } errlogInit(0); if (pvtData.atExit) return 0; isOkToBlock = epicsThreadIsOkToBlock(); pbuffer = msgbufGetFree(isOkToBlock); if (!pbuffer) { vfprintf(pvtData.console, pFormat, pvar); fflush(pvtData.console); return 0; } nchar = tvsnPrint(pbuffer, pvtData.maxMsgSize, pFormat?pFormat:"", pvar); if (pvtData.atExit || (isOkToBlock && pvtData.toConsole)) { fprintf(pvtData.console, "%s", pbuffer); fflush(pvtData.console); } msgbufSetSize(nchar); return nchar; }
void ni1014Err(void *pvt) { niport *pniport = (niport *)pvt; char message[50]; sprintf(message,"%s errorInterrupt\n",pniport->portName); epicsInterruptContextMessage(message); ni1014(pvt); }
epicsShareFunc int errlogPrintfNoConsole( const char *pFormat, ...) { va_list pvar; int nchar; if (epicsInterruptIsInterruptContext()) { epicsInterruptContextMessage ("errlogPrintfNoConsole called from interrupt level\n"); return 0; } errlogInit(0); va_start(pvar, pFormat); nchar = errlogVprintfNoConsole(pFormat, pvar); va_end(pvar); return nchar; }
static epicsUInt8 readRegister(niport *pniport, int offset) { volatile epicsUInt8 *pregister = (epicsUInt8 *) (((char *)pniport->registers)+offset); epicsUInt8 value; value = *pregister; if(ni1014Debug) { char message[100]; sprintf(message,"readRegister pregister %p offset %x value %2.2x\n", pregister,offset,value); if(epicsInterruptIsInterruptContext()) { epicsInterruptContextMessage(message); } else { printf("%s",message); } } return value; }
epicsShareFunc int errlogVprintfNoConsole( const char *pFormat,va_list pvar) { int nchar; char *pbuffer; if (epicsInterruptIsInterruptContext()) { epicsInterruptContextMessage ("errlogVprintfNoConsole called from interrupt level\n"); return 0; } errlogInit(0); if (pvtData.atExit) return 0; pbuffer = msgbufGetFree(1); if (!pbuffer) return 0; nchar = tvsnPrint(pbuffer, pvtData.maxMsgSize, pFormat?pFormat:"", pvar); msgbufSetSize(nchar); return nchar; }
void ni1014(void *pvt) { niport *pniport = (niport *)pvt; transferState_t state = pniport->transferState; epicsUInt8 isr1,isr2,octet; char message[80]; pniport->isr2 = isr2 = readRegister(pniport,ISR2); pniport->isr1 = isr1 = readRegister(pniport,ISR1); writeRegister(pniport,CSR1,2); /*acknowledge interrupt*/ if(isr2&SRQI) callbackRequest(&pniport->callback); if(isr1&ERR) { if(state!=transferStateIdle) { sprintf(pniport->errorMessage,"\n%s interruptHandler ERR state %d\n", pniport->portName,state); pniport->status = asynError; epicsEventSignal(pniport->waitForInterrupt); } goto exit; } switch(state) { case transferStateCmd: if(!isr2&CO) goto exit; if(pniport->bytesRemainingCmd == 0) { pniport->transferState = pniport->nextTransferState; if(pniport->transferState==transferStateIdle) { epicsEventSignal(pniport->waitForInterrupt); } else { writeRegister(pniport,AUXMR,AUXGTS); } break ; } octet = *pniport->nextByteCmd; writeRegister(pniport,CDOR,(epicsUInt8)octet); --(pniport->bytesRemainingCmd); ++(pniport->nextByteCmd); break; case transferStateWrite: if(!isr1&DO) goto exit; if(pniport->bytesRemainingWrite == 0) { pniport->transferState = transferStateIdle; writeRegister(pniport,AUXMR,AUXTCA); epicsEventSignal(pniport->waitForInterrupt); break ; } if(pniport->bytesRemainingWrite==1) writeRegister(pniport,AUXMR,AUXEOI); octet = *pniport->nextByteWrite; writeRegister(pniport,CDOR,(epicsUInt8)octet); --(pniport->bytesRemainingWrite); ++(pniport->nextByteWrite); break; case transferStateRead: if(!isr1&DI) break; octet = readRegister(pniport,DIR); *pniport->nextByteRead = octet; --(pniport->bytesRemainingRead); ++(pniport->nextByteRead); if((pniport->eos != -1 ) && (octet == pniport->eos)) pniport->eomReason |= ASYN_EOM_EOS; if(ENDRX&isr1) pniport->eomReason |= ASYN_EOM_END; if(pniport->bytesRemainingRead == 0) pniport->eomReason |= ASYN_EOM_CNT; if(pniport->eomReason) { pniport->transferState = transferStateIdle; writeRegister(pniport,AUXMR,AUXTCS); epicsEventSignal(pniport->waitForInterrupt); break; } writeRegister(pniport,AUXMR,AUXFH); break; case transferStateIdle: if(!isr1&DI) goto exit; octet = readRegister(pniport,DIR); sprintf(message,"%s ni1014IH transferStateIdle received %2.2x\n", pniport->portName,octet); epicsInterruptContextMessage(message); } exit: /* Force synchronization of VMEbus writes on PPC CPU boards. */ readRegister(pniport,ADSR); }
epicsShareFunc void errPrintf(long status, const char *pFileName, int lineno, const char *pformat, ...) { va_list pvar; char *pnext; int nchar; int totalChar=0; int isOkToBlock; char name[256]; if (epicsInterruptIsInterruptContext()) { epicsInterruptContextMessage("errPrintf called from interrupt level\n"); return; } errlogInit(0); isOkToBlock = epicsThreadIsOkToBlock(); if (status == 0) status = errno; if (status > 0) { errSymLookup(status, name, sizeof(name)); } if (pvtData.atExit || (isOkToBlock && pvtData.toConsole)) { if (pFileName) fprintf(pvtData.console, "filename=\"%s\" line number=%d\n", pFileName, lineno); if (status > 0) fprintf(pvtData.console, "%s ", name); va_start(pvar, pformat); vfprintf(pvtData.console, pformat, pvar); va_end(pvar); fputc('\n', pvtData.console); fflush(pvtData.console); } if (pvtData.atExit) return; pnext = msgbufGetFree(isOkToBlock); if (!pnext) return; if (pFileName) { nchar = sprintf(pnext,"filename=\"%s\" line number=%d\n", pFileName, lineno); pnext += nchar; totalChar += nchar; } if (status > 0) { nchar = sprintf(pnext,"%s ",name); pnext += nchar; totalChar += nchar; } va_start(pvar, pformat); nchar = tvsnPrint(pnext, pvtData.maxMsgSize - totalChar - 1, pformat, pvar); va_end(pvar); if (nchar>0) { pnext += nchar; totalChar += nchar; } strcpy(pnext, "\n"); totalChar++ ; /*include the \n */ msgbufSetSize(totalChar); }
// Called from ISR context void SoftSequence::sync() { DEBUG(3, ("Syncing %c\n", is_insync ? 'Y' : 'N') ); if(is_insync) {DEBUG(3, ("Skip\n")); return;} assert(hw); if(nat_ioread32(hw->ctrlreg)&EVG_SEQ_RAM_RUNNING) { // we may still be _ENABLED at this point, but the trigger source is set to // Disabled, so this makes no difference. epicsInterruptContextMessage("SoftSequence::sync() while running\n"); return; } // At this point the sequencer is not running and effectively disabled. // From paranoia, reset it anyway nat_iowrite32(hw->ctrlreg, hw->ctrlreg_hw | EVG_SEQ_RAM_RESET); hw->ctrlreg_user &= ~(EVG_SEQ_RAM_REPEAT_MASK|EVG_SEQ_RAM_SRC_MASK); switch(committed.mode) { case Single: hw->ctrlreg_user |= EVG_SEQ_RAM_SINGLE; break; case Normal: hw->ctrlreg_user |= EVG_SEQ_RAM_NORMAL; break; } epicsUInt8 src; // default to disabled switch(owner->type) { case SeqManager::TypeEVG: src = 31; break; case SeqManager::TypeEVR: src = 63; break; default: return; } // paranoia: disable any external trigger mappings owner->mapTriggerSrc(hw->idx, 0x02000000); // map trigger source codes // MSB governs the type of mapping switch(committed.src&0xff000000) { case 0x00000000: // raw mapping DEBUG(5, (" Raw mapping %x\n", committed.src)); // LSB is code src = committed.src&0xff; break; case 0x01000000: // software trigger mapping DEBUG(5, (" SW mapping %x\n", committed.src)); // ignore 0x00ffffff switch(owner->type) { case SeqManager::TypeEVG: src = 17+hw->idx; break; case SeqManager::TypeEVR: src = 61; break; } break; case 0x02000000: // external trigger DEBUG(5, (" EXT mapping %x\n", committed.src)); if(owner->type==SeqManager::TypeEVG) { // pass through to sub-class owner->mapTriggerSrc(hw->idx, committed.src); src = 24+hw->idx; } break; case 0x03000000: // disable trigger DEBUG(5, (" NO mapping %x\n", committed.src)); // use default break; default: DEBUG(0, ("unknown sequencer trigger code %08x\n", (unsigned)committed.src)); break; } DEBUG(5, (" Trig Src %x\n", src)); hw->ctrlreg_user |= src; // write out the RAM volatile epicsUInt32 *ram = static_cast<volatile epicsUInt32 *>(hw->rambase); for(size_t i=0, N=committed.codes.size(); i<N; i++) { nat_iowrite32(ram++, committed.times[i]); nat_iowrite32(ram++, committed.codes[i]); if(committed.codes[i]==0x7f) break; } { epicsUInt32 ctrl = hw->ctrlreg_hw = hw->ctrlreg_user; if(is_enabled) ctrl |= EVG_SEQ_RAM_ARM; else ctrl |= EVG_SEQ_RAM_DISABLE; // paranoia DEBUG(3, (" SeqCtrl %x\n", ctrl)); nat_iowrite32(hw->ctrlreg, ctrl); } is_insync = true; DEBUG(3, ("In Sync\n") ); }