aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/lib/usrp/common/usrp3_fw_ctrl_iface.cpp15
-rw-r--r--host/lib/usrp/common/usrp3_fw_ctrl_iface.hpp9
-rw-r--r--host/lib/usrp/n230/n230_image_loader.cpp36
-rw-r--r--host/lib/usrp/n230/n230_impl.cpp69
-rw-r--r--host/lib/usrp/n230/n230_resource_manager.cpp30
-rw-r--r--host/lib/usrp/n230/n230_resource_manager.hpp1
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();