From 4d9c03d44b02d0ee91355280dbc58d1f19deddea Mon Sep 17 00:00:00 2001 From: Michael West Date: Tue, 18 Feb 2014 16:18:04 -0800 Subject: - Fix for BUG #264: ./test_pps_input --source external passes even with no 1 PPS on external input on X3xx - Fixed behavior of PPS and clock references to be consistent and intuitive. -- Added detection of clock reference and PPS. -- Changed order of precedence to external, gpsdo, internal for default of clock and PPS. -- Throws runtime error if the user requests a reference clock or PPS that is not present. - Bumped FPGA compatibility to 4. --- host/lib/usrp/x300/x300_fw_common.h | 2 +- host/lib/usrp/x300/x300_impl.cpp | 101 +++++++++++++++++++++++------------- host/lib/usrp/x300/x300_impl.hpp | 1 + host/lib/usrp/x300/x300_regs.hpp | 14 +++++ 4 files changed, 81 insertions(+), 37 deletions(-) (limited to 'host/lib/usrp/x300') diff --git a/host/lib/usrp/x300/x300_fw_common.h b/host/lib/usrp/x300/x300_fw_common.h index c470e9bff..632391644 100644 --- a/host/lib/usrp/x300/x300_fw_common.h +++ b/host/lib/usrp/x300/x300_fw_common.h @@ -31,7 +31,7 @@ extern "C" { #define X300_FW_COMPAT_MAJOR 3 #define X300_FW_COMPAT_MINOR 0 -#define X300_FPGA_COMPAT_MAJOR 3 +#define X300_FPGA_COMPAT_MAJOR 4 //shared memory sections - in between the stack and the program space #define X300_FW_SHMEM_BASE 0x6000 diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index b20897fc6..5e0635767 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -581,12 +581,11 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) // Init shadow and clock source; the device comes up with it's internal // clock source before locking to something else (if requested). - mb.clock_control_regs__clock_source = 0; - mb.clock_control_regs__pps_select = 0; + mb.clock_control_regs__clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_INTERNAL; + mb.clock_control_regs__pps_select = ZPU_SR_CLOCK_CTRL_PPS_SRC_INTERNAL; mb.clock_control_regs__pps_out_enb = 0; mb.clock_control_regs__tcxo_enb = 1; mb.clock_control_regs__gpsdo_pwr = 1; - this->update_clock_source(mb, "internal"); this->update_clock_control(mb); size_t hw_rev = 0; @@ -767,32 +766,29 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) _tree->access(mb_path / "rx_subdev_spec").set(rx_fe_spec); _tree->access(mb_path / "tx_subdev_spec").set(tx_fe_spec); - //GPS installed: use external ref, time, and init time spec - if (mb.gps and mb.gps->gps_detected()) - { - UHD_MSG(status) << "Setting references to the internal GPSDO" << std::endl; - _tree->access(mb_path / "time_source" / "value").set("gpsdo"); - _tree->access(mb_path / "clock_source" / "value").set("gpsdo"); - UHD_MSG(status) << "Initializing time to the internal GPSDO" << std::endl; - const time_t tp = time_t(mb.gps->get_sensor("gps_time").to_int()+1); - _tree->access(mb_path / "time" / "pps").set(time_spec_t(tp)); - } - else - { - _tree->access(mb_path / "time_source" / "value").set("external"); + UHD_MSG(status) << "Initializing clock and PPS references..." << std::endl; + try { + //First, try external source _tree->access(mb_path / "clock_source" / "value").set("external"); - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - if (this->get_ref_locked(mb.zpu_ctrl).to_bool()) - { - UHD_MSG(status) << "Setting references to external sources" << std::endl; - } - else + _tree->access(mb_path / "time_source" / "value").set("external"); + UHD_MSG(status) << "References initialized to external sources" << std::endl; + } catch (uhd::exception::runtime_error &e) { + //No external source detected - set to the GPSDO if installed + if (mb.gps and mb.gps->gps_detected()) { - UHD_MSG(status) << "Setting references to internal sources" << std::endl; - _tree->access(mb_path / "time_source" / "value").set("internal"); + _tree->access(mb_path / "clock_source" / "value").set("gpsdo"); + _tree->access(mb_path / "time_source" / "value").set("gpsdo"); + UHD_MSG(status) << "References initialized to GPSDO sources" << std::endl; + UHD_MSG(status) << "Initializing time to the GPSDO time" << std::endl; + const time_t tp = time_t(mb.gps->get_sensor("gps_time").to_int()+1); + _tree->access(mb_path / "time" / "pps").set(time_spec_t(tp)); + } else { _tree->access(mb_path / "clock_source" / "value").set("internal"); + _tree->access(mb_path / "time_source" / "value").set("internal"); + UHD_MSG(status) << "References initialized to internal sources" << std::endl; } } + } x300_impl::~x300_impl(void) @@ -1297,9 +1293,9 @@ void x300_impl::update_clock_control(mboard_members_t &mb) { const size_t reg = mb.clock_control_regs__clock_source | (mb.clock_control_regs__pps_select << 2) - | (mb.clock_control_regs__pps_out_enb << 3) - | (mb.clock_control_regs__tcxo_enb << 4) - | (mb.clock_control_regs__gpsdo_pwr << 5) + | (mb.clock_control_regs__pps_out_enb << 4) + | (mb.clock_control_regs__tcxo_enb << 5) + | (mb.clock_control_regs__gpsdo_pwr << 6) ; mb.zpu_ctrl->poke32(SR_ADDR(SET0_BASE, ZPU_SR_CLOCK_CTRL), reg); } @@ -1307,42 +1303,75 @@ void x300_impl::update_clock_control(mboard_members_t &mb) void x300_impl::update_clock_source(mboard_members_t &mb, const std::string &source) { mb.clock_control_regs__clock_source = 0; + mb.clock_control_regs__tcxo_enb = 0; if (source == "internal") { - mb.clock_control_regs__clock_source = 0x2; - - mb.clock_control_regs__tcxo_enb = (source == "internal")? 1 : 0; + mb.clock_control_regs__clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_INTERNAL; + mb.clock_control_regs__tcxo_enb = 1; } else if (source == "external") { - mb.clock_control_regs__clock_source = 0x0; + mb.clock_control_regs__clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_EXTERNAL; } else if (source == "gpsdo") { - mb.clock_control_regs__clock_source = 0x3; + mb.clock_control_regs__clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_GPSDO; } else { throw uhd::key_error("update_clock_source: unknown source: " + source); } this->update_clock_control(mb); + + //check for lock - poll every 10 ms for up to 1 second + for (int i = 0; i < 10; i++) + { + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + if (get_ref_locked(mb.zpu_ctrl).to_bool()) + return; + } + + //failed to lock on reference + throw uhd::runtime_error((boost::format("The %d reference clock failed to lock. Please check the clock and try again.") % source).str()); } void x300_impl::update_time_source(mboard_members_t &mb, const std::string &source) { if (source == "internal") { - // no action needed + mb.clock_control_regs__pps_select = ZPU_SR_CLOCK_CTRL_PPS_SRC_INTERNAL; } else if (source == "external") { - mb.clock_control_regs__pps_select = (source == "external")? 1 : 0; + mb.clock_control_regs__pps_select = ZPU_SR_CLOCK_CTRL_PPS_SRC_EXTERNAL; } else if (source == "gpsdo") { - // no action needed + mb.clock_control_regs__pps_select = ZPU_SR_CLOCK_CTRL_PPS_SRC_GPSDO; } else { throw uhd::key_error("update_time_source: unknown source: " + source); } this->update_clock_control(mb); + + //check for valid pps + if (!is_pps_present(mb.zpu_ctrl)) + { + throw uhd::runtime_error((boost::format("The %d PPS was not detected. Please check the PPS source and try again.") % source).str()); + } } sensor_value_t x300_impl::get_ref_locked(wb_iface::sptr ctrl) { - const bool lock = (ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_CLK_STATUS)) & (1 << 2)) != 0; + uint32_t clk_status = ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_CLK_STATUS)); + const bool lock = ((clk_status & ZPU_RB_CLK_STATUS_LMK_LOCK) != 0); return sensor_value_t("Ref", lock, "locked", "unlocked"); } +bool x300_impl::is_pps_present(wb_iface::sptr ctrl) +{ + // The ZPU_RB_CLK_STATUS_PPS_DETECT bit toggles with each rising edge of the PPS. + // We monitor it for up to 1.5 seconds looking for it to toggle. + uint32_t pps_detect = ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_CLK_STATUS)) & ZPU_RB_CLK_STATUS_PPS_DETECT; + for (int i = 0; i < 15; i++) + { + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + uint32_t clk_status = ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_CLK_STATUS)); + if (pps_detect != (clk_status & ZPU_RB_CLK_STATUS_PPS_DETECT)) + return true; + } + return false; +} + void x300_impl::set_db_eeprom(i2c_iface::sptr i2c, const size_t addr, const uhd::usrp::dboard_eeprom_t &db_eeprom) { db_eeprom.store(*i2c, addr); diff --git a/host/lib/usrp/x300/x300_impl.hpp b/host/lib/usrp/x300/x300_impl.hpp index 1fb3676a0..b64f9ad01 100644 --- a/host/lib/usrp/x300/x300_impl.hpp +++ b/host/lib/usrp/x300/x300_impl.hpp @@ -302,6 +302,7 @@ private: void update_time_source(mboard_members_t&, const std::string &); uhd::sensor_value_t get_ref_locked(uhd::wb_iface::sptr); + bool is_pps_present(uhd::wb_iface::sptr); void set_db_eeprom(uhd::i2c_iface::sptr i2c, const size_t, const uhd::usrp::dboard_eeprom_t &); void set_mb_eeprom(uhd::i2c_iface::sptr i2c, const uhd::usrp::mboard_eeprom_t &); diff --git a/host/lib/usrp/x300/x300_regs.hpp b/host/lib/usrp/x300/x300_regs.hpp index e4ae76a38..fb1786deb 100644 --- a/host/lib/usrp/x300/x300_regs.hpp +++ b/host/lib/usrp/x300/x300_regs.hpp @@ -68,12 +68,26 @@ localparam ZPU_SR_SPI = 32; localparam ZPU_SR_ETHINT0 = 40; localparam ZPU_SR_ETHINT1 = 56; +//clock controls +#define ZPU_SR_CLOCK_CTRL_CLK_SRC_EXTERNAL 0x00 +#define ZPU_SR_CLOCK_CTRL_CLK_SRC_INTERNAL 0x02 +#define ZPU_SR_CLOCK_CTRL_CLK_SRC_GPSDO 0x03 +#define ZPU_SR_CLOCK_CTRL_PPS_SRC_EXTERNAL 0x00 +#define ZPU_SR_CLOCK_CTRL_PPS_SRC_INTERNAL 0x02 +#define ZPU_SR_CLOCK_CTRL_PPS_SRC_GPSDO 0x03 + localparam ZPU_RB_SPI = 2; localparam ZPU_RB_CLK_STATUS = 3; localparam ZPU_RB_COMPAT_NUM = 6; localparam ZPU_RB_ETH_TYPE0 = 4; localparam ZPU_RB_ETH_TYPE1 = 5; +//clock status +#define ZPU_RB_CLK_STATUS_LMK_STATUS (0x3 << 0) +#define ZPU_RB_CLK_STATUS_LMK_LOCK (0x1 << 2) +#define ZPU_RB_CLK_STATUS_LMK_HOLDOVER (0x1 << 3) +#define ZPU_RB_CLK_STATUS_PPS_DETECT (0x1 << 4) + //spi slaves on radio #define DB_DAC_SEN (1 << 7) #define DB_ADC_SEN (1 << 6) -- cgit v1.2.3 From 9ccd93ab11ebf2338b763a86aaf740c710fcc13d Mon Sep 17 00:00:00 2001 From: Michael West Date: Thu, 20 Feb 2014 11:27:57 -0800 Subject: Fixed bug found during testing where internal clock reference was taking several seconds to lock. Added reset to the clock control and called it whenever the clock reference is changed. --- host/lib/usrp/x300/x300_clock_ctrl.cpp | 4 ++++ host/lib/usrp/x300/x300_clock_ctrl.hpp | 6 ++++++ host/lib/usrp/x300/x300_impl.cpp | 26 +++++++++++++++----------- 3 files changed, 25 insertions(+), 11 deletions(-) (limited to 'host/lib/usrp/x300') diff --git a/host/lib/usrp/x300/x300_clock_ctrl.cpp b/host/lib/usrp/x300/x300_clock_ctrl.cpp index a986928a7..6a0b19c8c 100644 --- a/host/lib/usrp/x300/x300_clock_ctrl.cpp +++ b/host/lib/usrp/x300/x300_clock_ctrl.cpp @@ -48,6 +48,10 @@ x300_clock_ctrl_impl(uhd::spi_iface::sptr spiface, set_master_clock_rate(master_clock_rate); } +void reset() { + set_master_clock_rate(_master_clock_rate); +} + void sync_clocks(void) { //soft sync: //put the sync IO into output mode - FPGA must be input diff --git a/host/lib/usrp/x300/x300_clock_ctrl.hpp b/host/lib/usrp/x300/x300_clock_ctrl.hpp index 0e3caf900..4e7d6fc8e 100644 --- a/host/lib/usrp/x300/x300_clock_ctrl.hpp +++ b/host/lib/usrp/x300/x300_clock_ctrl.hpp @@ -78,6 +78,12 @@ public: * \param true = on, false = off */ virtual void set_ref_out(const bool) = 0; + + /*! Reset the clock control. + * Should be called if the reference clock changes + * to reduce the time required to achieve a lock. + */ + virtual void reset(void) = 0; }; #endif /* INCLUDED_X300_CLOCK_CTRL_HPP */ diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index 5e0635767..a231d7059 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -579,15 +579,6 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) //////////////////////////////////////////////////////////////////// UHD_MSG(status) << "Setup RF frontend clocking..." << std::endl; - // Init shadow and clock source; the device comes up with it's internal - // clock source before locking to something else (if requested). - mb.clock_control_regs__clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_INTERNAL; - mb.clock_control_regs__pps_select = ZPU_SR_CLOCK_CTRL_PPS_SRC_INTERNAL; - mb.clock_control_regs__pps_out_enb = 0; - mb.clock_control_regs__tcxo_enb = 1; - mb.clock_control_regs__gpsdo_pwr = 1; - this->update_clock_control(mb); - size_t hw_rev = 0; if(mb_eeprom.has_key("revision") and not mb_eeprom["revision"].empty()) { try { @@ -604,6 +595,15 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) hw_rev = X300_REV("D"); } + //Initialize clock control with internal references and GPSDO power on. + mb.clock_control_regs__clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_INTERNAL; + mb.clock_control_regs__pps_select = ZPU_SR_CLOCK_CTRL_PPS_SRC_INTERNAL; + mb.clock_control_regs__pps_out_enb = 0; + mb.clock_control_regs__tcxo_enb = 1; + mb.clock_control_regs__gpsdo_pwr = 1; + this->update_clock_control(mb); + + //Create clock control mb.clock = x300_clock_ctrl::make(mb.zpu_spi, 1 /*slaveno*/, hw_rev, @@ -782,13 +782,13 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) UHD_MSG(status) << "Initializing time to the GPSDO time" << std::endl; const time_t tp = time_t(mb.gps->get_sensor("gps_time").to_int()+1); _tree->access(mb_path / "time" / "pps").set(time_spec_t(tp)); + boost::this_thread::sleep(boost::posix_time::seconds(1)); //wait for time to be set } else { _tree->access(mb_path / "clock_source" / "value").set("internal"); _tree->access(mb_path / "time_source" / "value").set("internal"); UHD_MSG(status) << "References initialized to internal sources" << std::endl; } } - } x300_impl::~x300_impl(void) @@ -1317,7 +1317,11 @@ void x300_impl::update_clock_source(mboard_members_t &mb, const std::string &sou this->update_clock_control(mb); - //check for lock - poll every 10 ms for up to 1 second + //reset the clock control + //without this, the lock time is multiple seconds and the poll below will fail + mb.clock->reset(); + + //check for lock - poll every 100 ms for up to 1 second for (int i = 0; i < 10; i++) { boost::this_thread::sleep(boost::posix_time::milliseconds(100)); -- cgit v1.2.3 From fe90695e96630864e376e3becee30cb1f01083b8 Mon Sep 17 00:00:00 2001 From: michael-west Date: Fri, 21 Feb 2014 13:16:31 -0800 Subject: - Added wait for reference clock to lock. - Modified wait for GPSDO time setting to timeout after 1 second. --- host/lib/usrp/x300/x300_impl.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'host/lib/usrp/x300') diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index a231d7059..a92a1c806 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -610,6 +610,10 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) dev_addr.cast("master_clock_rate", X300_DEFAULT_TICK_RATE), dev_addr.cast("system_ref_rate", X300_DEFAULT_SYSREF_RATE)); + //wait for reference clock to lock + while (not get_ref_locked(mb.zpu_ctrl).to_bool()) + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + //////////////////////////////////////////////////////////////////// // create clock properties //////////////////////////////////////////////////////////////////// @@ -782,7 +786,9 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) UHD_MSG(status) << "Initializing time to the GPSDO time" << std::endl; const time_t tp = time_t(mb.gps->get_sensor("gps_time").to_int()+1); _tree->access(mb_path / "time" / "pps").set(time_spec_t(tp)); - boost::this_thread::sleep(boost::posix_time::seconds(1)); //wait for time to be set + //wait for time to be set (timeout after 1 second) + for (int i = 0; i < 10 && tp != (_tree->access(mb_path / "time" / "pps").get()).get_full_secs(); i++) + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); } else { _tree->access(mb_path / "clock_source" / "value").set("internal"); _tree->access(mb_path / "time_source" / "value").set("internal"); -- cgit v1.2.3 From 9126069560de0a462f58596055dad15b35693dce Mon Sep 17 00:00:00 2001 From: michael-west Date: Sat, 15 Mar 2014 08:42:05 -0700 Subject: Addressed comments from review. - Fixed typos. - Renamed reset() to reset_clocks(). - Created wait_for_ref_locked() function. --- host/lib/usrp/x300/x300_clock_ctrl.cpp | 2 +- host/lib/usrp/x300/x300_clock_ctrl.hpp | 4 +- host/lib/usrp/x300/x300_impl.cpp | 76 ++++++++++++++++++++-------------- host/lib/usrp/x300/x300_impl.hpp | 11 ++--- 4 files changed, 53 insertions(+), 40 deletions(-) (limited to 'host/lib/usrp/x300') diff --git a/host/lib/usrp/x300/x300_clock_ctrl.cpp b/host/lib/usrp/x300/x300_clock_ctrl.cpp index 6a0b19c8c..a8b30a0ab 100644 --- a/host/lib/usrp/x300/x300_clock_ctrl.cpp +++ b/host/lib/usrp/x300/x300_clock_ctrl.cpp @@ -48,7 +48,7 @@ x300_clock_ctrl_impl(uhd::spi_iface::sptr spiface, set_master_clock_rate(master_clock_rate); } -void reset() { +void reset_clocks() { set_master_clock_rate(_master_clock_rate); } diff --git a/host/lib/usrp/x300/x300_clock_ctrl.hpp b/host/lib/usrp/x300/x300_clock_ctrl.hpp index 4e7d6fc8e..e9904d25c 100644 --- a/host/lib/usrp/x300/x300_clock_ctrl.hpp +++ b/host/lib/usrp/x300/x300_clock_ctrl.hpp @@ -79,11 +79,11 @@ public: */ virtual void set_ref_out(const bool) = 0; - /*! Reset the clock control. + /*! Reset the clocks. * Should be called if the reference clock changes * to reduce the time required to achieve a lock. */ - virtual void reset(void) = 0; + virtual void reset_clocks(void) = 0; }; #endif /* INCLUDED_X300_CLOCK_CTRL_HPP */ diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index a92a1c806..6044a7e44 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -596,11 +596,11 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) } //Initialize clock control with internal references and GPSDO power on. - mb.clock_control_regs__clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_INTERNAL; - mb.clock_control_regs__pps_select = ZPU_SR_CLOCK_CTRL_PPS_SRC_INTERNAL; - mb.clock_control_regs__pps_out_enb = 0; - mb.clock_control_regs__tcxo_enb = 1; - mb.clock_control_regs__gpsdo_pwr = 1; + mb.clock_control_regs_clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_INTERNAL; + mb.clock_control_regs_pps_select = ZPU_SR_CLOCK_CTRL_PPS_SRC_INTERNAL; + mb.clock_control_regs_pps_out_enb = 0; + mb.clock_control_regs_tcxo_enb = 1; + mb.clock_control_regs_gpsdo_pwr = 1; this->update_clock_control(mb); //Create clock control @@ -611,8 +611,7 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) dev_addr.cast("system_ref_rate", X300_DEFAULT_SYSREF_RATE)); //wait for reference clock to lock - while (not get_ref_locked(mb.zpu_ctrl).to_bool()) - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + wait_for_ref_locked(mb.zpu_ctrl, 1.0); //////////////////////////////////////////////////////////////////// // create clock properties @@ -1291,32 +1290,32 @@ void x300_impl::register_loopback_self_test(wb_iface::sptr iface) void x300_impl::set_time_source_out(mboard_members_t &mb, const bool enb) { - mb.clock_control_regs__pps_out_enb = enb? 1 : 0; + mb.clock_control_regs_pps_out_enb = enb? 1 : 0; this->update_clock_control(mb); } void x300_impl::update_clock_control(mboard_members_t &mb) { - const size_t reg = mb.clock_control_regs__clock_source - | (mb.clock_control_regs__pps_select << 2) - | (mb.clock_control_regs__pps_out_enb << 4) - | (mb.clock_control_regs__tcxo_enb << 5) - | (mb.clock_control_regs__gpsdo_pwr << 6) + const size_t reg = mb.clock_control_regs_clock_source + | (mb.clock_control_regs_pps_select << 2) + | (mb.clock_control_regs_pps_out_enb << 4) + | (mb.clock_control_regs_tcxo_enb << 5) + | (mb.clock_control_regs_gpsdo_pwr << 6) ; mb.zpu_ctrl->poke32(SR_ADDR(SET0_BASE, ZPU_SR_CLOCK_CTRL), reg); } void x300_impl::update_clock_source(mboard_members_t &mb, const std::string &source) { - mb.clock_control_regs__clock_source = 0; - mb.clock_control_regs__tcxo_enb = 0; + mb.clock_control_regs_clock_source = 0; + mb.clock_control_regs_tcxo_enb = 0; if (source == "internal") { - mb.clock_control_regs__clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_INTERNAL; - mb.clock_control_regs__tcxo_enb = 1; + mb.clock_control_regs_clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_INTERNAL; + mb.clock_control_regs_tcxo_enb = 1; } else if (source == "external") { - mb.clock_control_regs__clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_EXTERNAL; + mb.clock_control_regs_clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_EXTERNAL; } else if (source == "gpsdo") { - mb.clock_control_regs__clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_GPSDO; + mb.clock_control_regs_clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_GPSDO; } else { throw uhd::key_error("update_clock_source: unknown source: " + source); } @@ -1325,28 +1324,27 @@ void x300_impl::update_clock_source(mboard_members_t &mb, const std::string &sou //reset the clock control //without this, the lock time is multiple seconds and the poll below will fail - mb.clock->reset(); + mb.clock->reset_clocks(); - //check for lock - poll every 100 ms for up to 1 second - for (int i = 0; i < 10; i++) - { - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - if (get_ref_locked(mb.zpu_ctrl).to_bool()) - return; + //wait for lock + try { + wait_for_ref_locked(mb.zpu_ctrl, 1.0); + } catch (uhd::runtime_error &e) { + //failed to lock on reference + throw uhd::runtime_error( + (boost::format("Error setting the clock source to %s: %s Please check the clock and try again.") + % source % e.what()).str()); } - - //failed to lock on reference - throw uhd::runtime_error((boost::format("The %d reference clock failed to lock. Please check the clock and try again.") % source).str()); } void x300_impl::update_time_source(mboard_members_t &mb, const std::string &source) { if (source == "internal") { - mb.clock_control_regs__pps_select = ZPU_SR_CLOCK_CTRL_PPS_SRC_INTERNAL; + mb.clock_control_regs_pps_select = ZPU_SR_CLOCK_CTRL_PPS_SRC_INTERNAL; } else if (source == "external") { - mb.clock_control_regs__pps_select = ZPU_SR_CLOCK_CTRL_PPS_SRC_EXTERNAL; + mb.clock_control_regs_pps_select = ZPU_SR_CLOCK_CTRL_PPS_SRC_EXTERNAL; } else if (source == "gpsdo") { - mb.clock_control_regs__pps_select = ZPU_SR_CLOCK_CTRL_PPS_SRC_GPSDO; + mb.clock_control_regs_pps_select = ZPU_SR_CLOCK_CTRL_PPS_SRC_GPSDO; } else { throw uhd::key_error("update_time_source: unknown source: " + source); } @@ -1360,6 +1358,20 @@ void x300_impl::update_time_source(mboard_members_t &mb, const std::string &sour } } +void x300_impl::wait_for_ref_locked(wb_iface::sptr ctrl, double timeout) +{ + boost::system_time timeout_time = boost::get_system_time() + boost::posix_time::milliseconds(timeout * 1000.0); + do + { + if (get_ref_locked(ctrl).to_bool()) + return; + boost::this_thread::sleep(boost::posix_time::milliseconds(1)); + } while (boost::get_system_time() < timeout_time); + + //failed to lock on reference + throw uhd::runtime_error("The reference clock failed to lock."); +} + sensor_value_t x300_impl::get_ref_locked(wb_iface::sptr ctrl) { uint32_t clk_status = ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_CLK_STATUS)); diff --git a/host/lib/usrp/x300/x300_impl.hpp b/host/lib/usrp/x300/x300_impl.hpp index b64f9ad01..059c1265c 100644 --- a/host/lib/usrp/x300/x300_impl.hpp +++ b/host/lib/usrp/x300/x300_impl.hpp @@ -204,11 +204,11 @@ private: gpio_core_200::sptr fp_gpio; //clock control register bits - int clock_control_regs__clock_source; - int clock_control_regs__pps_select; - int clock_control_regs__pps_out_enb; - int clock_control_regs__tcxo_enb; - int clock_control_regs__gpsdo_pwr; + int clock_control_regs_clock_source; + int clock_control_regs_pps_select; + int clock_control_regs_pps_out_enb; + int clock_control_regs_tcxo_enb; + int clock_control_regs_gpsdo_pwr; //which FPGA image is loaded std::string loaded_fpga_image; @@ -302,6 +302,7 @@ private: void update_time_source(mboard_members_t&, const std::string &); uhd::sensor_value_t get_ref_locked(uhd::wb_iface::sptr); + void wait_for_ref_locked(uhd::wb_iface::sptr, double timeout = 0.0); bool is_pps_present(uhd::wb_iface::sptr); void set_db_eeprom(uhd::i2c_iface::sptr i2c, const size_t, const uhd::usrp::dboard_eeprom_t &); -- cgit v1.2.3