aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/x300/x300_impl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/usrp/x300/x300_impl.cpp')
-rw-r--r--host/lib/usrp/x300/x300_impl.cpp240
1 files changed, 180 insertions, 60 deletions
diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp
index 8c565a252..c742d34df 100644
--- a/host/lib/usrp/x300/x300_impl.cpp
+++ b/host/lib/usrp/x300/x300_impl.cpp
@@ -37,6 +37,7 @@
#include <uhd/transport/nirio_zero_copy.hpp>
#include <uhd/transport/nirio/niusrprio_session.h>
#include <uhd/utils/platform.hpp>
+#include <boost/date_time/posix_time/posix_time_io.hpp>
#define NIUSRPRIO_DEFAULT_RPC_PORT "5444"
@@ -399,7 +400,7 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
default:
nirio_status_to_exception(status, "Motherboard detection error. Please ensure that you \
have a valid USRP X3x0, NI USRP-294xR or NI USRP-295xR device and that all the device \
- driver have been loaded.");
+ drivers have loaded successfully.");
}
//Load the lvbitx onto the device
UHD_MSG(status) << boost::format("Using LVBITX bitfile %s...\n") % lvbitx->get_bitfile_path();
@@ -558,6 +559,13 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
.set(mb_eeprom)
.subscribe(boost::bind(&x300_impl::set_mb_eeprom, this, mb.zpu_i2c, _1));
+ bool recover_mb_eeprom = dev_addr.has_key("recover_mb_eeprom");
+ if (recover_mb_eeprom) {
+ UHD_MSG(warning) << "UHD is operating in EEPROM Recovery Mode which disables hardware version "
+ "checks.\nOperating in this mode may cause hardware damage and unstable "
+ "radio performance!"<< std::endl;
+ }
+
////////////////////////////////////////////////////////////////////
// parse the product number
////////////////////////////////////////////////////////////////////
@@ -570,7 +578,10 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
product_name = "X310";
break;
default:
- break;
+ if (not recover_mb_eeprom)
+ throw uhd::runtime_error("Unrecognized product type.\n"
+ "Either the software does not support this device in which case please update your driver software to the latest version and retry OR\n"
+ "The product code in the EEPROM is corrupt and may require reprogramming.");
}
_tree->create<std::string>(mb_path / "name").set(product_name);
_tree->create<std::string>(mb_path / "codename").set("Yetti");
@@ -602,36 +613,57 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
}
////////////////////////////////////////////////////////////////////
- // create clock control objects
+ // read hardware revision and compatibility number
////////////////////////////////////////////////////////////////////
- UHD_MSG(status) << "Setup RF frontend clocking..." << std::endl;
-
mb.hw_rev = 0;
if(mb_eeprom.has_key("revision") and not mb_eeprom["revision"].empty()) {
try {
mb.hw_rev = boost::lexical_cast<size_t>(mb_eeprom["revision"]);
} catch(...) {
- UHD_MSG(warning) << "Revision in EEPROM is invalid! Please reprogram your EEPROM." << std::endl;
+ if (not recover_mb_eeprom)
+ throw uhd::runtime_error("Revision in EEPROM is invalid! Please reprogram your EEPROM.");
+ }
+ } else {
+ if (not recover_mb_eeprom)
+ throw uhd::runtime_error("No revision detected. MB EEPROM must be reprogrammed!");
+ }
+
+ size_t hw_rev_compat = 0;
+ if (mb.hw_rev >= 7) { //Revision compat was added with revision 7
+ if (mb_eeprom.has_key("revision_compat") and not mb_eeprom["revision_compat"].empty()) {
+ try {
+ hw_rev_compat = boost::lexical_cast<size_t>(mb_eeprom["revision_compat"]);
+ } catch(...) {
+ if (not recover_mb_eeprom)
+ throw uhd::runtime_error("Revision compat in EEPROM is invalid! Please reprogram your EEPROM.");
+ }
+ } else {
+ if (not recover_mb_eeprom)
+ throw uhd::runtime_error("No revision compat detected. MB EEPROM must be reprogrammed!");
}
} else {
- UHD_MSG(warning) << "No revision detected MB EEPROM must be reprogrammed!" << std::endl;
+ //For older HW just assume that revision_compat = revision
+ hw_rev_compat = mb.hw_rev;
}
- if(mb.hw_rev == 0) {
- UHD_MSG(warning) << "Defaulting to X300 RevD Clock Settings. This will result in non-optimal lock times." << std::endl;
- mb.hw_rev = X300_REV("D");
+ if (hw_rev_compat > X300_REVISION_COMPAT) {
+ if (not recover_mb_eeprom)
+ throw uhd::runtime_error(str(boost::format(
+ "Hardware is too new for this software. Please upgrade to a driver that supports hardware revision %d.")
+ % mb.hw_rev));
+ } else if (mb.hw_rev < X300_REVISION_MIN) { //Compare min against the revision (and not compat) to give us more leeway for partial support for a compat
+ if (not recover_mb_eeprom)
+ throw uhd::runtime_error(str(boost::format(
+ "Software is too new for this hardware. Please downgrade to a driver that supports hardware revision %d.")
+ % mb.hw_rev));
}
- if (mb.hw_rev > X300_MAX_HW_REV) {
- throw uhd::runtime_error(str(
- boost::format("Unsupported board revision number: %d.\n"
- "The maximum board revision number supported in this version is %d.\n"
- "Please update your UHD version.")
- % mb.hw_rev % X300_MAX_HW_REV
- ));
- }
+ ////////////////////////////////////////////////////////////////////
+ // create clock control objects
+ ////////////////////////////////////////////////////////////////////
+ UHD_MSG(status) << "Setup RF frontend clocking..." << std::endl;
- //Create clock control. NOTE: This does not configure the LMK yet.
+ //Initialize clock control registers. NOTE: This does not configure the LMK yet.
initialize_clock_control(mb);
mb.clock = x300_clock_ctrl::make(mb.zpu_spi,
1 /*slaveno*/,
@@ -705,7 +737,11 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
if (dev_addr.has_key("self_cal_adc_delay")) {
self_cal_adc_xfer_delay(mb, true /* Apply ADC delay */);
}
- self_test_adcs(mb);
+ if (dev_addr.has_key("ext_adc_self_test")) {
+ extended_adc_test(mb, dev_addr.cast<double>("ext_adc_self_test", 30));
+ } else {
+ self_test_adcs(mb);
+ }
////////////////////////////////////////////////////////////////////
// front panel gpio
@@ -1743,23 +1779,39 @@ x300_impl::x300_mboard_t x300_impl::get_mb_type_from_pcie(const std::string& res
if (nirio_status_not_fatal(status)) {
//The PCIe ID -> MB mapping may be different from the EEPROM -> MB mapping
switch (pid) {
- case X300_USRP_PCIE_SSID:
+ case X300_USRP_PCIE_SSID_ADC_33:
+ case X300_USRP_PCIE_SSID_ADC_18:
mb_type = USRP_X300_MB; break;
- case X310_USRP_PCIE_SSID:
- case X310_2940R_40MHz_PCIE_SSID:
- case X310_2940R_120MHz_PCIE_SSID:
- case X310_2942R_40MHz_PCIE_SSID:
- case X310_2942R_120MHz_PCIE_SSID:
- case X310_2943R_40MHz_PCIE_SSID:
- case X310_2943R_120MHz_PCIE_SSID:
- case X310_2944R_40MHz_PCIE_SSID:
- case X310_2950R_40MHz_PCIE_SSID:
- case X310_2950R_120MHz_PCIE_SSID:
- case X310_2952R_40MHz_PCIE_SSID:
- case X310_2952R_120MHz_PCIE_SSID:
- case X310_2953R_40MHz_PCIE_SSID:
- case X310_2953R_120MHz_PCIE_SSID:
- case X310_2954R_40MHz_PCIE_SSID:
+ case X310_USRP_PCIE_SSID_ADC_33:
+ case X310_2940R_40MHz_PCIE_SSID_ADC_33:
+ case X310_2940R_120MHz_PCIE_SSID_ADC_33:
+ case X310_2942R_40MHz_PCIE_SSID_ADC_33:
+ case X310_2942R_120MHz_PCIE_SSID_ADC_33:
+ case X310_2943R_40MHz_PCIE_SSID_ADC_33:
+ case X310_2943R_120MHz_PCIE_SSID_ADC_33:
+ case X310_2944R_40MHz_PCIE_SSID_ADC_33:
+ case X310_2950R_40MHz_PCIE_SSID_ADC_33:
+ case X310_2950R_120MHz_PCIE_SSID_ADC_33:
+ case X310_2952R_40MHz_PCIE_SSID_ADC_33:
+ case X310_2952R_120MHz_PCIE_SSID_ADC_33:
+ case X310_2953R_40MHz_PCIE_SSID_ADC_33:
+ case X310_2953R_120MHz_PCIE_SSID_ADC_33:
+ case X310_2954R_40MHz_PCIE_SSID_ADC_33:
+ case X310_USRP_PCIE_SSID_ADC_18:
+ case X310_2940R_40MHz_PCIE_SSID_ADC_18:
+ case X310_2940R_120MHz_PCIE_SSID_ADC_18:
+ case X310_2942R_40MHz_PCIE_SSID_ADC_18:
+ case X310_2942R_120MHz_PCIE_SSID_ADC_18:
+ case X310_2943R_40MHz_PCIE_SSID_ADC_18:
+ case X310_2943R_120MHz_PCIE_SSID_ADC_18:
+ case X310_2944R_40MHz_PCIE_SSID_ADC_18:
+ case X310_2950R_40MHz_PCIE_SSID_ADC_18:
+ case X310_2950R_120MHz_PCIE_SSID_ADC_18:
+ case X310_2952R_40MHz_PCIE_SSID_ADC_18:
+ case X310_2952R_120MHz_PCIE_SSID_ADC_18:
+ case X310_2953R_40MHz_PCIE_SSID_ADC_18:
+ case X310_2953R_120MHz_PCIE_SSID_ADC_18:
+ case X310_2954R_40MHz_PCIE_SSID_ADC_18:
mb_type = USRP_X310_MB; break;
default:
mb_type = UNKNOWN; break;
@@ -1784,23 +1836,39 @@ x300_impl::x300_mboard_t x300_impl::get_mb_type_from_eeprom(const uhd::usrp::mbo
switch (product_num) {
//The PCIe ID -> MB mapping may be different from the EEPROM -> MB mapping
- case X300_USRP_PCIE_SSID:
+ case X300_USRP_PCIE_SSID_ADC_33:
+ case X300_USRP_PCIE_SSID_ADC_18:
mb_type = USRP_X300_MB; break;
- case X310_USRP_PCIE_SSID:
- case X310_2940R_40MHz_PCIE_SSID:
- case X310_2940R_120MHz_PCIE_SSID:
- case X310_2942R_40MHz_PCIE_SSID:
- case X310_2942R_120MHz_PCIE_SSID:
- case X310_2943R_40MHz_PCIE_SSID:
- case X310_2943R_120MHz_PCIE_SSID:
- case X310_2944R_40MHz_PCIE_SSID:
- case X310_2950R_40MHz_PCIE_SSID:
- case X310_2950R_120MHz_PCIE_SSID:
- case X310_2952R_40MHz_PCIE_SSID:
- case X310_2952R_120MHz_PCIE_SSID:
- case X310_2953R_40MHz_PCIE_SSID:
- case X310_2953R_120MHz_PCIE_SSID:
- case X310_2954R_40MHz_PCIE_SSID:
+ case X310_USRP_PCIE_SSID_ADC_33:
+ case X310_2940R_40MHz_PCIE_SSID_ADC_33:
+ case X310_2940R_120MHz_PCIE_SSID_ADC_33:
+ case X310_2942R_40MHz_PCIE_SSID_ADC_33:
+ case X310_2942R_120MHz_PCIE_SSID_ADC_33:
+ case X310_2943R_40MHz_PCIE_SSID_ADC_33:
+ case X310_2943R_120MHz_PCIE_SSID_ADC_33:
+ case X310_2944R_40MHz_PCIE_SSID_ADC_33:
+ case X310_2950R_40MHz_PCIE_SSID_ADC_33:
+ case X310_2950R_120MHz_PCIE_SSID_ADC_33:
+ case X310_2952R_40MHz_PCIE_SSID_ADC_33:
+ case X310_2952R_120MHz_PCIE_SSID_ADC_33:
+ case X310_2953R_40MHz_PCIE_SSID_ADC_33:
+ case X310_2953R_120MHz_PCIE_SSID_ADC_33:
+ case X310_2954R_40MHz_PCIE_SSID_ADC_33:
+ case X310_USRP_PCIE_SSID_ADC_18:
+ case X310_2940R_40MHz_PCIE_SSID_ADC_18:
+ case X310_2940R_120MHz_PCIE_SSID_ADC_18:
+ case X310_2942R_40MHz_PCIE_SSID_ADC_18:
+ case X310_2942R_120MHz_PCIE_SSID_ADC_18:
+ case X310_2943R_40MHz_PCIE_SSID_ADC_18:
+ case X310_2943R_120MHz_PCIE_SSID_ADC_18:
+ case X310_2944R_40MHz_PCIE_SSID_ADC_18:
+ case X310_2950R_40MHz_PCIE_SSID_ADC_18:
+ case X310_2950R_120MHz_PCIE_SSID_ADC_18:
+ case X310_2952R_40MHz_PCIE_SSID_ADC_18:
+ case X310_2952R_120MHz_PCIE_SSID_ADC_18:
+ case X310_2953R_40MHz_PCIE_SSID_ADC_18:
+ case X310_2953R_120MHz_PCIE_SSID_ADC_18:
+ case X310_2954R_40MHz_PCIE_SSID_ADC_18:
mb_type = USRP_X310_MB; break;
default:
UHD_MSG(warning) << "X300 unknown product code in EEPROM: " << product_num << std::endl;
@@ -2078,20 +2146,72 @@ void x300_impl::self_test_adcs(mboard_members_t& mb, boost::uint32_t ramp_time_m
perif.misc_outs->write(radio_misc_outs_reg::ADC_CHECKER_ENABLED, 1);
}
boost::this_thread::sleep(boost::posix_time::milliseconds(ramp_time_ms));
+
+ bool passed = true;
+ std::string status_str;
for (size_t r = 0; r < mboard_members_t::NUM_RADIOS; r++) {
radio_perifs_t &perif = mb.radio_perifs[r];
+ perif.misc_ins->refresh();
+
+ std::string i_status, q_status;
+ if (perif.misc_ins->get(radio_misc_ins_reg::ADC_CHECKER1_I_LOCKED))
+ if (perif.misc_ins->get(radio_misc_ins_reg::ADC_CHECKER1_I_ERROR))
+ i_status = "Bit Errors!";
+ else
+ i_status = "Good";
+ else
+ i_status = "Not Locked!";
- if (!perif.misc_ins->read(radio_misc_ins_reg::ADC_CHECKER1_I_LOCKED) ||
- perif.misc_ins->read(radio_misc_ins_reg::ADC_CHECKER1_I_ERROR) ||
- !perif.misc_ins->read(radio_misc_ins_reg::ADC_CHECKER1_Q_LOCKED) ||
- perif.misc_ins->read(radio_misc_ins_reg::ADC_CHECKER1_Q_ERROR))
- {
- throw uhd::runtime_error(
- (boost::format("ADC self-test failed for Radio%d. (Ramp checker failure)")%r).str());
- }
+ if (perif.misc_ins->get(radio_misc_ins_reg::ADC_CHECKER1_Q_LOCKED))
+ if (perif.misc_ins->get(radio_misc_ins_reg::ADC_CHECKER1_Q_ERROR))
+ q_status = "Bit Errors!";
+ else
+ q_status = "Good";
+ else
+ q_status = "Not Locked!";
+
+ passed = passed && (i_status == "Good") && (q_status == "Good");
+ status_str += (boost::format(", ADC%d_I=%s, ADC%d_Q=%s")%r%i_status%r%q_status).str();
//Return to normal mode
perif.adc->set_test_word("normal", "normal");
}
+
+ if (not passed) {
+ throw uhd::runtime_error(
+ (boost::format("ADC self-test failed! Ramp checker status: {%s}")%status_str.substr(2)).str());
+ }
}
+void x300_impl::extended_adc_test(mboard_members_t& mb, double duration_s)
+{
+ static const size_t SECS_PER_ITER = 5;
+ UHD_MSG(status) << boost::format("Running Extended ADC Self-Test (Duration=%.0fs, %ds/iteration)...\n")
+ % duration_s % SECS_PER_ITER;
+
+ size_t num_iters = static_cast<size_t>(ceil(duration_s/SECS_PER_ITER));
+ size_t num_failures = 0;
+ for (size_t iter = 0; iter < num_iters; iter++) {
+ //Print date and time
+ boost::posix_time::time_facet *facet = new boost::posix_time::time_facet("%d-%b-%Y %H:%M:%S");
+ std::ostringstream time_strm;
+ time_strm.imbue(std::locale(std::locale::classic(), facet));
+ time_strm << boost::posix_time::second_clock::local_time();
+ //Run self-test
+ UHD_MSG(status) << boost::format("-- [%s] Iteration %06d... ") % time_strm.str() % (iter+1);
+ try {
+ self_test_adcs(mb, SECS_PER_ITER*1000);
+ UHD_MSG(status) << "passed" << std::endl;
+ } catch(std::exception &e) {
+ num_failures++;
+ UHD_MSG(status) << e.what() << std::endl;
+ }
+
+ }
+ if (num_failures == 0) {
+ UHD_MSG(status) << "Extended ADC Self-Test PASSED\n";
+ } else {
+ throw uhd::runtime_error(
+ (boost::format("Extended ADC Self-Test FAILED!!! (%d/%d failures)\n") % num_failures % num_iters).str());
+ }
+}