diff options
-rw-r--r-- | host/docs/usrp_e3x0.dox | 2 | ||||
-rw-r--r-- | host/lib/usrp/common/ad936x_manager.cpp | 39 | ||||
-rw-r--r-- | host/lib/usrp/e300/e300_sysfs_hooks.cpp | 2 |
3 files changed, 38 insertions, 5 deletions
diff --git a/host/docs/usrp_e3x0.dox b/host/docs/usrp_e3x0.dox index d49310c2c..6baf7b7c8 100644 --- a/host/docs/usrp_e3x0.dox +++ b/host/docs/usrp_e3x0.dox @@ -518,7 +518,7 @@ frontends share the TX LO. Each LO is tunable between 50 MHz and 6 GHz. \subsubsection e3x0_dboard_e310_gain Frontend gain All frontends have individual analog gain controls. The receive -frontends have 73 dB of available gain; and the transmit frontends have +frontends have 76 dB of available gain; and the transmit frontends have 89.5 dB of available gain. Gain settings are application specific, but it is recommended that users consider using at least half of the available gain to get reasonable dynamic range. diff --git a/host/lib/usrp/common/ad936x_manager.cpp b/host/lib/usrp/common/ad936x_manager.cpp index 8c8897803..de8c4c7ab 100644 --- a/host/lib/usrp/common/ad936x_manager.cpp +++ b/host/lib/usrp/common/ad936x_manager.cpp @@ -19,6 +19,7 @@ #include <uhd/utils/msg.hpp> #include <boost/foreach.hpp> #include <boost/functional/hash.hpp> +#include <boost/thread/thread.hpp> using namespace uhd; using namespace uhd::usrp; @@ -80,34 +81,64 @@ class ad936x_manager_impl : public ad936x_manager } } + + // + // loopback_self_test checks the integrity of the FPGA->AD936x->FPGA sample interface. + // The AD936x is put in loopback mode that sends the TX data unchanged to the RX side. + // A test value is written to the codec_idle register in the TX side of the radio. + // The readback register is then used to capture the values on the TX and RX sides + // simultaneously for comparison. It is a reasonably effective test for AC timing + // since I/Q Ch0/Ch1 alternate over the same wires. Note, however, that it uses + // whatever timing is configured at the time the test is called rather than select + // worst case conditions to stress the interface. + // void loopback_self_test( wb_iface::sptr iface, wb_iface::wb_addr_type codec_idle_addr, wb_iface::wb_addr_type codec_readback_addr ) { + // Put AD936x in loopback mode _codec_ctrl->data_port_loopback(true); UHD_MSG(status) << "Performing CODEC loopback test... " << std::flush; UHD_ASSERT_THROW(bool(iface)); size_t hash = size_t(time(NULL)); + + // Allow some time for AD936x to enter loopback mode. + // There is no clear statement in the documentation of how long it takes, + // but UG-570 does say to "allow six ADC_CLK/64 clock cycles of flush time" + // when leaving the TX or RX states. That works out to ~75us at the + // minimum clock rate of 5 MHz, which lines up with test results. + // Sleeping 1ms is far more than enough. + boost::this_thread::sleep(boost::posix_time::milliseconds(1)); + for (size_t i = 0; i < 100; i++) { + // Create test word boost::hash_combine(hash, i); const boost::uint32_t word32 = boost::uint32_t(hash) & 0xfff0fff0; + + // Write test word to codec_idle idle register (on TX side) iface->poke32(codec_idle_addr, word32); - // We do 2 peeks so we have enough idleness for loopback to propagate - iface->peek64(codec_readback_addr); + + // Read back values - TX is lower 32-bits and RX is upper 32-bits const boost::uint64_t rb_word64 = iface->peek64(codec_readback_addr); const boost::uint32_t rb_tx = boost::uint32_t(rb_word64 >> 32); const boost::uint32_t rb_rx = boost::uint32_t(rb_word64 & 0xffffffff); + + // Compare TX and RX values to test word bool test_fail = word32 != rb_tx or word32 != rb_rx; - if (test_fail) { + if(test_fail) + { UHD_MSG(status) << "fail" << std::endl; throw uhd::runtime_error("CODEC loopback test failed."); } } UHD_MSG(status) << "pass" << std::endl; - /* Zero out the idle data. */ + + // Zero out the idle data. iface->poke32(codec_idle_addr, 0); + + // Take AD936x out of loopback mode _codec_ctrl->data_port_loopback(false); } diff --git a/host/lib/usrp/e300/e300_sysfs_hooks.cpp b/host/lib/usrp/e300/e300_sysfs_hooks.cpp index fdeaf0858..ee2ac21d7 100644 --- a/host/lib/usrp/e300/e300_sysfs_hooks.cpp +++ b/host/lib/usrp/e300/e300_sysfs_hooks.cpp @@ -67,6 +67,8 @@ std::string e300_get_sysfs_attr(const std::string &node, const std::string &attr retstring = udev_device_get_sysattr_value(dev, attr.c_str()); if (retstring.size()) break; + + udev_device_unref(dev); } udev_enumerate_unref(enumerate); |