diff options
-rw-r--r-- | host/include/uhd/utils/log.hpp | 2 | ||||
-rw-r--r-- | host/lib/usrp/usrp_e100/usrp_e100_impl.cpp | 70 | ||||
-rw-r--r-- | host/lib/utils/log.cpp | 116 | ||||
-rw-r--r-- | host/lib/utils/msg.cpp | 32 | ||||
-rw-r--r-- | host/usrp_e_utils/usrp-e-utility.cpp | 3 |
5 files changed, 116 insertions, 107 deletions
diff --git a/host/include/uhd/utils/log.hpp b/host/include/uhd/utils/log.hpp index 8d8f42fd0..7f83fd2a9 100644 --- a/host/include/uhd/utils/log.hpp +++ b/host/include/uhd/utils/log.hpp @@ -38,7 +38,7 @@ * (in other words, as often or less often than the current log level) * are recorded into the log file. All other messages are sent to null. * - * The default log level is "regular", but can be overridden: + * The default log level is "never", but can be overridden: * - at compile time by setting the pre-processor define UHD_LOG_LEVEL. * - at runtime by setting the environment variable UHD_LOG_LEVEL. * diff --git a/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp b/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp index 5fba0c153..e9e9b6e20 100644 --- a/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp +++ b/host/lib/usrp/usrp_e100/usrp_e100_impl.cpp @@ -76,6 +76,15 @@ static device_addrs_t usrp_e100_find(const device_addr_t &hint){ /*********************************************************************** * Make **********************************************************************/ +static size_t hash_fpga_file(const std::string &file_path){ + size_t hash = 0; + std::ifstream file(file_path.c_str()); + if (not file.good()) throw uhd::io_error("cannot open fpga file for read: " + file_path); + while (file.good()) boost::hash_combine(hash, file.get()); + file.close(); + return hash; +} + static device::sptr usrp_e100_make(const device_addr_t &device_addr){ //setup the main interface into fpga @@ -83,55 +92,44 @@ static device::sptr usrp_e100_make(const device_addr_t &device_addr){ UHD_MSG(status) << boost::format("Opening USRP-E on %s") % node << std::endl; usrp_e100_iface::sptr iface = usrp_e100_iface::make(node); - //------------------------------------------------------------------ - //-- Handle the FPGA loading... - //-- The image can be confimed as already loaded when: - //-- 1) The compatibility number matches. - //-- 2) The hash in the hash-file matches. - //------------------------------------------------------------------ - static const char *hash_file_path = "/tmp/usrp_e100_hash"; - //extract the fpga path for usrp-e - std::string usrp_e100_fpga_image = find_image_path( - device_addr.has_key("fpga")? device_addr["fpga"] : "usrp_e100_fpga.bin" - ); - - //calculate a hash of the fpga file - size_t fpga_hash = 0; - { - std::ifstream file(usrp_e100_fpga_image.c_str()); - if (not file.good()) throw uhd::io_error( - "cannot open fpga file for read: " + usrp_e100_fpga_image - ); - do{ - boost::hash_combine(fpga_hash, file.get()); - } while (file.good()); - file.close(); - } + std::string usrp_e100_fpga_image = find_image_path(device_addr.get("fpga", "usrp_e100_fpga.bin")); - //read the compatibility number - boost::uint16_t fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT); + //compute a hash of the fpga file + const boost::uint32_t file_hash = boost::uint32_t(hash_fpga_file(usrp_e100_fpga_image)); - //read the hash in the hash-file - size_t loaded_hash = 0; - try{std::ifstream(hash_file_path) >> loaded_hash;}catch(...){} - - //if not loaded: load the fpga image and write the hash-file - if (fpga_compat_num != USRP_E_FPGA_COMPAT_NUM or loaded_hash != fpga_hash){ + //When the hash does not match: + // - unload the iface to free the node + // - load the fpga configuration file + // - re-open the iface on the node + if (iface->peek32(UE_REG_RB_MISC_TEST32) != file_hash){ iface.reset(); usrp_e100_load_fpga(usrp_e100_fpga_image); sleep(1); ///\todo do this better one day. UHD_MSG(status) << boost::format("re-Opening USRP-E on %s") % node << std::endl; iface = usrp_e100_iface::make(node); - try{std::ofstream(hash_file_path) << fpga_hash;}catch(...){} + } + + //store the hash into the FPGA register + iface->poke32(UE_REG_SR_MISC_TEST32, file_hash); + + //check that the hash can be readback correctly + if (iface->peek32(UE_REG_RB_MISC_TEST32) != file_hash){ + UHD_MSG(error) << boost::format( + "The FPGA hash readback failed!\n" + "The FPGA is either clocked improperly\n" + "or the FPGA build is not compatible.\n" + ); } //check that the compatibility is correct - fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT); + const boost::uint16_t fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT); if (fpga_compat_num != USRP_E_FPGA_COMPAT_NUM){ throw uhd::runtime_error(str(boost::format( - "Expected fpga compatibility number 0x%x, but got 0x%x:\n" - "The fpga build is not compatible with the host code build." + "\nPlease update the FPGA image for your device.\n" + "See the application notes for USRP E-Series for instructions.\n" + "Expected FPGA compatibility number 0x%x, but got 0x%x:\n" + "The FPGA build is not compatible with the host code build." ) % USRP_E_FPGA_COMPAT_NUM % fpga_compat_num)); } diff --git a/host/lib/utils/log.cpp b/host/lib/utils/log.cpp index 5e8039fda..7d11877a1 100644 --- a/host/lib/utils/log.cpp +++ b/host/lib/utils/log.cpp @@ -16,6 +16,7 @@ // #include <uhd/utils/log.hpp> +#include <uhd/utils/msg.hpp> #include <uhd/utils/static.hpp> #include <boost/filesystem.hpp> #include <boost/format.hpp> @@ -41,6 +42,7 @@ namespace boost{ namespace interprocess{ #include <stdio.h> //P_tmpdir #include <cstdlib> //getenv #include <fstream> +#include <sstream> #include <cctype> namespace fs = boost::filesystem; @@ -84,22 +86,21 @@ static fs::path get_temp_path(void){ } /*********************************************************************** - * The library's streamer resource (static initialization) + * Global resources for the logger **********************************************************************/ -class null_streambuf_class : public std::streambuf{ - int overflow(int c) { return c; } -}; -UHD_SINGLETON_FCN(null_streambuf_class, null_streambuf); - -class uhd_logger_stream_resource_class{ +class log_resource_type{ public: - uhd_logger_stream_resource_class(void) : _null_stream(&null_streambuf()){ - const std::string log_path = (get_temp_path() / "uhd.log").string(); - _file_stream.open(log_path.c_str(), std::fstream::out | std::fstream::app); - _file_lock = new ip::file_lock(log_path.c_str()); + boost::mutex mutex; + std::ostringstream ss; + uhd::_log::verbosity_t verbosity, level; + + log_resource_type(void){ + + //file lock pointer must be null + _file_lock = NULL; //set the default log level - _log_level = uhd::_log::regularly; + level = uhd::_log::never; //allow override from macro definition #ifdef UHD_LOG_LEVEL @@ -109,42 +110,34 @@ public: //allow override from environment variable const char * log_level_env = std::getenv("UHD_LOG_LEVEL"); if (log_level_env != NULL) _set_log_level(log_level_env); - } - ~uhd_logger_stream_resource_class(void){ + ~log_resource_type(void){ _file_stream.close(); - delete _file_lock; - } - - std::ostream &get(void){ - if (_verbosity >= _log_level) return _file_stream; - return _null_stream; + if (_file_lock != NULL) delete _file_lock; } - void aquire(bool lock){ - if (lock){ - _mutex.lock(); - _file_lock->lock(); + void log_to_file(void){ + if (verbosity < level) return; + if (_file_lock == NULL){ + const std::string log_path = (get_temp_path() / "uhd.log").string(); + _file_stream.open(log_path.c_str(), std::fstream::out | std::fstream::app); + _file_lock = new ip::file_lock(log_path.c_str()); } - else{ - _file_lock->unlock(); - _mutex.unlock(); - } - } - - void set_verbosity(uhd::_log::verbosity_t verbosity){ - _verbosity = verbosity; + _file_lock->lock(); + _file_stream << ss.str() << std::flush; + _file_lock->unlock(); } private: //! set the log level from a string that is either a digit or an enum name void _set_log_level(const std::string &log_level_str){ - const uhd::_log::verbosity_t log_level = uhd::_log::verbosity_t(log_level_str[0]-'0'); - if (std::isdigit(log_level_str[0]) and log_level >= uhd::_log::always and log_level <= uhd::_log::never){ - _log_level = log_level; + const uhd::_log::verbosity_t log_level_num = uhd::_log::verbosity_t(log_level_str[0]-'0'); + if (std::isdigit(log_level_str[0]) and log_level_num >= uhd::_log::always and log_level_num <= uhd::_log::never){ + this->level = log_level_num; + return; } - #define if_lls_equal(name) else if(log_level_str == #name) _log_level = uhd::_log::name + #define if_lls_equal(name) else if(log_level_str == #name) this->level = uhd::_log::name if_lls_equal(always); if_lls_equal(often); if_lls_equal(regularly); @@ -153,20 +146,12 @@ private: if_lls_equal(never); } - //available stream objects + //file stream and lock: std::ofstream _file_stream; - std::ostream _null_stream; - - //synchronization mechanisms - boost::mutex _mutex; //process-level - ip::file_lock *_file_lock; //system-level - - //log-level settings - uhd::_log::verbosity_t _verbosity; - uhd::_log::verbosity_t _log_level; + ip::file_lock *_file_lock; }; -UHD_SINGLETON_FCN(uhd_logger_stream_resource_class, uhd_logger_stream_resource); +UHD_SINGLETON_FCN(log_resource_type, log_rs); /*********************************************************************** * The logger object implementation @@ -188,14 +173,14 @@ uhd::_log::log::log( const unsigned int line, const std::string &function ){ - uhd_logger_stream_resource().aquire(true); - uhd_logger_stream_resource().set_verbosity(verbosity); + log_rs().mutex.lock(); + log_rs().verbosity = verbosity; const std::string time = pt::to_simple_string(pt::microsec_clock::local_time()); const std::string header1 = str(boost::format("-- %s - level %d") % time % int(verbosity)); const std::string header2 = str(boost::format("-- %s") % function).substr(0, 80); const std::string header3 = str(boost::format("-- %s:%u") % get_rel_file_path(file) % line); const std::string border = std::string(std::max(std::max(header1.size(), header2.size()), header3.size()), '-'); - uhd_logger_stream_resource().get() + log_rs().ss << std::endl << border << std::endl << header1 << std::endl @@ -206,10 +191,35 @@ uhd::_log::log::log( } uhd::_log::log::~log(void){ - uhd_logger_stream_resource().get() << std::endl; - uhd_logger_stream_resource().aquire(false); + log_rs().ss << std::endl; + try{ + log_rs().log_to_file(); + } + catch(const std::exception &e){ + /*! + * Critical behavior below. + * The following steps must happen in order to avoid a lock-up condition. + * This is because the message facility will call into the logging facility. + * Therefore we must disable the logger (level = never) and unlock the mutex. + * + * 1) Set logging level to never. + * 2) Unlock the mutex. + * 3) Send the error message. + * 4) Return. + */ + log_rs().level = never; + log_rs().ss.str(""); //clear for next call + log_rs().mutex.unlock(); + UHD_MSG(error) + << "Logging failed: " << e.what() << std::endl + << "Logging has been disabled for this process" << std::endl + ; + return; + } + log_rs().ss.str(""); //clear for next call + log_rs().mutex.unlock(); } std::ostream & uhd::_log::log::operator()(void){ - return uhd_logger_stream_resource().get(); + return log_rs().ss; } diff --git a/host/lib/utils/msg.cpp b/host/lib/utils/msg.cpp index e850b5a6d..0fd62bfc1 100644 --- a/host/lib/utils/msg.cpp +++ b/host/lib/utils/msg.cpp @@ -61,20 +61,24 @@ static void msg_to_cerr(const std::string &title, const std::string &msg){ } /*********************************************************************** - * Global settings for the messenger + * Global resources for the messenger **********************************************************************/ -static boost::mutex msg_mutex; -static std::ostringstream msg_ss; -static uhd::msg::type_t msg_type; -static uhd::msg::handler_t msg_handler; +struct msg_resource_type{ + boost::mutex mutex; + std::ostringstream ss; + uhd::msg::type_t type; + uhd::msg::handler_t handler; +}; + +UHD_SINGLETON_FCN(msg_resource_type, msg_rs); /*********************************************************************** * Setup the message handlers **********************************************************************/ void uhd::msg::register_handler(const handler_t &handler){ - msg_mutex.lock(); - msg_handler = handler; - msg_mutex.unlock(); + msg_rs().mutex.lock(); + msg_rs().handler = handler; + msg_rs().mutex.unlock(); } static void default_msg_handler(uhd::msg::type_t type, const std::string &msg){ @@ -108,16 +112,16 @@ UHD_STATIC_BLOCK(msg_register_default_handler){ * The message object implementation **********************************************************************/ uhd::msg::_msg::_msg(const type_t type){ - msg_mutex.lock(); - msg_type = type; + msg_rs().mutex.lock(); + msg_rs().type = type; } uhd::msg::_msg::~_msg(void){ - msg_handler(msg_type, msg_ss.str()); - msg_ss.str(""); //clear for next call - msg_mutex.unlock(); + msg_rs().handler(msg_rs().type, msg_rs().ss.str()); + msg_rs().ss.str(""); //clear for next call + msg_rs().mutex.unlock(); } std::ostream & uhd::msg::_msg::operator()(void){ - return msg_ss; + return msg_rs().ss; } diff --git a/host/usrp_e_utils/usrp-e-utility.cpp b/host/usrp_e_utils/usrp-e-utility.cpp index b926cf49d..47a2c0900 100644 --- a/host/usrp_e_utils/usrp-e-utility.cpp +++ b/host/usrp_e_utils/usrp-e-utility.cpp @@ -64,9 +64,6 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ " usrp-e-utility --reclk --fpga=/usr/share/uhd/images/usrp_e1xx_pt_fpga.bin" ); clock_genconfig_main(); - if (std::system("rm /tmp/usrp*hash") != 0){ //clear hash so driver must reload - std::cerr << "No hash to remove! Don't worry, its not a problem." << std::endl; - } } std::cout << "Done!" << std::endl; |