aboutsummaryrefslogtreecommitdiffstats
path: root/host/utils
diff options
context:
space:
mode:
Diffstat (limited to 'host/utils')
-rw-r--r--host/utils/uhd_cal_rx_iq_balance.cpp31
-rw-r--r--host/utils/uhd_cal_tx_dc_offset.cpp31
-rw-r--r--host/utils/uhd_cal_tx_iq_balance.cpp36
-rw-r--r--host/utils/usrp_burn_mb_eeprom.cpp51
-rw-r--r--host/utils/usrp_cal_utils.hpp64
-rw-r--r--host/utils/usrp_n2xx_simple_net_burner.cpp495
-rw-r--r--host/utils/usrp_simple_burner_utils.hpp99
7 files changed, 377 insertions, 430 deletions
diff --git a/host/utils/uhd_cal_rx_iq_balance.cpp b/host/utils/uhd_cal_rx_iq_balance.cpp
index 551da7544..3188e02a0 100644
--- a/host/utils/uhd_cal_rx_iq_balance.cpp
+++ b/host/utils/uhd_cal_rx_iq_balance.cpp
@@ -121,37 +121,14 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
if (vm.count("help")){
std::cout << boost::format("USRP Generate RX IQ Balance Calibration Table %s") % desc << std::endl;
std::cout <<
- "This application measures leakage between RX and TX on an XCVR daughterboard to self-calibrate.\n"
+ "This application measures leakage between RX and TX on a transceiver daughterboard to self-calibrate.\n"
+ "Note: Not all daughterboards support this feature. Refer to the UHD manual for details.\n"
<< std::endl;
return EXIT_FAILURE;
}
- //create a usrp device
- std::cout << std::endl;
- std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl;
- uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args);
-
- // Configure subdev
- if (vm.count("subdev")) {
- usrp->set_tx_subdev_spec(subdev);
- usrp->set_rx_subdev_spec(subdev);
- }
- UHD_MSG(status) << "Running calibration for " << usrp->get_tx_subdev_name(0) << std::endl;
- serial = get_serial(usrp, "tx");
- UHD_MSG(status) << "Daughterboard serial: " << serial << std::endl;
-
- //set the antennas to cal
- if (not uhd::has(usrp->get_rx_antennas(), "CAL") or not uhd::has(usrp->get_tx_antennas(), "CAL")){
- throw std::runtime_error("This board does not have the CAL antenna option, cannot self-calibrate.");
- }
- usrp->set_rx_antenna("CAL");
- usrp->set_tx_antenna("CAL");
-
- //fail if daughterboard has no serial
- check_for_empty_serial(usrp, "RX", "rx", args);
-
- //set optimum defaults
- set_optimum_defaults(usrp);
+ // Create a USRP device
+ uhd::usrp::multi_usrp::sptr usrp = setup_usrp_for_cal(args, subdev, serial);
//create a receive streamer
uhd::stream_args_t stream_args("fc32"); //complex floats
diff --git a/host/utils/uhd_cal_tx_dc_offset.cpp b/host/utils/uhd_cal_tx_dc_offset.cpp
index eb82db826..b5c5293f0 100644
--- a/host/utils/uhd_cal_tx_dc_offset.cpp
+++ b/host/utils/uhd_cal_tx_dc_offset.cpp
@@ -123,37 +123,14 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
if (vm.count("help")){
std::cout << boost::format("USRP Generate TX DC Offset Calibration Table %s") % desc << std::endl;
std::cout <<
- "This application measures leakage between RX and TX on an XCVR daughterboard to self-calibrate.\n"
+ "This application measures leakage between RX and TX on a transceiver daughterboard to self-calibrate.\n"
+ "Note: Not all daughterboards support this feature. Refer to the UHD manual for details.\n"
<< std::endl;
return EXIT_FAILURE;
}
- //create a usrp device
- std::cout << std::endl;
- std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl;
- uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args);
-
- // Configure subdev
- if (vm.count("subdev")) {
- usrp->set_tx_subdev_spec(subdev);
- usrp->set_rx_subdev_spec(subdev);
- }
- UHD_MSG(status) << "Running calibration for " << usrp->get_tx_subdev_name(0) << std::endl;
- serial = get_serial(usrp, "tx");
- UHD_MSG(status) << "Daughterboard serial: " << serial << std::endl;
-
- //set the antennas to cal
- if (not uhd::has(usrp->get_rx_antennas(), "CAL") or not uhd::has(usrp->get_tx_antennas(), "CAL")){
- throw std::runtime_error("This board does not have the CAL antenna option, cannot self-calibrate.");
- }
- usrp->set_rx_antenna("CAL");
- usrp->set_tx_antenna("CAL");
-
- //fail if daughterboard has no serial
- check_for_empty_serial(usrp, "TX", "tx", args);
-
- //set optimum defaults
- set_optimum_defaults(usrp);
+ // Create a USRP device
+ uhd::usrp::multi_usrp::sptr usrp = setup_usrp_for_cal(args, subdev, serial);
//create a receive streamer
uhd::stream_args_t stream_args("fc32"); //complex floats
diff --git a/host/utils/uhd_cal_tx_iq_balance.cpp b/host/utils/uhd_cal_tx_iq_balance.cpp
index 786aac061..6461b3d71 100644
--- a/host/utils/uhd_cal_tx_iq_balance.cpp
+++ b/host/utils/uhd_cal_tx_iq_balance.cpp
@@ -18,12 +18,7 @@
#include "usrp_cal_utils.hpp"
#include <uhd/utils/thread_priority.hpp>
#include <uhd/utils/safe_main.hpp>
-#include <uhd/utils/paths.hpp>
-#include <uhd/utils/algorithm.hpp>
-#include <uhd/utils/msg.hpp>
-#include <uhd/usrp/multi_usrp.hpp>
#include <boost/program_options.hpp>
-#include <boost/format.hpp>
#include <boost/thread/thread.hpp>
#include <boost/math/special_functions/round.hpp>
#include <iostream>
@@ -124,37 +119,14 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
if (vm.count("help")){
std::cout << boost::format("USRP Generate TX IQ Balance Calibration Table %s") % desc << std::endl;
std::cout <<
- "This application measures leakage between RX and TX on a daughterboard to self-calibrate.\n"
+ "This application measures leakage between RX and TX on a transceiver daughterboard to self-calibrate.\n"
+ "Note: Not all daughterboards support this feature. Refer to the UHD manual for details.\n"
<< std::endl;
return EXIT_FAILURE;
}
- //create a usrp device
- std::cout << std::endl;
- std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl;
- uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args);
-
- // Configure subdev
- if (vm.count("subdev")) {
- usrp->set_tx_subdev_spec(subdev);
- usrp->set_rx_subdev_spec(subdev);
- }
- UHD_MSG(status) << "Running calibration for " << usrp->get_tx_subdev_name(0) << std::endl;
- serial = get_serial(usrp, "tx");
- UHD_MSG(status) << "Daughterboard serial: " << serial << std::endl;
-
- //set the antennas to cal
- if (not uhd::has(usrp->get_rx_antennas(), "CAL") or not uhd::has(usrp->get_tx_antennas(), "CAL")){
- throw std::runtime_error("This board does not have the CAL antenna option, cannot self-calibrate.");
- }
- usrp->set_rx_antenna("CAL");
- usrp->set_tx_antenna("CAL");
-
- //fail if daughterboard has no serial
- check_for_empty_serial(usrp, "TX", "tx", args);
-
- //set optimum defaults
- set_optimum_defaults(usrp);
+ // Create a USRP device
+ uhd::usrp::multi_usrp::sptr usrp = setup_usrp_for_cal(args, subdev, serial);
//create a receive streamer
uhd::stream_args_t stream_args("fc32"); //complex floats
diff --git a/host/utils/usrp_burn_mb_eeprom.cpp b/host/utils/usrp_burn_mb_eeprom.cpp
index ce0879c8e..c631c9c09 100644
--- a/host/utils/usrp_burn_mb_eeprom.cpp
+++ b/host/utils/usrp_burn_mb_eeprom.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010,2013 Ettus Research LLC
+// Copyright 2010,2013-2014 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
@@ -19,6 +19,7 @@
#include <uhd/device.hpp>
#include <uhd/property_tree.hpp>
#include <uhd/usrp/mboard_eeprom.hpp>
+#include <uhd/types/device_addr.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/program_options.hpp>
#include <boost/format.hpp>
@@ -28,14 +29,16 @@
namespace po = boost::program_options;
int UHD_SAFE_MAIN(int argc, char *argv[]){
- std::string args, key, val;
+ std::string args, input_str, key, val;
po::options_description desc("Allowed options");
desc.add_options()
("help", "help message")
("args", po::value<std::string>(&args)->default_value(""), "device address args [default = \"\"]")
- ("key", po::value<std::string>(&key), "identifiers for new values in EEPROM, separate multiple by \",\"")
- ("val", po::value<std::string>(&val), "the new values to set, omit for readback, separate multiple by \",\"")
+ ("values", po::value<std::string>(&input_str), "keys+values to read/write, separate multiple by \",\"")
+ ("key", po::value<std::string>(&key), "identifiers for new values in EEPROM, separate multiple by \",\" (DEPRECATED)")
+ ("val", po::value<std::string>(&val), "the new values to set, omit for readback, separate multiple by \",\" (DEPRECATED)")
+ ("read-all", "Read all motherboard EEPROM values without writing")
;
po::variables_map vm;
@@ -43,7 +46,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
po::notify(vm);
//print the help message
- if (vm.count("help") or not vm.count("key")){
+ if (vm.count("help") or (not vm.count("key") and not vm.count("values") and not vm.count("read-all"))){
std::cout << boost::format("USRP Burn Motherboard EEPROM %s") % desc << std::endl;
std::cout << boost::format(
"Omit the value argument to perform a readback,\n"
@@ -55,23 +58,33 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
std::cout << "Creating USRP device from address: " + args << std::endl;
uhd::device::sptr dev = uhd::device::make(args);
uhd::property_tree::sptr tree = dev->get_tree();
+ uhd::usrp::mboard_eeprom_t mb_eeprom = tree->access<uhd::usrp::mboard_eeprom_t>("/mboards/0/eeprom").get();
std::cout << std::endl;
- //remove whitespace, split arguments and values
- boost::algorithm::erase_all(key, " ");
- boost::algorithm::erase_all(val, " ");
-
std::vector<std::string> keys_vec, vals_vec;
- boost::split(keys_vec, key, boost::is_any_of("\"',"));
- boost::split(vals_vec, val, boost::is_any_of("\"',"));
+ if(vm.count("read-all")) keys_vec = mb_eeprom.keys(); //Leaving vals_vec empty will force utility to only read
+ else if(vm.count("values")){
+ //uhd::device_addr_t properly parses input values
+ uhd::device_addr_t vals(input_str);
+ keys_vec = vals.keys();
+ vals_vec = vals.vals();
+ }
+ else{
+ std::cout << "WARNING: Use of --key and --val is deprecated!" << std::endl;
+ //remove whitespace, split arguments and values
+ boost::algorithm::erase_all(key, " ");
+ boost::algorithm::erase_all(val, " ");
+
+ boost::split(keys_vec, key, boost::is_any_of("\"',"));
+ boost::split(vals_vec, val, boost::is_any_of("\"',"));
- if((keys_vec.size() != vals_vec.size()) and val != "") {
- //If zero values are given, then user just wants values read to them
- throw std::runtime_error("Number of keys must match number of values!");
+ if((keys_vec.size() != vals_vec.size()) and val != "") {
+ //If zero values are given, then user just wants values read to them
+ throw std::runtime_error("Number of keys must match number of values!");
+ }
}
std::cout << "Fetching current settings from EEPROM..." << std::endl;
- uhd::usrp::mboard_eeprom_t mb_eeprom = tree->access<uhd::usrp::mboard_eeprom_t>("/mboards/0/eeprom").get();
for(size_t i = 0; i < keys_vec.size(); i++){
if (not mb_eeprom.has_key(keys_vec[i])){
std::cerr << boost::format("Cannot find value for EEPROM[%s]") % keys_vec[i] << std::endl;
@@ -80,15 +93,15 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
std::cout << boost::format(" EEPROM [\"%s\"] is \"%s\"") % keys_vec[i] % mb_eeprom[keys_vec[i]] << std::endl;
}
std::cout << std::endl;
- if (vm.count("val")){
- for(size_t i = 0; i < vals_vec.size(); i++){
+ for(size_t i = 0; i < vals_vec.size(); i++){
+ if(vals_vec[i] != ""){
uhd::usrp::mboard_eeprom_t mb_eeprom; mb_eeprom[keys_vec[i]] = vals_vec[i];
std::cout << boost::format("Setting EEPROM [\"%s\"] to \"%s\"...") % keys_vec[i] % vals_vec[i] << std::endl;
tree->access<uhd::usrp::mboard_eeprom_t>("/mboards/0/eeprom").set(mb_eeprom);
}
- std::cout << "Power-cycle the USRP device for the changes to take effect." << std::endl;
- std::cout << std::endl;
}
+ std::cout << "Power-cycle the USRP device for the changes to take effect." << std::endl;
+ std::cout << std::endl;
std::cout << "Done" << std::endl;
return EXIT_SUCCESS;
diff --git a/host/utils/usrp_cal_utils.hpp b/host/utils/usrp_cal_utils.hpp
index 5aff5e22f..9e7f4c469 100644
--- a/host/utils/usrp_cal_utils.hpp
+++ b/host/utils/usrp_cal_utils.hpp
@@ -20,6 +20,8 @@
#include <uhd/usrp/multi_usrp.hpp>
#include <uhd/usrp/dboard_eeprom.hpp>
#include <uhd/utils/paths.hpp>
+#include <uhd/utils/algorithm.hpp>
+#include <uhd/utils/msg.hpp>
#include <boost/filesystem.hpp>
#include <boost/format.hpp>
#include <iostream>
@@ -50,6 +52,8 @@ static const size_t default_num_samps = 10000;
**********************************************************************/
static inline void set_optimum_defaults(uhd::usrp::multi_usrp::sptr usrp){
uhd::property_tree::sptr tree = usrp->get_device()->get_tree();
+ // Will work on 1st subdev, top-level must make sure it's the right one
+ uhd::usrp::subdev_spec_t subdev_spec = usrp->get_rx_subdev_spec();
const uhd::fs_path mb_path = "/mboards/0";
const std::string mb_name = tree->access<std::string>(mb_path / "name").get();
@@ -69,7 +73,7 @@ static inline void set_optimum_defaults(uhd::usrp::multi_usrp::sptr usrp){
throw std::runtime_error("self-calibration is not supported for this hardware");
}
- const uhd::fs_path tx_fe_path = "/mboards/0/dboards/A/tx_frontends/0";
+ const uhd::fs_path tx_fe_path = "/mboards/0/dboards/" + subdev_spec[0].db_name + "/tx_frontends/0";
const std::string tx_name = tree->access<std::string>(tx_fe_path / "name").get();
if (tx_name.find("WBX") != std::string::npos){
usrp->set_tx_gain(0);
@@ -87,7 +91,7 @@ static inline void set_optimum_defaults(uhd::usrp::multi_usrp::sptr usrp){
throw std::runtime_error("self-calibration is not supported for this hardware");
}
- const uhd::fs_path rx_fe_path = "/mboards/0/dboards/A/rx_frontends/0";
+ const uhd::fs_path rx_fe_path = "/mboards/0/dboards/" + subdev_spec[0].db_name + "/rx_frontends/0";
const std::string rx_name = tree->access<std::string>(rx_fe_path / "name").get();
if (rx_name.find("WBX") != std::string::npos){
usrp->set_rx_gain(25);
@@ -110,24 +114,19 @@ static inline void set_optimum_defaults(uhd::usrp::multi_usrp::sptr usrp){
/***********************************************************************
* Check for empty serial
**********************************************************************/
-
void check_for_empty_serial(
- uhd::usrp::multi_usrp::sptr usrp,
- std::string XX,
- std::string xx,
- std::string uhd_args
+ uhd::usrp::multi_usrp::sptr usrp
){
+ // Will work on 1st subdev, top-level must make sure it's the right one
+ uhd::usrp::subdev_spec_t subdev_spec = usrp->get_rx_subdev_spec();
//extract eeprom
uhd::property_tree::sptr tree = usrp->get_device()->get_tree();
- const uhd::fs_path db_path = "/mboards/0/dboards/A/" + xx + "_eeprom";
+ // This only works with transceiver boards, so we can always check rx side
+ const uhd::fs_path db_path = "/mboards/0/dboards/" + subdev_spec[0].db_name + "/rx_eeprom";
const uhd::usrp::dboard_eeprom_t db_eeprom = tree->access<uhd::usrp::dboard_eeprom_t>(db_path).get();
- std::string args_str = "";
- if(uhd_args != "") args_str = str(boost::format(" --args=%s") % uhd_args);
-
- std::string error_string = str(boost::format("This %s dboard has no serial!\n\nPlease see the Calibration documentation for details on how to fix this.") % XX);
-
+ std::string error_string = "This dboard has no serial!\n\nPlease see the Calibration documentation for details on how to fix this.";
if (db_eeprom.serial.empty()) throw std::runtime_error(error_string);
}
@@ -188,6 +187,7 @@ static std::string get_serial(
const std::string &tx_rx
){
uhd::property_tree::sptr tree = usrp->get_device()->get_tree();
+ // Will work on 1st subdev, top-level must make sure it's the right one
uhd::usrp::subdev_spec_t subdev_spec = usrp->get_rx_subdev_spec();
const uhd::fs_path db_path = "/mboards/0/dboards/" + subdev_spec[0].db_name + "/" + tx_rx + "_eeprom";
const uhd::usrp::dboard_eeprom_t db_eeprom = tree->access<uhd::usrp::dboard_eeprom_t>(db_path).get();
@@ -257,8 +257,8 @@ static void capture_samples(
//validate the received data
if (md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE){
throw std::runtime_error(str(boost::format(
- "Unexpected error code 0x%x"
- ) % md.error_code));
+ "Receiver error: %s"
+ ) % md.strerror()));
}
//we can live if all the data didnt come in
if (num_rx_samps > buff.size()/2){
@@ -270,3 +270,37 @@ static void capture_samples(
}
}
+/***********************************************************************
+ * Setup function
+ **********************************************************************/
+static uhd::usrp::multi_usrp::sptr setup_usrp_for_cal(std::string &args, std::string &subdev, std::string &serial)
+{
+ std::cout << std::endl;
+ std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl;
+ uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args);
+
+ // Configure subdev
+ if (!subdev.empty()) {
+ usrp->set_tx_subdev_spec(subdev);
+ usrp->set_rx_subdev_spec(subdev);
+ }
+ UHD_MSG(status) << "Running calibration for " << usrp->get_tx_subdev_name(0) << std::endl;
+ serial = get_serial(usrp, "tx");
+ UHD_MSG(status) << "Daughterboard serial: " << serial << std::endl;
+
+ //set the antennas to cal
+ if (not uhd::has(usrp->get_rx_antennas(), "CAL") or not uhd::has(usrp->get_tx_antennas(), "CAL")){
+ throw std::runtime_error("This board does not have the CAL antenna option, cannot self-calibrate.");
+ }
+ usrp->set_rx_antenna("CAL");
+ usrp->set_tx_antenna("CAL");
+
+ //fail if daughterboard has no serial
+ check_for_empty_serial(usrp);
+
+ //set optimum defaults
+ set_optimum_defaults(usrp);
+
+ return usrp;
+}
+
diff --git a/host/utils/usrp_n2xx_simple_net_burner.cpp b/host/utils/usrp_n2xx_simple_net_burner.cpp
index 277e807d9..cecac5588 100644
--- a/host/utils/usrp_n2xx_simple_net_burner.cpp
+++ b/host/utils/usrp_n2xx_simple_net_burner.cpp
@@ -17,13 +17,13 @@
#include <csignal>
#include <iostream>
-#include <map>
#include <fstream>
#include <time.h>
#include <vector>
#include <boost/foreach.hpp>
#include <boost/asio.hpp>
+#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
#include <boost/assign.hpp>
#include <boost/assign/list_of.hpp>
@@ -32,21 +32,97 @@
#include <boost/filesystem.hpp>
#include <boost/thread/thread.hpp>
-#include "usrp_simple_burner_utils.hpp"
#include <uhd/exception.hpp>
#include <uhd/property_tree.hpp>
#include <uhd/transport/if_addrs.hpp>
#include <uhd/transport/udp_simple.hpp>
+#include <uhd/types/dict.hpp>
#include <uhd/utils/byteswap.hpp>
#include <uhd/utils/images.hpp>
#include <uhd/utils/safe_main.hpp>
#include <uhd/utils/safe_call.hpp>
+namespace fs = boost::filesystem;
namespace po = boost::program_options;
using namespace boost::algorithm;
using namespace uhd;
using namespace uhd::transport;
+#define UDP_FW_UPDATE_PORT 49154
+#define UDP_MAX_XFER_BYTES 1024
+#define UDP_TIMEOUT 3
+#define UDP_POLL_INTERVAL 0.10 //in seconds
+#define USRP2_FW_PROTO_VERSION 7 //should be unused after r6
+#define USRP2_UDP_UPDATE_PORT 49154
+#define FLASH_DATA_PACKET_SIZE 256
+#define FPGA_IMAGE_SIZE_BYTES 1572864
+#define FW_IMAGE_SIZE_BYTES 31744
+#define PROD_FPGA_IMAGE_LOCATION_ADDR 0x00180000
+#define PROD_FW_IMAGE_LOCATION_ADDR 0x00300000
+#define SAFE_FPGA_IMAGE_LOCATION_ADDR 0x00000000
+#define SAFE_FW_IMAGE_LOCATION_ADDR 0x003F0000
+
+typedef enum {
+ UNKNOWN = ' ',
+
+ USRP2_QUERY = 'a',
+ USRP2_ACK = 'A',
+
+ GET_FLASH_INFO_CMD = 'f',
+ GET_FLASH_INFO_ACK = 'F',
+
+ ERASE_FLASH_CMD = 'e',
+ ERASE_FLASH_ACK = 'E',
+
+ CHECK_ERASING_DONE_CMD = 'd',
+ DONE_ERASING_ACK = 'D',
+ NOT_DONE_ERASING_ACK = 'B',
+
+ WRITE_FLASH_CMD = 'w',
+ WRITE_FLASH_ACK = 'W',
+
+ READ_FLASH_CMD = 'r',
+ READ_FLASH_ACK = 'R',
+
+ RESET_USRP_CMD = 's',
+ RESET_USRP_ACK = 'S',
+
+ GET_HW_REV_CMD = 'v',
+ GET_HW_REV_ACK = 'V',
+
+} usrp2_fw_update_id_t;
+
+typedef struct {
+ uint32_t proto_ver;
+ uint32_t id;
+ uint32_t seq;
+ union {
+ uint32_t ip_addr;
+ uint32_t hw_rev;
+ struct {
+ uint32_t flash_addr;
+ uint32_t length;
+ uint8_t data[256];
+ } flash_args;
+ struct {
+ uint32_t sector_size_bytes;
+ uint32_t memory_size_bytes;
+ } flash_info_args;
+ } data;
+} usrp2_fw_update_data_t;
+
+//Mapping revision numbers to filenames
+uhd::dict<boost::uint32_t, std::string> filename_map = boost::assign::map_list_of
+ (0xa, "n200_r3")
+ (0x100a, "n200_r4")
+ (0x10a, "n210_r3")
+ (0x110a, "n210_r4")
+;
+
+boost::uint8_t usrp2_update_data_in_mem[udp_simple::mtu];
+boost::uint8_t fpga_image[FPGA_IMAGE_SIZE_BYTES];
+boost::uint8_t fw_image[FW_IMAGE_SIZE_BYTES];
+
/***********************************************************************
* Signal handlers
**********************************************************************/
@@ -66,59 +142,94 @@ void sig_int_handler(int){
}
}
-//Mapping revision numbers to filenames
-std::map<boost::uint32_t, std::string> filename_map = boost::assign::map_list_of
- (0xa, "n200_r3")
- (0x100a, "n200_r4")
- (0x10a, "n210_r3")
- (0x110a, "n210_r4")
-;
+/***********************************************************************
+ * List all connected USRP N2XX devices
+ **********************************************************************/
+void list_usrps(){
+ udp_simple::sptr udp_bc_transport;
+ const usrp2_fw_update_data_t *update_data_in = reinterpret_cast<const usrp2_fw_update_data_t *>(usrp2_update_data_in_mem);
+ boost::uint32_t hw_rev;
-//Images and image sizes, to be populated as necessary
-boost::uint8_t fpga_image[FPGA_IMAGE_SIZE_BYTES];
-boost::uint8_t fw_image[FW_IMAGE_SIZE_BYTES];
-int fpga_image_size = 0;
-int fw_image_size = 0;
+ usrp2_fw_update_data_t usrp2_ack_pkt = usrp2_fw_update_data_t();
+ usrp2_ack_pkt.proto_ver = htonx<boost::uint32_t>(USRP2_FW_PROTO_VERSION);
+ usrp2_ack_pkt.id = htonx<boost::uint32_t>(USRP2_QUERY);
+
+ std::cout << "Available USRP N2XX devices:" << std::endl;
-//For non-standard images not covered by uhd::find_image_path()
-bool does_image_exist(std::string image_filepath){
+ //Send UDP packets to all broadcast addresses
+ BOOST_FOREACH(const if_addrs_t &if_addrs, get_if_addrs()){
+ //Avoid the loopback device
+ if(if_addrs.inet == boost::asio::ip::address_v4::loopback().to_string()) continue;
+ udp_bc_transport = udp_simple::make_broadcast(if_addrs.bcast, BOOST_STRINGIZE(USRP2_UDP_UPDATE_PORT));
+ udp_bc_transport->send(boost::asio::buffer(&usrp2_ack_pkt, sizeof(usrp2_ack_pkt)));
- std::ifstream ifile((char*)image_filepath.c_str());
- return ifile;
+ size_t len = udp_bc_transport->recv(boost::asio::buffer(usrp2_update_data_in_mem), UDP_TIMEOUT);
+ if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) == USRP2_ACK){
+ usrp2_ack_pkt.id = htonx<boost::uint32_t>(GET_HW_REV_CMD);
+ udp_bc_transport->send(boost::asio::buffer(&usrp2_ack_pkt, sizeof(usrp2_ack_pkt)));
+
+ size_t len = udp_bc_transport->recv(boost::asio::buffer(usrp2_update_data_in_mem), UDP_TIMEOUT);
+ if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) == GET_HW_REV_ACK){
+ hw_rev = ntohl(update_data_in->data.hw_rev);
+ }
+
+ std::cout << boost::format(" * %s (%s)\n") % udp_bc_transport->get_recv_addr() % filename_map[hw_rev];
+ }
+ }
+}
+
+/***********************************************************************
+ * Find USRP N2XX with specified IP address and return type
+ **********************************************************************/
+boost::uint32_t find_usrp(udp_simple::sptr udp_transport){
+ boost::uint32_t hw_rev;
+ bool found_it = false;
+
+ const usrp2_fw_update_data_t *update_data_in = reinterpret_cast<const usrp2_fw_update_data_t *>(usrp2_update_data_in_mem);
+ usrp2_fw_update_data_t hw_info_pkt = usrp2_fw_update_data_t();
+ hw_info_pkt.proto_ver = htonx<boost::uint32_t>(USRP2_FW_PROTO_VERSION);
+ hw_info_pkt.id = htonx<boost::uint32_t>(GET_HW_REV_CMD);
+ udp_transport->send(boost::asio::buffer(&hw_info_pkt, sizeof(hw_info_pkt)));
+
+ //Loop and receive until the timeout
+ size_t len = udp_transport->recv(boost::asio::buffer(usrp2_update_data_in_mem), UDP_TIMEOUT);
+ if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) == GET_HW_REV_ACK){
+ hw_rev = ntohl(update_data_in->data.hw_rev);
+ if(filename_map.has_key(hw_rev)){
+ std::cout << boost::format("Found %s.\n\n") % filename_map[hw_rev];
+ found_it = true;
+ }
+ else throw std::runtime_error("Invalid revision found.");
+ }
+ if(not found_it) throw std::runtime_error("No USRP N2XX found.");
+
+ return hw_rev;
}
/***********************************************************************
* Custom filename validation functions
**********************************************************************/
-void validate_custom_fpga_file(std::string rev_str, std::string fpga_path){
+void validate_custom_fpga_file(std::string rev_str, std::string& fpga_path){
//Check for existence of file
- if(!does_image_exist(fpga_path)) throw std::runtime_error(str(boost::format("No file at specified FPGA path: %s") % fpga_path));
+ if(not fs::exists(fpga_path)) throw std::runtime_error(str(boost::format("No file at specified FPGA path: %s") % fpga_path));
//Check to find rev_str in filename
uhd::fs_path custom_fpga_path(fpga_path);
- if(custom_fpga_path.leaf().find("fw") != std::string::npos){
- throw std::runtime_error(str(boost::format("Invalid FPGA image filename at path: %s\nFilename indicates that this is a firmware image.")
- % fpga_path));
- }
if(custom_fpga_path.leaf().find(rev_str) == std::string::npos){
throw std::runtime_error(str(boost::format("Invalid FPGA image filename at path: %s\nFilename must contain '%s' to be considered valid for this model.")
% fpga_path % rev_str));
}
}
-void validate_custom_fw_file(std::string rev_str, std::string fw_path){
+void validate_custom_fw_file(std::string rev_str, std::string& fw_path){
//Check for existence of file
- if(!does_image_exist(fw_path)) throw std::runtime_error(str(boost::format("No file at specified firmware path: %s") % fw_path));
+ if(not fs::exists(fw_path)) throw std::runtime_error(str(boost::format("No file at specified firmware path: %s") % fw_path));
//Check to find truncated rev_str in filename
uhd::fs_path custom_fw_path(fw_path);
- if(custom_fw_path.leaf().find("fpga") != std::string::npos){
- throw std::runtime_error(str(boost::format("Invalid firmware image filename at path: %s\nFilename indicates that this is an FPGA image.")
- % fw_path));
- }
if(custom_fw_path.leaf().find(erase_tail_copy(rev_str,3)) == std::string::npos){
throw std::runtime_error(str(boost::format("Invalid firmware image filename at path: %s\nFilename must contain '%s' to be considered valid for this model.")
% fw_path % erase_tail_copy(rev_str,3)));
@@ -126,89 +237,91 @@ void validate_custom_fw_file(std::string rev_str, std::string fw_path){
}
/***********************************************************************
- * Grabbing and validating image binaries
+ * Reading and validating image binaries
**********************************************************************/
-int grab_fpga_image(std::string fpga_path){
+int read_fpga_image(std::string& fpga_path){
- //Reading FPGA image from file
- std::ifstream to_read_fpga((char*)fpga_path.c_str(), std::ios::binary);
- to_read_fpga.seekg(0, std::ios::end);
- fpga_image_size = to_read_fpga.tellg();
- to_read_fpga.seekg(0, std::ios::beg);
- char fpga_read[FPGA_IMAGE_SIZE_BYTES];
- to_read_fpga.read(fpga_read,fpga_image_size);
- to_read_fpga.close();
- for(int i = 0; i < fpga_image_size; i++) fpga_image[i] = (boost::uint8_t)fpga_read[i];
-
- //Checking validity of image
+ //Check size of given image
+ std::ifstream fpga_file(fpga_path.c_str(), std::ios::binary);
+ fpga_file.seekg(0, std::ios::end);
+ int fpga_image_size = fpga_file.tellg();
if(fpga_image_size > FPGA_IMAGE_SIZE_BYTES){
- throw std::runtime_error(str(boost::format("FPGA image is too large. %d > %d") % fpga_image_size % FPGA_IMAGE_SIZE_BYTES));
+ throw std::runtime_error(str(boost::format("FPGA image is too large. %d > %d")
+ % fpga_image_size % FPGA_IMAGE_SIZE_BYTES));
}
- //Check sequence of bytes in image
+ //Check sequence of bytes in image before reading
+ boost::uint8_t fpga_test_bytes[63];
+ fpga_file.seekg(0, std::ios::beg);
+ fpga_file.read((char*)fpga_test_bytes,63);
bool is_good = false;
for(int i = 0; i < 63; i++){
- if((boost::uint8_t)fpga_image[i] == 255) continue;
- else if((boost::uint8_t)fpga_image[i] == 170 and
- (boost::uint8_t)fpga_image[i+1] == 153){
+ if(fpga_test_bytes[i] == 255) continue;
+ else if(fpga_test_bytes[i] == 170 and
+ fpga_test_bytes[i+1] == 153){
is_good = true;
break;
}
}
+ if(not is_good) throw std::runtime_error("Not a valid FPGA image.");
- if(!is_good) throw std::runtime_error("Not a valid FPGA image.");
+ //With image validated, read into utility
+ fpga_file.seekg(0, std::ios::beg);
+ fpga_file.read((char*)fpga_image,fpga_image_size);
+ fpga_file.close();
//Return image size
return fpga_image_size;
}
-int grab_fw_image(std::string fw_path){
-
- //Reading firmware image from file
- std::ifstream to_read_fw((char*)fw_path.c_str(), std::ios::binary);
- to_read_fw.seekg(0, std::ios::end);
- fw_image_size = to_read_fw.tellg();
- to_read_fw.seekg(0, std::ios::beg);
- char fw_read[FW_IMAGE_SIZE_BYTES];
- to_read_fw.read(fw_read,fw_image_size);
- to_read_fw.close();
- for(int i = 0; i < fw_image_size; i++) fw_image[i] = (boost::uint8_t)fw_read[i];
+int read_fw_image(std::string& fw_path){
- //Checking validity of image
+ //Check size of given image
+ std::ifstream fw_file(fw_path.c_str(), std::ios::binary);
+ fw_file.seekg(0, std::ios::end);
+ int fw_image_size = fw_file.tellg();
if(fw_image_size > FW_IMAGE_SIZE_BYTES){
- throw std::runtime_error(str(boost::format("Firmware image is too large. %d > %d") % fw_image_size % FW_IMAGE_SIZE_BYTES));
+ throw std::runtime_error(str(boost::format("Firmware image is too large. %d > %d")
+ % fw_image_size % FW_IMAGE_SIZE_BYTES));
}
- //Check first four bytes of image
- for(int i = 0; i < 4; i++) if((boost::uint8_t)fw_image[i] != 11) throw std::runtime_error("Not a valid firmware image.");
+ //Check sequence of bytes in image before reading
+ boost::uint8_t fw_test_bytes[4];
+ fw_file.seekg(0, std::ios::beg);
+ fw_file.read((char*)fw_test_bytes,4);
+ for(int i = 0; i < 4; i++) if(fw_test_bytes[i] != 11) throw std::runtime_error("Not a valid firmware image.");
+
+ //With image validated, read into utility
+ fw_file.seekg(0, std::ios::beg);
+ fw_file.read((char*)fw_image,fw_image_size);
+ fw_file.close();
- //Return image size
return fw_image_size;
}
-boost::uint32_t* get_flash_info(std::string ip_addr){
+boost::uint32_t* get_flash_info(std::string& ip_addr){
boost::uint32_t *flash_info = new boost::uint32_t[2];
- boost::uint8_t usrp2_update_data_in_mem[udp_simple::mtu];
const usrp2_fw_update_data_t *update_data_in = reinterpret_cast<const usrp2_fw_update_data_t *>(usrp2_update_data_in_mem);
udp_simple::sptr udp_transport = udp_simple::make_connected(ip_addr, BOOST_STRINGIZE(USRP2_UDP_UPDATE_PORT));
usrp2_fw_update_data_t get_flash_info_pkt = usrp2_fw_update_data_t();
get_flash_info_pkt.proto_ver = htonx<boost::uint32_t>(USRP2_FW_PROTO_VERSION);
- get_flash_info_pkt.id = htonx<boost::uint32_t>(USRP2_FW_UPDATE_ID_WATS_TEH_FLASH_INFO_LOL);
+ get_flash_info_pkt.id = htonx<boost::uint32_t>(GET_FLASH_INFO_CMD);
udp_transport->send(boost::asio::buffer(&get_flash_info_pkt, sizeof(get_flash_info_pkt)));
//Loop and receive until the timeout
size_t len = udp_transport->recv(boost::asio::buffer(usrp2_update_data_in_mem), UDP_TIMEOUT);
- if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) == USRP2_FW_UPDATE_ID_HERES_TEH_FLASH_INFO_OMG){
+ if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) == GET_FLASH_INFO_ACK){
flash_info[0] = ntohl(update_data_in->data.flash_info_args.sector_size_bytes);
flash_info[1] = ntohl(update_data_in->data.flash_info_args.memory_size_bytes);
}
- else if(ntohl(update_data_in->id) != USRP2_FW_UPDATE_ID_HERES_TEH_FLASH_INFO_OMG){
- throw std::runtime_error(str(boost::format("Received invalid reply %d from device.\n") % ntohl(update_data_in->id)));
+ else if(ntohl(update_data_in->id) != GET_FLASH_INFO_ACK){
+ throw std::runtime_error(str(boost::format("Received invalid reply %d from device.\n")
+ % ntohl(update_data_in->id)));
}
-
+
return flash_info;
}
@@ -218,102 +331,100 @@ boost::uint32_t* get_flash_info(std::string ip_addr){
void erase_image(udp_simple::sptr udp_transport, bool is_fw, boost::uint32_t memory_size){
+ boost::uint32_t image_location_addr = is_fw ? PROD_FW_IMAGE_LOCATION_ADDR
+ : PROD_FPGA_IMAGE_LOCATION_ADDR;
+ boost::uint32_t image_size = is_fw ? FW_IMAGE_SIZE_BYTES
+ : FPGA_IMAGE_SIZE_BYTES;
+
//Making sure this won't attempt to erase past end of device
- if(is_fw){
- if(PROD_FW_IMAGE_LOCATION_ADDR+FW_IMAGE_SIZE_BYTES > memory_size) throw std::runtime_error("Cannot erase past end of device.");
- }
- else{
- if(PROD_FPGA_IMAGE_LOCATION_ADDR+FPGA_IMAGE_SIZE_BYTES > memory_size) throw std::runtime_error("Cannot erase past end of device.");
- }
+ if((image_location_addr+image_size) > memory_size) throw std::runtime_error("Cannot erase past end of device.");
- //Setting up UDP transport
- boost::uint8_t usrp2_update_data_in_mem[udp_simple::mtu];
+ //UDP receive buffer
const usrp2_fw_update_data_t *update_data_in = reinterpret_cast<const usrp2_fw_update_data_t *>(usrp2_update_data_in_mem);
//Setting up UDP packet
usrp2_fw_update_data_t erase_pkt = usrp2_fw_update_data_t();
- erase_pkt.id = htonx<boost::uint32_t>(USRP2_FW_UPDATE_ID_ERASE_TEH_FLASHES_LOL);
+ erase_pkt.id = htonx<boost::uint32_t>(ERASE_FLASH_CMD);
erase_pkt.proto_ver = htonx<boost::uint32_t>(USRP2_FW_PROTO_VERSION);
- if(is_fw){
- erase_pkt.data.flash_args.flash_addr = htonx<boost::uint32_t>(PROD_FW_IMAGE_LOCATION_ADDR);
- erase_pkt.data.flash_args.length = htonx<boost::uint32_t>(FW_IMAGE_SIZE_BYTES);
- }
- else{
- erase_pkt.data.flash_args.flash_addr = htonx<boost::uint32_t>(PROD_FPGA_IMAGE_LOCATION_ADDR);
- erase_pkt.data.flash_args.length = htonx<boost::uint32_t>(FPGA_IMAGE_SIZE_BYTES);
- }
+ erase_pkt.data.flash_args.flash_addr = htonx<boost::uint32_t>(image_location_addr);
+ erase_pkt.data.flash_args.length = htonx<boost::uint32_t>(image_size);
//Begin erasing
udp_transport->send(boost::asio::buffer(&erase_pkt, sizeof(erase_pkt)));
size_t len = udp_transport->recv(boost::asio::buffer(usrp2_update_data_in_mem), UDP_TIMEOUT);
- if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) == USRP2_FW_UPDATE_ID_ERASING_TEH_FLASHES_OMG){
+ if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) == ERASE_FLASH_ACK){
if(is_fw) std::cout << "Erasing firmware image." << std::endl;
else std::cout << "Erasing FPGA image." << std::endl;
}
- else if(ntohl(update_data_in->id) != USRP2_FW_UPDATE_ID_ERASING_TEH_FLASHES_OMG){
- throw std::runtime_error(str(boost::format("Received invalid reply %d from device.\n") % ntohl(update_data_in->id)));
+ else if(ntohl(update_data_in->id) != ERASE_FLASH_ACK){
+ throw std::runtime_error(str(boost::format("Received invalid reply %d from device.\n")
+ % ntohl(update_data_in->id)));
}
//Check for erase completion
- erase_pkt.id = htonx<boost::uint32_t>(USRP2_FW_UPDATE_ID_R_U_DONE_ERASING_LOL);
+ erase_pkt.id = htonx<boost::uint32_t>(CHECK_ERASING_DONE_CMD);
while(true){
udp_transport->send(boost::asio::buffer(&erase_pkt, sizeof(erase_pkt)));
size_t len = udp_transport->recv(boost::asio::buffer(usrp2_update_data_in_mem), UDP_TIMEOUT);
- if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) == USRP2_FW_UPDATE_ID_IM_DONE_ERASING_OMG){
- if(is_fw) std::cout << boost::format(" * Successfully erased %d bytes at %d.\n") % FW_IMAGE_SIZE_BYTES % PROD_FW_IMAGE_LOCATION_ADDR;
- else std::cout << boost::format(" * Successfully erased %d bytes at %d.\n") % FPGA_IMAGE_SIZE_BYTES % PROD_FPGA_IMAGE_LOCATION_ADDR;
+ if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) == DONE_ERASING_ACK){
+ std::cout << boost::format(" * Successfully erased %d bytes at %d.\n")
+ % image_size % image_location_addr;
break;
}
- else if(ntohl(update_data_in->id) != USRP2_FW_UPDATE_ID_NOPE_NOT_DONE_ERASING_OMG){
- throw std::runtime_error(str(boost::format("Received invalid reply %d from device.\n") % ntohl(update_data_in->id)));
+ else if(ntohl(update_data_in->id) != NOT_DONE_ERASING_ACK){
+ throw std::runtime_error(str(boost::format("Received invalid reply %d from device.\n")
+ % ntohl(update_data_in->id)));
}
}
}
void write_image(udp_simple::sptr udp_transport, bool is_fw, boost::uint8_t* image, boost::uint32_t memory_size, int image_size){
- boost::uint32_t current_addr;
- if(is_fw) current_addr = PROD_FW_IMAGE_LOCATION_ADDR;
- else current_addr = PROD_FPGA_IMAGE_LOCATION_ADDR;
+ boost::uint32_t begin_addr = is_fw ? PROD_FW_IMAGE_LOCATION_ADDR
+ : PROD_FPGA_IMAGE_LOCATION_ADDR;
+ boost::uint32_t current_addr = begin_addr;
+ std::string type = is_fw ? "firmware" : "FPGA";
//Making sure this won't attempt to write past end of device
if(current_addr+image_size > memory_size) throw std::runtime_error("Cannot write past end of device.");
- //Setting up UDP transport
- boost::uint8_t usrp2_update_data_in_mem[udp_simple::mtu];
+ //UDP receive buffer
const usrp2_fw_update_data_t *update_data_in = reinterpret_cast<const usrp2_fw_update_data_t *>(usrp2_update_data_in_mem);
//Setting up UDP packet
usrp2_fw_update_data_t write_pkt = usrp2_fw_update_data_t();
- write_pkt.id = htonx<boost::uint32_t>(USRP2_FW_UPDATE_ID_WRITE_TEH_FLASHES_LOL);
+ write_pkt.id = htonx<boost::uint32_t>(WRITE_FLASH_CMD);
write_pkt.proto_ver = htonx<boost::uint32_t>(USRP2_FW_PROTO_VERSION);
write_pkt.data.flash_args.length = htonx<boost::uint32_t>(FLASH_DATA_PACKET_SIZE);
- //Write image
- if(is_fw) std::cout << "Writing firmware image." << std::endl;
- else std::cout << "Writing FPGA image." << std::endl;
-
for(int i = 0; i < ((image_size/FLASH_DATA_PACKET_SIZE)+1); i++){
+ //Print progress
+ std::cout << "\rWriting " << type << " image ("
+ << int((double(current_addr-begin_addr)/double(image_size))*100) << "%)." << std::flush;
+
write_pkt.data.flash_args.flash_addr = htonx<boost::uint32_t>(current_addr);
std::copy(image+(i*FLASH_DATA_PACKET_SIZE), image+((i+1)*FLASH_DATA_PACKET_SIZE), write_pkt.data.flash_args.data);
udp_transport->send(boost::asio::buffer(&write_pkt, sizeof(write_pkt)));
size_t len = udp_transport->recv(boost::asio::buffer(usrp2_update_data_in_mem), UDP_TIMEOUT);
- if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) != USRP2_FW_UPDATE_ID_WROTE_TEH_FLASHES_OMG){
- throw std::runtime_error(str(boost::format("Invalid reply %d from device.") % ntohl(update_data_in->id)));
+ if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) != WRITE_FLASH_ACK){
+ throw std::runtime_error(str(boost::format("Invalid reply %d from device.")
+ % ntohl(update_data_in->id)));
}
current_addr += FLASH_DATA_PACKET_SIZE;
}
+ std::cout << std::flush << "\rWriting " << type << " image (100%)." << std::endl;
std::cout << boost::format(" * Successfully wrote %d bytes.\n") % image_size;
}
void verify_image(udp_simple::sptr udp_transport, bool is_fw, boost::uint8_t* image, boost::uint32_t memory_size, int image_size){
int current_index = 0;
- boost::uint32_t current_addr;
- if(is_fw) current_addr = PROD_FW_IMAGE_LOCATION_ADDR;
- else current_addr = PROD_FPGA_IMAGE_LOCATION_ADDR;
+ boost::uint32_t begin_addr = is_fw ? PROD_FW_IMAGE_LOCATION_ADDR
+ : PROD_FPGA_IMAGE_LOCATION_ADDR;
+ boost::uint32_t current_addr = begin_addr;
+ std::string type = is_fw ? "firmware" : "FPGA";
//Array size needs to be known at runtime, this constant is guaranteed to be larger than any firmware or FPGA image
boost::uint8_t from_usrp[FPGA_IMAGE_SIZE_BYTES];
@@ -321,27 +432,27 @@ void verify_image(udp_simple::sptr udp_transport, bool is_fw, boost::uint8_t* im
//Making sure this won't attempt to read past end of device
if(current_addr+image_size > memory_size) throw std::runtime_error("Cannot read past end of device.");
- //Setting up UDP transport
- boost::uint8_t usrp2_update_data_in_mem[udp_simple::mtu];
+ //UDP receive buffer
const usrp2_fw_update_data_t *update_data_in = reinterpret_cast<const usrp2_fw_update_data_t *>(usrp2_update_data_in_mem);
//Setting up UDP packet
usrp2_fw_update_data_t verify_pkt = usrp2_fw_update_data_t();
- verify_pkt.id = htonx<boost::uint32_t>(USRP2_FW_UPDATE_ID_READ_TEH_FLASHES_LOL);
+ verify_pkt.id = htonx<boost::uint32_t>(READ_FLASH_CMD);
verify_pkt.proto_ver = htonx<boost::uint32_t>(USRP2_FW_PROTO_VERSION);
verify_pkt.data.flash_args.length = htonx<boost::uint32_t>(FLASH_DATA_PACKET_SIZE);
- //Verify image
- if(is_fw) std::cout << "Verifying firmware image." << std::endl;
- else std::cout << "Verifying FPGA image." << std::endl;
-
for(int i = 0; i < ((image_size/FLASH_DATA_PACKET_SIZE)+1); i++){
+ //Print progress
+ std::cout << "\rVerifying " << type << " image ("
+ << int((double(current_addr-begin_addr)/double(image_size))*100) << "%)." << std::flush;
+
verify_pkt.data.flash_args.flash_addr = htonx<boost::uint32_t>(current_addr);
udp_transport->send(boost::asio::buffer(&verify_pkt, sizeof(verify_pkt)));
size_t len = udp_transport->recv(boost::asio::buffer(usrp2_update_data_in_mem), UDP_TIMEOUT);
- if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) != USRP2_FW_UPDATE_ID_KK_READ_TEH_FLASHES_OMG){
- throw std::runtime_error(str(boost::format("Invalid reply %d from device.") % ntohl(update_data_in->id)));
+ if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) != READ_FLASH_ACK){
+ throw std::runtime_error(str(boost::format("Invalid reply %d from device.")
+ % ntohl(update_data_in->id)));
}
for(int j = 0; j < FLASH_DATA_PACKET_SIZE; j++) from_usrp[current_index+j] = update_data_in->data.flash_args.data[j];
@@ -350,27 +461,27 @@ void verify_image(udp_simple::sptr udp_transport, bool is_fw, boost::uint8_t* im
}
for(int i = 0; i < image_size; i++) if(from_usrp[i] != image[i]) throw std::runtime_error("Image write failed.");
+ std::cout << std::flush << "\rVerifying " << type << " image (100%)." << std::endl;
std::cout << " * Successful." << std::endl;
}
void reset_usrp(udp_simple::sptr udp_transport){
//Set up UDP transport
- boost::uint8_t usrp2_update_data_in_mem[udp_simple::mtu];
const usrp2_fw_update_data_t *update_data_in = reinterpret_cast<const usrp2_fw_update_data_t *>(usrp2_update_data_in_mem);
//Set up UDP packet
usrp2_fw_update_data_t reset_pkt = usrp2_fw_update_data_t();
- reset_pkt.id = htonx<boost::uint32_t>(USRP2_FW_UPDATE_ID_RESET_MAH_COMPUTORZ_LOL);
+ reset_pkt.id = htonx<boost::uint32_t>(RESET_USRP_CMD);
reset_pkt.proto_ver = htonx<boost::uint32_t>(USRP2_FW_PROTO_VERSION);
//Reset USRP
udp_transport->send(boost::asio::buffer(&reset_pkt, sizeof(reset_pkt)));
size_t len = udp_transport->recv(boost::asio::buffer(usrp2_update_data_in_mem), UDP_TIMEOUT);
- if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) == USRP2_FW_UPDATE_ID_RESETTIN_TEH_COMPUTORZ_OMG){
+ if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) == RESET_USRP_ACK){
throw std::runtime_error("USRP reset failed."); //There should be no response to this UDP packet
}
- else std::cout << "Resetting USRP." << std::endl;
+ else std::cout << std::endl << "Resetting USRP." << std::endl;
}
int UHD_SAFE_MAIN(int argc, char *argv[]){
@@ -386,125 +497,88 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
("addr", po::value<std::string>(&ip_addr)->default_value("192.168.10.2"), "Specify an IP address.")
("fw", po::value<std::string>(&fw_path), "Specify a filepath for a custom firmware image.")
("fpga", po::value<std::string>(&fpga_path), "Specify a filepath for a custom FPGA image.")
- ("no_fw", "Do not burn a firmware image.")
- ("no_fpga", "Do not burn an FPGA image.")
- ("auto_reboot", "Automatically reboot N2XX without prompting.")
+ ("no-fw", "Do not burn a firmware image.")
+ ("no_fw", "Do not burn a firmware image (DEPRECATED).")
+ ("no-fpga", "Do not burn an FPGA image.")
+ ("no_fpga", "Do not burn an FPGA image (DEPRECATED).")
+ ("auto-reboot", "Automatically reboot N2XX without prompting.")
+ ("auto_reboot", "Automatically reboot N2XX without prompting (DEPRECATED).")
("list", "List available N2XX USRP devices.")
;
po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc), vm);
po::notify(vm);
- //Apply options
+ //Print help message
if(vm.count("help") > 0){
std::cout << boost::format("N2XX Simple Net Burner\n");
std::cout << boost::format("Automatically detects and burns standard firmware and FPGA images onto USRP N2XX devices.\n");
std::cout << boost::format("Can optionally take user input for custom images.\n\n");
std::cout << desc << std::endl;
- return EXIT_FAILURE;
+ return EXIT_SUCCESS;
}
- bool burn_fpga = (vm.count("no_fpga") == 0);
- bool burn_fw = (vm.count("no_fw") == 0);
+ //List option
+ if(vm.count("list")){
+ list_usrps();
+ return EXIT_SUCCESS;
+ }
+
+ //Process user options
+ bool burn_fpga = (vm.count("no-fpga") == 0) and (vm.count("no_fpga") == 0);
+ bool burn_fw = (vm.count("no-fw") == 0) and (vm.count("no_fw") == 0);
bool use_custom_fpga = (vm.count("fpga") > 0);
bool use_custom_fw = (vm.count("fw") > 0);
- bool list_usrps = (vm.count("list") > 0);
- bool auto_reboot = (vm.count("auto_reboot") > 0);
+ bool auto_reboot = (vm.count("auto-reboot") > 0) or (vm.count("auto_reboot") > 0);
+ int fpga_image_size = 0;
+ int fw_image_size = 0;
- if(!burn_fpga && !burn_fw){
+ if(not burn_fpga && not burn_fw){
std::cout << "No images will be burned." << std::endl;
return EXIT_FAILURE;
}
- if(!burn_fw && use_custom_fw) std::cout << boost::format("Conflicting firmware options presented. Will not burn a firmware image.\n\n");
- if(!burn_fpga && use_custom_fpga) std::cout << boost::format("Conflicting FPGA options presented. Will not burn an FPGA image.\n\n");
-
- //Variables not from options
- boost::uint32_t hw_rev;
- bool found_it = false;
- boost::uint8_t usrp2_update_data_in_mem[udp_simple::mtu];
- const usrp2_fw_update_data_t *update_data_in = reinterpret_cast<const usrp2_fw_update_data_t *>(usrp2_update_data_in_mem);
-
- //List option
- if(list_usrps){
- udp_simple::sptr udp_bc_transport;
- usrp2_fw_update_data_t usrp2_ack_pkt = usrp2_fw_update_data_t();
- usrp2_ack_pkt.proto_ver = htonx<boost::uint32_t>(USRP2_FW_PROTO_VERSION);
- usrp2_ack_pkt.id = htonx<boost::uint32_t>(USRP2_FW_UPDATE_ID_OHAI_LOL);
-
- std::cout << "Available USRP N2XX devices:" << std::endl;
-
- //Send UDP packets to all broadcast addresses
- BOOST_FOREACH(const if_addrs_t &if_addrs, get_if_addrs()){
- //Avoid the loopback device
- if(if_addrs.inet == boost::asio::ip::address_v4::loopback().to_string()) continue;
- udp_bc_transport = udp_simple::make_broadcast(if_addrs.bcast, BOOST_STRINGIZE(USRP2_UDP_UPDATE_PORT));
- udp_bc_transport->send(boost::asio::buffer(&usrp2_ack_pkt, sizeof(usrp2_ack_pkt)));
-
- size_t len = udp_bc_transport->recv(boost::asio::buffer(usrp2_update_data_in_mem), UDP_TIMEOUT);
- if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) == USRP2_FW_UPDATE_ID_OHAI_OMG){
- usrp2_ack_pkt.id = htonx<boost::uint32_t>(USRP2_FW_UPDATE_ID_I_CAN_HAS_HW_REV_LOL);
- udp_bc_transport->send(boost::asio::buffer(&usrp2_ack_pkt, sizeof(usrp2_ack_pkt)));
-
- size_t len = udp_bc_transport->recv(boost::asio::buffer(usrp2_update_data_in_mem), UDP_TIMEOUT);
- if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) == USRP2_FW_UPDATE_ID_HERES_TEH_HW_REV_OMG){
- hw_rev = ntohl(update_data_in->data.hw_rev);
- }
+ //Print deprecation messages if necessary
+ if(vm.count("no_fpga") > 0) std::cout << "WARNING: --no_fpga option is deprecated! Use --no-fpga instead." << std::endl << std::endl;
+ if(vm.count("no_fw") > 0) std::cout << "WARNING: --no_fw option is deprecated! Use --no-fw instead." << std::endl << std::endl;
+ if(vm.count("auto_reboot") > 0) std::cout << "WARNING: --auto_reboot option is deprecated! Use --auto-reboot instead." << std::endl << std::endl;
- std::cout << boost::format(" * %s (%s)\n") % udp_bc_transport->get_recv_addr() % filename_map[hw_rev];
- }
-
- }
- return EXIT_FAILURE;
- }
+ //Find USRP and establish connection
std::cout << boost::format("Searching for USRP N2XX with IP address %s.\n") % ip_addr;
-
- //Address specified
udp_simple::sptr udp_transport = udp_simple::make_connected(ip_addr, BOOST_STRINGIZE(USRP2_UDP_UPDATE_PORT));
- usrp2_fw_update_data_t hw_info_pkt = usrp2_fw_update_data_t();
- hw_info_pkt.proto_ver = htonx<boost::uint32_t>(USRP2_FW_PROTO_VERSION);
- hw_info_pkt.id = htonx<boost::uint32_t>(USRP2_FW_UPDATE_ID_I_CAN_HAS_HW_REV_LOL);
- udp_transport->send(boost::asio::buffer(&hw_info_pkt, sizeof(hw_info_pkt)));
-
- //Loop and receive until the timeout
- size_t len = udp_transport->recv(boost::asio::buffer(usrp2_update_data_in_mem), UDP_TIMEOUT);
- if(len > offsetof(usrp2_fw_update_data_t, data) and ntohl(update_data_in->id) == USRP2_FW_UPDATE_ID_HERES_TEH_HW_REV_OMG){
- hw_rev = ntohl(update_data_in->data.hw_rev);
- if(filename_map.find(hw_rev) != filename_map.end()){
- std::cout << boost::format("Found %s.\n\n") % filename_map[hw_rev];
- found_it = true;
- }
- else throw std::runtime_error("Invalid revision found.");
- }
- if(!found_it) throw std::runtime_error("No USRP N2XX found.");
-
- //Determining default image filenames for validation
- std::string default_fw_filename = str(boost::format("usrp_%s_fw.bin") % erase_tail_copy(filename_map[hw_rev],3));
- std::string default_fpga_filename = str(boost::format("usrp_%s_fpga.bin") % filename_map[hw_rev]);
- std::string default_fw_filepath = "";
- std::string default_fpga_filepath = "";
+ boost::uint32_t hw_rev = find_usrp(udp_transport);
//Check validity of file locations and binaries before attempting burn
std::cout << "Searching for specified images." << std::endl << std::endl;
if(burn_fpga){
- if(!use_custom_fpga) fpga_path = find_image_path(default_fpga_filename);
- else{
- //Replace ~ with home directory
- if(fpga_path.find("~/") == 0) fpga_path.replace(0,1,getenv("HOME"));
+ if(use_custom_fpga){
+ //Expand tilde usage if applicable
+ #ifndef UHD_PLATFORM_WIN32
+ if(fpga_path.find("~/") == 0) fpga_path.replace(0,1,getenv("HOME"));
+ #endif
validate_custom_fpga_file(filename_map[hw_rev], fpga_path);
}
+ else{
+ std::string default_fpga_filename = str(boost::format("usrp_%s_fpga.bin") % filename_map[hw_rev]);
+ fpga_path = find_image_path(default_fpga_filename);
+ }
- grab_fpga_image(fpga_path);
+ fpga_image_size = read_fpga_image(fpga_path);
}
if(burn_fw){
- if(!use_custom_fw) fw_path = find_image_path(default_fw_filename);
- else{
- //Replace ~ with home directory
- if(fw_path.find("~/") == 0) fw_path.replace(0,1,getenv("HOME"));
+ if(use_custom_fw){
+ //Expand tilde usage if applicable
+ #ifndef UHD_PLATFORM_WIN32
+ if(fw_path.find("~/") == 0) fw_path.replace(0,1,getenv("HOME"));
+ #endif
validate_custom_fw_file(filename_map[hw_rev], fw_path);
}
+ else{
+ std::string default_fw_filename = str(boost::format("usrp_%s_fw.bin") % erase_tail_copy(filename_map[hw_rev],3));
+ fw_path = find_image_path(default_fw_filename);
+ }
- grab_fw_image(fw_path);
+ fw_image_size = read_fw_image(fw_path);
}
std::cout << "Will burn the following images:" << std::endl;
@@ -547,7 +621,6 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
std::cout << std::endl; //Formatting
}
if(reset) reset_usrp(udp_transport);
- else return EXIT_SUCCESS;
return EXIT_SUCCESS;
}
diff --git a/host/utils/usrp_simple_burner_utils.hpp b/host/utils/usrp_simple_burner_utils.hpp
deleted file mode 100644
index f386c3620..000000000
--- a/host/utils/usrp_simple_burner_utils.hpp
+++ /dev/null
@@ -1,99 +0,0 @@
-//
-// Copyright 2012 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
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-
-#include <iostream>
-#include <math.h>
-#include <stdint.h>
-
-#include <boost/foreach.hpp>
-#include <boost/asio.hpp>
-#include <boost/filesystem.hpp>
-
-#include <uhd/exception.hpp>
-#include <uhd/transport/if_addrs.hpp>
-#include <uhd/transport/udp_simple.hpp>
-#include <uhd/types/device_addr.hpp>
-#include <uhd/utils/msg.hpp>
-
-#define UDP_FW_UPDATE_PORT 49154
-#define UDP_MAX_XFER_BYTES 1024
-#define UDP_TIMEOUT 3
-#define UDP_POLL_INTERVAL 0.10 //in seconds
-#define USRP2_FW_PROTO_VERSION 7 //should be unused after r6
-#define USRP2_UDP_UPDATE_PORT 49154
-#define FLASH_DATA_PACKET_SIZE 256
-#define FPGA_IMAGE_SIZE_BYTES 1572864
-#define FW_IMAGE_SIZE_BYTES 31744
-#define PROD_FPGA_IMAGE_LOCATION_ADDR 0x00180000
-#define PROD_FW_IMAGE_LOCATION_ADDR 0x00300000
-#define SAFE_FPGA_IMAGE_LOCATION_ADDR 0x00000000
-#define SAFE_FW_IMAGE_LOCATION_ADDR 0x003F0000
-
-using namespace uhd;
-using namespace uhd::transport;
-namespace asio = boost::asio;
-
-typedef enum {
- USRP2_FW_UPDATE_ID_WAT = ' ',
-
- USRP2_FW_UPDATE_ID_OHAI_LOL = 'a',
- USRP2_FW_UPDATE_ID_OHAI_OMG = 'A',
-
- USRP2_FW_UPDATE_ID_WATS_TEH_FLASH_INFO_LOL = 'f',
- USRP2_FW_UPDATE_ID_HERES_TEH_FLASH_INFO_OMG = 'F',
-
- USRP2_FW_UPDATE_ID_ERASE_TEH_FLASHES_LOL = 'e',
- USRP2_FW_UPDATE_ID_ERASING_TEH_FLASHES_OMG = 'E',
-
- USRP2_FW_UPDATE_ID_R_U_DONE_ERASING_LOL = 'd',
- USRP2_FW_UPDATE_ID_IM_DONE_ERASING_OMG = 'D',
- USRP2_FW_UPDATE_ID_NOPE_NOT_DONE_ERASING_OMG = 'B',
-
- USRP2_FW_UPDATE_ID_WRITE_TEH_FLASHES_LOL = 'w',
- USRP2_FW_UPDATE_ID_WROTE_TEH_FLASHES_OMG = 'W',
-
- USRP2_FW_UPDATE_ID_READ_TEH_FLASHES_LOL = 'r',
- USRP2_FW_UPDATE_ID_KK_READ_TEH_FLASHES_OMG = 'R',
-
- USRP2_FW_UPDATE_ID_RESET_MAH_COMPUTORZ_LOL = 's',
- USRP2_FW_UPDATE_ID_RESETTIN_TEH_COMPUTORZ_OMG = 'S',
-
- USRP2_FW_UPDATE_ID_I_CAN_HAS_HW_REV_LOL = 'v',
- USRP2_FW_UPDATE_ID_HERES_TEH_HW_REV_OMG = 'V',
-
- USRP2_FW_UPDATE_ID_KTHXBAI = '~'
-
-} usrp2_fw_update_id_t;
-
-typedef struct {
- uint32_t proto_ver;
- uint32_t id;
- uint32_t seq;
- union {
- uint32_t ip_addr;
- uint32_t hw_rev;
- struct {
- uint32_t flash_addr;
- uint32_t length;
- uint8_t data[256];
- } flash_args;
- struct {
- uint32_t sector_size_bytes;
- uint32_t memory_size_bytes;
- } flash_info_args;
- } data;
-} usrp2_fw_update_data_t;