Generic hardware access library
/home/cschwick/hal/generic/src/common/HardwareDevice.cc
Go to the documentation of this file.
00001 #include "hal/HardwareDevice.hh"
00002 #include <unistd.h>
00003 #include <sstream>
00004 #include <iomanip>
00005 #include <string.h>
00006 
00007 HAL::HardwareDevice::HardwareDevice( HAL::AddressTableInterface & addressTable )
00008   :  addressTable(addressTable) {}
00009 
00010 HAL::HardwareDevice::~HardwareDevice() {}
00011 
00012 void HAL::HardwareDevice::unmaskedWrite( std::string item, 
00013                                          uint32_t data,
00014                                          HalVerifyOption verifyFlag,
00015                                          uint32_t offset ) const
00016   throw (HAL::NoSuchItemException, 
00017          HAL::IllegalOperationException,
00018          HAL::BusAdapterException,
00019          HAL::VerifyException,
00020          HAL::AddressOutOfLimitsException) {
00021   const HAL::GeneralHardwareAddress& address = 
00022     addressTable.getWritableHardwareAddress(item);
00023   if ( offset != 0 ) addressTable.checkAddressLimits( address, offset );
00024   hardwareWrite( address, data, offset );
00025   if ( verifyFlag ) {
00026     uint32_t result;
00027     unmaskedRead( item, &result, offset);
00028     verify( result, data, "unmaskedWrite" );
00029   }
00030 }
00031 
00032 void HAL::HardwareDevice::write( std::string item, 
00033                                  uint32_t data, 
00034                                  HalVerifyOption verifyFlag,
00035                                  uint32_t offset ) const
00036   throw (HAL::NoSuchItemException, 
00037          HAL::BusAdapterException,
00038          HAL::IllegalOperationException, 
00039          HAL::VerifyException,
00040          HAL::MaskBoundaryException,
00041          HAL::AddressOutOfLimitsException ) {
00042 
00043   const HAL::AddressTableItem& addressItem = addressTable.checkItem( item );
00044   addressItem.checkWritable();
00045   writeAddressItem( addressItem, data, offset, verifyFlag );
00046 }
00047 
00048 void HAL::HardwareDevice::writePulse( std::string item, 
00049                                       uint32_t offset ) const
00050   throw (HAL::NoSuchItemException,
00051          HAL::BusAdapterException,
00052          HAL::IllegalOperationException,
00053          HAL::AddressOutOfLimitsException) {
00054   const HAL::GeneralHardwareAddress& address = 
00055     addressTable.getWritableHardwareAddress(item);
00056   if ( offset != 0 ) addressTable.checkAddressLimits( address, offset );
00057   hardwareWrite( address, 0x0, offset );
00058 }
00059 
00060 void HAL::HardwareDevice::readPulse( std::string item, 
00061                                      uint32_t offset ) const
00062   throw (HAL::NoSuchItemException,
00063          HAL::BusAdapterException,
00064          HAL::IllegalOperationException,
00065          HAL::AddressOutOfLimitsException) {
00066   uint32_t dummy;
00067   const HAL::GeneralHardwareAddress& address = 
00068     addressTable.getReadableHardwareAddress(item);
00069   if ( offset != 0 ) addressTable.checkAddressLimits( address, offset );
00070   hardwareRead( address, &dummy, offset );
00071 }
00072 
00073 void HAL::HardwareDevice::unmaskedRead( std::string item,
00074                                         uint32_t* result, 
00075                                         uint32_t offset ) const
00076   throw (HAL::NoSuchItemException,
00077          HAL::BusAdapterException,
00078          HAL::IllegalOperationException,
00079          HAL::AddressOutOfLimitsException) {
00080   const HAL::GeneralHardwareAddress& address = addressTable.getReadableHardwareAddress( item );
00081   if ( offset != 0 ) addressTable.checkAddressLimits( address, offset );
00082   hardwareRead( address, result, offset );
00083 }
00084 
00085 void HAL::HardwareDevice::read( std::string item, 
00086                                 uint32_t* result,
00087                                 uint32_t offset ) const
00088   throw (HAL::NoSuchItemException,
00089          HAL::BusAdapterException,
00090          HAL::IllegalOperationException,
00091          HAL::MaskBoundaryException,
00092          HAL::AddressOutOfLimitsException) {
00093   uint32_t data;
00094 
00095   const HAL::AddressTableItem& addressItem = addressTable.checkItem( item );
00096   addressItem.checkReadable();
00097   const HAL::GeneralHardwareAddress& address = addressItem.getGeneralHardwareAddress();
00098   if ( offset != 0 ) addressTable.checkAddressLimits( address, offset );
00099   hardwareRead( address, &data, offset );
00100   data &= addressItem.getMask();
00101   *result = addressItem.applyFromMask( data );
00102 }
00103 
00104 void HAL::HardwareDevice::pollItem( std::string item,
00105                                     uint32_t referenceValue,
00106                                     uint32_t timeout,
00107                                     uint32_t *result,
00108                                     HalPollMethod pollMethod,
00109                                     uint32_t offset ) const
00110     throw ( HAL::NoSuchItemException,
00111             HAL::IllegalOperationException,
00112             HAL::BusAdapterException,
00113             HAL::MaskBoundaryException,
00114             HAL::TimeoutException,
00115             HAL::AddressOutOfLimitsException) {
00116   HAL::StopWatch watch(0);
00117   const HAL::AddressTableItem& addressItem = addressTable.checkItem( item );
00118   addressItem.checkReadable();
00119   const HAL::GeneralHardwareAddress& address = addressItem.getGeneralHardwareAddress();
00120   if ( offset != 0 ) addressTable.checkAddressLimits( address, offset );
00121   uint32_t mask = addressItem.getMask();
00122   uint32_t compareValue = addressItem.applyToMask( referenceValue );
00123   uint32_t data;
00124   bool pollCondition = false;
00125   uint32_t loopCounter = 1;
00126   watch.start();
00127   uint32_t time;
00128 
00129   // here the poll loop starts
00130   while ( ! pollCondition ) {
00131     hardwareRead( address, &data, offset);
00132     if ( (pollMethod == HAL_POLL_UNTIL_EQUAL) ) 
00133       pollCondition = (compareValue == (data & mask));
00134     else 
00135       pollCondition = (compareValue != (data & mask));
00136     loopCounter++;
00137     if (loopCounter%1000 == 0) {
00138       watch.stop();
00139       time = watch.read();
00140       if ( time/1000 >= timeout ) {
00141         std::stringstream text;
00142         text << "Timeout during polling the item \"" 
00143              << item << "\"\n"
00144              << "      " << std::dec << time/1000 
00145              << "ms have passed wheras the timeout has been set to "
00146              << timeout << "ms\n"
00147              << "      " << std::dec << loopCounter << " polls have been carried out\n" 
00148              << std::ends; 
00149         throw( HAL::TimeoutException( text.str(), __FILE__, __LINE__, __FUNCTION__  ) );
00150       }
00151     }
00152   }
00153   *result = addressItem.applyFromMask( mask & data );
00154 }
00155 
00156 void HAL::HardwareDevice::setBit( std::string item, 
00157                                   HalVerifyOption verifyFlag,
00158                                   uint32_t offset ) const
00159   throw (HAL::NoSuchItemException, 
00160          HAL::IllegalOperationException, 
00161          HAL::BusAdapterException,
00162          HAL::VerifyException,
00163          HAL::AddressOutOfLimitsException ) {
00164   const HAL::AddressTableItem& addressItem = addressTable.checkItem( item );
00165   addressItem.checkWritable();
00166   addressItem.checkBit();
00167   writeAddressItem( addressItem, 0x01, offset, verifyFlag );
00168 }
00169 
00170 void HAL::HardwareDevice::resetBit( std::string item, 
00171                                     HalVerifyOption verifyFlag,
00172                                     uint32_t offset ) const
00173   throw (HAL::NoSuchItemException, 
00174          HAL::IllegalOperationException, 
00175          HAL::BusAdapterException,
00176          HAL::VerifyException,
00177          HAL::AddressOutOfLimitsException ) {
00178   const HAL::AddressTableItem& addressItem = addressTable.checkItem( item );
00179   addressItem.checkWritable();
00180   addressItem.checkBit();
00181   writeAddressItem( addressItem, 0x00, offset, verifyFlag );
00182 }
00183 
00184 bool HAL::HardwareDevice::isSet( std::string item, 
00185                                  uint32_t offset ) const  
00186   throw (HAL::NoSuchItemException, 
00187          HAL::BusAdapterException,
00188          HAL::IllegalOperationException,
00189          HAL::AddressOutOfLimitsException) {
00190 
00191   uint32_t data;
00192 
00193   const HAL::AddressTableItem& addressItem = addressTable.checkItem( item );
00194   addressItem.checkReadable();
00195   addressItem.checkBit();
00196   const HAL::GeneralHardwareAddress& address = addressItem.getGeneralHardwareAddress();
00197   if ( offset != 0 ) addressTable.checkAddressLimits( address, offset );
00198   hardwareRead( address, &data, offset );
00199   data &= addressItem.getMask();
00200   return( (bool)data );
00201 }
00202  
00203 bool HAL::HardwareDevice::check( std::string item,
00204                                  uint32_t expectation,
00205                                  std::string faultMessage,
00206                                  uint32_t offset,
00207                                  std::ostream& os ) const
00208   throw( HAL::NoSuchItemException,
00209          HAL::IllegalOperationException,
00210          HAL::BusAdapterException,
00211          HAL::AddressOutOfLimitsException) {
00212   uint32_t result;
00213   bool returnVal;
00214   returnVal = true;
00215   read( item, &result, offset );
00216   if ( expectation != result ) {
00217     // we found a mismatch: prepare the output string:
00218     returnVal = false;
00219     std::stringstream text;
00220     text << "Check was unsuccessfull for item \"" << item << "\"";
00221     if ( offset != 0 ) text << " with offset 0x" << std::hex << std::setw(8) << std::setfill('0') << offset;
00222     text << "\n   read 0x" << std::hex << result << " (dec: " << std::dec << result 
00223          << " )   expected 0x" << std::hex << expectation << " (dec: " << std::dec << expectation 
00224          << " )" ;
00225     if ( faultMessage != "" ) {
00226       text << "\n   " << faultMessage << std::ends;
00227     } else { 
00228       text << std::ends;
00229     }
00230     os << text.str() << std::endl;
00231   }
00232   return returnVal;
00233 }
00234 
00235 void HAL::HardwareDevice::writeBlock( std::string startItem, 
00236                                       uint32_t length,
00237                                       char *buffer,
00238                                       HalVerifyOption verifyFlag,
00239                                       HalAddressIncrement addressBehaviour,
00240                                       uint32_t offset ) const
00241   throw ( HAL::NoSuchItemException,
00242           HAL::IllegalValueException,
00243           HAL::UnsupportedException, 
00244           HAL::VerifyException,
00245           HAL::BusAdapterException,
00246           HAL::IllegalOperationException,
00247           HAL::AddressOutOfLimitsException ){
00248   const HAL::GeneralHardwareAddress& address = addressTable.getWritableHardwareAddress( startItem );
00249   // check the start address only if there is an offset given
00250   if ( offset != 0 ) addressTable.checkAddressLimits( address, offset );
00251   // always check the end of the block
00252   // for block-transfers the width of the item is irrelevant. Since checkAddressLimits 
00253   // implicitly adds an offset=item-data-width to the address (which it should do for 
00254   // single read/write accesses) this data width must be substracted here. (Block transfers
00255   // are special in the sense that the start item only gives the startaddress and the 
00256   // width of this item is irrelevant for the transfer)
00257   if ( addressBehaviour == HAL_DO_INCREMENT ) {
00258     addressTable.checkAddressLimits( address, offset+length-address.getDataWidth() );
00259   }
00260   hardwareWriteBlock( address,
00261                       length,
00262                       buffer,
00263                       addressBehaviour,
00264                       offset);
00265   if ( verifyFlag ) {
00266     char* verifyBuffer = new char[length];
00267     readBlock( startItem, length, verifyBuffer, addressBehaviour, offset ); 
00268     if ( memcmp(buffer, verifyBuffer, length ) != 0) {
00269       delete (verifyBuffer);
00270       std::stringstream text;
00271       text << "Verify error in writeBlock "
00272            << "\n    (HAL::HardwareDevice::writeBlock)" << std::ends;
00273       throw( HAL::VerifyException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) );
00274     }
00275     delete( verifyBuffer );
00276   }
00277 }
00278 
00279 void HAL::HardwareDevice::readBlock( std::string startItem, 
00280                                      uint32_t length,
00281                                      char *buffer,
00282                                      HalAddressIncrement addressBehaviour,
00283                                      uint32_t offset) const
00284   throw ( HAL::NoSuchItemException,
00285           HAL::IllegalValueException,
00286           HAL::UnsupportedException, 
00287           HAL::BusAdapterException,
00288           HAL::IllegalOperationException,
00289           HAL::AddressOutOfLimitsException ){
00290   const HAL::GeneralHardwareAddress& address = addressTable.getReadableHardwareAddress( startItem );
00291   // check the start address only if there is an offset given
00292   if ( offset != 0 ) addressTable.checkAddressLimits( address, offset );
00293   // always check the end of the block
00294   // for block-transfers the width of the item is irrelevant. Since checkAddressLimits 
00295   // implicitly adds an offset=item-data-width to the address (which it should do for 
00296   // single read/write accesses) this data width must be substracted here. (Block transfers
00297   // are special in the sense that the start item only gives the startaddress and the 
00298   // width of this item is irrelevant for the transfer)
00299   if ( addressBehaviour == HAL_DO_INCREMENT ) {
00300     addressTable.checkAddressLimits( address, offset+length-address.getDataWidth() );
00301   }
00302   hardwareReadBlock( address,
00303                      length,
00304                      buffer,
00305                      addressBehaviour,
00306                      offset);
00307 }
00308 
00309 const HAL::AddressTableInterface& HAL::HardwareDevice::getAddressTableInterface() const {
00310   return addressTable;
00311 }
00312 
00313 void HAL::HardwareDevice::printAddressTable() const {
00314   addressTable.print();
00315 }
00316 
00317 void HAL::HardwareDevice::verify( uint32_t readBack,
00318                                   uint32_t data,
00319                                   std::string methodName ) const
00320   throw( HAL::VerifyException ) {
00321   if ( readBack != data ) {
00322       std::stringstream text;
00323       text << "Verify error: wrote " << std::hex << data 
00324            << "          read back " << std::hex << readBack
00325            << "\n    (HAL::HardwareDevice::" << methodName 
00326            << ")" << std::ends;
00327       throw( HAL::VerifyException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) );
00328     }
00329 }
00330 
00331 void HAL::HardwareDevice::writeAddressItem( const HAL::AddressTableItem& addressItem, 
00332                                             uint32_t data,
00333                                             uint32_t offset,
00334                                             HalVerifyOption verifyFlag ) const
00335   throw( HAL::MaskBoundaryException,
00336          HAL::IllegalValueException,
00337          HAL::BusAdapterException,
00338          HAL::VerifyException,
00339          HAL::AddressOutOfLimitsException ) {
00340   uint32_t mask;
00341   uint32_t newData = addressItem.applyToMask( data );
00342 
00343   const HAL::GeneralHardwareAddress& address = addressItem.getGeneralHardwareAddress();  
00344 
00345   if ( offset != 0 ) addressTable.checkAddressLimits( address, offset );
00346 
00347   mask = addressItem.getMask();
00348   if ( addressItem.isReadable() ){
00349     uint32_t oldData; 
00350     hardwareRead( address, &oldData, offset );
00351     newData |= ( oldData & (~ mask) );
00352   }
00353   hardwareWrite( address, newData, offset );
00354 
00355   // verify if wanted
00356   if ( verifyFlag ) {
00357     uint32_t result;
00358     addressItem.checkReadable();
00359     hardwareRead( addressItem.getGeneralHardwareAddress(), &result, offset );
00360     result &= mask;
00361     result = addressItem.applyFromMask( result );
00362     verify( result, data, "writeAddressItem" );
00363   }
00364 }