Generic hardware access library
|
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 }