From be54951d4c14b11e21518f2e7d87fd527102c948 Mon Sep 17 00:00:00 2001 From: michael-west Date: Wed, 15 Apr 2015 13:55:10 -0700 Subject: UHD host code changes for B200 rev 5 support. --- host/lib/usrp/b200/b200_impl.cpp | 35 ++++++++++++++++++++++------------- host/lib/usrp/b200/b200_impl.hpp | 4 ++++ 2 files changed, 26 insertions(+), 13 deletions(-) (limited to 'host/lib/usrp/b200') diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index e567ff434..cea7e5969 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -43,10 +43,6 @@ using namespace uhd::transport; static const boost::posix_time::milliseconds REENUMERATION_TIMEOUT_MS(3000); -//! mapping of frontend to radio perif index -static const size_t FE1 = 1; -static const size_t FE2 = 0; - class b200_ad9361_client_t : public ad9361_params { public: ~b200_ad9361_client_t() {} @@ -264,6 +260,19 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : UHD_ASSERT_THROW(device_addr.has_key("fpga")); } + //set up frontend mapping + _fe1 = 1; + _fe2 = 0; + if (not mb_eeprom["revision"].empty()) + { + size_t rev = boost::lexical_cast(mb_eeprom["revision"]); + if (rev == 5) + { + _fe1 = 0; + _fe2 = 1; + } + } + //extract the FPGA path for the B200 std::string b200_fpga_image = find_image_path( device_addr.has_key("fpga")? device_addr["fpga"] : default_file_name @@ -628,7 +637,7 @@ void b200_impl::setup_radio(const size_t dspno) for(size_t direction = 0; direction < 2; direction++) { const std::string x = direction? "rx" : "tx"; - const std::string key = std::string((direction? "RX" : "TX")) + std::string(((dspno == FE1)? "1" : "2")); + const std::string key = std::string((direction? "RX" : "TX")) + std::string(((dspno == _fe1)? "1" : "2")); const fs_path rf_fe_path = mb_path / "dboards" / "A" / (x+"_frontends") / (dspno? "B" : "A"); _tree->create(rf_fe_path / "name").set("FE-"+key); @@ -924,9 +933,9 @@ void b200_impl::reset_codec_dcm(void) void b200_impl::update_atrs(void) { - if (_radio_perifs.size() > FE1 and _radio_perifs[FE1].atr) + if (_radio_perifs.size() > _fe1 and _radio_perifs[_fe1].atr) { - radio_perifs_t &perif = _radio_perifs[FE1]; + radio_perifs_t &perif = _radio_perifs[_fe1]; const bool enb_rx = bool(perif.rx_streamer.lock()); const bool enb_tx = bool(perif.tx_streamer.lock()); const bool is_rx2 = perif.ant_rx2; @@ -942,9 +951,9 @@ void b200_impl::update_atrs(void) atr->set_atr_reg(dboard_iface::ATR_REG_TX_ONLY, txonly); atr->set_atr_reg(dboard_iface::ATR_REG_FULL_DUPLEX, fd); } - if (_radio_perifs.size() > FE2 and _radio_perifs[FE2].atr) + if (_radio_perifs.size() > _fe2 and _radio_perifs[_fe2].atr) { - radio_perifs_t &perif = _radio_perifs[FE2]; + radio_perifs_t &perif = _radio_perifs[_fe2]; const bool enb_rx = bool(perif.rx_streamer.lock()); const bool enb_tx = bool(perif.tx_streamer.lock()); const bool is_rx2 = perif.ant_rx2; @@ -972,10 +981,10 @@ void b200_impl::update_antenna_sel(const size_t which, const std::string &ant) void b200_impl::update_enables(void) { //extract settings from state variables - const bool enb_tx1 = (_radio_perifs.size() > FE1) and bool(_radio_perifs[FE1].tx_streamer.lock()); - const bool enb_rx1 = (_radio_perifs.size() > FE1) and bool(_radio_perifs[FE1].rx_streamer.lock()); - const bool enb_tx2 = (_radio_perifs.size() > FE2) and bool(_radio_perifs[FE2].tx_streamer.lock()); - const bool enb_rx2 = (_radio_perifs.size() > FE2) and bool(_radio_perifs[FE2].rx_streamer.lock()); + const bool enb_tx1 = (_radio_perifs.size() > _fe1) and bool(_radio_perifs[_fe1].tx_streamer.lock()); + const bool enb_rx1 = (_radio_perifs.size() > _fe1) and bool(_radio_perifs[_fe1].rx_streamer.lock()); + const bool enb_tx2 = (_radio_perifs.size() > _fe2) and bool(_radio_perifs[_fe2].tx_streamer.lock()); + const bool enb_rx2 = (_radio_perifs.size() > _fe2) and bool(_radio_perifs[_fe2].rx_streamer.lock()); const size_t num_rx = (enb_rx1?1:0) + (enb_rx2?1:0); const size_t num_tx = (enb_tx1?1:0) + (enb_tx2?1:0); const bool mimo = num_rx == 2 or num_tx == 2; diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp index 396819f9a..e871e6b9a 100644 --- a/host/lib/usrp/b200/b200_impl.hpp +++ b/host/lib/usrp/b200/b200_impl.hpp @@ -119,6 +119,10 @@ private: boost::mutex _transport_setup_mutex; + // mapping of frontend to radio perif index + size_t _fe1; + size_t _fe2; + //async ctrl + msgs uhd::msg_task::sptr _async_task; typedef uhd::transport::bounded_buffer async_md_type; -- cgit v1.2.3 From df6bf0e77d42f2281fbe07296766924c3c066962 Mon Sep 17 00:00:00 2001 From: michael-west Date: Wed, 15 Apr 2015 17:38:44 -0700 Subject: B200: Stricter checking of product and revision for frontend mapping. --- host/lib/usrp/b200/b200_impl.cpp | 15 ++++++++------- host/lib/usrp/b200/b200_impl.hpp | 11 +++++++---- 2 files changed, 15 insertions(+), 11 deletions(-) (limited to 'host/lib/usrp/b200') diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index cea7e5969..f55ae2a71 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -238,6 +238,7 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : //////////////////////////////////////////////////////////////////// std::string default_file_name; std::string product_name = "B200?"; + enum {UNKNOWN,B200,B210} product = UNKNOWN; if (not mb_eeprom["product"].empty()) { switch (boost::lexical_cast(mb_eeprom["product"])) @@ -246,11 +247,13 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : case 0x7737: product_name = "B200"; default_file_name = B200_FPGA_FILE_NAME; + product = B200; break; case 0x7738: case 0x0002: product_name = "B210"; default_file_name = B210_FPGA_FILE_NAME; + product = B210; break; default: UHD_MSG(error) << "B200 unknown product code: " << mb_eeprom["product"] << std::endl; } @@ -263,14 +266,12 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : //set up frontend mapping _fe1 = 1; _fe2 = 0; - if (not mb_eeprom["revision"].empty()) + if (product == B200 and + not mb_eeprom["revision"].empty() and + boost::lexical_cast(mb_eeprom["revision"]) >= 5) { - size_t rev = boost::lexical_cast(mb_eeprom["revision"]); - if (rev == 5) - { - _fe1 = 0; - _fe2 = 1; - } + _fe1 = 0; + _fe2 = 1; } //extract the FPGA path for the B200 diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp index e871e6b9a..fd94d36ab 100644 --- a/host/lib/usrp/b200/b200_impl.hpp +++ b/host/lib/usrp/b200/b200_impl.hpp @@ -119,10 +119,6 @@ private: boost::mutex _transport_setup_mutex; - // mapping of frontend to radio perif index - size_t _fe1; - size_t _fe2; - //async ctrl + msgs uhd::msg_task::sptr _async_task; typedef uhd::transport::bounded_buffer async_md_type; @@ -165,6 +161,13 @@ private: }; std::vector _radio_perifs; + //mapping of AD936x frontends (FE1 and FE2) to radio perif index (0 and 1) + //FE1 corresponds to the ports labeled "RF B" on the B200/B210 + //FE2 corresponds to the ports labeled "RF A" on the B200/B210 + //the mapping is product and revision specific + size_t _fe1; + size_t _fe2; + /*! \brief Setup the DSP chain for one radio front-end. * */ -- cgit v1.2.3 From 24c370781e7ea2e627ce36d3b102a686eaedcf1b Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Fri, 13 Mar 2015 14:39:09 -0700 Subject: b2x0: Cleaned up device lookup (moved all constants to one place) Conflicts: host/lib/usrp/b200/b200_iface.hpp host/lib/usrp/b200/b200_impl.cpp --- host/lib/usrp/b200/b200_iface.hpp | 45 +++++++++++++++++---- host/lib/usrp/b200/b200_impl.cpp | 84 +++++++++++++++++++++------------------ host/lib/usrp/b200/b200_impl.hpp | 2 + 3 files changed, 84 insertions(+), 47 deletions(-) (limited to 'host/lib/usrp/b200') diff --git a/host/lib/usrp/b200/b200_iface.hpp b/host/lib/usrp/b200/b200_iface.hpp index 83adfdd64..1d123439a 100644 --- a/host/lib/usrp/b200/b200_iface.hpp +++ b/host/lib/usrp/b200/b200_iface.hpp @@ -1,5 +1,5 @@ // -// Copyright 2012-2013 Ettus Research LLC +// Copyright 2012-2013,2015 Ettus Research LLC // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -21,19 +21,48 @@ #include #include #include //i2c iface +#include +#include #include #include #include "ad9361_ctrl.hpp" -const static boost::uint16_t B200_VENDOR_ID = 0x2500; -const static boost::uint16_t B200_PRODUCT_ID = 0x0020; -const static boost::uint16_t FX3_VID = 0x04b4; -const static boost::uint16_t FX3_DEFAULT_PID = 0x00f3; -const static boost::uint16_t FX3_REENUM_PID = 0x00f0; +enum b200_type_t { + B200, + B210 +}; + +const static boost::uint16_t B200_VENDOR_ID = 0x2500; +const static boost::uint16_t B200_VENDOR_NI_ID = 0x3923; +const static boost::uint16_t B200_PRODUCT_ID = 0x0020; +const static boost::uint16_t B200_PRODUCT_NI_ID = 0x7813; +const static boost::uint16_t B210_PRODUCT_NI_ID = 0x7814; +const static boost::uint16_t FX3_VID = 0x04b4; +const static boost::uint16_t FX3_DEFAULT_PID = 0x00f3; +const static boost::uint16_t FX3_REENUM_PID = 0x00f0; static const std::string B200_FW_FILE_NAME = "usrp_b200_fw.hex"; -static const std::string B200_FPGA_FILE_NAME = "usrp_b200_fpga.bin"; -static const std::string B210_FPGA_FILE_NAME = "usrp_b210_fpga.bin"; + +//! Map the product ID (in the EEPROM) to a device type +static const uhd::dict B2X0_PRODUCT_ID = boost::assign::map_list_of + (0x0001, B200) + (0x7737, B200) + (B200_PRODUCT_NI_ID, B200) + (0x0002, B210) + (0x7738, B210) + (B210_PRODUCT_NI_ID, B210) +; + +static const uhd::dict B2X0_STR_NAMES = boost::assign::map_list_of + (B200, "B200") + (B210, "B210") +; + +static const uhd::dict B2X0_FPGA_FILE_NAME = boost::assign::map_list_of + (B200, "usrp_b200_fpga.bin") + (B210, "usrp_b210_fpga.bin") +; + class UHD_API b200_iface: boost::noncopyable, public virtual uhd::i2c_iface { public: diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index f55ae2a71..f4a124a32 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -73,6 +73,24 @@ public: /*********************************************************************** * Discovery **********************************************************************/ +//! Look up the type of B-Series device we're currently running. +// If the product ID stored in mb_eeprom is invalid, throws a +// uhd::runtime_error. +static b200_type_t get_b200_type(const mboard_eeprom_t &mb_eeprom) +{ + if (mb_eeprom["product"].empty()) { + throw uhd::runtime_error("B200: Missing product ID on EEPROM."); + } + boost::uint16_t product_id = boost::lexical_cast(mb_eeprom["product"]); + if (not B2X0_PRODUCT_ID.has_key(product_id)) { + throw uhd::runtime_error(str( + boost::format("B200 unknown product code: 0x%04x") + % product_id + )); + } + return B2X0_PRODUCT_ID[product_id]; +} + static device_addrs_t b200_find(const device_addr_t &hint) { device_addrs_t b200_addrs; @@ -148,20 +166,14 @@ static device_addrs_t b200_find(const device_addr_t &hint) new_addr["type"] = "b200"; new_addr["name"] = mb_eeprom["name"]; new_addr["serial"] = handle->get_serial(); - if (not mb_eeprom["product"].empty()) - { - switch (boost::lexical_cast(mb_eeprom["product"])) - { - case 0x0001: - case 0x7737: - new_addr["product"] = "B200"; - break; - case 0x7738: - case 0x0002: - new_addr["product"] = "B210"; - break; - default: UHD_MSG(error) << "B200 unknown product code: " << mb_eeprom["product"] << std::endl; - } + try { + // Turn the 16-Bit product ID into a string representation + new_addr["product"] = B2X0_STR_NAMES[get_b200_type(mb_eeprom)]; + } catch (const uhd::runtime_error &e) { + // No problem if this fails -- this is just device discovery, after all. + UHD_MSG(error) << e.what() << std::endl; + // Skip this loop. + continue; } //this is a found b200 when the hint serial and name match or blank if ( @@ -234,39 +246,30 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : .subscribe(boost::bind(&b200_impl::set_mb_eeprom, this, _1)); //////////////////////////////////////////////////////////////////// - // Load the FPGA image, then reset GPIF + // Identify the device type //////////////////////////////////////////////////////////////////// std::string default_file_name; - std::string product_name = "B200?"; - enum {UNKNOWN,B200,B210} product = UNKNOWN; - if (not mb_eeprom["product"].empty()) - { - switch (boost::lexical_cast(mb_eeprom["product"])) - { - case 0x0001: - case 0x7737: - product_name = "B200"; - default_file_name = B200_FPGA_FILE_NAME; - product = B200; - break; - case 0x7738: - case 0x0002: - product_name = "B210"; - default_file_name = B210_FPGA_FILE_NAME; - product = B210; - break; - default: UHD_MSG(error) << "B200 unknown product code: " << mb_eeprom["product"] << std::endl; + std::string product_name; + try { + // This will throw if the product ID is invalid: + _b200_type = get_b200_type(mb_eeprom); + default_file_name = B2X0_FPGA_FILE_NAME.get(_b200_type); + product_name = B2X0_STR_NAMES.get(_b200_type); + } catch (const uhd::runtime_error &e) { + // The only reason we may let this pass is if the user specified + // the FPGA file name: + if (not device_addr.has_key("fpga")) { + throw e; } - } - if (default_file_name.empty()) - { - UHD_ASSERT_THROW(device_addr.has_key("fpga")); + // In this case, we must provide a default product name: + product_name = "B200?"; + _b200_type = B200; } //set up frontend mapping _fe1 = 1; _fe2 = 0; - if (product == B200 and + if (_b200_type == B200 and not mb_eeprom["revision"].empty() and boost::lexical_cast(mb_eeprom["revision"]) >= 5) { @@ -274,6 +277,9 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : _fe2 = 1; } + //////////////////////////////////////////////////////////////////// + // Load the FPGA image, then reset GPIF + //////////////////////////////////////////////////////////////////// //extract the FPGA path for the B200 std::string b200_fpga_image = find_image_path( device_addr.has_key("fpga")? device_addr["fpga"] : default_file_name diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp index fd94d36ab..b580ff260 100644 --- a/host/lib/usrp/b200/b200_impl.hpp +++ b/host/lib/usrp/b200/b200_impl.hpp @@ -101,6 +101,8 @@ public: void check_streamer_args(const uhd::stream_args_t &args, double tick_rate, const char* direction = NULL); private: + b200_type_t _b200_type; + //controllers b200_iface::sptr _iface; radio_ctrl_core_3000::sptr _local_ctrl; -- cgit v1.2.3 From 0a103ba2bad243652e8c57732190a18a2ee31d38 Mon Sep 17 00:00:00 2001 From: michael-west Date: Fri, 17 Apr 2015 17:43:07 -0700 Subject: B200: Bumped FPGA compat number to 5 B200: Added bit to SR_MISC_OUT register to control ATR mapping from radio to frontend --- host/lib/usrp/b200/b200_impl.cpp | 7 ++++--- host/lib/usrp/b200/b200_impl.hpp | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'host/lib/usrp/b200') diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index f4a124a32..273153c16 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -273,8 +273,9 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : not mb_eeprom["revision"].empty() and boost::lexical_cast(mb_eeprom["revision"]) >= 5) { - _fe1 = 0; - _fe2 = 1; + _fe1 = 0; //map radio0 to FE1 + _fe2 = 1; //map radio1 to FE2 + _gpio_state.atr_sel = 1; //map radio0 ATR pins to FE2 } //////////////////////////////////////////////////////////////////// @@ -332,7 +333,6 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : /* Initialize the GPIOs, set the default bandsels to the lower range. Note * that calling update_bandsel calls update_gpio_state(). */ - _gpio_state = gpio_state(); update_bandsel("RX", 800e6); update_bandsel("TX", 850e6); @@ -916,6 +916,7 @@ void b200_impl::update_bandsel(const std::string& which, double freq) void b200_impl::update_gpio_state(void) { const boost::uint32_t misc_word = 0 + | (_gpio_state.atr_sel << 8) | (_gpio_state.tx_bandsel_a << 7) | (_gpio_state.tx_bandsel_b << 6) | (_gpio_state.rx_bandsel_a << 5) diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp index b580ff260..8d0c637d7 100644 --- a/host/lib/usrp/b200/b200_impl.hpp +++ b/host/lib/usrp/b200/b200_impl.hpp @@ -47,7 +47,7 @@ #include "recv_packet_demuxer_3000.hpp" static const boost::uint8_t B200_FW_COMPAT_NUM_MAJOR = 7; static const boost::uint8_t B200_FW_COMPAT_NUM_MINOR = 0; -static const boost::uint16_t B200_FPGA_COMPAT_NUM = 4; +static const boost::uint16_t B200_FPGA_COMPAT_NUM = 5; static const double B200_BUS_CLOCK_RATE = 100e6; static const double B200_DEFAULT_TICK_RATE = 32e6; static const double B200_DEFAULT_FREQ = 100e6; // Hz @@ -177,7 +177,7 @@ private: void handle_overflow(const size_t radio_index); struct gpio_state { - boost::uint32_t tx_bandsel_a, tx_bandsel_b, rx_bandsel_a, rx_bandsel_b, rx_bandsel_c, codec_arst, mimo, ref_sel; + boost::uint32_t tx_bandsel_a, tx_bandsel_b, rx_bandsel_a, rx_bandsel_b, rx_bandsel_c, codec_arst, mimo, ref_sel, atr_sel; gpio_state() { tx_bandsel_a = 0; @@ -188,6 +188,7 @@ private: codec_arst = 0; mimo = 0; ref_sel = 0; + atr_sel = 0; } } _gpio_state; -- cgit v1.2.3 From eacd36d94d8d9432c09a8ab79884845efeb5fd4b Mon Sep 17 00:00:00 2001 From: Michael Dickens Date: Mon, 20 Apr 2015 14:32:28 -0400 Subject: b200: Boost 1.58-related fixes in B200 IO code. When returning an invalid payload in handle_async_task, Boost 1.58 does not allow NULL to be returned; instead, to be more compatible, use the correct type initialized to (0, []). --- host/lib/usrp/b200/b200_io_impl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'host/lib/usrp/b200') diff --git a/host/lib/usrp/b200/b200_io_impl.cpp b/host/lib/usrp/b200/b200_io_impl.cpp index cf5ba7a11..3e156f9bb 100644 --- a/host/lib/usrp/b200/b200_io_impl.cpp +++ b/host/lib/usrp/b200/b200_io_impl.cpp @@ -194,7 +194,7 @@ boost::optional b200_impl::handle_async_task( { managed_recv_buffer::sptr buff = xport->get_recv_buff(); if (not buff or buff->size() < 8) - return NULL; + return uhd::msg_task::msg_type_t(0, uhd::msg_task::msg_payload_t()); const boost::uint32_t sid = uhd::wtohx(buff->cast()[1]); switch (sid) { @@ -258,7 +258,7 @@ boost::optional b200_impl::handle_async_task( default: UHD_MSG(error) << "Got a ctrl packet with unknown SID " << sid << std::endl; } - return NULL; + return uhd::msg_task::msg_type_t(0, uhd::msg_task::msg_payload_t()); } /*********************************************************************** -- cgit v1.2.3 From a9b6141d7c5f46fd85a629c568ff0e8ebd46ec24 Mon Sep 17 00:00:00 2001 From: Michael Dickens Date: Mon, 20 Apr 2015 14:32:28 -0400 Subject: b200: Boost 1.58-related fixes in B200 IO code. When returning an invalid payload in handle_async_task, Boost 1.58 does not allow NULL to be returned; instead, to be more compatible, use the correct type initialized to (0, []). --- host/lib/usrp/b200/b200_io_impl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'host/lib/usrp/b200') diff --git a/host/lib/usrp/b200/b200_io_impl.cpp b/host/lib/usrp/b200/b200_io_impl.cpp index d6df726af..eb7bbe048 100644 --- a/host/lib/usrp/b200/b200_io_impl.cpp +++ b/host/lib/usrp/b200/b200_io_impl.cpp @@ -300,7 +300,7 @@ boost::optional b200_impl::handle_async_task( { managed_recv_buffer::sptr buff = xport->get_recv_buff(); if (not buff or buff->size() < 8) - return NULL; + return uhd::msg_task::msg_type_t(0, uhd::msg_task::msg_payload_t()); const boost::uint32_t sid = uhd::wtohx(buff->cast()[1]); switch (sid) { @@ -364,7 +364,7 @@ boost::optional b200_impl::handle_async_task( default: UHD_MSG(error) << "Got a ctrl packet with unknown SID " << sid << std::endl; } - return NULL; + return uhd::msg_task::msg_type_t(0, uhd::msg_task::msg_payload_t()); } /*********************************************************************** -- cgit v1.2.3 From da800edf099db2adcb6b2fd4038cc6d15cdaf57f Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Fri, 13 Mar 2015 14:39:09 -0700 Subject: b2x0: Cleaned up device lookup (moved all constants to one place) --- host/lib/usrp/b200/b200_iface.hpp | 44 ++++++++++++++++---- host/lib/usrp/b200/b200_impl.cpp | 87 ++++++++++++++++++++------------------- host/lib/usrp/b200/b200_impl.hpp | 2 + 3 files changed, 81 insertions(+), 52 deletions(-) (limited to 'host/lib/usrp/b200') diff --git a/host/lib/usrp/b200/b200_iface.hpp b/host/lib/usrp/b200/b200_iface.hpp index 1821865d3..1d123439a 100644 --- a/host/lib/usrp/b200/b200_iface.hpp +++ b/host/lib/usrp/b200/b200_iface.hpp @@ -1,5 +1,5 @@ // -// Copyright 2012-2013 Ettus Research LLC +// Copyright 2012-2013,2015 Ettus Research LLC // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -21,22 +21,48 @@ #include #include #include //i2c iface +#include +#include #include #include #include "ad9361_ctrl.hpp" -const static boost::uint16_t B200_VENDOR_ID = 0x2500; -const static boost::uint16_t B200_VENDOR_NI_ID = 0x3923; -const static boost::uint16_t B200_PRODUCT_ID = 0x0020; +enum b200_type_t { + B200, + B210 +}; + +const static boost::uint16_t B200_VENDOR_ID = 0x2500; +const static boost::uint16_t B200_VENDOR_NI_ID = 0x3923; +const static boost::uint16_t B200_PRODUCT_ID = 0x0020; const static boost::uint16_t B200_PRODUCT_NI_ID = 0x7813; const static boost::uint16_t B210_PRODUCT_NI_ID = 0x7814; -const static boost::uint16_t FX3_VID = 0x04b4; -const static boost::uint16_t FX3_DEFAULT_PID = 0x00f3; -const static boost::uint16_t FX3_REENUM_PID = 0x00f0; +const static boost::uint16_t FX3_VID = 0x04b4; +const static boost::uint16_t FX3_DEFAULT_PID = 0x00f3; +const static boost::uint16_t FX3_REENUM_PID = 0x00f0; static const std::string B200_FW_FILE_NAME = "usrp_b200_fw.hex"; -static const std::string B200_FPGA_FILE_NAME = "usrp_b200_fpga.bin"; -static const std::string B210_FPGA_FILE_NAME = "usrp_b210_fpga.bin"; + +//! Map the product ID (in the EEPROM) to a device type +static const uhd::dict B2X0_PRODUCT_ID = boost::assign::map_list_of + (0x0001, B200) + (0x7737, B200) + (B200_PRODUCT_NI_ID, B200) + (0x0002, B210) + (0x7738, B210) + (B210_PRODUCT_NI_ID, B210) +; + +static const uhd::dict B2X0_STR_NAMES = boost::assign::map_list_of + (B200, "B200") + (B210, "B210") +; + +static const uhd::dict B2X0_FPGA_FILE_NAME = boost::assign::map_list_of + (B200, "usrp_b200_fpga.bin") + (B210, "usrp_b210_fpga.bin") +; + class UHD_API b200_iface: boost::noncopyable, public virtual uhd::i2c_iface { public: diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index afc21d031..14c2c31aa 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -77,6 +77,24 @@ public: /*********************************************************************** * Discovery **********************************************************************/ +//! Look up the type of B-Series device we're currently running. +// If the product ID stored in mb_eeprom is invalid, throws a +// uhd::runtime_error. +static b200_type_t get_b200_type(const mboard_eeprom_t &mb_eeprom) +{ + if (mb_eeprom["product"].empty()) { + throw uhd::runtime_error("B200: Missing product ID on EEPROM."); + } + boost::uint16_t product_id = boost::lexical_cast(mb_eeprom["product"]); + if (not B2X0_PRODUCT_ID.has_key(product_id)) { + throw uhd::runtime_error(str( + boost::format("B200 unknown product code: 0x%04x") + % product_id + )); + } + return B2X0_PRODUCT_ID[product_id]; +} + static device_addrs_t b200_find(const device_addr_t &hint) { device_addrs_t b200_addrs; @@ -155,24 +173,14 @@ static device_addrs_t b200_find(const device_addr_t &hint) new_addr["type"] = "b200"; new_addr["name"] = mb_eeprom["name"]; new_addr["serial"] = handle->get_serial(); - if (not mb_eeprom["product"].empty()) - { - switch (boost::lexical_cast(mb_eeprom["product"])) - { - //0x0001 and 0x7737 are Ettus B200 product Ids. - case 0x0001: - case 0x7737: - case B200_PRODUCT_NI_ID: - new_addr["product"] = "B200"; - break; - //0x0002 and 0x7738 are Ettus B210 product Ids. - case 0x0002: - case 0x7738: - case B210_PRODUCT_NI_ID: - new_addr["product"] = "B210"; - break; - default: UHD_MSG(error) << "B200 unknown product code: " << mb_eeprom["product"] << std::endl; - } + try { + // Turn the 16-Bit product ID into a string representation + new_addr["product"] = B2X0_STR_NAMES[get_b200_type(mb_eeprom)]; + } catch (const uhd::runtime_error &e) { + // No problem if this fails -- this is just device discovery, after all. + UHD_MSG(error) << e.what() << std::endl; + // Skip this loop. + continue; } //this is a found b200 when the hint serial and name match or blank if ( @@ -282,36 +290,29 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : .subscribe(boost::bind(&b200_impl::set_mb_eeprom, this, _1)); //////////////////////////////////////////////////////////////////// - // Load the FPGA image, then reset GPIF + // Identify the device type //////////////////////////////////////////////////////////////////// std::string default_file_name; - std::string product_name = "B200?"; - if (not mb_eeprom["product"].empty()) - { - switch (boost::lexical_cast(mb_eeprom["product"])) - { - //0x0001 and 0x7737 are Ettus B200 product Ids. - case 0x0001: - case 0x7737: - case B200_PRODUCT_NI_ID: - product_name = "B200"; - default_file_name = B200_FPGA_FILE_NAME; - break; - //0x0002 and 0x7738 are Ettus B210 product Ids. - case 0x0002: - case 0x7738: - case B210_PRODUCT_NI_ID: - product_name = "B210"; - default_file_name = B210_FPGA_FILE_NAME; - break; - default: UHD_MSG(error) << "B200 unknown product code: " << mb_eeprom["product"] << std::endl; + std::string product_name; + try { + // This will throw if the product ID is invalid: + _b200_type = get_b200_type(mb_eeprom); + default_file_name = B2X0_FPGA_FILE_NAME.get(_b200_type); + product_name = B2X0_STR_NAMES.get(_b200_type); + } catch (const uhd::runtime_error &e) { + // The only reason we may let this pass is if the user specified + // the FPGA file name: + if (not device_addr.has_key("fpga")) { + throw e; } - } - if (default_file_name.empty()) - { - UHD_ASSERT_THROW(device_addr.has_key("fpga")); + // In this case, we must provide a default product name: + product_name = "B200?"; + _b200_type = B200; } + //////////////////////////////////////////////////////////////////// + // Load the FPGA image, then reset GPIF + //////////////////////////////////////////////////////////////////// //extract the FPGA path for the B200 std::string b200_fpga_image = find_image_path( device_addr.has_key("fpga")? device_addr["fpga"] : default_file_name diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp index b68293109..0e5e09d4b 100644 --- a/host/lib/usrp/b200/b200_impl.hpp +++ b/host/lib/usrp/b200/b200_impl.hpp @@ -107,6 +107,8 @@ public: void check_streamer_args(const uhd::stream_args_t &args, double tick_rate, const std::string &direction = ""); private: + b200_type_t _b200_type; + //controllers b200_iface::sptr _iface; radio_ctrl_core_3000::sptr _local_ctrl; -- cgit v1.2.3 From 0eac5ac12dd92c90921633f89e2228972f74aade Mon Sep 17 00:00:00 2001 From: Ashish Chaudhari Date: Thu, 23 Apr 2015 12:23:54 -0700 Subject: b200: Bumped FPGA compat number to 6 --- host/lib/usrp/b200/b200_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'host/lib/usrp/b200') diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp index 8d0c637d7..318b35947 100644 --- a/host/lib/usrp/b200/b200_impl.hpp +++ b/host/lib/usrp/b200/b200_impl.hpp @@ -47,7 +47,7 @@ #include "recv_packet_demuxer_3000.hpp" static const boost::uint8_t B200_FW_COMPAT_NUM_MAJOR = 7; static const boost::uint8_t B200_FW_COMPAT_NUM_MINOR = 0; -static const boost::uint16_t B200_FPGA_COMPAT_NUM = 5; +static const boost::uint16_t B200_FPGA_COMPAT_NUM = 6; static const double B200_BUS_CLOCK_RATE = 100e6; static const double B200_DEFAULT_TICK_RATE = 32e6; static const double B200_DEFAULT_FREQ = 100e6; // Hz -- cgit v1.2.3 From 908b5429917ef8f3f5363f5ffc4710e0258914e6 Mon Sep 17 00:00:00 2001 From: Ashish Chaudhari Date: Thu, 23 Apr 2015 15:48:36 -0700 Subject: b200: Bumped FPGA compat number to 7. --- host/lib/usrp/b200/b200_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'host/lib/usrp/b200') diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp index 97dc21fc5..3628745a1 100644 --- a/host/lib/usrp/b200/b200_impl.hpp +++ b/host/lib/usrp/b200/b200_impl.hpp @@ -47,7 +47,7 @@ #include "recv_packet_demuxer_3000.hpp" static const boost::uint8_t B200_FW_COMPAT_NUM_MAJOR = 7; static const boost::uint8_t B200_FW_COMPAT_NUM_MINOR = 0; -static const boost::uint16_t B200_FPGA_COMPAT_NUM = 6; +static const boost::uint16_t B200_FPGA_COMPAT_NUM = 7; static const double B200_BUS_CLOCK_RATE = 100e6; static const double B200_DEFAULT_TICK_RATE = 32e6; static const double B200_DEFAULT_FREQ = 100e6; // Hz -- cgit v1.2.3 From d74af0b4d17d66f9bb94638a06a25195f6dc885a Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Fri, 24 Apr 2015 15:15:40 -0700 Subject: b200: Fixed FE swapping register --- host/lib/usrp/b200/b200_impl.cpp | 20 +++++++++++++++++--- host/lib/usrp/b200/b200_impl.hpp | 4 ++-- 2 files changed, 19 insertions(+), 5 deletions(-) (limited to 'host/lib/usrp/b200') diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index 273153c16..84153309e 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -266,16 +266,30 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : _b200_type = B200; } - //set up frontend mapping + //////////////////////////////////////////////////////////////////// + // Set up frontend mapping + //////////////////////////////////////////////////////////////////// + // Explanation: The AD9361 has 2 frontends, FE1 and FE2. + // On the B210 FE1 maps to the B-side (or radio 1), and FE2 maps + // to the A-side (or radio 0). So, logically, the radios are swapped + // between the host side and the AD9361-side. + // B200 is more complicated: On Revs <= 4, the A-side is connected, + // which means FE2 is used (like B210). On Revs >= 5, the left side + // ("B-side") is connected, because these revs use an AD9364, which + // does not have an FE2, so we don't swap FEs. + + // Swapped setup: _fe1 = 1; _fe2 = 0; + _gpio_state.swap_atr = 1; + // Unswapped setup: if (_b200_type == B200 and not mb_eeprom["revision"].empty() and boost::lexical_cast(mb_eeprom["revision"]) >= 5) { _fe1 = 0; //map radio0 to FE1 _fe2 = 1; //map radio1 to FE2 - _gpio_state.atr_sel = 1; //map radio0 ATR pins to FE2 + _gpio_state.swap_atr = 0; //map radio0 ATR pins to FE2 } //////////////////////////////////////////////////////////////////// @@ -916,7 +930,7 @@ void b200_impl::update_bandsel(const std::string& which, double freq) void b200_impl::update_gpio_state(void) { const boost::uint32_t misc_word = 0 - | (_gpio_state.atr_sel << 8) + | (_gpio_state.swap_atr << 8) | (_gpio_state.tx_bandsel_a << 7) | (_gpio_state.tx_bandsel_b << 6) | (_gpio_state.rx_bandsel_a << 5) diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp index 318b35947..f3d3d0e98 100644 --- a/host/lib/usrp/b200/b200_impl.hpp +++ b/host/lib/usrp/b200/b200_impl.hpp @@ -177,7 +177,7 @@ private: void handle_overflow(const size_t radio_index); struct gpio_state { - boost::uint32_t tx_bandsel_a, tx_bandsel_b, rx_bandsel_a, rx_bandsel_b, rx_bandsel_c, codec_arst, mimo, ref_sel, atr_sel; + boost::uint32_t tx_bandsel_a, tx_bandsel_b, rx_bandsel_a, rx_bandsel_b, rx_bandsel_c, codec_arst, mimo, ref_sel, swap_atr; gpio_state() { tx_bandsel_a = 0; @@ -188,7 +188,7 @@ private: codec_arst = 0; mimo = 0; ref_sel = 0; - atr_sel = 0; + swap_atr = 0; } } _gpio_state; -- cgit v1.2.3 From 47ddba6fcc0c14ddac961dfe73ce5c3aa15dbba4 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Tue, 14 Apr 2015 15:04:30 -0500 Subject: b200: Throw error for unreachable sampling rates When auto tick rate is used, and the sampling rate exceeds the limits, throw an error instead of coercing to the default rate. --- host/lib/usrp/b200/b200_io_impl.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'host/lib/usrp/b200') diff --git a/host/lib/usrp/b200/b200_io_impl.cpp b/host/lib/usrp/b200/b200_io_impl.cpp index eb7bbe048..52a90a623 100644 --- a/host/lib/usrp/b200/b200_io_impl.cpp +++ b/host/lib/usrp/b200/b200_io_impl.cpp @@ -81,6 +81,7 @@ void b200_impl::set_auto_tick_rate( if (num_chans == 0) { // Divine them num_chans = std::max(size_t(1), max_chan_count()); } + const double max_tick_rate = ad9361_device_t::AD9361_MAX_CLOCK_RATE/num_chans; // See also the doxygen documentation for these steps in b200_impl.hpp // Step 1: Obtain LCM and max rate from all relevant dsps @@ -94,6 +95,13 @@ void b200_impl::set_auto_tick_rate( continue; } double this_dsp_rate = _tree->access(dsp_path / "rate/value").get(); + // Check if the user selected something completely unreasonable: + if (this_dsp_rate > max_tick_rate) { + throw uhd::value_error(str( + boost::format("Requested sampling rate (%.2f Msps) exceeds maximum tick rate of %.2f MHz.") + % (this_dsp_rate / 1e6) % (max_tick_rate / 1e6) + )); + } // If this_dsp_rate == B200_DEFAULT_RATE, we assume the user did not actually set // the sampling rate. If the user *did* set the rate to // B200_DEFAULT_RATE on all DSPs, then this will still work (see below). @@ -118,7 +126,6 @@ void b200_impl::set_auto_tick_rate( // Step 2: Determine whether if we can use lcm_rate (preferred), // or have to give up because too large: - const double max_tick_rate = ad9361_device_t::AD9361_MAX_CLOCK_RATE/num_chans; double base_rate = static_cast(lcm_rate); if (base_rate > max_tick_rate) { UHD_MSG(warning) @@ -175,10 +182,19 @@ void b200_impl::update_tick_rate(const double new_tick_rate) } } +#define CHECK_RATE_AND_THROW(rate) \ + if (rate >ad9361_device_t::AD9361_MAX_CLOCK_RATE ) { \ + throw uhd::value_error(str( \ + boost::format("Requested sampling rate (%.2f Msps) exceeds maximum tick rate.") \ + % (rate / 1e6) \ + )); \ + } + double b200_impl::coerce_rx_samp_rate(rx_dsp_core_3000::sptr ddc, size_t dspno, const double rx_rate) { // Have to set tick rate first, or the ddc will change the requested rate based on default tick rate if (_tree->access("/mboards/0/auto_tick_rate").get()) { + CHECK_RATE_AND_THROW(rx_rate); const std::string dsp_path = (boost::format("/mboards/0/rx_dsps/%s") % dspno).str(); set_auto_tick_rate(rx_rate, dsp_path); } @@ -208,6 +224,7 @@ double b200_impl::coerce_tx_samp_rate(tx_dsp_core_3000::sptr duc, size_t dspno, { // Have to set tick rate first, or the duc will change the requested rate based on default tick rate if (_tree->access("/mboards/0/auto_tick_rate").get()) { + CHECK_RATE_AND_THROW(tx_rate); const std::string dsp_path = (boost::format("/mboards/0/tx_dsps/%s") % dspno).str(); set_auto_tick_rate(tx_rate, dsp_path); } -- cgit v1.2.3 From 0e1bba1ae05aa3edff65eddfc174d98d64fa1f42 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Mon, 27 Apr 2015 10:09:04 -0700 Subject: b200: Added convenience subdev override for consistent subdev experience --- host/lib/usrp/b200/b200_impl.cpp | 15 +++++++++------ host/lib/usrp/b200/b200_impl.hpp | 2 ++ host/lib/usrp/b200/b200_io_impl.cpp | 34 ++++++++++++++++++---------------- 3 files changed, 29 insertions(+), 22 deletions(-) (limited to 'host/lib/usrp/b200') diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index 84153309e..d66920bd9 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -205,7 +205,8 @@ UHD_STATIC_BLOCK(register_b200_device) * Structors **********************************************************************/ b200_impl::b200_impl(const device_addr_t &device_addr) : - _tick_rate(0.0) // Forces a clock initialization at startup + _tick_rate(0.0), // Forces a clock initialization at startup + _revision(0) { _tree = property_tree::make(); _type = device::USRP; @@ -265,6 +266,9 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : product_name = "B200?"; _b200_type = B200; } + if (not mb_eeprom["revision"].empty()) { + _revision = boost::lexical_cast(mb_eeprom["revision"]); + } //////////////////////////////////////////////////////////////////// // Set up frontend mapping @@ -283,13 +287,10 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : _fe2 = 0; _gpio_state.swap_atr = 1; // Unswapped setup: - if (_b200_type == B200 and - not mb_eeprom["revision"].empty() and - boost::lexical_cast(mb_eeprom["revision"]) >= 5) - { + if (_b200_type == B200 and _revision >= 5) { _fe1 = 0; //map radio0 to FE1 _fe2 = 1; //map radio1 to FE2 - _gpio_state.swap_atr = 0; //map radio0 ATR pins to FE2 + _gpio_state.swap_atr = 0; // ATRs for radio0 are mapped to FE1 } //////////////////////////////////////////////////////////////////// @@ -462,9 +463,11 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : _tree->create >(mb_path / "rx_chan_dsp_mapping").set(default_map); _tree->create >(mb_path / "tx_chan_dsp_mapping").set(default_map); _tree->create(mb_path / "rx_subdev_spec") + .coerce(boost::bind(&b200_impl::coerce_subdev_spec, this, _1)) .set(subdev_spec_t()) .subscribe(boost::bind(&b200_impl::update_subdev_spec, this, "rx", _1)); _tree->create(mb_path / "tx_subdev_spec") + .coerce(boost::bind(&b200_impl::coerce_subdev_spec, this, _1)) .set(subdev_spec_t()) .subscribe(boost::bind(&b200_impl::update_subdev_spec, this, "tx", _1)); diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp index f3d3d0e98..bc49595b9 100644 --- a/host/lib/usrp/b200/b200_impl.hpp +++ b/host/lib/usrp/b200/b200_impl.hpp @@ -102,6 +102,7 @@ public: private: b200_type_t _b200_type; + size_t _revision; //controllers b200_iface::sptr _iface; @@ -139,6 +140,7 @@ private: void set_mb_eeprom(const uhd::usrp::mboard_eeprom_t &); void check_fw_compat(void); void check_fpga_compat(void); + uhd::usrp::subdev_spec_t coerce_subdev_spec(const uhd::usrp::subdev_spec_t &); void update_subdev_spec(const std::string &tx_rx, const uhd::usrp::subdev_spec_t &); void update_time_source(const std::string &); void update_clock_source(const std::string &); diff --git a/host/lib/usrp/b200/b200_io_impl.cpp b/host/lib/usrp/b200/b200_io_impl.cpp index 3e156f9bb..1e11e7ff6 100644 --- a/host/lib/usrp/b200/b200_io_impl.cpp +++ b/host/lib/usrp/b200/b200_io_impl.cpp @@ -122,29 +122,31 @@ void b200_impl::update_tx_samp_rate(const size_t dspno, const double rate) /*********************************************************************** * frontend selection **********************************************************************/ +uhd::usrp::subdev_spec_t b200_impl::coerce_subdev_spec(const uhd::usrp::subdev_spec_t &spec_) +{ + uhd::usrp::subdev_spec_t spec = spec_; + // Because of the confusing nature of the subdevs on B200 + // with different revs, we provide a convenience override, + // where both A:A and A:B are mapped to A:A. + // + // Any other spec is probably illegal and will be caught by + // validate_subdev_spec(). + if (spec.size() and _b200_type == B200 and spec[0].sd_name == "B") { + spec[0].sd_name = "A"; + } + return spec; +} + void b200_impl::update_subdev_spec(const std::string &tx_rx, const uhd::usrp::subdev_spec_t &spec) { //sanity checking - if (spec.size()) validate_subdev_spec(_tree, spec, tx_rx); - UHD_ASSERT_THROW(spec.size() <= _radio_perifs.size()); - - if (spec.size() >= 1) - { - UHD_ASSERT_THROW(spec[0].db_name == "A"); - UHD_ASSERT_THROW(spec[0].sd_name == "A" or spec[0].sd_name == "B"); - } - if (spec.size() == 2) - { - UHD_ASSERT_THROW(spec[1].db_name == "A"); - UHD_ASSERT_THROW( - (spec[0].sd_name == "A" and spec[1].sd_name == "B") or - (spec[0].sd_name == "B" and spec[1].sd_name == "A") - ); + if (spec.size()) { + validate_subdev_spec(_tree, spec, tx_rx); } std::vector chan_to_dsp_map(spec.size(), 0); for (size_t i = 0; i < spec.size(); i++) { - chan_to_dsp_map[i] = (spec[i].sd_name == "A") ? 0 : 1; + chan_to_dsp_map[i] = (spec[i].sd_name == "A") ? 0 : 1; } _tree->access >("/mboards/0" / (tx_rx + "_chan_dsp_mapping")).set(chan_to_dsp_map); -- cgit v1.2.3 From 15a61a77f499363d64d92e5bb79b0867f66a8f1f Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Thu, 30 Apr 2015 12:36:58 -0700 Subject: b200: Fixed compiler warning --- host/lib/usrp/b200/b200_impl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'host/lib/usrp/b200') diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index d66920bd9..724f5f8b9 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -205,8 +205,8 @@ UHD_STATIC_BLOCK(register_b200_device) * Structors **********************************************************************/ b200_impl::b200_impl(const device_addr_t &device_addr) : - _tick_rate(0.0), // Forces a clock initialization at startup - _revision(0) + _revision(0), + _tick_rate(0.0) // Forces a clock initialization at startup { _tree = property_tree::make(); _type = device::USRP; -- cgit v1.2.3