diff options
-rw-r--r-- | host/lib/usrp/common/usrp3_fw_ctrl_iface.cpp | 15 | ||||
-rw-r--r-- | host/lib/usrp/common/usrp3_fw_ctrl_iface.hpp | 9 | ||||
-rw-r--r-- | host/lib/usrp/n230/n230_image_loader.cpp | 36 | ||||
-rw-r--r-- | host/lib/usrp/n230/n230_impl.cpp | 69 | ||||
-rw-r--r-- | host/lib/usrp/n230/n230_resource_manager.cpp | 30 | ||||
-rw-r--r-- | host/lib/usrp/n230/n230_resource_manager.hpp | 1 |
6 files changed, 111 insertions, 49 deletions
diff --git a/host/lib/usrp/common/usrp3_fw_ctrl_iface.cpp b/host/lib/usrp/common/usrp3_fw_ctrl_iface.cpp index aefd84882..ef541e37f 100644 --- a/host/lib/usrp/common/usrp3_fw_ctrl_iface.cpp +++ b/host/lib/usrp/common/usrp3_fw_ctrl_iface.cpp @@ -32,9 +32,10 @@ namespace uhd { namespace usrp { namespace usrp3 { //---------------------------------------------------------- uhd::wb_iface::sptr usrp3_fw_ctrl_iface::make( uhd::transport::udp_simple::sptr udp_xport, - boost::uint16_t product_id) + const boost::uint16_t product_id, + const bool verbose) { - return wb_iface::sptr(new usrp3_fw_ctrl_iface(udp_xport, product_id)); + return wb_iface::sptr(new usrp3_fw_ctrl_iface(udp_xport, product_id, verbose)); } //---------------------------------------------------------- @@ -43,8 +44,10 @@ uhd::wb_iface::sptr usrp3_fw_ctrl_iface::make( usrp3_fw_ctrl_iface::usrp3_fw_ctrl_iface( uhd::transport::udp_simple::sptr udp_xport, - boost::uint16_t product_id) : - _product_id(product_id), _udp_xport(udp_xport), _seq_num(0) + const boost::uint16_t product_id, + const bool verbose) : + _product_id(product_id), _verbose(verbose), _udp_xport(udp_xport), + _seq_num(0) { flush(); peek32(0); @@ -72,7 +75,7 @@ void usrp3_fw_ctrl_iface::poke32(const wb_addr_type addr, const boost::uint32_t } catch(const std::exception &ex) { const std::string error_msg = str(boost::format( "udp fw poke32 failure #%u\n%s") % i % ex.what()); - UHD_MSG(warning) << error_msg << std::endl; + if (_verbose) UHD_MSG(warning) << error_msg << std::endl; if (i == NUM_RETRIES) throw uhd::io_error(error_msg); } } @@ -88,7 +91,7 @@ boost::uint32_t usrp3_fw_ctrl_iface::peek32(const wb_addr_type addr) } catch(const std::exception &ex) { const std::string error_msg = str(boost::format( "udp fw peek32 failure #%u\n%s") % i % ex.what()); - UHD_MSG(warning) << error_msg << std::endl; + if (_verbose) UHD_MSG(warning) << error_msg << std::endl; if (i == NUM_RETRIES) throw uhd::io_error(error_msg); } } diff --git a/host/lib/usrp/common/usrp3_fw_ctrl_iface.hpp b/host/lib/usrp/common/usrp3_fw_ctrl_iface.hpp index 3617f3083..33286861b 100644 --- a/host/lib/usrp/common/usrp3_fw_ctrl_iface.hpp +++ b/host/lib/usrp/common/usrp3_fw_ctrl_iface.hpp @@ -30,7 +30,8 @@ class usrp3_fw_ctrl_iface : public uhd::wb_iface public: usrp3_fw_ctrl_iface( uhd::transport::udp_simple::sptr udp_xport, - boost::uint16_t product_id); + const boost::uint16_t product_id, + const bool verbose); virtual ~usrp3_fw_ctrl_iface(); // -- uhd::wb_iface -- @@ -40,7 +41,8 @@ public: static uhd::wb_iface::sptr make( uhd::transport::udp_simple::sptr udp_xport, - boost::uint16_t product_id); + const boost::uint16_t product_id, + const bool verbose = true); // -- uhd::wb_iface -- static std::vector<std::string> discover_devices( @@ -56,7 +58,8 @@ private: boost::uint32_t _peek32(const wb_addr_type addr); void _flush(void); - boost::uint16_t _product_id; + const boost::uint16_t _product_id; + const bool _verbose; uhd::transport::udp_simple::sptr _udp_xport; boost::uint32_t _seq_num; boost::mutex _mutex; diff --git a/host/lib/usrp/n230/n230_image_loader.cpp b/host/lib/usrp/n230/n230_image_loader.cpp index f8a6ba092..9dd4a252d 100644 --- a/host/lib/usrp/n230/n230_image_loader.cpp +++ b/host/lib/usrp/n230/n230_image_loader.cpp @@ -21,10 +21,11 @@ #include <uhd/exception.hpp> #include <uhd/utils/static.hpp> #include <uhd/utils/byteswap.hpp> +#include <uhd/utils/paths.hpp> #include <uhd/transport/udp_simple.hpp> #include <boost/algorithm/string.hpp> #include <boost/filesystem.hpp> - +#include <boost/format.hpp> #include "n230_fw_host_iface.h" #include "n230_impl.hpp" @@ -129,11 +130,27 @@ static bool n230_image_loader(const image_loader::image_loader_args_t &loader_ar device_addr_t dev = devs[0]; // Sanity check the specified bitfile - if (not boost::filesystem::exists(loader_args.fpga_path)) { - throw uhd::runtime_error(str(boost::format("The file \"%s\" does not exist.") % loader_args.fpga_path)); + std::string fpga_img_path = loader_args.fpga_path; + bool fpga_path_specified = !loader_args.fpga_path.empty(); + if (not fpga_path_specified) { + fpga_img_path = ( + fs::path(uhd::get_pkg_path()) / "share" / "uhd" / "images" / "usrp_n230_fpga.bit" + ).string(); + } + + if (not boost::filesystem::exists(fpga_img_path)) { + if (fpga_path_specified) { + throw uhd::runtime_error(str(boost::format("The file \"%s\" does not exist.") % fpga_img_path)); + } else { + throw uhd::runtime_error(str(boost::format( + "Could not find the default FPGA image: %s.\n" + "Either specify the --fpga-path argument or download the latest prebuilt images:\n" + "%s\n") + % fpga_img_path % print_utility_error("uhd_images_downloader.py"))); + } } xil_bitfile_hdr_t hdr; - _parse_bitfile_header(loader_args.fpga_path, hdr); + _parse_bitfile_header(fpga_img_path, hdr); // Create a UDP communication link udp_simple::sptr udp_xport = @@ -142,11 +159,11 @@ static bool n230_image_loader(const image_loader::image_loader_args_t &loader_ar if (hdr.valid and hdr.product == "n230") { if (hdr.userid != 0x5AFE0000) { std::cout << boost::format("Unit: USRP N230 (%s, %s)\n-- FPGA Image: %s\n") - % dev["addr"] % dev["serial"] % loader_args.fpga_path; + % dev["addr"] % dev["serial"] % fpga_img_path; // Write image - std::ifstream image(loader_args.fpga_path.c_str(), std::ios::binary); - size_t image_size = boost::filesystem::file_size(loader_args.fpga_path); + std::ifstream image(fpga_img_path.c_str(), std::ios::binary); + size_t image_size = boost::filesystem::file_size(fpga_img_path); static const size_t SECTOR_SIZE = 65536; static const size_t IMAGE_BASE = 0x400000; @@ -171,14 +188,15 @@ static bool n230_image_loader(const image_loader::image_loader_args_t &loader_ar % (int(double(bytes_written) / double(image_size) * 100.0)) << std::flush; } - std::cout << std::endl << "Image loaded successfully." << std::endl; + std::cout << std::endl << "FPGA image loaded successfully." << std::endl; + std::cout << std::endl << "Power-cycle the device to run the image." << std::endl; return true; } else { throw uhd::runtime_error("This utility cannot burn a failsafe image!"); } } else { throw uhd::runtime_error(str(boost::format("The file at path \"%s\" is not a valid USRP N230 FPGA image.") - % loader_args.fpga_path)); + % fpga_img_path)); } } diff --git a/host/lib/usrp/n230/n230_impl.cpp b/host/lib/usrp/n230/n230_impl.cpp index ab7fa6fe6..b005182cf 100644 --- a/host/lib/usrp/n230/n230_impl.cpp +++ b/host/lib/usrp/n230/n230_impl.cpp @@ -130,30 +130,47 @@ uhd::device_addrs_t n230_impl::n230_find(const uhd::device_addr_t &multi_dev_hin //we may not be able to communicate directly (non-broadcast). udp_simple::sptr ctrl_xport = udp_simple::make_connected(new_addr["addr"], BOOST_STRINGIZE(N230_FW_COMMS_UDP_PORT)); - usrp3::usrp3_fw_ctrl_iface::sptr fw_ctrl = usrp3::usrp3_fw_ctrl_iface::make(ctrl_xport, N230_FW_PRODUCT_ID); - uint32_t compat_reg_addr = fw::reg_addr(fw::WB_SBRB_BASE, fw::RB_ZPU_COMPAT); - if (fw::get_prod_num(fw_ctrl->peek32(compat_reg_addr)) == fw::PRODUCT_NUM) { - if (!n230_resource_manager::is_device_claimed(fw_ctrl)) { - //Not claimed by another process or host - try { - //Try to read the EEPROM to get the name and serial - n230_eeprom_manager eeprom_mgr(new_addr["addr"]); - const mboard_eeprom_t& eeprom = eeprom_mgr.get_mb_eeprom(); - new_addr["name"] = eeprom["name"]; - new_addr["serial"] = eeprom["serial"]; - } - catch(const std::exception &) - { - //set these values as empty string so the device may still be found - //and the filter's below can still operate on the discovered device - new_addr["name"] = ""; - new_addr["serial"] = ""; - } - //filter the discovered device below by matching optional keys - if ((not hint.has_key("name") or hint["name"] == new_addr["name"]) and - (not hint.has_key("serial") or hint["serial"] == new_addr["serial"])) - { - n230_addrs.push_back(new_addr); + //Corner case: If two devices have the same IP but different MAC + //addresses and are used back-to-back it takes a while for ARP tables + //on the host to update in which period brodcasts will respond but + //connected communication can fail. Retry the following call to allow + //the stack to update + size_t first_conn_retries = 10; + usrp3::usrp3_fw_ctrl_iface::sptr fw_ctrl; + while (first_conn_retries > 0) { + try { + fw_ctrl = usrp3::usrp3_fw_ctrl_iface::make(ctrl_xport, N230_FW_PRODUCT_ID, false /*verbose*/); + break; + } catch (uhd::io_error& ex) { + boost::this_thread::sleep(boost::posix_time::milliseconds(500)); + first_conn_retries--; + } + } + if (first_conn_retries > 0) { + uint32_t compat_reg = fw_ctrl->peek32(fw::reg_addr(fw::WB_SBRB_BASE, fw::RB_ZPU_COMPAT)); + if (fw::get_prod_num(compat_reg) == fw::PRODUCT_NUM) { + if (!n230_resource_manager::is_device_claimed(fw_ctrl)) { + //Not claimed by another process or host + try { + //Try to read the EEPROM to get the name and serial + n230_eeprom_manager eeprom_mgr(new_addr["addr"]); + const mboard_eeprom_t& eeprom = eeprom_mgr.get_mb_eeprom(); + new_addr["name"] = eeprom["name"]; + new_addr["serial"] = eeprom["serial"]; + } + catch(const std::exception &) + { + //set these values as empty string so the device may still be found + //and the filter's below can still operate on the discovered device + new_addr["name"] = ""; + new_addr["serial"] = ""; + } + //filter the discovered device below by matching optional keys + if ((not hint.has_key("name") or hint["name"] == new_addr["name"]) and + (not hint.has_key("serial") or hint["serial"] == new_addr["serial"])) + { + n230_addrs.push_back(new_addr); + } } } } @@ -204,10 +221,6 @@ n230_impl::n230_impl(const uhd::device_addr_t& dev_addr) throw uhd::runtime_error(str(boost::format( "Hardware is too new for this software. Please upgrade to a driver that supports hardware revision %d.") % hw_rev)); - } else if (hw_rev < N230_HW_REVISION_MIN) { //Compare min against the revision (and not compat) to give us more leeway for partial support for a compat - throw uhd::runtime_error(str(boost::format( - "Software is too new for this hardware. Please downgrade to a driver that supports hardware revision %d.") - % hw_rev)); } } diff --git a/host/lib/usrp/n230/n230_resource_manager.cpp b/host/lib/usrp/n230/n230_resource_manager.cpp index 4db494302..f13dd0b33 100644 --- a/host/lib/usrp/n230/n230_resource_manager.cpp +++ b/host/lib/usrp/n230/n230_resource_manager.cpp @@ -84,6 +84,7 @@ n230_resource_manager::n230_resource_manager( UHD_MSG(status) << "Setup basic communication...\n"; //Discover ethernet interfaces + bool dual_eth_expected = (ip_addrs.size() > 1); BOOST_FOREACH(const std::string& addr, ip_addrs) { n230_eth_conn_t conn_iface; conn_iface.ip_addr = addr; @@ -100,7 +101,15 @@ n230_resource_manager::n230_resource_manager( switch (iface_id) { case N230_ETH0_IFACE_ID: conn_iface.type = ETH0; break; case N230_ETH1_IFACE_ID: conn_iface.type = ETH1; break; - default: throw uhd::runtime_error("N230 Initialization Error: Could not detect ethernet port number.)"); + default: { + if (dual_eth_expected) { + throw uhd::runtime_error("N230 Initialization Error: Could not detect ethernet port number."); + } else { + //For backwards compatibility, if only one port is specified, assume that a detection + //failure means that the device does not support dual-ethernet behavior. + conn_iface.type = ETH0; break; + } + } } _eth_conns.push_back(conn_iface); } @@ -488,6 +497,21 @@ bool n230_resource_manager::_radio_data_loopback_self_test(wb_iface::sptr iface) return !test_fail; } +std::string n230_resource_manager::_get_fpga_upgrade_msg() { + std::string img_loader_path = + (fs::path(uhd::get_pkg_path()) / "bin" / "uhd_image_loader").string(); + + return str(boost::format( + "\nDownload the appropriate FPGA images for this version of UHD.\n" + "%s\n\n" + "Then burn a new image to the on-board flash storage of your\n" + "USRP N230 device using the image loader utility. Use this command:\n" + "\n \"%s\" --args=\"type=n230,addr=%s\"\n") + % print_utility_error("uhd_images_downloader.py") + % img_loader_path % _get_conn(PRI_ETH).ip_addr); + +} + void n230_resource_manager::_check_fw_compat() { boost::uint32_t compat_num = _fw_ctrl->peek32(N230_FW_HOST_SHMEM_OFFSET(fw_compat_num)); @@ -503,7 +527,7 @@ void n230_resource_manager::_check_fw_compat() ) % static_cast<boost::uint32_t>(N230_FW_COMPAT_NUM_MAJOR) % static_cast<boost::uint32_t>(_fw_version.compat_major) % static_cast<boost::uint32_t>(_fw_version.compat_minor) - % print_utility_error("uhd_images_downloader.py"))); + % _get_fpga_upgrade_msg())); } } @@ -538,7 +562,7 @@ void n230_resource_manager::_check_fpga_compat() ) % static_cast<boost::uint32_t>(fpga::RB_N230_COMPAT_MAJOR) % static_cast<boost::uint32_t>(_fpga_version.compat_major) % static_cast<boost::uint32_t>(_fpga_version.compat_minor) - % print_utility_error("uhd_images_downloader.py"))); + % _get_fpga_upgrade_msg())); } } diff --git a/host/lib/usrp/n230/n230_resource_manager.hpp b/host/lib/usrp/n230/n230_resource_manager.hpp index 3a0b13329..0a1178bd2 100644 --- a/host/lib/usrp/n230/n230_resource_manager.hpp +++ b/host/lib/usrp/n230/n230_resource_manager.hpp @@ -240,6 +240,7 @@ private: void _initialize_radio(size_t instance); + std::string _get_fpga_upgrade_msg(); void _check_fw_compat(); void _check_fpga_compat(); |