summaryrefslogtreecommitdiffstats
path: root/host/lib
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib')
-rw-r--r--host/lib/usrp/usrp_e100/usrp_e100_impl.cpp70
-rw-r--r--host/lib/utils/log.cpp116
-rw-r--r--host/lib/utils/msg.cpp32
3 files changed, 115 insertions, 103 deletions
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;
}