//File: RodModule.cxx // $Header: /afs/cern.ch/user/s/sctpixel/private/cvsroot//RodDaq/RodCrate/RodModule.cxx,v 1.69 2004/09/09 16:15:36 tmeyer Exp $ #include "RodModule.h" #include "BocCard.h" //! Namespace for the common routines for SCT and PIXEL ROD software. namespace SctPixelRod { // Flag to force endian-ness swap before calls to HPI registers. This should be // a temporary patch. static long endianSwap = 0; static const long rodInitTimeout = 10; //******************************Class NoImageFile************************** // // Description: // This class is thrown if If we try to load a binary image for a master or // slave DSP and the file is not found // // Author(s): // Tom Meyer (meyer@iastate.edu) - originator // Constructors. Use defaults for destructor, copy, and assignment. NoImageFile::NoImageFile(std::string descriptor, std::string fileName) : BaseException(descriptor) { m_fileName = fileName; setType(NOIMAGEFILE); } void NoImageFile::what(std::ostream& os) { os << "NoImageFile Exception. Descriptor, File name: " << getDescriptor() << ";" << m_fileName << std::endl; } //******************************Class HpiException************************** // // Description: // This class is thrown if an error in an HPI read/write operation is detected. // // Author(s): // Tom Meyer (meyer@iastate.edu) - originator // Constructors. Use defaults for destructor, copy, and assignment. HpiException::HpiException( std::string descriptor, unsigned long calcAddr, unsigned long readAddr) : BaseException(descriptor) { m_calcAddr = calcAddr; m_readAddr = readAddr; setType(HPI); } void HpiException::what(std::ostream& os) { os << "HpiException: " << getDescriptor() << std::endl; os << "Calculated Address:" << std::hex << getCalcAddr() << std::endl; os << "Read Address:" << std::hex << getReadAddr() << std::endl; } //***************************Class RodException************************** // // Description: // This class is thrown if an error in a ROD operation is detected. // // Author(s): // Tom Meyer (meyer@iastate.edu) - originator // Constructors. Use defaults for destructor, copy, and assignment. RodException::RodException( std::string descriptor) : BaseException(descriptor) { m_numData = 0; m_data1 = m_data2 = 0; setType(ROD); } RodException::RodException( std::string descriptor, unsigned long data1) : BaseException(descriptor) { m_numData = 1; m_data1 = data1; m_data2 = 0; setType(ROD); } RodException::RodException( std::string descriptor, unsigned long data1, unsigned long data2) : BaseException(descriptor) { m_numData = 2; m_data1 = data1; m_data2 = data2; setType(ROD); } void RodException::what(std::ostream& os) { unsigned long numData; numData = getNumData(); os << "RodException: " << getDescriptor() << std::endl; if (0 == numData) return; os << "Data1:" << getData1() << std::endl; if (1 == numData) return; os << "Data2:" << getData2() << std::endl; } //********************************Class RodModule*************************** // // Description: // This is a derived class providing the software interface for VME ROD modules. // // Author(s): // Tom Meyer (meyer@iastate.edu) - originator //---------------------------------Constructor------------------------------ /* This is the only constructor to use. */ RodModule::RodModule( unsigned long baseAddr, unsigned long mapSize, VmeInterface & ourInterface, long numSlaves) throw (RodException&, VmeException&) : VmeModule(baseAddr, mapSize, ourInterface) { m_slot = baseAddr>>24; m_serialNumber = 0xFFFFFFFF; // Will be overwritten during init m_revision = 0; // Will be overwritten during init m_numSlaves = numSlaves; m_finBufferSize = 4096; m_masterImageName = std::string(""); m_myOutList = 0; try { m_myVmePort = new VmePort(m_baseAddress, m_mapSize, VmeInterface::A32, m_ourInterface); } catch (std::bad_alloc & ba) { throw RodException("Failed to get VME Port."); } for (long i=0; i<4; i++) { m_slaveIpramName[i]= std::string(""); m_slaveIdramName[i]= std::string(""); m_slaveExtName[i]= std::string(""); } m_myOutList = 0; m_myMdspMap = new MdspMemoryMap(); m_mySdspMap = new SdspMemoryMap(); for (long i=0; isetExceptionTrapping(true); m_myBoc = new BocCard(*this); } //---------------------------------Destructor------------------------------ /* Be sure to delete all VME Ports and other "new" things in constructor. */ RodModule::~RodModule() { delete(m_myVmePort); delete m_myBoc; m_myVmePort = 0; delete m_myMdspMap; m_myMdspMap = 0; delete m_mySdspMap; m_mySdspMap = 0; for (int i=0; iwrite32(FPGA_CONTROL_REG_REL_ADDR[0], fpgaReset); //FPGA config // Test that FPGA has finished its reset rodRegValue = 0; startTime = time(NULL); bool change = false; do { rodRegValue = m_myVmePort->read32(FPGA_STATUS_REG_REL_ADDR[0]); if ((time(NULL)-startTime) > DSP_RESET_TIMEOUT) { throw RodException("FPGA reset timeout in initialize(), DSP_RESET_TIMEOUT=30", rodRegValue); } // Check for configuration active if ((rodRegValue&0x20) == 0x20) change = true; } while (((rodRegValue&0x3f) != 0x1f) || change==false); // Wait a bit in between reconfigure and MDSP reset sleep(500); rodRegValue = readRodStatusReg(0); m_myVmePort->write32(FPGA_CONTROL_REG_REL_ADDR[2], rodReset); // MDSP reset // Test that MDSP has finished its reset rodRegValue = 0; startTime = clock(); do { rodRegValue = m_myVmePort->read32(FPGA_STATUS_REG_REL_ADDR[2]); if ((clock()-startTime)/CLOCKS_PER_SEC > DSP_RESET_TIMEOUT) { throw RodException("DSP reset timeout in initialize(), DSP_RESET_TIMEOUT=", (long)DSP_RESET_TIMEOUT); } } while ((rodRegValue&0x3e) != 0x3e); rodRegValue = readRodStatusReg(0); // Wait an extra half a second sleep(500); } // Read ROD serial number m_serialNumber = m_myVmePort->read32(FPGA_STATUS_REG_REL_ADDR[6]); if (endianSwap) m_serialNumber = endianReverse32(m_serialNumber); // Temporary (I hope) m_revision = (m_serialNumber&0x00ff0000)>>16; m_serialNumber = m_serialNumber & 0x3ff; // Mask to get 10 least significant bits // Initialize Master HPIC register to set half-word order unsigned long hpicValue = 0x00010001; hpiLoad(HPIC, hpicValue); hpicReadback = hpiFetch(HPIC); // for debugging sleep(100); // Wait for MasterDSP init for (long i=0; ; ++i) { if (readRodStatusBit(0, SR_RUNNING)) { break; } if (i>rodInitTimeout*10) throw RodException("Master DSP init timed out. Tries, Limit:", i, rodInitTimeout); sleep(100); } mdspStart = mdspSingleRead(MEMORY_MAP_REG); mdspMapSize = mdspSingleRead(mdspStart); sdspStart = m_myMdspMap->load(mdspStart, m_myVmePort); sdspEnd = m_mySdspMap->load(sdspStart, m_myVmePort); structSize = m_myMdspMap->structureSize(); dspDiff=(sdspEnd-mdspStart)/4; for (int i=0; i< N_TXT_BUFFS; i++) { m_textBuff[i] = (unsigned long *)m_myMdspMap->txtBuffer(i); m_textBufferSize[i] = m_myMdspMap->txtBufferSize(i); m_textData[i] = new char[m_textBufferSize[i]]; } // Reinitialize state variables m_myTextState = TEXT_IDLE; m_myPrimState = PRIM_IDLE; return; } //---------------------------------reset------------------------------------ /* This method resets the ROD. */ void RodModule::reset() throw (RodException&, VmeException &) { // Reset all FPGAs and DSPs (bit 7 = 0x80) const unsigned long rodResetValue = 0x00000040; unsigned long rodReset; unsigned long rodRegValue; unsigned long idramBase, idramSize; clock_t startTime; if (endianSwap) { rodReset = endianReverse32(rodResetValue); } else { rodReset = rodResetValue; } m_myVmePort->write32(FPGA_CONTROL_REG_REL_ADDR[2], rodReset); sleep(10000); rodRegValue = 0; startTime = clock(); do { rodRegValue = m_myVmePort->read32(FPGA_STATUS_REG_REL_ADDR[2]); if ((clock()-startTime)/CLOCKS_PER_SEC > DSP_RESET_TIMEOUT) { throw RodException("DSP reset timeout in reset() (first call), DSP_RESET_TIMEOUT=", (long)DSP_RESET_TIMEOUT); } } while (rodRegValue != 0x3e); // Clear IDRAM unsigned long * buff; try { // Allocate a buffer of zeros idramSize = m_myMdspMap->idramSize(); buff = new unsigned long[idramSize/sizeof(long)]; for(unsigned int i=0; i= m_numSlaves)) throw RodException( "Slave Number out of Range. slaveNumber, m_numSlaves:", slaveNumber, m_numSlaves); // Set HPIC registers to make first halfword the most significant slvIpramAddr = m_mySdspMap->ipram(); slvHpiLoad(SLAVE_HPIC_BASE, hpicValue, slaveNumber); readBack = slvHpiFetch(SLAVE_HPIC_BASE, slaveNumber); // Load the memory images and remember the file names slvIpramAddr = m_mySdspMap->ipram(); loadSlaveImage(ipramFile, slvIpramAddr, slaveNumber, opt); m_slaveIpramName[slaveNumber] = ipramFile; slvIdramAddr = m_mySdspMap->idram(); loadSlaveImage(idramFile, slvIdramAddr, slaveNumber, opt); m_slaveIdramName[slaveNumber] = idramFile; slvXcodeAddr = m_mySdspMap->xcode(); loadSlaveImage(extFile, slvXcodeAddr, slaveNumber, opt); m_slaveExtName[slaveNumber] = extFile; // Send the START_SLAVE_EXECUTING primitive. Do the primList dialog synchronously startSlave(slaveNumber); // Check that slave has finished its reset rodRegValue = 0; startTime = clock(); do { rodRegValue = m_myVmePort->read32(FPGA_STATUS_REG_REL_ADDR[2]); if ((clock()-startTime)/CLOCKS_PER_SEC > DSP_RESET_TIMEOUT) { throw RodException("DSP reset timeout in initSlaveDsp(), DSP_RESET_TIMEOUT=", (long)DSP_RESET_TIMEOUT); } } while (rodRegValue != 0x3e); return; } //------------------------------loadSlaveImage----------------------------- void RodModule::loadSlaveImage(const std::string & fileName, const unsigned long address, const long slaveNum, char opt) throw (NoImageFile&, RodException&, VmeException &) { long numWords; unsigned long readBack; int fileSize, i; const unsigned long DSP_BUSY_MASK=0x00000002; std::ifstream fin; // Cannot load image if slave is running. Check it and throw a rodException if it is readBack = slvHpiFetch(SLAVE_HPIC_BASE, slaveNum); if (readBack & DSP_BUSY_MASK) throw RodException( "loadSlaveImage tried to load to a running SDSP. slavenum = ", slaveNum); fin.open(fileName.c_str(),std::ios::binary); if (fin.is_open()) { // Get size of file fin.seekg(0, std::ios::end); // go to end of file fileSize = fin.tellg(); // file size is current location fin.seekg(0, std::ios::beg); // go back to beginning of file // Create buffer and fill it with file contents char * buffer; try { buffer = new char[fileSize]; } catch (std::bad_alloc & ba) { throw RodException( "primLoadSlaveImage buffer failed to allocate. buffer, fileSize:", (unsigned long)buffer, (unsigned long)fileSize); } fin.read(buffer, fileSize); // Use RW_SLAVE_MEMORY to transfer buffer into slave DSP memory long* writeSlvBuff; numWords = (fileSize+3)/4 + 5; writeSlvBuff = new long[numWords]; writeSlvBuff[0] = slaveNum; writeSlvBuff[1] = 0; writeSlvBuff[2] = address; writeSlvBuff[3] = DEFAULT; writeSlvBuff[4] = numWords; long tempWord; for (i = 0; i< numWords-5; i++) { tempWord = 0; tempWord = tempWord | (buffer[(i)*4+3]&0xff)<<24; tempWord = tempWord | (buffer[(i)*4+2]&0xff)<<16; tempWord = tempWord | (buffer[(i)*4+1]&0xff)<<8; tempWord = tempWord | (buffer[(i)*4]&0xff); writeSlvBuff[i+5] = tempWord; } RodPrimitive* slvRWPrim; slvRWPrim = new RodPrimitive(numWords+4, 1, RW_SLAVE_MEMORY, R_RW_SLAVE_MEMORY, writeSlvBuff); synchSendPrim(*slvRWPrim); delete [] writeSlvBuff; delete slvRWPrim; // Retrieve output buffer, if there is one RodOutList* outList = getOutList(); if (outList) { /* UINT32 outListLength = UINT32(outList->getLength()); unsigned long* outBody = outList->getBody(); UINT32 outLength = UINT32(outBody[0]); UINT32 outIndex = UINT32(outBody[1]); UINT32 outNumPrims = outBody[2]; UINT32 outPrimVersion = outBody[3]; UINT32 primLength = outBody[4]; UINT32 primIndex = outBody[5]; UINT32 primId = outBody[6]; UINT32 primVersion = outBody[7]; */ deleteOutList(); } // Read back buffer for verification if 'v' option was given if (opt=='v') { char* buffer2; try { buffer2 = new char[fileSize]; } catch (std::bad_alloc & ba) { throw RodException( "loadSlaveImage buffer2 failed to allocate. buffer, fileSize:", (unsigned long)buffer, (unsigned long)fileSize); } long * readSlvBuff; readSlvBuff = new long[numWords]; readSlvBuff[0] = slaveNum; readSlvBuff[1] = 1; readSlvBuff[2] = address; readSlvBuff[3] = DEFAULT; readSlvBuff[4] = numWords; slvRWPrim = new RodPrimitive(numWords+4, 1, RW_SLAVE_MEMORY, R_RW_SLAVE_MEMORY, readSlvBuff); synchSendPrim(*slvRWPrim); delete [] readSlvBuff; // Retrieve output buffer - there should be only one primitive in the reply list RodOutList* outList = getOutList(); if (outList) { // UINT32 outListLength = UINT32(outList->getLength()); unsigned long* outBody = outList->getBody(); UINT32 outLength = UINT32(outBody[0]); // UINT32 outIndex = UINT32(outBody[1]); // UINT32 outNumPrims = outBody[2]; // UINT32 outPrimVersion = outBody[3]; // UINT32 primLength = outBody[4]; // UINT32 primIndex = outBody[5]; // UINT32 primId = outBody[6]; // UINT32 primVersion = outBody[7]; int fileSize2 = (outLength-15)*4; if (fileSize2 != fileSize) throw RodException("primLoadSlaveImage read back wrong file size; expected, got =", fileSize, fileSize2); char tempChar0, tempChar1, tempChar2, tempChar3; for (int i=0; i<((fileSize+3)/4); i++) { tempWord = outBody[i+8]; tempChar0 = tempWord & 0x000000ff; tempChar1 = (tempWord & 0x0000ff00)>>8; tempChar2 = (tempWord & 0x00ff0000)>>16; tempChar3 = (tempWord & 0xff000000)>>24; buffer2[4*i] = tempChar0; buffer2[4*i+1] = tempChar1; buffer2[4*i+2] = tempChar2; buffer2[4*i+3] = tempChar3; } for (int i=0; isendPrimList(&primList); } catch (BaseException &h) { std::cout << h; }; // Wait for ROD to begin executing and then wait for it to finish executing // Check for error messages in text buffer and read them out if they exist. // Note: this is the synchronous way to do it. In general, it is better to do it // asynchronously. do { returnPState = this->primHandler(); returnTState = this->textHandler(); // Use while to print out multiple buffers while (returnTState == TEXT_RQ_SET) { do { returnTState = this->textHandler(); } while (returnTState != TEXT_READOUT); this->getTextBuffer(myTextBuffer, myTextLength, myTextType); this->clearTextBuffer(); for (int i=0; itextHandler(); } } while (returnPState != PRIM_EXECUTING); do { try { returnPState = this->primHandler(); } catch (RodException &r) { std::cout << r.getDescriptor() <<", " << r.getData1() << ", " << r.getData2() << '\n'; } } while (returnPState != PRIM_WAITING && returnPState != PRIM_IDLE); delete [] myTextBuffer; // Found by valgrind return; } //---------------------------------sendPrimList------------------------------- void RodModule::sendPrimList(RodPrimList *l) throw(PrimListException &, VmeException &) { unsigned long * buffAddr; unsigned long primBuffer, primBufferSize; long buffCount; primBuffer = m_myMdspMap->primBuffer(); primBufferSize = m_myMdspMap->primBufferSize(); if (!l->getBuffer()) { l->bufferBuild(); }; buffCount = l->getBufferLength(); if(abs(buffCount) > primBufferSize) { throw PrimListException("PrimList is bigger than DSP buffer", buffCount, primBufferSize); } buffAddr = l->getBuffer(); mdspBlockWrite(primBuffer, buffAddr, buffCount); m_myPrimState = PRIM_LOADED; return; } //---------------------------------primHandler------------------------------- PrimState RodModule::primHandler() throw(RodException &, VmeException &) { long wordCount; unsigned long status; unsigned long* buffptr; unsigned long replyBuffer; replyBuffer = m_myMdspMap->replyBuffer(); switch (m_myPrimState) { case PRIM_LOADED: { if (0==getDspAck()) { setInListReady(); m_myPrimState = PRIM_EXECUTING; }; break; }; case PRIM_EXECUTING: { try { status = readRodStatusRegSafe(0); } catch (VmeException ex) { std::cout << "RodModule::primHandler: Warning : BUS error reading status reg" << std::endl; break; } if (1==getDspAck()) { if (status >> TEXT_BUFF_NOT_EMPTY[0]) { // throw RodException ("Error buffer not empty in primHandler(PRIM_EXECUTING)"); } if (1==readRodStatusBit(0,OUTLIST_READY)) { // read buffer size hpiLoad(HPIA, replyBuffer); wordCount = hpiFetch(HPID_NOAUTO); // create new OutList object. Note that this object persists until it is deleted // in deleteOutList. The pointer in outList dies when this routine exists but // the object itself persists in memory until deleted. By copying the pointer // value in the address "outList" to m_myOutList, we keep knowledge of where the // object is an may continue to use it until it is deleted. RodOutList* outList; try { outList = new RodOutList(wordCount); } catch (std::bad_alloc & ba) { throw RodException("Outlist creation failed. WordCount=", wordCount); } if (0==outList->getBody()) throw RodException( "Outlist failed to allocate body array.WordCount=", wordCount); // This is where the value of m_myOutList gets set to the value of outList. this->setOutList(outList); // fill OutList object buffptr = m_myOutList->getBody(); mdspBlockRead(replyBuffer, buffptr, wordCount); m_myPrimState = PRIM_WAITING; } else m_myPrimState = PRIM_IDLE; clearVmeCommandRegBit(INLISTRDY); } break; }; default: { break; }; }; return m_myPrimState; }; //--------------------------------deleteOutList-------------------------------- void RodModule::deleteOutList() { delete m_myOutList; m_myOutList = 0; return; }; //---------------------------------textHandler------------------------------- TextBuffState RodModule::textHandler() throw(VmeException &) { unsigned long regValue; unsigned long dataPtr; long txtLength, txtLength1, txtLength2, txtWords; switch (m_myTextState) { case TEXT_IDLE: { regValue = readRodStatusReg(0) & SR_TEXT_MASK; if (0==regValue) return m_myTextState; // Quick return if no text for (long i=0; i<4; i++) { if (regValue & SR_TEXT_BIT_MASK[i]) { m_textType = (TEXT_BUFFER_TYPE)i; setVmeCommandRegBit(TEXT_BUFF_READ_REQ[m_textType]); sleep(10); m_myTextState = TEXT_RQ_SET; return m_myTextState; }; } break; }; case TEXT_RQ_SET: { if (readRodStatusReg(0) & SR_TEXT_BIT_MASK[m_textType]) { return m_myTextState; }; hpiLoad( HPIA, (unsigned long)m_textBuff[m_textType]); m_txtBuffer.dataEnd = hpiFetch(HPID_AUTO); m_txtBuffer.readIndx = hpiFetch(HPID_AUTO); m_txtBuffer.writeIndx = hpiFetch(HPID_AUTO); m_txtBuffer.mode = hpiFetch(HPID_AUTO); m_txtBuffer.overwrite = hpiFetch(HPID_AUTO); m_txtBuffer.overflow = hpiFetch(HPID_AUTO); m_txtBuffer.wrap = hpiFetch(HPID_AUTO); m_txtBuffer.state = hpiFetch(HPID_AUTO); m_txtBuffer.id = hpiFetch(HPID_AUTO); m_txtBuffer.data = (char *)hpiFetch(HPID_AUTO); dataPtr = (unsigned long)m_txtBuffer.data; // If there was a wrap-around we need to read two blocks, otherwise only one if (m_txtBuffer.readIndx < m_txtBuffer.writeIndx) { // No wrap txtLength = m_txtBuffer.writeIndx - m_txtBuffer.readIndx; txtWords = (txtLength+3)/4; // Convert char count to words mdspBlockRead(dataPtr, (unsigned long *)m_textData[m_textType], txtWords); } else { // Wrap txtLength1 = m_textBufferSize[m_textType] - m_txtBuffer.readIndx; txtLength2 = m_txtBuffer.writeIndx; txtWords = (txtLength1+3)/4 + (txtLength2+3)/4; mdspBlockRead(dataPtr+4*m_txtBuffer.readIndx, (unsigned long *)m_textData[m_textType], txtWords); mdspBlockRead(dataPtr, ((unsigned long *)m_textData[m_textType]+4*txtLength1), txtWords); txtLength = txtLength1 + txtLength2; }; clearVmeCommandRegBit(TEXT_BUFF_READ_REQ[m_textType]); sleep(10); m_myTextState = TEXT_READOUT; m_txtBuffer.state = txtLength; return m_myTextState; break; }; default: { return m_myTextState; break; }; }; return m_myTextState; }; //-----------------------------getTextBuffer------------------------------- void RodModule::getTextBuffer(char* buffer, long & length, TEXT_BUFFER_TYPE & type) { length = (m_txtBuffer.state+3)/4; type = (TEXT_BUFFER_TYPE)m_textType; for (int i=0; iwrite32(hpiReg, hpiValue); }; //--------------------------------hpiFetch------------------------------------- unsigned long RodModule::hpiFetch(unsigned long hpiReg) throw(VmeException &){ unsigned long hpiValue; hpiValue=m_myVmePort->read32(hpiReg); if (endianSwap) hpiValue = endianReverse32(hpiValue); return hpiValue; }; //-----------------------------mdspSingleRead--------------------------------- unsigned long RodModule::mdspSingleRead(const unsigned long dspAddr) throw(VmeException &) { unsigned long value; // Load the DSP address into the HPIA register hpiLoad(HPIA, dspAddr); // Do the read value = m_myVmePort->read32(HPID_NOAUTO); if (endianSwap) { value = endianReverse32(value); } return value; }; //------------------------------mdspSingleWrite------------------------------------ void RodModule::mdspSingleWrite(unsigned long dspAddr, unsigned long buffer) throw(VmeException &) { // Load the HPID address into the HPIA register hpiLoad(HPIA, dspAddr); // Do the write if (endianSwap) { buffer = endianReverse32(buffer); } m_myVmePort->write32(HPID_NOAUTO, buffer); return; }; //--------------------------readRodStatusRegSafe------------------------------ unsigned long RodModule::readRodStatusRegSafe(long regNumber) throw(VmeException &) { unsigned long hpiValue = STATUS_REG[regNumber]; unsigned long regValue; if (endianSwap) hpiValue = endianReverse32(hpiValue); m_myVmePort->writeS32(HPIA, hpiValue); // Do the read regValue = m_myVmePort->readS32(HPID_NOAUTO); if (endianSwap) { regValue = endianReverse32(regValue); } return regValue; }; //-----------------------------mdspBlockRead--------------------------------- void RodModule::mdspBlockRead(const unsigned long dspAddr, unsigned long buffer[], const long wordCount, HpidMode mode) throw (HpiException &, VmeException &) { unsigned long hpidAddr; long myCount, localCount, blockWordCount, wordIncr; // Determine the HPI mode to use. switch (mode) { case AUTO: hpidAddr= HPID_AUTO; break; case NO_AUTO: hpidAddr = HPID_NOAUTO; break; case DYNAMIC: default: if (wordCount == 1){ hpidAddr = HPID_NOAUTO; } else { hpidAddr = HPID_AUTO; }; break; }; // Load the DSP address into the HPIA register hpiLoad(HPIA, dspAddr); // Check if wordcount is odd and, if so, first do a single word read. localCount = wordCount; wordIncr = 0; if (wordCount%2 !=0) { buffer[0] = m_myVmePort->read32(hpidAddr); wordIncr = 1; localCount -= 1; } // Check to see that we don't access too large a block. // MAX_HPID_WORD_ELEMENTS is defined in RodVmeAddresses.h blockWordCount = std::min(localCount, MAX_HPID_WORD_ELEMENTS); // Set up the transfer as a series of block transfers for (myCount=localCount; myCount>0; myCount-=blockWordCount, wordIncr+=blockWordCount) { // Recheck each block blockWordCount = std::min(myCount, MAX_HPID_WORD_ELEMENTS); // Do the transfer for this block // Block reads are being done in hardware as from 10 June 03. m_myVmePort->blockRead32(hpidAddr, buffer+wordIncr, blockWordCount*4); // Use this code if you have problems with the hardware block transfers /* for (int i=0; iread32(hpidAddr); } if (endianSwap) { for (int i=0; iwrite32(hpidAddr, buffer[0]); wordIncr = 1; localCount -= 1; } // Check to see that we don't access too large a block. // MAX_HPID_WORD_ELEMENTS is defined in vmeAddressMap.h blockWordCount = std::min(wordCount, MAX_HPID_WORD_ELEMENTS); // Set up the transfer as a series of block transfers for (myCount=localCount; myCount>0; myCount-=blockWordCount, wordIncr+=blockWordCount) { // Recheck each block blockWordCount = std::min(myCount, MAX_HPID_WORD_ELEMENTS); // Do the transfer for this block if (endianSwap) { for (int i=0; iblockWrite32(hpidAddr, &buffer[wordIncr], blockWordCount*4); // Use this code if harfdware block transfers are a problem. /* for (int i=0; iwrite32(hpidAddr, buffer[wordIncr+i]); } */ } return; }; //-----------------------------mdspBlockDump-------------------------------- void RodModule::mdspBlockDump(const unsigned long firstAddress, const unsigned long lastAddress, const std::string & fileName) throw(RodException &, VmeException &) { long numBytes; std::ofstream fout; numBytes = lastAddress - firstAddress + 1; fout.open(fileName.c_str(), std::ios::binary); if (fout.is_open()) { unsigned long * buffer; try { buffer = new unsigned long[numBytes]; } catch (std::bad_alloc & ba) { throw RodException( "mdspBlockDump failed to allocate buffer; buffer size in bytes=", numBytes); } mdspBlockRead(firstAddress, buffer, numBytes/4); fout.write((char*)buffer, numBytes); fout.close(); delete [] buffer; } else { throw RodException("mdspBlockDump failed to open file"); } return; } //--------------------------------slvHpiLoad----------------------------------- void RodModule::slvHpiLoad(unsigned long hpiReg, unsigned long hpiValue, long slaveNum) throw(VmeException &) { unsigned long address; address = hpiReg + slaveNum*SLAVE_HPI_OFFSET; mdspSingleWrite(address, hpiValue); }; //------------------------------slvHpiFetch------------------------------------ unsigned long RodModule::slvHpiFetch(unsigned long hpiReg, long slaveNum) throw(VmeException &) { unsigned long hpiValue; unsigned long address; address = hpiReg + slaveNum*SLAVE_HPI_OFFSET; hpiValue=mdspSingleRead(address); return hpiValue; }; //-------------------------------slvHpiSingleRead--------------------------------- unsigned long RodModule::slvHpiSingleRead(unsigned long dspAddr, long slaveNum ) throw(VmeException &, RodException &) { unsigned long slvHpia, slvHpid; unsigned long value; slvHpia = SLAVE_HPIA_BASE + slaveNum*SLAVE_HPI_OFFSET; slvHpid = SLAVE_HPID_NOAUTO_BASE + slaveNum*SLAVE_HPI_OFFSET; // Check that address is not in forbidden area as per TI errata doc SPRZ191F, p. 11 if ((dspAddr >= 0x60000000) && (dspAddr <= 0x7FFFFFFF)) throw RodException( "Slave address is in forbidden range of 0x60000000 to 0x7FFFFFFF; address =", dspAddr); // Load the DSP address into the HPIA register mdspSingleWrite(slvHpia, dspAddr); // Do the read value = mdspSingleRead(slvHpid); return value; }; //------------------------------slvHpiSingleWrite------------------------------------ void RodModule::slvHpiSingleWrite(unsigned long dspAddr, unsigned long buffer, long slaveNum) throw(VmeException &, RodException &) { unsigned long slvHpia, slvHpid; slvHpia = SLAVE_HPIA_BASE + slaveNum*SLAVE_HPI_OFFSET; slvHpid = SLAVE_HPID_NOAUTO_BASE + slaveNum*SLAVE_HPI_OFFSET; // Check that address is not in forbidden area as per TI errata doc SPRZ191F, p. 11 if ((dspAddr >= 0x60000000) && (dspAddr <= 0x7FFFFFFF)) throw RodException( "Slave address is in forbidden range of 0x60000000 to 0x7FFFFFFF; address =", dspAddr); mdspSingleWrite(slvHpia, dspAddr); // Do the write mdspSingleWrite(slvHpid, buffer); return; }; //-----------------------------slvHpiBlockRead--------------------------------- void RodModule::slvHpiBlockRead(const unsigned long dspAddr, unsigned long buffer[], const long wordCount, long slaveNum, HpidMode mode) throw (HpiException &, VmeException &, RodException &) { unsigned long hpidAddr, dspAddrLocal; long myCount, blockWordCount, wordIncr; unsigned long slvHpia, slvHpidAuto, slvHpidNoAuto; // Check that starting address is not in forbidden area as per TI errata doc SPRZ191F, p. 11 if ((dspAddr >= 0x60000000) && (dspAddr <= 0x7FFFFFFF)) throw RodException( "Slave start address is in forbidden range of 0x60000000 to 0x7FFFFFFF; address =", dspAddr); // Check that ending address is not in forbidden area as per TI errata doc SPRZ191F, p. 11 unsigned long endAddr = dspAddr + 4*wordCount; if ((endAddr >= 0x60000000) && (endAddr <= 0x7FFFFFFF)) throw RodException( "Slave stop address is in forbidden range of 0x60000000 to 0x7FFFFFFF; address =", endAddr); // Check that addresses do not straddle the forbidden area as per TI errata doc SPRZ191F, p. 11 if ((dspAddr < 0x60000000) && (endAddr > 0x7FFFFFFF)) throw RodException( "Block of slave addresses straddles forbidden range of 0x60000000 to 0x7FFFFFFF; addresses =", dspAddr, endAddr); slvHpia = SLAVE_HPIA_BASE + slaveNum*SLAVE_HPI_OFFSET; slvHpidAuto = SLAVE_HPID_AUTO_BASE + slaveNum*SLAVE_HPI_OFFSET; slvHpidNoAuto = SLAVE_HPID_NOAUTO_BASE + slaveNum*SLAVE_HPI_OFFSET; // Determine the HPI mode to use. switch (mode) { case AUTO: hpidAddr= slvHpidAuto; break; case NO_AUTO: hpidAddr = slvHpidNoAuto; break; case DYNAMIC: default: if (wordCount == 1){ hpidAddr = slvHpidNoAuto; } else { hpidAddr = slvHpidAuto; }; break; }; // TI Errata SPRZ191F, p. 17, requires that every autoincrement read/write be terminated with a fixed // mode read/write. This routine has been modified to comply with this. long modCount = wordCount -1; if (modCount == 0) modCount = 1; // Load the DSP address into the HPIA register mdspSingleWrite(slvHpia, dspAddr); // Check to see that we don't access too large a block. HPID has 20 bits of // address space available. MAX_HPID_WORD_ELEMENTS is defined in RodVmeAddresses.h blockWordCount = std::min(modCount, MAX_HPID_WORD_ELEMENTS); // Set up the transfer as a series of block transfers for (myCount=modCount, wordIncr=0; myCount>0; myCount-=blockWordCount, wordIncr+=blockWordCount) { // Recheck each block blockWordCount = std::min(myCount, MAX_HPID_WORD_ELEMENTS); // Do the transfer for this block dspAddrLocal = dspAddr+ (4*wordIncr); mdspBlockRead(hpidAddr, &buffer[wordIncr], blockWordCount, NO_AUTO); } // Do the final fixed-mode transfer if (hpidAddr == slvHpidAuto) { hpidAddr = slvHpidNoAuto; mdspSingleWrite(slvHpia, modCount*4); buffer[modCount] = mdspSingleRead(hpidAddr); } return; }; //------------------------------slvHpiBlockWrite----------------------------------- void RodModule::slvHpiBlockWrite(unsigned long dspAddr, unsigned long buffer[], long wordCount, long slaveNum, HpidMode mode) throw (HpiException &, VmeException &, RodException &) { unsigned long hpidAddr, dspAddrLocal; long myCount, blockWordCount, wordIncr; unsigned long slvHpia, slvHpidAuto, slvHpidNoAuto; // Check that starting address is not in forbidden area as per TI errata doc SPRZ191F, p. 11 if ((dspAddr >= 0x60000000) && (dspAddr <= 0x7FFFFFFF)) throw RodException( "Slave start address is in forbidden range of 0x60000000 to 0x7FFFFFFF; address =", dspAddr); unsigned long endAddr = dspAddr + 4*wordCount; // Check that ending address is not in forbidden area as per TI errata doc SPRZ191F, p. 11 if ((endAddr >= 0x60000000) && (endAddr <= 0x7FFFFFFF)) throw RodException( "Slave stop address is in forbidden range of 0x60000000 to 0x7FFFFFFF; address =", endAddr); // Check that addresses do not straddle the forbidden area as per TI errata doc SPRZ191F, p. 11 if ((dspAddr < 0x60000000) && (endAddr > 0x7FFFFFFF)) throw RodException( "Block of slave addresses straddles forbidden range of 0x60000000 to 0x7FFFFFFF; addresses =", dspAddr, endAddr); slvHpia = SLAVE_HPIA_BASE + slaveNum*SLAVE_HPI_OFFSET; slvHpidAuto = SLAVE_HPID_AUTO_BASE + slaveNum*SLAVE_HPI_OFFSET; slvHpidNoAuto = SLAVE_HPID_NOAUTO_BASE + slaveNum*SLAVE_HPI_OFFSET; // Load the initial dsp address into the HPIA register mdspSingleWrite(slvHpia, dspAddr); // Determine the HPI mode to use. switch (mode) { case AUTO: hpidAddr= slvHpidAuto; break; case NO_AUTO: hpidAddr = slvHpidNoAuto; break; case DYNAMIC: default: if (wordCount == 1){ hpidAddr = slvHpidNoAuto; } else { hpidAddr = slvHpidAuto; }; break; }; // TI Errata SPRZ191F, p. 17, requires that every autoincrement read/write be terminated with a fixed // mode read/write. This routine has been modified to comply with this. long modCount = wordCount -1; if (modCount == 0) modCount = 1; // Check to see that we don't access too large a block. HPID has 20 bits of // address space available. MAX_HPID_WORD_ELEMENTS is defined in vmeAddressMap.h blockWordCount = std::min(modCount, MAX_HPID_WORD_ELEMENTS); // Set up the transfer as a series of block transfers for (myCount=modCount, wordIncr=0; myCount>0; myCount-=blockWordCount, wordIncr+=blockWordCount) { // Recheck each block blockWordCount = std::min(myCount, MAX_HPID_WORD_ELEMENTS); // Do the transfer for this block dspAddrLocal = dspAddr+ (4*wordIncr); mdspBlockWrite(hpidAddr, &buffer[wordIncr], blockWordCount, NO_AUTO); } // If autoincrement was used, do the final fixed-mode transfer if (hpidAddr == slvHpidAuto) { hpidAddr = slvHpidNoAuto; mdspSingleWrite(slvHpia, modCount*4); mdspSingleWrite(hpidAddr, buffer[modCount]); } return; }; //-------------------------------slvSingleRead--------------------------------- unsigned long RodModule::slvSingleRead(unsigned long dspAddr, long slaveNum ) throw(VmeException &, RodException &) { unsigned long slvHpia, slvHpid; unsigned long value; long numWords; slvHpia = SLAVE_HPIA_BASE + slaveNum*SLAVE_HPI_OFFSET; slvHpid = SLAVE_HPID_NOAUTO_BASE + slaveNum*SLAVE_HPI_OFFSET; // Check that address is not in forbidden area as per TI errata doc SPRZ191F, p. 11 if ((dspAddr >= 0x60000000) && (dspAddr <= 0x7FFFFFFF)) throw RodException( "Slave address is in forbidden range of 0x60000000 to 0x7FFFFFFF; address =", dspAddr); // Use RW_SLAVE_MEMORY to read slave DSP memory long* writeSlvBuff; numWords = 1; writeSlvBuff = new long[numWords+5]; writeSlvBuff[0] = slaveNum; writeSlvBuff[1] = 1; writeSlvBuff[2] = dspAddr; writeSlvBuff[3] = DEFAULT; writeSlvBuff[4] = numWords; writeSlvBuff[5] = 0; RodPrimitive* slvRWPrim; slvRWPrim = new RodPrimitive(numWords+9, 1, RW_SLAVE_MEMORY, R_RW_SLAVE_MEMORY, writeSlvBuff); synchSendPrim(*slvRWPrim); delete [] writeSlvBuff; delete slvRWPrim; // Get reply buffer and extract the value RodOutList* outList = getOutList(); if (outList) { unsigned long* outBody = outList->getBody(); value = outBody[8]; deleteOutList(); } else { throw RodException("No outList in slvPrimSingleRead"); } return value; }; //------------------------------slvSingleWrite------------------------------------ void RodModule::slvSingleWrite(unsigned long dspAddr, unsigned long buffer, long slaveNum) throw(VmeException &, RodException &) { unsigned long slvHpia, slvHpid; long numWords; slvHpia = SLAVE_HPIA_BASE + slaveNum*SLAVE_HPI_OFFSET; slvHpid = SLAVE_HPID_NOAUTO_BASE + slaveNum*SLAVE_HPI_OFFSET; // Check that address is not in forbidden area as per TI errata doc SPRZ191F, p. 11 if ((dspAddr >= 0x60000000) && (dspAddr <= 0x7FFFFFFF)) throw RodException( "Slave address is in forbidden range of 0x60000000 to 0x7FFFFFFF; address =", dspAddr); // Use RW_SLAVE_MEMORY to wrtie to slave DSP memory long* writeSlvBuff; numWords = 1; writeSlvBuff = new long[numWords+5]; writeSlvBuff[0] = slaveNum; writeSlvBuff[1] = 0; writeSlvBuff[2] = dspAddr; writeSlvBuff[3] = DEFAULT; writeSlvBuff[4] = numWords; writeSlvBuff[5] = buffer; RodPrimitive* slvRWPrim; slvRWPrim = new RodPrimitive(numWords+9, 1, RW_SLAVE_MEMORY, R_RW_SLAVE_MEMORY, writeSlvBuff); synchSendPrim(*slvRWPrim); delete [] writeSlvBuff; delete slvRWPrim; return; }; //-----------------------------slvBlockRead--------------------------------- void RodModule::slvBlockRead(const unsigned long dspAddr, unsigned long buffer[], const long wordCount, long slaveNum, HpidMode mode) throw (HpiException &, VmeException &, RodException &) { long numWords; // Check that starting address is not in forbidden area as per TI errata doc SPRZ191F, p. 11 if ((dspAddr >= 0x60000000) && (dspAddr <= 0x7FFFFFFF)) throw RodException( "Slave start address is in forbidden range of 0x60000000 to 0x7FFFFFFF; address =", dspAddr); // Check that ending address is not in forbidden area as per TI errata doc SPRZ191F, p. 11 unsigned long endAddr = dspAddr + 4*wordCount; if ((endAddr >= 0x60000000) && (endAddr <= 0x7FFFFFFF)) throw RodException( "Slave stop address is in forbidden range of 0x60000000 to 0x7FFFFFFF; address =", endAddr); // Check that addresses do not straddle the forbidden area as per TI errata doc SPRZ191F, p. 11 if ((dspAddr < 0x60000000) && (endAddr > 0x7FFFFFFF)) throw RodException( "Block of slave addresses straddles forbidden range of 0x60000000 to 0x7FFFFFFF; addresses =", dspAddr, endAddr); // Use RW_SLAVE_MEMORY to read slave DSP memory long* writeSlvBuff; numWords = wordCount; writeSlvBuff = new long[5]; writeSlvBuff[0] = slaveNum; writeSlvBuff[1] = 1; writeSlvBuff[2] = dspAddr; writeSlvBuff[3] = DEFAULT; writeSlvBuff[4] = numWords; RodPrimitive* slvRWPrim; slvRWPrim = new RodPrimitive(9, 1, RW_SLAVE_MEMORY, R_RW_SLAVE_MEMORY, writeSlvBuff); synchSendPrim(*slvRWPrim); delete [] writeSlvBuff; delete slvRWPrim; // Get reply buffer and extract the value RodOutList* outList = getOutList(); if (outList) { unsigned long* outBody = outList->getBody(); for (int i=0; i< numWords; i++) { buffer[i] = outBody[i+8]; } deleteOutList(); } else { throw RodException("No outList in slvPrimBlockRead"); } return; }; //------------------------------slvBlockWrite----------------------------------- void RodModule::slvBlockWrite(unsigned long dspAddr, unsigned long buffer[], long wordCount, long slaveNum, HpidMode mode) throw (HpiException &, VmeException &, RodException &) { long numWords; // Check that starting address is not in forbidden area as per TI errata doc SPRZ191F, p. 11 if ((dspAddr >= 0x60000000) && (dspAddr <= 0x7FFFFFFF)) throw RodException( "Slave start address is in forbidden range of 0x60000000 to 0x7FFFFFFF; address =", dspAddr); unsigned long endAddr = dspAddr + 4*wordCount; // Check that ending address is not in forbidden area as per TI errata doc SPRZ191F, p. 11 if ((endAddr >= 0x60000000) && (endAddr <= 0x7FFFFFFF)) throw RodException( "Slave stop address is in forbidden range of 0x60000000 to 0x7FFFFFFF; address =", endAddr); // Check that addresses do not straddle the forbidden area as per TI errata doc SPRZ191F, p. 11 if ((dspAddr < 0x60000000) && (endAddr > 0x7FFFFFFF)) throw RodException( "Block of slave addresses straddles forbidden range of 0x60000000 to 0x7FFFFFFF; addresses =", dspAddr, endAddr); // Use RW_SLAVE_MEMORY to write to slave DSP memory long* writeSlvBuff; numWords = wordCount; writeSlvBuff = new long[numWords+5]; writeSlvBuff[0] = slaveNum; writeSlvBuff[1] = 0; writeSlvBuff[2] = dspAddr; writeSlvBuff[3] = DEFAULT; writeSlvBuff[4] = numWords; for (int i=0; iwrite32(FPGA_CONTROL_REG_REL_ADDR[2], value); sleep(4000); rodRegValue = 0; startTime = clock(); do { rodRegValue = m_myVmePort->read32(FPGA_STATUS_REG_REL_ADDR[2]); if ((clock()-startTime)/CLOCKS_PER_SEC > DSP_RESET_TIMEOUT) { throw RodException("DSP reset timeout in resetMasterDsp(), DSP_RESET_TIMEOUT=", (long)DSP_RESET_TIMEOUT); } } while (rodRegValue != 0x3e); rodRegValue = readRodStatusReg(0); return; }; //------------------------------resetSlaveDsp-------------------------------- void RodModule::resetSlaveDsp(long slaveNumber) throw(RodException&, VmeException &) { unsigned long value=0; unsigned long rodRegValue; clock_t startTime; setBit(&value, 2+slaveNumber); if (endianSwap) { value = endianReverse32(value); } m_myVmePort->write32(FPGA_CONTROL_REG_REL_ADDR[2], value); sleep(4000); rodRegValue = 0; startTime = clock(); do { rodRegValue = m_myVmePort->read32(FPGA_STATUS_REG_REL_ADDR[2]); if ((clock()-startTime)/CLOCKS_PER_SEC > DSP_RESET_TIMEOUT) { throw RodException("DSP reset timeout in resetSlaveDsp(), DSP_RESET_TIMEOUT=", (long)DSP_RESET_TIMEOUT); } } while (rodRegValue != 0x3e); return; }; //------------------------------resetAllDsps-------------------------------- void RodModule::resetAllDsps() throw(RodException &, VmeException &) { unsigned long value=0; unsigned long rodRegValue; clock_t startTime; setBit(&value, 6); if (endianSwap) { value = endianReverse32(value); } m_myVmePort->write32(FPGA_CONTROL_REG_REL_ADDR[2], value); sleep(4000); rodRegValue = 0; startTime = clock(); do { rodRegValue = m_myVmePort->read32(FPGA_STATUS_REG_REL_ADDR[2]); if ((clock()-startTime)/CLOCKS_PER_SEC > DSP_RESET_TIMEOUT) { throw RodException("DSP reset timeout in resetAllDsps(), DSP_RESET_TIMEOUT=", (long)DSP_RESET_TIMEOUT); } } while (rodRegValue != 0x3e); return; }; //-------------------------------chipEraseHpi--------------------------------- void RodModule::chipEraseHpi() throw(VmeException &) { unsigned long value = 0x10; unsigned long flashBase; flashBase = m_myMdspMap->flashBase(); // Commands 1 to 5 commonEraseCommandsHpi(flashBase); // Command 6 mdspSingleWrite(flashBase+(0x5555<<2), value); // Wait for operation to complete sleep(CHIP_ERASE_TIME_MS); return; }; //--------------------------------sectorErase--------------------------------- void RodModule::sectorErase(unsigned long sectorBaseAddress) throw(RodException &, VmeException &) { unsigned long flashBaseAddress, valueD32; bool busyBit; // Get flash base address switch (m_revision) { case 0x0e: case 0x0f: flashBaseAddress = FPGA_FLASH_REL_ADDR_REVE; break; case 0x0b: case 0x0c: default: if ((sectorBaseAddressFPGA_FLASH_2_BOTTOM+FLASH_MEMORY_SIZE)) { throw RodException("Flash sector base addr out of range, sectorBaseAddress=", sectorBaseAddress); } if (sectorBaseAddressread32(FPGA_STATUS_REG_REL_ADDR[4]); busyBit = readBit(valueD32, 3); } while (busyBit); break; case 0x0b: case 0x0c: default: sleep(SECTOR_ERASE_TIME_MS); break; } return; }; //---------------_-------------writeByteToFlash------------------------------- void RodModule::writeByteToFlash(unsigned long address, UINT8 data) throw (RodException &, VmeException &) { UINT8 readData; clock_t startTime; // start time for DQ7 data polling, in seconds long updateAddress; if (data!=0xFF) { // if erased, don't rewrite. 0xFF is default after erasing // write data vmeWriteElementFlash(data, address, WRITE_DATA_HANDSHAKE_BIT); updateAddress = 0; } else { updateAddress = 1; } // Wait for operation to complete - data polling startTime = clock(); while(1) { readData = readByteFromFlash(address, updateAddress); if (readData == data) return; else if((clock()-startTime)/CLOCKS_PER_SEC > FLASH_TIMEOUT) { throw RodException("Flash timeout in writeByteToFlash, FLASH_TIMEOUT=", (long)FLASH_TIMEOUT); } } return; }; //----------------------------writeBlockToFlash------------------------------- void RodModule::writeBlockToFlash(unsigned long address, UINT8 *data, unsigned long numBytes) throw(RodException &, VmeException &) { unsigned long index, sectorSize; switch (m_revision) { case 0x0e: case 0x0f: sectorSize = FLASH_SECTOR_SIZE_REVE; break; case 0x0b: case 0x0c: default: sectorSize = FLASH_SECTOR_SIZE; break; } for (index=0; index> 8; break; case 2: busyVal = busyVal >> 16; break; case 3: busyVal = busyVal >> 24; break; default: break; } busyVal = busyVal & 0x000000FF; if (busyVal == longVal) break; } }; }; // Verification words = (numBytes+3)/4; // round up UINT8 *buffer; try { buffer = new UINT8[words*4]; } catch (std::bad_alloc & ba) { throw RodException("writeBlockToFlashHpi unable to get buffer."); } mdspBlockRead(address, (unsigned long*)buffer, words); for (index=0; indexwrite32(FPGA_CONTROL_REG_REL_ADDR[4], address); } // Set rd bit setBit(&handshakeBitValue, READ_HANDSHAKE_BIT); m_myVmePort->write32(FPGA_CONTROL_REG_REL_ADDR[3], handshakeBitValue); // Wait for valid data startTime = clock(); while (1) { commandReg = m_myVmePort->read32(FPGA_CONTROL_REG_REL_ADDR[3]); if (0==readBit(commandReg, READ_HANDSHAKE_BIT)) break; if ((clock()-startTime)>FLASH_TIMEOUT) throw RodException( "Timeout in readByteFromFlash. Address=", address); } // Read valid data valueD32 = m_myVmePort->read32(FPGA_STATUS_REG_REL_ADDR[7]); dataByte = (UINT8)(valueD32&0xFF); return dataByte; }; //---------------------------vmeWriteElementFlash------------------------------ void RodModule::vmeWriteElementFlash(UINT8 value, unsigned long address, long handshakeBit) throw (RodException &, VmeException &) { unsigned long ctrlReg4Val; // address(23:0) + data(31:24) unsigned long commandReg; clock_t startTime; unsigned long handshakeBitValue=0; ctrlReg4Val = (value<<24)| address; m_myVmePort->write32(FPGA_CONTROL_REG_REL_ADDR[4], ctrlReg4Val); // Set wr bit setBit(&handshakeBitValue, handshakeBit); m_myVmePort->write32(FPGA_CONTROL_REG_REL_ADDR[3], handshakeBitValue); // Wait for ack startTime = clock(); while(1) { commandReg = m_myVmePort->read32(FPGA_CONTROL_REG_REL_ADDR[3]); if (0==readBit(commandReg, handshakeBit)) break; if ((clock()-startTime)>FLASH_TIMEOUT) throw RodException( "Timeout in vmeWriteElementFlash. Address, value=", address, (unsigned long)value); } return; }; //-----------------------------readBlockFromFlash------------------------------ void RodModule::readBlockFromFlash(unsigned long address, UINT8 *buffer, unsigned long numBytes) throw(RodException &, VmeException &) { unsigned long index; for (index=0; index> 8; outVal |= (inVal & 0xff000000) >> 24; return outVal; }; } // End namespace SctPixelRod //------------------------- Overload insertion operators "<<" ------------------------- /* This overloaded operator lets us use cout to print the status of the ROD */ std::ostream& operator<<(std::ostream& os, SctPixelRod::RodModule& rod) { os << "Slot: " << rod.getSlot() << std::endl; os << "Serial Number(hex):" << std::hex << rod.getSerialNumber() << std::endl; os << "Number of slave DSPs: " << rod.getNumSlaves() << std::endl; os << "Status registers[0-2](hex): "; try { for (int i=0; i<3; i++) { os << std::hex << rod.readRodStatusReg(i) << " "; } os << std::endl; } catch (SctPixelRod::VmeException &) { os << "VmeException while reading ROD status registers. " << std::endl; } os << "Command registers[0-1](hex): "; try { for (int i=0; i<2; i++) { os << std::hex << rod.readRodCommandReg(i) << " "; } os << std::endl; } catch (SctPixelRod::VmeException &) { os << "VmeException while reading ROD command registers. " << std::endl; } os << "Primitive state: " << rod.getPrimState() << " Text State: " << rod.getTextState() << std::dec << std::endl; return os; } /* This overloaded operator lets us use cout to print the RodException information. We use the virtual * what() method to get the information from the derived class instead of BaseException. */ /* std::ostream& operator<<(std::ostream& os, SctPixelRod::RodException& rodEx) { return rodEx.what(os, rodEx); } */ /* This overloaded operator lets us use cout to print the HpiException information */ /* std::ostream& operator<<(std::ostream& os, SctPixelRod::HpiException& hpiEx) { return hpiEx.what(os,hpiEx); } */ /* This overloaded operator lets us use cout to print the NoImagerFile exception information */ /* std::ostream& operator<<(std::ostream& os, SctPixelRod::NoImageFile& imaEx) { return imaEx.what(os, imaEx); } */