diff options
Diffstat (limited to 'host/utils')
| -rw-r--r-- | host/utils/uhd_cal_rx_iq_balance.cpp | 31 | ||||
| -rw-r--r-- | host/utils/uhd_cal_tx_dc_offset.cpp | 31 | ||||
| -rw-r--r-- | host/utils/uhd_cal_tx_iq_balance.cpp | 36 | ||||
| -rw-r--r-- | host/utils/usrp_burn_mb_eeprom.cpp | 51 | ||||
| -rw-r--r-- | host/utils/usrp_cal_utils.hpp | 64 | ||||
| -rw-r--r-- | host/utils/usrp_n2xx_simple_net_burner.cpp | 495 | ||||
| -rw-r--r-- | host/utils/usrp_simple_burner_utils.hpp | 99 | 
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; | 
