aboutsummaryrefslogtreecommitdiffstats
path: root/host/utils
diff options
context:
space:
mode:
Diffstat (limited to 'host/utils')
-rw-r--r--host/utils/CMakeLists.txt4
-rw-r--r--host/utils/b2xx_fx3_utils.cpp86
-rwxr-xr-xhost/utils/b2xx_side_channel.py818
-rw-r--r--host/utils/nirio_programmer.cpp275
-rw-r--r--host/utils/octoclock_firmware_burner.cpp81
-rw-r--r--host/utils/uhd_image_loader.cpp122
-rw-r--r--host/utils/uhd_images_downloader.py.in161
-rwxr-xr-xhost/utils/usrp_n2xx_net_burner.py51
-rw-r--r--host/utils/usrp_n2xx_simple_net_burner.cpp57
-rw-r--r--host/utils/usrp_x3xx_fpga_burner.cpp71
10 files changed, 1318 insertions, 408 deletions
diff --git a/host/utils/CMakeLists.txt b/host/utils/CMakeLists.txt
index e24b417c1..530bcf087 100644
--- a/host/utils/CMakeLists.txt
+++ b/host/utils/CMakeLists.txt
@@ -1,5 +1,5 @@
#
-# Copyright 2010-2014 Ettus Research LLC
+# Copyright 2010-2015 Ettus Research LLC
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -21,11 +21,11 @@
SET(util_runtime_sources
uhd_find_devices.cpp
uhd_usrp_probe.cpp
+ uhd_image_loader.cpp
uhd_cal_rx_iq_balance.cpp
uhd_cal_tx_dc_offset.cpp
uhd_cal_tx_iq_balance.cpp
usrp_n2xx_simple_net_burner.cpp
- nirio_programmer.cpp
)
SET(x3xx_burner_sources
diff --git a/host/utils/b2xx_fx3_utils.cpp b/host/utils/b2xx_fx3_utils.cpp
index 572daef70..bc14932f1 100644
--- a/host/utils/b2xx_fx3_utils.cpp
+++ b/host/utils/b2xx_fx3_utils.cpp
@@ -51,20 +51,26 @@ struct vid_pid_t {
const static vid_pid_t known_vid_pids[] = {
{FX3_VID, FX3_DEFAULT_PID},
{FX3_VID, FX3_REENUM_PID},
- {B200_VENDOR_ID, B200_PRODUCT_ID}
+ {B200_VENDOR_ID, B200_PRODUCT_ID},
+ {B200_VENDOR_NI_ID, B200_PRODUCT_NI_ID},
+ {B200_VENDOR_NI_ID, B210_PRODUCT_NI_ID}
};
const static std::vector<vid_pid_t> known_vid_pid_vector(known_vid_pids, known_vid_pids + (sizeof(known_vid_pids) / sizeof(known_vid_pids[0])));
-const static boost::uint8_t eeprom_init_values[] = {
- 0x43,
- 0x59,
- 0x14,
- 0xB2,
- (B200_PRODUCT_ID & 0xff),
- (B200_PRODUCT_ID >> 8),
- (B200_VENDOR_ID & 0xff),
- (B200_VENDOR_ID >> 8)
- };
-const static uhd::byte_vector_t eeprom_init_value_vector(eeprom_init_values, eeprom_init_values + (sizeof(eeprom_init_values) / sizeof(eeprom_init_values[0])));
+
+static const size_t EEPROM_INIT_VALUE_VECTOR_SIZE = 8;
+static uhd::byte_vector_t construct_eeprom_init_value_vector(boost::uint16_t vid, boost::uint16_t pid)
+{
+ uhd::byte_vector_t init_values(EEPROM_INIT_VALUE_VECTOR_SIZE);
+ init_values.at(0) = 0x43;
+ init_values.at(1) = 0x59;
+ init_values.at(2) = 0x14;
+ init_values.at(3) = 0xB2;
+ init_values.at(4) = static_cast<boost::uint8_t>(pid & 0xff);
+ init_values.at(5) = static_cast<boost::uint8_t>(pid >> 8);
+ init_values.at(6) = static_cast<boost::uint8_t>(vid & 0xff);
+ init_values.at(7) = static_cast<boost::uint8_t>(vid >> 8);
+ return init_values;
+}
//!used with lexical cast to parse a hex string
template <class T> struct to_hex{
@@ -153,15 +159,22 @@ uhd::transport::usb_device_handle::sptr open_device(const boost::uint16_t vid, c
try {
// try caller's VID/PID first
- handles = uhd::transport::usb_device_handle::get_device_list(vp.vid,vp.pid);
- if (user_supplied && handles.size() == 0)
- std::cerr << (boost::format("Failed to open device with VID 0x%04x and PID 0x%04x - trying other known VID/PIDs") % vid % pid).str() << std::endl;
-
- // try known VID/PIDs next
- for (size_t i = 0; handles.size() == 0 && i < known_vid_pid_vector.size(); i++)
+ std::vector<uhd::transport::usb_device_handle::vid_pid_pair_t> vid_pid_pair_list(1,uhd::transport::usb_device_handle::vid_pid_pair_t(vid,pid));
+ handles = uhd::transport::usb_device_handle::get_device_list(vid_pid_pair_list);
+ if (handles.size() == 0)
{
- vp = known_vid_pid_vector[i];
- handles = uhd::transport::usb_device_handle::get_device_list(vp.vid,vp.pid);
+ if (user_supplied)
+ {
+ std::cerr << (boost::format("Failed to open device with VID 0x%04x and PID 0x%04x - trying other known VID/PIDs") % vid % pid).str() << std::endl;
+ }
+
+ // try known VID/PIDs next
+ for (size_t i = 0; handles.size() == 0 && i < known_vid_pid_vector.size(); i++)
+ {
+ vp = known_vid_pid_vector[i];
+ handles = uhd::transport::usb_device_handle::get_device_list(vp.vid, vp.pid);
+ }
+
}
if (handles.size() > 0)
@@ -221,7 +234,7 @@ int read_eeprom(b200_iface::sptr& b200, uhd::byte_vector_t& data)
int write_eeprom(b200_iface::sptr& b200, const uhd::byte_vector_t& data)
{
try {
- b200->write_eeprom(0x0, 0x0, data);
+ b200->write_eeprom(0x0, 0x0, data);
} catch (std::exception &e) {
std::cerr << "Exception while writing EEPROM: " << e.what() << std::endl;
return -1;
@@ -281,7 +294,7 @@ int erase_eeprom(b200_iface::sptr& b200)
boost::int32_t main(boost::int32_t argc, char *argv[]) {
boost::uint16_t vid, pid;
- std::string pid_str, vid_str, fw_file, fpga_file;
+ std::string pid_str, vid_str, fw_file, fpga_file, writevid_str, writepid_str;
bool user_supplied_vid_pid = false;
po::options_description visible("Allowed options");
@@ -295,7 +308,6 @@ boost::int32_t main(boost::int32_t argc, char *argv[]) {
("reset-device,D", "Reset the B2xx Device.")
("reset-fpga,F", "Reset the FPGA (does not require re-programming.")
("reset-usb,U", "Reset the USB subsystem on your host computer.")
- ("init-device,I", "Initialize a B2xx device.")
("load-fw,W", po::value<std::string>(&fw_file),
"Load a firmware (hex) file into the FX3.")
("load-fpga,L", po::value<std::string>(&fpga_file),
@@ -305,9 +317,14 @@ boost::int32_t main(boost::int32_t argc, char *argv[]) {
// Hidden options provided for testing - use at your own risk!
po::options_description hidden("Hidden options");
hidden.add_options()
- ("uninit-device,U", "Uninitialize a B2xx device.")
+ ("init-device,I", "Initialize a B2xx device.")
+ ("uninit-device", "Uninitialize a B2xx device.")
("read-eeprom,R", "Read first 8 bytes of EEPROM")
- ("erase-eeprom,E", "Erase first 8 bytes of EEPROM");
+ ("erase-eeprom,E", "Erase first 8 bytes of EEPROM")
+ ("write-vid", po::value<std::string>(&writevid_str),
+ "Write VID field of EEPROM")
+ ("write-pid", po::value<std::string>(&writepid_str),
+ "Write PID field of EEPROM");
po::options_description desc;
desc.add(visible);
@@ -486,9 +503,24 @@ boost::int32_t main(boost::int32_t argc, char *argv[]) {
* Cypress VID/PID for the initial FW load, but we can initialize from any state. */
if (vm.count("init-device"))
{
+ uint16_t writevid = B200_VENDOR_ID;
+ uint16_t writepid = B200_PRODUCT_ID;
+
/* Now, initialize the device. */
- if (write_and_verify_eeprom(b200, eeprom_init_value_vector))
- return -1;
+ // Added for testing purposes - not exposed
+ if (vm.count("write-vid") && vm.count("write-pid"))
+ {
+ try {
+ writevid = atoh(writevid_str);
+ writepid = atoh(writepid_str);
+ } catch (std::exception &e) {
+ std::cerr << "Exception while parsing write VID and PID: " << e.what() << std:: endl;
+ return ~0;
+ }
+ }
+
+ std::cout << "Writing VID and PID to EEPROM..." << std::endl << std::endl;
+ if (write_and_verify_eeprom(b200, construct_eeprom_init_value_vector(writevid, writepid))) return -1;
std::cout << "EEPROM initialized, resetting device..."
<< std::endl << std::endl;
diff --git a/host/utils/b2xx_side_channel.py b/host/utils/b2xx_side_channel.py
new file mode 100755
index 000000000..070f5684c
--- /dev/null
+++ b/host/utils/b2xx_side_channel.py
@@ -0,0 +1,818 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2013-2015 Ettus Research LLC
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# 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/>.
+#
+"""
+Tool to read log buffers from the FX3. Use to debug USB connection issues.
+Requires PyUSB 1.0.
+"""
+
+import sys
+import time
+import struct
+from optparse import OptionParser
+import serial
+
+try:
+ import usb.core
+ import usb.util
+except Exception as e:
+ print("Failed to import module 'usb'.")
+ print("Please make sure you have PyUSB installed and in your PYTHONPATH.")
+ print("PyUSB PyPI website: https://pypi.python.org/pypi/pyusb")
+ print("To install, download from the website or use 'pip install pyusb'")
+ exit(1)
+
+VRT_OUT = usb.util.CTRL_TYPE_VENDOR | usb.util.CTRL_OUT
+VRT_IN = usb.util.CTRL_TYPE_VENDOR | usb.util.CTRL_IN
+
+VRQS = {}
+B200_VREQ_GET_LOG = 0x23
+VRQS[B200_VREQ_GET_LOG] = 'B200_VREQ_GET_LOG'
+B200_VREQ_GET_COUNTERS = 0x24
+VRQS[B200_VREQ_GET_COUNTERS] = 'B200_VREQ_GET_COUNTERS'
+B200_VREQ_CLEAR_COUNTERS = 0x25
+VRQS[B200_VREQ_CLEAR_COUNTERS] = 'B200_VREQ_CLEAR_COUNTERS'
+B200_VREQ_GET_USB_EVENT_LOG = 0x26
+VRQS[B200_VREQ_GET_USB_EVENT_LOG] = 'B200_VREQ_GET_USB_EVENT_LOG'
+B200_VREQ_SET_CONFIG = 0x27
+VRQS[B200_VREQ_SET_CONFIG] = 'B200_VREQ_SET_CONFIG'
+B200_VREQ_GET_CONFIG = 0x28
+VRQS[B200_VREQ_GET_CONFIG] = 'B200_VREQ_GET_CONFIG'
+B200_VREQ_GET_USB_SPEED = 0x80
+VRQS[B200_VREQ_GET_USB_SPEED] ='B200_VREQ_GET_USB_SPEED'
+B200_VREQ_WRITE_SB = 0x29
+VRQS[B200_VREQ_WRITE_SB] = 'B200_VREQ_WRITE_SB'
+B200_VREQ_SET_SB_BAUD_DIV = 0x30
+VRQS[B200_VREQ_SET_SB_BAUD_DIV] = 'B200_VREQ_SET_SB_BAUD_DIV'
+B200_VREQ_FLUSH_DATA_EPS = 0x31
+VRQS[B200_VREQ_FLUSH_DATA_EPS] = 'B200_VREQ_FLUSH_DATA_EPS'
+B200_VREQ_AD9361_LOOPBACK = 0x92
+VRQS[B200_VREQ_AD9361_LOOPBACK] = 'B200_VREQ_AD9361_LOOPBACK'
+
+COUNTER_MAGIC = 0x10024001
+"""
+typedef struct Counters {
+ int magic;
+
+ DMA_COUNTERS dma_to_host;
+ DMA_COUNTERS dma_from_host;
+
+ int log_overrun_count;
+
+ int usb_error_update_count;
+ USB_ERROR_COUNTERS usb_error_counters;
+
+ int usb_ep_underrun_count;
+
+ int heap_size;
+} COUNTERS, *PCOUNTERS;
+
+typedef struct USBErrorCounters {
+ int phy_error_count;
+ int link_error_count;
+
+ int PHY_LOCK_EV;
+ int TRAINING_ERROR_EV;
+ int RX_ERROR_CRC32_EV;
+ int RX_ERROR_CRC16_EV;
+ int RX_ERROR_CRC5_EV;
+ int PHY_ERROR_DISPARITY_EV;
+ int PHY_ERROR_EB_UND_EV;
+ int PHY_ERROR_EB_OVR_EV;
+ int PHY_ERROR_DECODE_EV;
+} USB_ERROR_COUNTERS, *PUSB_ERROR_COUNTERS;
+
+typedef struct DMACounters {
+ int XFER_CPLT;
+ int SEND_CPLT;
+ int RECV_CPLT;
+ int PROD_EVENT;
+ int CONS_EVENT;
+ int ABORTED;
+ int ERROR;
+ int PROD_SUSP;
+ int CONS_SUSP;
+
+ int BUFFER_MARKER;
+ int BUFFER_EOP;
+ int BUFFER_ERROR;
+ int BUFFER_OCCUPIED;
+
+ int last_count;
+ int last_size;
+
+ int last_sid;
+ int bad_sid_count;
+
+ int resume_count;
+} DMA_COUNTERS, *PDMA_COUNTERS;
+"""
+DMA_COUNTERS = [
+ 'XFER_CPLT',
+ 'SEND_CPLT',
+ 'RECV_CPLT',
+ 'PROD_EVENT',
+ 'CONS_EVENT',
+ 'ABORTED',
+ 'ERROR',
+ 'PROD_SUSP',
+ 'CONS_SUSP',
+
+ 'BUFFER_MARKER',
+ 'BUFFER_EOP',
+ 'BUFFER_ERROR',
+ 'BUFFER_OCCUPIED',
+
+ 'last_count',
+ 'last_size',
+
+ 'last_sid',
+ 'bad_sid_count'
+]
+
+USB_ERROR_COUNTERS = [
+ 'phy_error_count',
+ 'link_error_count'
+]
+
+USB_PHY_ERROR_REGISTERS = [
+ 'PHY_LOCK_EV',
+ 'TRAINING_ERROR_EV',
+ 'RX_ERROR_CRC32_EV',
+ 'RX_ERROR_CRC16_EV',
+ 'RX_ERROR_CRC5_EV',
+ 'PHY_ERROR_DISPARITY_EV',
+ 'PHY_ERROR_EB_UND_EV',
+ 'PHY_ERROR_EB_OVR_EV',
+ 'PHY_ERROR_DECODE_EV'
+]
+
+USB_ERROR_COUNTERS += USB_PHY_ERROR_REGISTERS
+
+PIB_COUNTERS = [
+ 'socket_inactive'
+]
+
+COUNTERS = [
+ 'magic',
+
+ ('dma_to_host', DMA_COUNTERS),
+ ('dma_from_host', DMA_COUNTERS),
+
+ 'log_overrun_count',
+
+ 'usb_error_update_count',
+ ('usb_error_counters', USB_ERROR_COUNTERS),
+
+ 'usb_ep_underrun_count',
+
+ 'heap_size',
+
+ 'resume_count',
+ 'state_transition_count',
+ 'invalid_gpif_state',
+ ('thread_0', PIB_COUNTERS),
+ ('thread_1', PIB_COUNTERS),
+ ('thread_2', PIB_COUNTERS),
+ ('thread_3', PIB_COUNTERS),
+]
+
+USB_EVENTS = {}
+USB_EVENTS[0x01] = ('CYU3P_USB_LOG_VBUS_OFF' , 'Indicates VBus turned off.')
+USB_EVENTS[0x02] = ('CYU3P_USB_LOG_VBUS_ON' , 'Indicates VBus turned on.')
+USB_EVENTS[0x03] = ('CYU3P_USB_LOG_USB2_PHY_OFF' , 'Indicates that the 2.0 PHY has been turned off.')
+USB_EVENTS[0x04] = ('CYU3P_USB_LOG_USB3_PHY_OFF' , 'Indicates that the 3.0 PHY has been turned off.')
+USB_EVENTS[0x05] = ('CYU3P_USB_LOG_USB2_PHY_ON' , 'Indicates that the 2.0 PHY has been turned on.')
+USB_EVENTS[0x06] = ('CYU3P_USB_LOG_USB3_PHY_ON' , 'Indicates that the 3.0 PHY has been turned on.')
+USB_EVENTS[0x10] = ('CYU3P_USB_LOG_USBSS_DISCONNECT' , 'Indicates that the USB 3.0 link has been disabled.')
+USB_EVENTS[0x11] = ('CYU3P_USB_LOG_USBSS_RESET' , 'Indicates that a USB 3.0 reset (warm/hot) has happened.')
+USB_EVENTS[0x12] = ('CYU3P_USB_LOG_USBSS_CONNECT' , 'Indicates that USB 3.0 Rx Termination has been detected.')
+USB_EVENTS[0x14] = ('CYU3P_USB_LOG_USBSS_CTRL' , 'Indicates that a USB 3.0 control request has been received.')
+USB_EVENTS[0x15] = ('CYU3P_USB_LOG_USBSS_STATUS' , 'Indicates completion of status stage for a 3.0 control request.')
+USB_EVENTS[0x16] = ('CYU3P_USB_LOG_USBSS_ACKSETUP' , 'Indicates that the CyU3PUsbAckSetup API has been called.')
+USB_EVENTS[0x21] = ('CYU3P_USB_LOG_LGO_U1' , 'Indicates that a LGO_U1 command has been received.')
+USB_EVENTS[0x22] = ('CYU3P_USB_LOG_LGO_U2' , 'Indicates that a LGO_U2 command has been received.')
+USB_EVENTS[0x23] = ('CYU3P_USB_LOG_LGO_U3' , 'Indicates that a LGO_U3 command has been received.')
+USB_EVENTS[0x40] = ('CYU3P_USB_LOG_USB2_SUSP' , 'Indicates that a USB 2.0 suspend condition has been detected.')
+USB_EVENTS[0x41] = ('CYU3P_USB_LOG_USB2_RESET' , 'Indicates that a USB 2.0 bus reset has been detected.')
+USB_EVENTS[0x42] = ('CYU3P_USB_LOG_USB2_HSGRANT' , 'Indicates that the USB High-Speed handshake has been completed.')
+USB_EVENTS[0x44] = ('CYU3P_USB_LOG_USB2_CTRL' , 'Indicates that a FS/HS control request has been received.')
+USB_EVENTS[0x45] = ('CYU3P_USB_LOG_USB2_STATUS' , 'Indicates completion of status stage for a FS/HS control transfer.')
+USB_EVENTS[0x50] = ('CYU3P_USB_LOG_USB_FALLBACK' , 'Indicates that the USB connection is dropping from 3.0 to 2.0')
+USB_EVENTS[0x51] = ('CYU3P_USB_LOG_USBSS_ENABLE' , 'Indicates that a USB 3.0 connection is being attempted again.')
+USB_EVENTS[0x52] = ('CYU3P_USB_LOG_USBSS_LNKERR' , 'The number of link errors has crossed the threshold.')
+USB_EVENTS[0x80] = ('CYU3P_USB_LOG_LTSSM_CHG' , 'Base of values that indicate a USB 3.0 LTSSM state change.')
+
+LTSSM_STATES = {}
+LTSSM_STATES[0x00] = ['00000', "SS.Disabled"]
+LTSSM_STATES[0x01] = ['00001', "Rx.Detect.Reset"]
+LTSSM_STATES[0x02] = ['00010', "Rx.Detect.Active"]
+LTSSM_STATES[0x03] = ['00011', "Rx.Detect.Quiet"]
+LTSSM_STATES[0x04] = ['00100', "SS.Inactive.Quiet"]
+LTSSM_STATES[0x05] = ['00101', "SS.Inactive.Disconnect.Detect"]
+LTSSM_STATES[0x06] = ['00110', "Hot Reset.Active"]
+LTSSM_STATES[0x07] = ['00111', "Hot Reset.Exit"]
+LTSSM_STATES[0x08] = ['01000', "Polling.LFPS"]
+LTSSM_STATES[0x09] = ['01001', "Polling.RxEQ"]
+LTSSM_STATES[0x0a] = ['01010', "Polling.Active"]
+LTSSM_STATES[0x0b] = ['01011', "Polling.Configuration"]
+LTSSM_STATES[0x0c] = ['01100', "Polling.Idle"]
+LTSSM_STATES[0x0d] = ['01101', "(none)"]
+#LTSSM_STATES[0x0X] = ['0111X', "(none)"]
+LTSSM_STATES[0x0e] = ['0111X', "(none)"]
+LTSSM_STATES[0x0f] = ['0111X', "(none)"]
+LTSSM_STATES[0x10] = ['10000', "U0"]
+LTSSM_STATES[0x11] = ['10001', "U1"]
+LTSSM_STATES[0x12] = ['10010', "U2"]
+LTSSM_STATES[0x13] = ['10011', "U3"]
+LTSSM_STATES[0x14] = ['10100', "Loopback.Active"]
+LTSSM_STATES[0x15] = ['10101', "Loopback.Exit"]
+LTSSM_STATES[0x16] = ['10110', "(none)"]
+LTSSM_STATES[0x17] = ['10111', "Compliance"]
+LTSSM_STATES[0x18] = ['11000', "Recovery.Active"]
+LTSSM_STATES[0x19] = ['11001', "Recovery.Configuration"]
+LTSSM_STATES[0x1a] = ['11010', "Recovery.Idle"]
+LTSSM_STATES[0x1b] = ['11011', "(none)"]
+#LTSSM_STATES[0x1X] = ['111XX', "(none)"]
+LTSSM_STATES[0x1c] = ['111XX', "(none)"]
+LTSSM_STATES[0x1d] = ['111XX', "(none)"]
+LTSSM_STATES[0x1c] = ['111XX', "(none)"]
+LTSSM_STATES[0x1f] = ['111XX', "(none)"]
+LTSSM_STATES[0x2c] = ['101100', "Cypress/Intel workaround"]
+
+CF_NONE = 0
+CF_TX_SWING = 1 << 0
+CF_TX_DEEMPHASIS = 1 << 1
+CF_DISABLE_USB2 = 1 << 2
+CF_ENABLE_AS_SUPERSPEED = 1 << 3
+CF_PPORT_DRIVE_STRENGTH = 1 << 4
+CF_DMA_BUFFER_SIZE = 1 << 5
+CF_DMA_BUFFER_COUNT = 1 << 6
+CF_MANUAL_DMA = 1 << 7
+CF_SB_BAUD_DIV = 1 << 8
+
+CF_RE_ENUM = 1 << 31
+
+"""
+typedef struct Config {
+ int tx_swing; // [90] [65] 45
+ int tx_deemphasis; // 0x11
+ int disable_usb2; // 0
+ int enable_as_superspeed; // 1
+ int pport_drive_strength; // CY_U3P_DS_THREE_QUARTER_STRENGTH
+ int dma_buffer_size; // [USB3] (max)
+ int dma_buffer_count; // [USB3] 1
+ int manual_dma; // 0
+ int sb_baud_div; // 434*2
+} CONFIG, *PCONFIG;
+
+typedef struct ConfigMod {
+ int flags;
+ CONFIG config;
+} CONFIG_MOD, *PCONFIG_MOD;
+"""
+
+class Config():
+ def __init__(self,
+ tx_swing=None, tx_deemphasis=None, disable_usb2=None, enable_as_superspeed=None,
+ pport_drive_strength=None,
+ dma_buffer_size=None, dma_buffer_count=None, manual_dma=None,
+ sb_baud_div=None,
+ raw=None):
+ self.tx_swing = tx_swing
+ self.tx_deemphasis = tx_deemphasis
+ self.disable_usb2 = disable_usb2
+ self.enable_as_superspeed = enable_as_superspeed
+ self.pport_drive_strength = pport_drive_strength
+ self.dma_buffer_size = dma_buffer_size
+ self.dma_buffer_count = dma_buffer_count
+ self.manual_dma = manual_dma
+ self.sb_baud_div = sb_baud_div
+ self._count = 9
+
+ if raw:
+ (self.tx_swing,
+ self.tx_deemphasis,
+ self.disable_usb2,
+ self.enable_as_superspeed,
+ self.pport_drive_strength,
+ self.dma_buffer_size,
+ self.dma_buffer_count,
+ self.manual_dma,
+ self.sb_baud_div) = struct.unpack("i"*self._count, raw)
+ def pack(self):
+ return struct.pack("i"*self._count,
+ self.tx_swing,
+ self.tx_deemphasis,
+ self.disable_usb2,
+ self.enable_as_superspeed,
+ self.pport_drive_strength,
+ self.dma_buffer_size,
+ self.dma_buffer_count,
+ self.manual_dma,
+ self.sb_baud_div)
+ def __str__(self):
+ return self.to_string()
+ def to_string(self, flags=-1):
+ s = ""
+ if flags & CF_TX_SWING:
+ s += "tx_swing = %s\n" % (self.tx_swing)
+ if flags & CF_TX_DEEMPHASIS:
+ s += "tx_deemphasis = %s\n" % (self.tx_deemphasis)
+ if flags & CF_DISABLE_USB2:
+ s += "disable_usb2 = %s\n" % (self.disable_usb2)
+ if flags & CF_ENABLE_AS_SUPERSPEED:
+ s += "enable_as_superspeed = %s\n" % (self.enable_as_superspeed)
+ if flags & CF_PPORT_DRIVE_STRENGTH:
+ s += "pport_drive_strength = %s\n" % (self.pport_drive_strength)
+ if flags & CF_DMA_BUFFER_SIZE:
+ s += "dma_buffer_size = %s\n" % (self.dma_buffer_size)
+ if flags & CF_DMA_BUFFER_COUNT:
+ s += "dma_buffer_count = %s\n" % (self.dma_buffer_count)
+ if flags & CF_MANUAL_DMA:
+ s += "manual_dma = %s\n" % (self.manual_dma)
+ if flags & CF_SB_BAUD_DIV:
+ s += "sb_baud_div = %s\n" % (self.sb_baud_div)
+ return s
+
+def _parse_usb_event_log(data):
+ l = []
+ for d in data:
+ if d == 0x14 or d == 0x15 or d == 0x16: # CTRL, STATUS, ACKSETUP
+ continue
+ elif (d & 0x80):
+ #l += [(USB_EVENTS[0x80][0] + "+%i" % (d & ~0x80), USB_EVENTS[0x80][1])]
+ ltssm_key = (d & ~0x80)
+ ltssm_val = "(unknown)"
+ if ltssm_key in LTSSM_STATES:
+ ltssm_val = LTSSM_STATES[ltssm_key][1]
+ ltssm_val = "LTSSM: " + ltssm_val
+ l += [(USB_EVENTS[0x80][0] + "+%i" % (d & ~0x80), ltssm_val)]
+ elif d in USB_EVENTS:
+ l += [USB_EVENTS[d]]
+ #else:
+ # l += [("?", "?")]
+ return l
+
+class counter_set():
+ def __init__(self, counters, name='(top)'):
+ self._counters = counters
+ self._counter_names = []
+ self._name = name
+ for c in counters:
+ o = 0
+ default_value = False
+ if isinstance(c, str):
+ name = c
+ default_value = True
+ elif isinstance(c, tuple):
+ name = c[0]
+ o = counter_set(c[1])
+ elif isinstance(c, dict):
+ raise Exception('Not implemented yet')
+ else:
+ raise Exception('Unknown counter format')
+ setattr(self, name, o)
+ self._counter_names += [(name, default_value)]
+ self._fmt_str = self._get_struct_format()
+
+ def _get_struct_format(self):
+ fmt_str = ""
+ for name, default_value in self._counter_names:
+ if default_value:
+ fmt_str += "i"
+ else:
+ o = getattr(self, name)
+ fmt_str += o._get_struct_format()
+ return fmt_str
+
+ def _update(self, data, parents=[]):
+ if len(data) == 0:
+ raise Exception('Ran out of data entering %s' % (self._name))
+ #return []
+ for name, default_value in self._counter_names:
+ if default_value:
+ if len(data) == 0:
+ raise Exception('Ran out of data setting %s in %s' % (name, self._name))
+ setattr(self, name, data[0])
+ data = data[1:]
+ else:
+ o = getattr(self, name)
+ data = o._update(data, parents+[self])
+ return data
+
+ def update(self, data):
+ try:
+ vals = struct.unpack(self._fmt_str, data)
+ self._update(vals)
+ except Exception as e:
+ print(("While updating counter set '%s':" % self._name), e)
+
+ def __str__(self):
+ return self.to_string()
+
+ def to_string(self, parents=[]):
+ s = ""
+ cnt = 0
+ for name, default_value in self._counter_names:
+ o = getattr(self, name)
+ if default_value:
+ if cnt > 0:
+ s += "\t"
+ s += "%s: %05i" % (name, o)
+ cnt += 1
+ else:
+ if cnt > 0:
+ s += "\n"
+ s += "\t"*(len(parents) + 1)
+ s += o.to_string(parents+[self])
+ cnt = 0
+ s += "\n"
+ return s
+
+class usb_device():
+ def __init__(self):
+ #self.max_buffer_size = 64 # Default to USB2
+ self.max_buffer_size = 1024*4 # Apparently it'll frag bigger packets
+ self.counters = counter_set(COUNTERS)
+ self.timeout = 2000
+
+ def open(self, idVendor, idProduct):
+ print("Finding %04x:%04x..." % (idVendor, idProduct))
+ self.dev = usb.core.find(idVendor=idVendor, idProduct=idProduct)
+ if self.dev is None:
+ raise ValueError('Device not found: %04x:%04x' % (idVendor, idProduct))
+
+ self.log_index = 0
+ self.log_read_count = 0
+ self.usb_event_log_read_count = 0
+ self.counters_read_count = 0
+
+ #if self.dev.is_kernel_driver_active(0):
+ # print "Detaching kernel driver..."
+ # self.dev.detach_kernel_driver(0)
+
+ #self.dev.set_configuration() # This will throw as device is already claimed
+
+ print("Opened %04x:%04x" % (idVendor, idProduct))
+
+ #self.dev.ctrl_transfer(0x21, 0x09, 0, 0, [0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00] )
+ #self.dev.ctrl_transfer(bmRequestType, bRequest, wValue=0, wIndex=0, data_or_wLength = None, timeout = None
+
+ #res = self.dev.ctrl_transfer(VRT_IN, 0x83, 0, 0, 1024)
+ # Can give 1024 byte size for IN, result will be actual payload size
+ # Invalid VREQ results in usb.core.USBError 32 Pipe error
+ #print res
+
+ #res = self.dev.ctrl_transfer(VRT_IN, B200_VREQ_GET_USB_SPEED, 0, 0, 1)
+ #self.usb_speed = res[0]
+ while True:
+ #l = self.vrt_get(B200_VREQ_GET_USB_SPEED)
+ l = []
+ try:
+ l = self.dev.ctrl_transfer(VRT_IN, B200_VREQ_GET_USB_SPEED, 0, 0, 1)
+ except usb.core.USBError as e:
+ if e.errno == 32:
+ print(e)
+ print("Is the firmware loaded?")
+ sys.exit(0)
+ if len(l) > 0:
+ self.usb_speed = l[0]
+ print("Operating at USB", self.usb_speed)
+ break
+ else:
+ print("Retrying...")
+ #if self.usb_speed == 3:
+ # self.max_buffer_size = 512
+ print("Max buffer size:", self.max_buffer_size)
+ print()
+
+ def _handle_error(self, e, vrt):
+ if e.errno == 19: # No such device
+ raise e
+ vrt_str = "0x%02x" % (vrt)
+ if vrt in VRQS:
+ vrt_str += " (%s)" % (VRQS[vrt])
+ print("%s: %s" % (vrt_str, str(e)))
+
+ def vrt_get(self, vrt):
+ try:
+ return self.dev.ctrl_transfer(VRT_IN, vrt, 0, 0, self.max_buffer_size, self.timeout)
+ except usb.core.USBError as e:
+ self._handle_error(e, vrt)
+ return []
+
+ def vrt_set(self, vrt, data=""):
+ try:
+ return self.dev.ctrl_transfer(VRT_OUT, vrt, 0, 0, data, self.timeout)
+ except usb.core.USBError as e:
+ self._handle_error(e, vrt)
+ return None
+
+ def get_log(self, with_log_index=True):
+ lines = []
+ raw = self.vrt_get(B200_VREQ_GET_LOG)
+ if len(raw) == 0:
+ return lines
+ if raw[0] == 0:
+ return lines
+ self.log_read_count += 1
+ raw = list(raw)
+ last = 0
+ while raw[last] != 0:
+ try:
+ try:
+ idx = raw.index(0, last)
+ except ValueError as e:
+ print("No null termination in log buffer (length: %d, last null: %d)" % (len(raw), last))
+ break
+ self.log_index += 1
+ line = "".join(map(chr, raw[last:idx]))
+ #print "[%05i %05i] %s" % (self.log_index, self.log_read_count, line)
+ if with_log_index:
+ lines += [(self.log_index, line)]
+ else:
+ lines += [line]
+ last = idx + 1
+ if last >= len(raw):
+ break
+ except Exception as e:
+ print("Exception while parsing log buffer:", e)
+ break
+ return lines
+
+ def print_log(self):
+ lines = self.get_log()
+ if len(lines) == 0:
+ return
+ for l in lines:
+ #print l
+ print("[%05i %05i] %s" % (l[0], self.log_read_count, l[1]))
+ print()
+
+ def get_counters(self):
+ data = self.vrt_get(B200_VREQ_GET_COUNTERS)
+ if len(data) == 0:
+ return
+ self.counters_read_count += 1
+ self.counters.update(data)
+
+ def print_counters(self):
+ self.get_counters()
+ print("[%05i]" % (self.counters_read_count))
+ print(self.counters)
+
+ def get_usb_event_log(self):
+ data = self.vrt_get(B200_VREQ_GET_USB_EVENT_LOG)
+ if len(data) == 0:
+ return []
+ if len(data) == self.max_buffer_size: # ZLP when no new events have been recorded
+ return []
+ if len(data) > 64:
+ raise Exception("USB event log data len = %i" % (len(data)))
+ self.usb_event_log_read_count += 1
+ return _parse_usb_event_log(data)
+
+ def print_usb_event_log(self):
+ l = self.get_usb_event_log()
+ if len(l) == 0:
+ return
+ print("\n".join([("[%05i] " % (self.usb_event_log_read_count)) + x[0] + ":\t" + x[1] for x in l]))
+ print()
+
+def run_log(dev, options):
+ items = [
+ (options.log, dev.print_log),
+ (options.counters, dev.print_counters),
+ (options.usb_events, dev.print_usb_event_log)
+ ]
+ items = [x for x in items if x[0] > 0]
+ smallest_interval = min([x[0] for x in items])
+ time_now = time.time()
+ last = [time_now]*len(items)
+
+ try:
+ for i in items:
+ if i[0] < 0:
+ i[1]()
+ while True:
+ time_now = time.time()
+ cleared = False
+ for i in range(len(items)):
+ time_last = last[i]
+ if time_now < (time_last + items[i][0]):
+ continue
+ if options.clear_screen and not cleared:
+ print(chr(27) + "[2J")
+ cleared = True
+ #print items[i][1]
+ items[i][1]()
+ last[i] = time.time()
+ time.sleep(smallest_interval)
+ except KeyboardInterrupt:
+ return
+
+def hex_to_int(s):
+ radix = 10
+ s = s.lower()
+ if (len(s) > 1 and s[0] == 'x') or (len(s) > 2 and s[0:2] == "0x"):
+ radix = 16
+ return int(s, radix)
+
+def recv_serial_data(ser):
+ data = ""
+ usb_event_log_read_count = 0
+ time_start = time.time()
+ while True:
+ c = ser.read()
+ data += c
+ #if c == '\n':
+ if len(data) >= 2 and data[-2:] == "\r\n":
+ time_now_str = "[%06d]" % (int(time.time() - time_start))
+ data = data[0:-2]
+ if data == "":
+ #print "[Received an empty line]"
+ print()
+ elif data[0] == ' ':
+ print(time_now_str, data[1:])
+ elif data[0] == 'U':
+ data = data[1:]
+ cur_type = 0
+ i = 0
+ usb_events = []
+ while len(data) > 0:
+ c = data[0]
+
+ if cur_type == 0:
+ if c == 'a':
+ cur_type = 1
+ elif (c >= 'A') and (c <= 'P'):
+ i = ord(c) - ord('A')
+ cur_type = 2
+ else:
+ print(time_now_str, "[Unknown type: '%s' (0x%02x) in '%s']" % (c, ord(c), data))
+
+ elif cur_type == 1:
+ i = ord(c) - ord('a')
+ if (i < 0) or (i >= len(USB_PHY_ERROR_REGISTERS)):
+ print(time_now_str, "[Unknown PHY error register index: '%s' (0x%02x) (%d) in '%s']" % (c, ord(c), i, data))
+ else:
+ print(time_now_str, USB_PHY_ERROR_REGISTERS[i])
+ cur_type = 0
+
+ elif cur_type == 2:
+ i2 = ord(c) - ord('A')
+ if (c < 'A') or (c > 'P'):
+ print(time_now_str, "[Unknown second USB event part: '%s' (0x%02x) (%d) in '%s']" % (c, ord(c), i2, data))
+ else:
+ i = (i << 4) | i2
+ usb_events += [i]
+
+ cur_type = 0
+
+ data = data[1:]
+
+ if len(usb_events) > 0:
+ usb_event_log_read_count += 1
+ l = _parse_usb_event_log(usb_events)
+ print("\n".join([time_now_str + ("[%05i] " % (usb_event_log_read_count)) + x[0] + ":\t" + x[1] for x in l]))
+ #print
+
+ data = ""
+
+def main():
+ parser = OptionParser(usage="%prog: [options]") #option_class=eng_option,
+
+ parser.add_option("-v", "--vid", type="string", default="0x2500", help="VID [default=%default]")
+ parser.add_option("-p", "--pid", type="string", default="0x0020", help="PID [default=%default]")
+ parser.add_option("-t", "--tty", type="string", default=None, help="TTY [default=%default]")
+ parser.add_option("-c", "--cmd", type="string", default="", help="Command (empty opens prompt)")
+ parser.add_option("-n", "--counters", type="float", default="5.0", help="Counter print interval [default=%default]")
+ parser.add_option("-l", "--log", type="float", default="0.25", help="Log print interval [default=%default]")
+ parser.add_option("-e", "--usb-events", type="float", default="0.25", help="USB event log print interval [default=%default]")
+ parser.add_option("-s", "--sb", type="string", default=None, help="Settings Bus write message [default=%default]")
+ parser.add_option("-d", "--sb-baud-div", type="int", default=None, help="Settings Bus baud rate divisor [default=%default]")
+ parser.add_option("-b", "--sb-baud", type="int", default=None, help="Settings Bus baud rate [default=%default]")
+ parser.add_option("-r", "--clear-screen", action="store_true", default=False, help="Clear screen [default=%default]")
+ parser.add_option("-R", "--reset-counters", action="store_true", default=False, help="Reset counters [default=%default]")
+ parser.add_option("-f", "--flush-data-eps", action="store_true", default=False, help="Flush data endpoints [default=%default]")
+ parser.add_option("-L", "--fe-loopback", type="int", default=None, help="Change AD9361 digital loopback [default=%default]")
+
+ (options, args) = parser.parse_args()
+
+ if options.tty is not None and options.tty != "":
+ while True:
+ try:
+ ser = serial.Serial(port=options.tty, baudrate=115200, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout=None) # timeout: None (blocking), 0 (non-blocking)
+ print("Opened", options.tty)
+
+ try:
+ recv_serial_data(ser)
+ except KeyboardInterrupt:
+ break
+ except Exception as e:
+ print("Unable to open serial port:", e)
+ break
+ else:
+ dev = usb_device()
+
+ while True:
+ try:
+ dev.open(idVendor=hex_to_int(options.vid), idProduct=hex_to_int(options.pid))
+
+ raw_config = dev.vrt_get(B200_VREQ_GET_CONFIG)
+ current_config = Config(raw=raw_config)
+ print("Current config:")
+ print(current_config)
+
+ if options.flush_data_eps:
+ dev.vrt_set(B200_VREQ_FLUSH_DATA_EPS)
+ if options.sb_baud_div is not None:
+ dev.vrt_set(B200_VREQ_SET_SB_BAUD_DIV, struct.pack('H', options.sb_baud_div))
+ if options.sb is not None and len(options.sb) > 0:
+ dev.vrt_set(B200_VREQ_WRITE_SB, " " + options.sb)
+ if options.reset_counters:
+ dev.vrt_set(B200_VREQ_CLEAR_COUNTERS)
+ if options.fe_loopback is not None:
+ dev.vrt_set(B200_VREQ_AD9361_LOOPBACK, struct.pack('B', int(options.fe_loopback)))
+ options.cmd = options.cmd.strip()
+ if len(options.cmd) == 0:
+ run_log(dev, options)
+ else:
+ cmds = options.cmd.split(',')
+ flags = 0
+ for cmd in cmds:
+ cmd = cmd.strip()
+ if len(cmd) == 0:
+ continue
+ parts = cmd.split(' ')
+ action = parts[0].lower()
+ try:
+ if action == "txswing":
+ current_config.tx_swing = int(parts[1])
+ flags |= CF_TX_SWING
+ elif action == "txdeemph":
+ current_config.tx_deemphasis = int(parts[1])
+ flags |= CF_TX_DEEMPHASIS
+ elif action == "ss":
+ current_config.enable_as_superspeed = int(parts[1])
+ flags |= CF_ENABLE_AS_SUPERSPEED
+ elif action == "disableusb2":
+ current_config.disable_usb2 = int(parts[1])
+ flags |= CF_DISABLE_USB2
+ elif action == "pportdrive":
+ current_config.pport_drive_strength = int(parts[1])
+ flags |= CF_PPORT_DRIVE_STRENGTH
+ elif action == "dmasize":
+ current_config.dma_buffer_size = int(parts[1])
+ flags |= CF_DMA_BUFFER_SIZE
+ elif action == "dmacount":
+ current_config.dma_buffer_count = int(parts[1])
+ flags |= CF_DMA_BUFFER_COUNT
+ elif action == "manualdma":
+ current_config.manual_dma = int(parts[1])
+ flags |= CF_MANUAL_DMA
+ elif action == "sbbauddiv":
+ current_config.sb_baud_div = int(parts[1])
+ flags |= CF_SB_BAUD_DIV
+ elif action == "reenum":
+ flags |= CF_RE_ENUM
+ else:
+ print("'%s' not implemented" % (action))
+ except Exception as e:
+ print("Exception while handling action '%s'" % (action), e)
+ if flags != 0:
+ print("New config to be set:")
+ print(current_config.to_string(flags))
+ #print current_config
+ #print "Update flags: 0x%x" % (flags)
+ new_config = struct.pack("I", flags) + current_config.pack()
+ dev.vrt_set(B200_VREQ_SET_CONFIG, new_config)
+ else:
+ print("Not updating config")
+ break
+ except usb.core.USBError as e:
+ if e.errno == 19: # No such device
+ pass
+ print(e)
+ break
+
+ return 0
+
+if __name__ == '__main__':
+ main()
diff --git a/host/utils/nirio_programmer.cpp b/host/utils/nirio_programmer.cpp
deleted file mode 100644
index c8c5e72d3..000000000
--- a/host/utils/nirio_programmer.cpp
+++ /dev/null
@@ -1,275 +0,0 @@
-
-#include <uhd/transport/nirio/niusrprio_session.h>
-#include <uhd/transport/nirio/niriok_proxy.h>
-#include <uhd/transport/nirio/nifpga_lvbitx.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <fcntl.h>
-#include <iostream>
-#include <fstream>
-#include <streambuf>
-#include <boost/program_options.hpp>
-#include <boost/format.hpp>
-#include <boost/thread/thread.hpp>
-#include <boost/algorithm/string.hpp>
-#include <boost/regex.hpp>
-
-using namespace uhd::niusrprio;
-using namespace uhd::usrprio_rpc;
-
-class dummy_lvbitx : public nifpga_lvbitx {
-public:
- dummy_lvbitx(const std::string& fpga_lvbitx_path) : _fpga_lvbitx_path(fpga_lvbitx_path) {
- std::ifstream lvbitx_stream(_fpga_lvbitx_path.c_str());
- if (lvbitx_stream.is_open()) {
- std::string lvbitx_contents;
- lvbitx_stream.seekg(0, std::ios::end);
- lvbitx_contents.reserve(static_cast<size_t>(lvbitx_stream.tellg()));
- lvbitx_stream.seekg(0, std::ios::beg);
- lvbitx_contents.assign((std::istreambuf_iterator<char>(lvbitx_stream)), std::istreambuf_iterator<char>());
- try {
- boost::smatch md5_match;
- if (boost::regex_search(lvbitx_contents, md5_match, boost::regex("<BitstreamMD5>([a-zA-Z0-9]{32})<\\/BitstreamMD5>", boost::regex::icase))) {
- _bitstream_checksum = std::string(md5_match[1].first, md5_match[1].second);
- }
- boost::to_upper(_bitstream_checksum);
- } catch (boost::exception&) {
- _bitstream_checksum = "";
- }
- try {
- boost::smatch sig_match;
- if (boost::regex_search(lvbitx_contents, sig_match, boost::regex("<SignatureRegister>([a-zA-Z0-9]{32})<\\/SignatureRegister>", boost::regex::icase))) {
- _signature = std::string(sig_match[1].first, sig_match[1].second);
- }
- boost::to_upper(_signature);
- } catch (boost::exception&) {
- _signature = "";
- }
- }
- }
- ~dummy_lvbitx() {}
-
- virtual const char* get_bitfile_path() { return _fpga_lvbitx_path.c_str(); }
- virtual const char* get_signature() { return _signature.c_str(); }
- virtual const char* get_bitstream_checksum() { return _bitstream_checksum.c_str(); }
-
- virtual size_t get_input_fifo_count() { return 0; }
- virtual const char** get_input_fifo_names() { return NULL; }
-
- virtual size_t get_output_fifo_count() { return 0; }
- virtual const char** get_output_fifo_names() { return NULL; }
-
- virtual size_t get_control_count() { return 0; }
- virtual const char** get_control_names() { return NULL; }
-
- virtual size_t get_indicator_count() { return 0; }
- virtual const char** get_indicator_names() { return NULL; }
-
- virtual void init_register_info(nirio_register_info_vtr& vtr) { vtr.clear(); }
- virtual void init_fifo_info(nirio_fifo_info_vtr& vtr) { vtr.clear(); }
-
-private:
- std::string _fpga_lvbitx_path;
- std::string _bitstream_checksum;
- std::string _signature;
-};
-
-int main(int argc, char *argv[])
-{
- nirio_status status = NiRio_Status_Success;
-
- //Setup the program options
- uint32_t interface_num, peek_addr, poke_addr, poke_data;
- std::string rpc_port, fpga_lvbitx_path, flash_path, peek_tokens_str, poke_tokens_str;
-
- namespace po = boost::program_options;
- po::options_description desc("Allowed options");
- desc.add_options()
- ("help", "help message")
- ("interface", po::value<uint32_t>(&interface_num)->default_value(0), "The interface number to communicate with.")
- ("port", po::value<std::string>(&rpc_port)->default_value("5444"), "Port to communicate with RPC server.")
- ("fpga", po::value<std::string>(&fpga_lvbitx_path)->default_value(""), "The absolute path to the LVBITX file to download to the FPGA.")
- ("flash", po::value<std::string>(&flash_path)->default_value(""), "The path to the image to download to the flash OR 'erase' to erase the FPGA image from flash.")
- ("peek", po::value<std::string>(&peek_tokens_str)->default_value(""), "Peek32.")
- ("poke", po::value<std::string>(&poke_tokens_str)->default_value(""), "Poke32.")
- ("stats", "Dump interface and DMA stats.")
- ;
- po::variables_map vm;
- po::store(po::parse_command_line(argc, argv, desc), vm);
- po::notify(vm);
-
- //Print the help message
- if (vm.count("help")){
- std::cout << boost::format("USRP-NIRIO-Programmer\n\n %s") % desc << std::endl;
- return ~0;
- }
-
- std::string resource_name = boost::str(boost::format("RIO%u") % interface_num);
-
- //Download LVBITX image
- if (fpga_lvbitx_path != "")
- {
- printf("Downloading image %s to FPGA as %s...", fpga_lvbitx_path.c_str(), resource_name.c_str());
- fflush(stdout);
- uhd::niusrprio::niusrprio_session fpga_session(resource_name, rpc_port);
- uhd::niusrprio::nifpga_lvbitx::sptr lvbitx(new dummy_lvbitx(fpga_lvbitx_path));
- nirio_status_chain(fpga_session.open(lvbitx, true), status);
- //Download BIN to flash or erase
- if (flash_path != "erase") {
- if (flash_path != "") {
- printf("Writing FPGA image %s to flash...", flash_path.c_str());
- fflush(stdout);
- nirio_status_chain(fpga_session.download_bitstream_to_flash(flash_path), status);
- printf("DONE\n");
- }
- } else {
- printf("Erasing FPGA image from flash...");
- fflush(stdout);
- nirio_status_chain(fpga_session.download_bitstream_to_flash(""), status);
- printf("DONE\n");
- }
- fpga_session.close();
- printf("DONE\n");
- }
-
- fflush(stdout);
- usrprio_rpc_client temp_rpc_client("localhost", rpc_port);
- std::string interface_path;
- nirio_status_chain(temp_rpc_client.niusrprio_get_interface_path(resource_name, interface_path), status);
- if (interface_path.empty()) {
- printf("ERROR: Could not open a proxy to interface %u. If it exists, try downloading an LVBITX to the FPGA first.\n", interface_num);
- exit(EXIT_FAILURE);
- }
-
- niriok_proxy::sptr dev_proxy = niriok_proxy::make_and_open(interface_path);
-
- if (poke_tokens_str != ""){
- std::stringstream ss;
- std::vector<std::string> poke_tokens;
- boost::split(poke_tokens, poke_tokens_str, boost::is_any_of(":"));
- ss.clear();
- ss << std::hex << poke_tokens[1];
- ss >> poke_addr;
- ss.clear();
- ss << std::hex << poke_tokens[2];
- ss >> poke_data;
-
- niriok_scoped_addr_space(dev_proxy, poke_tokens[0]=="c"?BUS_INTERFACE:FPGA, status);
- if (poke_tokens[0]=="z") {
- nirio_status_chain(dev_proxy->poke(poke_addr, (uint32_t)0x70000 + poke_addr), status);
- } else {
- nirio_status_chain(dev_proxy->poke(poke_addr, poke_data), status);
- }
- printf("[POKE] %s:0x%x <= 0x%x (%u)\n", poke_tokens[0]=="c"?"Chinch":(poke_tokens[0]=="z"?"ZPU":"FPGA"), poke_addr, poke_data, poke_data);
- }
-
- if (peek_tokens_str != ""){
- std::stringstream ss;
- std::vector<std::string> peek_tokens;
- boost::split(peek_tokens, peek_tokens_str, boost::is_any_of(":"));
- ss.clear();
- ss << std::hex << peek_tokens[1];
- ss >> peek_addr;
-
- niriok_scoped_addr_space(dev_proxy, peek_tokens[0]=="c"?BUS_INTERFACE:FPGA, status);
- uint32_t reg_val = 0;
- if (peek_tokens[0]=="z") {
- nirio_status_chain(dev_proxy->poke((uint32_t)0x60000 + peek_addr, (uint32_t)0), status);
- do {
- nirio_status_chain(dev_proxy->peek((uint32_t)0x60000 + peek_addr, reg_val), status);
- } while (reg_val != 0);
- nirio_status_chain(dev_proxy->peek((uint32_t)0x70000 + peek_addr, reg_val), status);
- } else {
- nirio_status_chain(dev_proxy->peek(peek_addr, reg_val), status);
- }
-
- printf("[PEEK] %s:0x%x = 0x%x (%u)\n", peek_tokens[0]=="c"?"Chinch":(peek_tokens[0]=="z"?"ZPU":"FPGA"), peek_addr, reg_val, reg_val);
- }
-
- //Display attributes
- if (vm.count("stats")){
- printf("[Interface %u]\n", interface_num);
- uint32_t attr_val = 0;
- nirio_status_chain(dev_proxy->get_attribute(RIO_IS_FPGA_PROGRAMMED, attr_val), status);
- printf("* Is FPGA Programmed? = %s\n", (attr_val==1)?"YES":"NO");
-
- std::string signature;
- for (int i = 0; i < 4; i++) {
- nirio_status_chain(dev_proxy->peek(0x3FFF4, attr_val), status);
- signature += boost::str(boost::format("%08x") % attr_val);
- }
- printf("* FPGA Signature = %s\n", signature.c_str());
-
- std::string checksum;
- for (int i = 0; i < 4; i++) {
- nirio_status_chain(dev_proxy->peek(0x40030 + (i * 4), attr_val), status);
- checksum += boost::str(boost::format("%08x") % attr_val);
- }
- printf("* FPGA Bitstream Checksum = %s\n", checksum.c_str());
-
- uint32_t reg_val = 0;
- nirio_status_chain(dev_proxy->set_attribute(RIO_ADDRESS_SPACE, BUS_INTERFACE), status);
- nirio_status_chain(dev_proxy->peek(0, reg_val), status);
- printf("* Chinch Signature = %x\n", reg_val);
- nirio_status_chain(dev_proxy->set_attribute(RIO_ADDRESS_SPACE, FPGA), status);
- nirio_status_chain(dev_proxy->peek(0, reg_val), status);
- printf("* PCIe FPGA Signature = %x\n", reg_val);
-
- printf("\n[DMA Stream Stats]\n");
-
- nirio_status_chain(dev_proxy->set_attribute(RIO_ADDRESS_SPACE, FPGA), status);
-
- printf("------------------------------------------------------------------------------------------------");
- printf("\nChannel => |");
- for (uint32_t i = 0; i < 6; i++) {
- printf("%11u |", i);
- }
- printf("\n------------------------------------------------------------------------------------------------");
- printf("\nTX Status |");
- for (uint32_t i = 0; i < 6; i++) {
- nirio_status_chain(dev_proxy->peek(0x40200 + (i * 16), reg_val), status);
- printf("%s |", reg_val==0 ? " Good" : " Error");
- }
- printf("\nRX Status |");
- for (uint32_t i = 0; i < 6; i++) {
- nirio_status_chain(dev_proxy->peek(0x40400 + (i * 16), reg_val), status);
- printf("%s |", reg_val==0 ? " Good" : " Error");
- }
- printf("\nTX Frm Size |");
- for (uint32_t i = 0; i < 6; i++) {
- nirio_status_chain(dev_proxy->peek(0x40204 + (i * 16), reg_val), status);
- printf("%11u |", reg_val);
- }
- printf("\nRX Frm Size |");
- for (uint32_t i = 0; i < 6; i++) {
- nirio_status_chain(dev_proxy->peek(0x40404 + (i * 16), reg_val), status);
- printf("%11u |", reg_val);
- }
- printf("\nTX Pkt Count |");
- for (uint32_t i = 0; i < 6; i++) {
- nirio_status_chain(dev_proxy->peek(0x4020C + (i * 16), reg_val), status);
- printf("%11u |", reg_val);
- }
- printf("\nTX Samp Count |");
- for (uint32_t i = 0; i < 6; i++) {
- nirio_status_chain(dev_proxy->peek(0x40208 + (i * 16), reg_val), status);
- printf("%11u |", reg_val);
- }
- printf("\nRX Pkt Count |");
- for (uint32_t i = 0; i < 6; i++) {
- nirio_status_chain(dev_proxy->peek(0x4040C + (i * 16), reg_val), status);
- printf("%11u |", reg_val);
- }
- printf("\nRX Samp Count |");
- for (uint32_t i = 0; i < 6; i++) {
- nirio_status_chain(dev_proxy->peek(0x40408 + (i * 16), reg_val), status);
- printf("%11u |", reg_val);
- }
- printf("\n------------------------------------------------------------------------------------------------\n");
- }
-
- exit(EXIT_SUCCESS);
-}
-
-
diff --git a/host/utils/octoclock_firmware_burner.cpp b/host/utils/octoclock_firmware_burner.cpp
index d624095e6..1ec77d0c8 100644
--- a/host/utils/octoclock_firmware_burner.cpp
+++ b/host/utils/octoclock_firmware_burner.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2014 Ettus Research LLC
+// Copyright 2014-2015 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -74,8 +74,23 @@ boost::uint8_t firmware_image[MAX_FIRMWARE_SIZE];
size_t firmware_size = 0;
boost::uint8_t octoclock_data[udp_simple::mtu];
octoclock_packet_t *pkt_in = reinterpret_cast<octoclock_packet_t *>(octoclock_data);
-std::string firmware_path;
+std::string firmware_path, actual_firmware_path;
size_t num_blocks = 0;
+bool hex = true;
+
+static uint16_t calculate_crc(boost::uint8_t* buffer, boost::uint16_t len){
+ boost::uint16_t crc = 0xFFFF;
+
+ for(size_t i = 0; i < len; i++){
+ crc ^= buffer[i];
+ for(boost::uint8_t j = 0; j < 8; ++j){
+ if(crc & 1) crc = (crc >> 1) ^ 0xA001;
+ else crc = (crc >> 1);
+ }
+ }
+
+ return crc;
+}
/*
* Functions
@@ -89,6 +104,28 @@ void list_octoclocks(){
}
}
+void print_image_loader_warning(const std::string &fw_path, const po::variables_map &vm){
+ // Newline + indent
+ #ifdef UHD_PLATFORM_WIN32
+ const std::string nl = " ^\n ";
+ #else
+ const std::string nl = " \\\n ";
+ #endif
+
+ std::string uhd_image_loader = str(boost::format("uhd_image_loader --args=\"type=octoclock,addr=%s\""
+ "%s --fw-path=%s")
+ % vm["addr"].as<std::string>() % nl % fw_path);
+
+ std::cout << "************************************************************************************************" << std::endl
+ << "WARNING: This utility will be removed in an upcoming version of UHD. In the future, use" << std::endl
+ << " this command:" << std::endl
+ << std::endl
+ << uhd_image_loader << std::endl
+ << std::endl
+ << "************************************************************************************************" << std::endl
+ << std::endl;
+}
+
/*
* Manually find bootloader. This sends multiple packets in order to increase chances of getting
* bootloader before it switches to the application.
@@ -121,26 +158,25 @@ device_addrs_t bootloader_find(const std::string &ip_addr){
}
void read_firmware(){
- std::ifstream firmware_file(firmware_path.c_str(), std::ios::binary);
- firmware_file.seekg(0, std::ios::end);
- firmware_size = size_t(firmware_file.tellg());
+ std::ifstream firmware_file(actual_firmware_path.c_str(), std::ios::binary);
+ firmware_size = size_t(fs::file_size(actual_firmware_path));
if(firmware_size > MAX_FIRMWARE_SIZE){
firmware_file.close();
throw uhd::runtime_error(str(boost::format("Firmware file too large: %d > %d")
% firmware_size % (MAX_FIRMWARE_SIZE)));
}
- firmware_file.seekg(0, std::ios::beg);
firmware_file.read((char*)firmware_image, firmware_size);
firmware_file.close();
- num_blocks = (firmware_size % BLOCK_SIZE) ? (firmware_size / BLOCK_SIZE)
- : ((firmware_size / BLOCK_SIZE) + 1);
+ num_blocks = (firmware_size % BLOCK_SIZE) ? ((firmware_size / BLOCK_SIZE) + 1)
+ : (firmware_size / BLOCK_SIZE);
}
void burn_firmware(udp_simple::sptr udp_transport){
octoclock_packet_t pkt_out;
pkt_out.sequence = uhd::htonx<boost::uint32_t>(std::rand());
- pkt_out.len = uhd::htonx<boost::uint16_t>((boost::uint16_t)firmware_size);
+ pkt_out.len = (boost::uint16_t)firmware_size;
+ pkt_out.crc = calculate_crc(firmware_image, firmware_size);
size_t len = 0, current_pos = 0;
//Tell OctoClock not to jump to application, wait for us instead
@@ -149,6 +185,7 @@ void burn_firmware(udp_simple::sptr udp_transport){
if(UHD_OCTOCLOCK_PACKET_MATCHES(FW_BURN_READY_ACK, pkt_out, pkt_in, len)) std::cout << "ready." << std::endl;
else{
std::cout << std::endl;
+ if(hex) fs::remove(actual_firmware_path);
throw uhd::runtime_error("Could not get OctoClock in valid state for firmware download.");
}
@@ -165,7 +202,7 @@ void burn_firmware(udp_simple::sptr udp_transport){
<< "% (" << (i+1) << "/" << num_blocks << " blocks)" << std::flush;
memset(pkt_out.data, 0, BLOCK_SIZE);
- memcpy((void*)(pkt_out.data), &firmware_image[i*BLOCK_SIZE], std::min(int(firmware_size-current_pos), BLOCK_SIZE));
+ memcpy((void*)(pkt_out.data), &firmware_image[i*BLOCK_SIZE], BLOCK_SIZE);
bool success = false;
while(num_tries <= 5){
@@ -181,6 +218,7 @@ void burn_firmware(udp_simple::sptr udp_transport){
}
if(not success){
std::cout << std::endl;
+ if(hex) fs::remove(actual_firmware_path);
throw uhd::runtime_error("Failed to burn firmware to OctoClock!");
}
@@ -196,7 +234,6 @@ void verify_firmware(udp_simple::sptr udp_transport){
pkt_out.sequence = uhd::htonx<boost::uint32_t>(std::rand());
size_t len = 0, current_pos = 0;
-
for(size_t i = 0; i < num_blocks; i++){
pkt_out.sequence++;
pkt_out.addr = i*BLOCK_SIZE;
@@ -208,11 +245,13 @@ void verify_firmware(udp_simple::sptr udp_transport){
if(memcmp((void*)(pkt_in->data), &firmware_image[i*BLOCK_SIZE],
std::min(int(firmware_size-current_pos), BLOCK_SIZE))){
std::cout << std::endl;
+ if(hex) fs::remove(actual_firmware_path);
throw uhd::runtime_error("Failed to verify OctoClock firmware!");
}
}
else{
std::cout << std::endl;
+ if(hex) fs::remove(actual_firmware_path);
throw uhd::runtime_error("Failed to verify OctoClock firmware!");
}
}
@@ -230,6 +269,7 @@ bool reset_octoclock(const std::string &ip_addr){
UHD_OCTOCLOCK_SEND_AND_RECV(udp_transport, RESET_CMD, pkt_out, len, octoclock_data);
if(not UHD_OCTOCLOCK_PACKET_MATCHES(RESET_ACK, pkt_out, pkt_in, len)){
std::cout << std::endl;
+ if(hex) fs::remove(actual_firmware_path);
throw uhd::runtime_error("Failed to place device in state to receive firmware.");
}
@@ -246,11 +286,13 @@ void finalize(udp_simple::sptr udp_transport){
UHD_OCTOCLOCK_SEND_AND_RECV(udp_transport, FINALIZE_BURNING_CMD, pkt_out, len, octoclock_data);
if(not UHD_OCTOCLOCK_PACKET_MATCHES(FINALIZE_BURNING_ACK, pkt_out, pkt_in, len)){
std::cout << std::endl;
+ if(hex) fs::remove(actual_firmware_path);
std::cout << "no ACK. Bootloader may not have loaded application." << std::endl;
}
}
-int UHD_SAFE_MAIN(int argc, char *argv[]){
+int UHD_SAFE_MAIN(UHD_UNUSED(int argc), UHD_UNUSED(char *argv[])){
+
std::string ip_addr;
po::options_description desc("Allowed options");
desc.add_options()
@@ -300,7 +342,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
throw uhd::runtime_error(str(boost::format("This filepath does not exist: %s") % firmware_path));
}
}
- else firmware_path = find_image_path("octoclock_r4_fw.bin");
+ else firmware_path = find_image_path("octoclock_r4_fw.hex");
//If Intel hex file detected, convert to binary
std::string ext = fs::extension(firmware_path);
@@ -312,9 +354,11 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
% time_spec_t::get_system_time().get_full_secs()));
Hex2Bin(firmware_path.c_str(), temp_bin.string().c_str(), false);
- firmware_path = temp_bin.string();
+ actual_firmware_path = temp_bin.string();
}
else if(ext == ".bin"){
+ hex = false;
+ actual_firmware_path = firmware_path;
std::cout << "Found firmware at path: " << firmware_path << std::endl;
}
else throw uhd::runtime_error("The firmware file has in improper extension (must be .hex or .bin).");
@@ -327,6 +371,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
if(reset_octoclock(ip_addr)) std::cout << "successful." << std::endl;
else{
std::cout << "failed." << std::endl;
+ if(hex) fs::remove(actual_firmware_path);
throw uhd::runtime_error("Failed to reset OctoClock device into its bootloader.");
}
}
@@ -334,11 +379,14 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
}
else{
std::cout << "failed." << std::endl;
+ if(hex) fs::remove(actual_firmware_path);
throw uhd::runtime_error("Could not find OctoClock with given IP address!");
}
read_firmware();
+ print_image_loader_warning(firmware_path, vm);
+
std::signal(SIGINT, &sig_int_handler);
burn_firmware(udp_transport);
@@ -354,7 +402,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
if(octoclocks.size() == 1){
if(octoclocks[0]["type"] == "octoclock-bootloader"){
std::cout << std::endl;
- throw uhd::runtime_error("OctoClock failed to leave bootloader state.");
+ if(hex) fs::remove(actual_firmware_path);
+ throw uhd::runtime_error("Firmware did not load properly.");
}
else{
std::cout << "found." << std::endl << std::endl
@@ -363,8 +412,10 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
}
else{
std::cout << std::endl;
+ if(hex) fs::remove(actual_firmware_path);
throw uhd::runtime_error("Failed to reinitialize OctoClock.");
}
+ if(hex) fs::remove(actual_firmware_path);
return EXIT_SUCCESS;
}
diff --git a/host/utils/uhd_image_loader.cpp b/host/utils/uhd_image_loader.cpp
new file mode 100644
index 000000000..39efc8f1e
--- /dev/null
+++ b/host/utils/uhd_image_loader.cpp
@@ -0,0 +1,122 @@
+//
+// Copyright 2015 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// 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 <csignal>
+#include <cstdlib>
+#include <iostream>
+
+#include <boost/assign.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/format.hpp>
+
+#include <uhd/config.hpp>
+#include <uhd/image_loader.hpp>
+#include <uhd/types/device_addr.hpp>
+#include <uhd/utils/safe_main.hpp>
+#include <boost/program_options.hpp>
+
+namespace fs = boost::filesystem;
+namespace po = boost::program_options;
+
+static std::string device_type = "";
+static int num_ctrl_c = 0;
+
+/*
+ * If the user presses Ctrl+C, warn them that they may corrupt their device.
+ * If they press it again, provide instructions on restoring the device
+ * (if applicable) and exit.
+ */
+void sigint_handler(int){
+ num_ctrl_c++;
+ if(num_ctrl_c == 1){
+ std::cout << std::endl
+ << "Are you sure you want to abort? If you do, your device will likely" << std::endl
+ << "be in an unstable or unusable state." << std::endl
+ << "Press Ctrl+C again to abort." << std::endl << std::endl;
+ }
+ else{
+ std::cout << std::endl << uhd::image_loader::get_recovery_instructions(device_type) << std::endl;
+ exit(EXIT_FAILURE);
+ }
+}
+
+int UHD_SAFE_MAIN(int argc, char *argv[]){
+
+ std::string fw_path = "";
+ std::string fpga_path = "";
+
+ po::options_description desc("Allowed options");
+ desc.add_options()
+ ("help", "help message")
+ ("args", po::value<std::string>()->default_value(""), "Device args, optional loader args")
+ ("fw-path", po::value<std::string>(&fw_path)->default_value(""), "Firmware path (uses default if none specified)")
+ ("fpga-path", po::value<std::string>(&fpga_path)->default_value(""), "FPGA path (uses default if none specified)")
+ ("no-fw", "Don't burn firmware")
+ ("no-fpga", "Don't burn FPGA")
+ ;
+
+ po::variables_map vm;
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ // Help message
+ if (vm.count("help")){
+ std::cout << "UHD Image Loader" << std::endl
+ << std::endl
+ << "Load firmware and/or FPGA images onto an Ettus Research device." << std::endl
+ << std::endl
+ << desc << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ // Convert user options
+ uhd::image_loader::image_loader_args_t image_loader_args;
+ image_loader_args.args = vm["args"].as<std::string>();
+ image_loader_args.load_firmware = (vm.count("no-fw") == 0);
+ image_loader_args.load_fpga = (vm.count("no-fpga") == 0);
+ image_loader_args.firmware_path = vm["fw-path"].as<std::string>();
+ image_loader_args.fpga_path = vm["fpga-path"].as<std::string>();
+
+ // Clean up paths, if given
+ if(image_loader_args.firmware_path != ""){
+ #ifndef UHD_PLATFORM_WIN32
+ if(image_loader_args.firmware_path.find("~") == 0){
+ image_loader_args.firmware_path.replace(0,1,getenv("HOME"));
+ }
+ #endif /* UHD_PLATFORM_WIN32 */
+ image_loader_args.firmware_path = fs::absolute(image_loader_args.firmware_path).string();
+ }
+ if(image_loader_args.fpga_path != ""){
+ #ifndef UHD_PLATFORM_WIN32
+ if(image_loader_args.fpga_path.find("~") == 0){
+ image_loader_args.fpga_path.replace(0,1,getenv("HOME"));
+ }
+ #endif /* UHD_PLATFORM_WIN32 */
+ image_loader_args.fpga_path = fs::absolute(image_loader_args.fpga_path).string();
+ }
+
+ // Detect which type of device we're working with
+ device_type = image_loader_args.args.get("type","");
+
+ std::signal(SIGINT, &sigint_handler);
+ if(not uhd::image_loader::load(image_loader_args)){
+ std::cerr << "No applicable UHD devices found" << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/host/utils/uhd_images_downloader.py.in b/host/utils/uhd_images_downloader.py.in
index 3903edc8c..e0375fb43 100644
--- a/host/utils/uhd_images_downloader.py.in
+++ b/host/utils/uhd_images_downloader.py.in
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2012-2014 Ettus Research LLC
+# Copyright 2012-2015 Ettus Research LLC
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -23,7 +23,7 @@ import math
import traceback
import shutil
import hashlib
-import urllib2
+import requests
import zipfile
from optparse import OptionParser
@@ -47,8 +47,8 @@ def md5Checksum(filePath):
break
m.update(data)
return m.hexdigest()
- except Exception, e:
- print "Failed to calculated MD5 sum of: %s (%s)" % (filePath, e)
+ except Exception as e:
+ print("Failed to calculated MD5 sum of: %s (%s)" % (filePath, e))
raise e
_checksum_fns = {
@@ -60,16 +60,16 @@ class temporary_directory():
try:
self.name = tempfile.mkdtemp()
return self.name
- except Exception, e:
- print "Failed to create a temporary directory (%s)" % (e)
+ except Exception as e:
+ print("Failed to create a temporary directory (%s)" % (e))
raise e
# Can return 'True' to suppress incoming exception
def __exit__(self, type, value, traceback):
try:
shutil.rmtree(self.name)
- except Exception, e:
- print "Could not delete temporary directory: %s (%s)" % (self.name, e)
+ except Exception as e:
+ print("Could not delete temporary directory: %s (%s)" % (self.name, e))
class uhd_images_downloader():
def __init__(self):
@@ -77,25 +77,20 @@ class uhd_images_downloader():
def download(self, images_url, filename, buffer_size=_DEFAULT_BUFFER_SIZE, print_progress=False):
""" Run the download, show progress """
- opener = urllib2.build_opener()
- opener.add_headers = [('User-Agent', 'UHD Images Downloader')]
- u = opener.open(images_url)
- meta = u.info()
- filesize = float(meta.getheaders("Content-Length")[0])
+ r = requests.get(images_url, stream=True, headers={'User-Agent': 'UHD Images Downloader'})
+ filesize = float(r.headers['content-length'])
filesize_dl = 0
with open(filename, "wb") as f:
- while True:
- buff = u.read(buffer_size)
- if not buff:
- break
- f.write(buff)
- filesize_dl += len(buff)
+ for buff in r.iter_content(chunk_size=buffer_size):
+ if buff:
+ f.write(buff)
+ filesize_dl += len(buff)
if print_progress:
status = r"%05d kB / %05d kB (%03d%%)" % (int(math.ceil(filesize_dl/1000.)), int(math.ceil(filesize/1000.)), int(math.ceil(filesize_dl*100.)/filesize))
status += chr(8)*(len(status)+1)
- print status,
+ sys.stdout.write(status)
if print_progress:
- print
+ print('')
return (filesize, filesize_dl)
def check_directories(self, dirs, print_progress=False):
@@ -105,23 +100,23 @@ class uhd_images_downloader():
def _check_part(head, tail=None):
if print_progress:
- print "Checking: %s" % (head)
+ print("Checking: %s" % (head))
if tail is not None and tail == "":
return True
if not os.path.exists(head):
if print_progress:
- print "Does not exist: %s" % (head)
+ print("Does not exist: %s" % (head))
return _check_part(*os.path.split(head))
if not os.path.isdir(head):
if print_progress:
- print "Is not a directory: %s" % (head)
+ print("Is not a directory: %s" % (head))
return (False, head)
if not os.access(head, os.W_OK):
if print_progress:
- print "Write permission denied on: %s" % (head)
+ print("Write permission denied on: %s" % (head))
return (False, head)
if print_progress:
- print "Write permission granted on: %s" % (head)
+ print("Write permission granted on: %s" % (head))
return (True, head)
return _check_part(dirs)
@@ -137,34 +132,34 @@ class uhd_images_downloader():
def extract_images_archive(self, archive_path, destination=None, print_progress=False):
if not os.path.exists(archive_path):
if print_progress:
- print "Path does not exist: %s" % (archive_path)
+ print("Path does not exist: %s" % (archive_path))
raise Exception("path does not exist: %s" % (archive_path))
if print_progress:
- print "Archive path: %s" % (archive_path)
+ print("Archive path: %s" % (archive_path))
(head, tail) = os.path.split(archive_path)
if not os.access(head, os.W_OK):
if print_progress:
- print "Write access denied on: %s" % (head)
+ print("Write access denied on: %s" % (head))
raise Exception("write access denied on: %s" % (head))
(root, ext) = os.path.splitext(tail)
temp_dir = os.path.join(head, root)
if print_progress:
- print "Temporary extraction location: %s" % (temp_dir)
+ print("Temporary extraction location: %s" % (temp_dir))
if os.path.exists(temp_dir):
if print_progress:
- print "Deleting existing location: %s" % (temp_dir)
+ print("Deleting existing location: %s" % (temp_dir))
shutil.rmtree(temp_dir)
if print_progress:
- print "Creating directory: %s" % (temp_dir)
+ print("Creating directory: %s" % (temp_dir))
os.mkdir(temp_dir)
if print_progress:
- print "Extracting archive %s to %s" % (archive_path, temp_dir)
+ print("Extracting archive %s to %s" % (archive_path, temp_dir))
images_zip = zipfile.ZipFile(archive_path)
images_zip.extractall(temp_dir)
@@ -175,27 +170,27 @@ class uhd_images_downloader():
def install_images(self, source, dest, keep=False, print_progress=False):
if not os.path.exists(source):
if print_progress:
- print "Source path does not exist: %s" % (source)
+ print("Source path does not exist: %s" % (source))
return
if keep:
if print_progress:
- print "Not wiping directory tree (existing files will be overwritten): %s" % (dest)
+ print("Not wiping directory tree (existing files will be overwritten): %s" % (dest))
elif os.path.exists(dest):
if print_progress:
- print "Deleting directory tree: %s" % (dest)
+ print("Deleting directory tree: %s" % (dest))
shutil.rmtree(dest)
(head, tail) = os.path.split(source)
if print_progress:
- print "Source install path: %s" % (source)
+ print("Source install path: %s" % (source))
uhd_source = os.path.join(source, tail, *_BASE_DIR_STRUCTURE_PARTS)
if print_progress:
- print "Copying files from: %s" % (uhd_source)
- print "Copying files to: %s" % (dest)
+ print("Copying files from: %s" % (uhd_source))
+ print("Copying files to: %s" % (dest))
if keep:
# mgrant @ http://stackoverflow.com/questions/12683834/how-to-copy-directory-recursively-in-python-and-overwrite-all
@@ -222,12 +217,12 @@ def main():
### Set defaults from env variables
if os.environ.get("UHD_IMAGES_DIR") != None and os.environ.get("UHD_IMAGES_DIR") != "":
default_images_dir = os.environ.get("UHD_IMAGES_DIR")
- print "UHD_IMAGES_DIR environment variable is set.\nDefault install location: {0}".format(default_images_dir)
+ print("UHD_IMAGES_DIR environment variable is set.\nDefault install location: {0}".format(default_images_dir))
else:
default_images_dir = _DEFAULT_INSTALL_PATH
if os.environ.get("UHD_IMAGES_BASE_URL") != None and os.environ.get("UHD_IMAGES_BASE_URL") != "":
default_base_url = os.environ.get("UHD_IMAGES_BASE_URL")
- print "UHD_IMAGES_BASE_URL environment variable is set.\nDefault base URL: {0}".format(default_base_url)
+ print("UHD_IMAGES_BASE_URL environment variable is set.\nDefault base URL: {0}".format(default_base_url))
else:
default_base_url = _DEFAULT_BASE_URL
@@ -244,22 +239,22 @@ def main():
parser.add_option("-c", "--checksum", type="string", default=_AUTOGEN_IMAGES_CHECKSUM,
help="Validate images archive against this checksum (blank to skip) [default=%default]")
parser.add_option("-t", "--checksum-type", type="string", default=_IMAGES_CHECKSUM_TYPE,
- help=("Select checksum hash function (options: %s) [default=%%default]" % (",".join(_checksum_fns.keys()))))
+ help=("Select checksum hash function (options: %s) [default=%%default]" % (",".join(list(_checksum_fns.keys())))))
parser.add_option("-k", "--keep", action="store_true", default=False,
help="Do not clear images directory before extracting new files [default=%default]")
parser.add_option("-v", "--verbose", action="store_true", default=False,
help="Enable verbose output [default=%default]")
(options, args) = parser.parse_args()
if options.buffer_size <= 0:
- print "Invalid buffer size: %s" % (options.buffer_size)
+ print("Invalid buffer size: %s" % (options.buffer_size))
return 1
### Select checksum algorithm (MD5)
checksum_fn = None
if options.checksum != "":
options.checksum_type = options.checksum_type.lower()
- if not _checksum_fns.has_key(options.checksum_type):
- print "Not a supported checksum function: %s" % (options.checksum_type)
+ if options.checksum_type not in _checksum_fns:
+ print("Not a supported checksum function: %s" % (options.checksum_type))
return 1
checksum_fn = _checksum_fns[options.checksum_type]
@@ -275,30 +270,30 @@ def main():
base_url_is_local = True
if options.verbose:
- print "Requested install location: %s" % (options.install_location)
- print "Images base URL: %s" % (options.base_url)
- print "Images filename: %s" % (options.filename)
- print "Images checksum: %s (%s)" % (options.checksum, _IMAGES_CHECKSUM_TYPE)
- print "Final install location: %s" % (images_dir)
- print "Copying locally: {0}".format("Yes" if base_url_is_local else "No")
+ print("Requested install location: %s" % (options.install_location))
+ print("Images base URL: %s" % (options.base_url))
+ print("Images filename: %s" % (options.filename))
+ print("Images checksum: %s (%s)" % (options.checksum, _IMAGES_CHECKSUM_TYPE))
+ print("Final install location: %s" % (images_dir))
+ print("Copying locally: {0}".format("Yes" if base_url_is_local else "No"))
else:
- print "Images destination: %s" % (images_dir)
+ print("Images destination: %s" % (images_dir))
### Download or copy
downloader = uhd_images_downloader()
try:
(access, last_path) = downloader.check_directories(images_dir, print_progress=options.verbose)
if not access:
- print "You do not have sufficient permissions to write to: %s" % (last_path)
- print "Are you root?"
+ print("You do not have sufficient permissions to write to: %s" % (last_path))
+ print("Are you root?")
return 1
with temporary_directory() as temp_dir:
if options.verbose:
- print "Using temporary directory: %s" % (temp_dir)
+ print("Using temporary directory: %s" % (temp_dir))
temp_images_dest = os.path.join(temp_dir, options.filename)
if not base_url_is_local:
- print "Downloading images from: {0}".format(images_url)
- print "Downloading images to: {0}".format(temp_images_dest)
+ print("Downloading images from: {0}".format(images_url))
+ print("Downloading images to: {0}".format(temp_images_dest))
(reported_size, downloaded_size) = downloader.download(
images_url=images_url,
filename=temp_images_dest,
@@ -306,12 +301,12 @@ def main():
print_progress=True
)
if options.verbose:
- print "Downloaded %d of %d bytes" % (downloaded_size, reported_size)
+ print("Downloaded %d of %d bytes" % (downloaded_size, reported_size))
else:
local_images_pkg = os.path.join(options.base_url, options.filename)
- print "Copying images from: {0}".format(local_images_pkg)
+ print("Copying images from: {0}".format(local_images_pkg))
if not os.path.isfile(local_images_pkg):
- print "[ERROR] No such file."
+ print("[ERROR] No such file.")
return 1
shutil.copyfile(local_images_pkg, temp_images_dest)
(checksum_match, calculated_checksum) = downloader.validate_checksum(
@@ -321,48 +316,46 @@ def main():
print_progress=options.verbose
)
if options.verbose:
- print "Calculated checksum: %s" % (calculated_checksum)
+ print("Calculated checksum: %s" % (calculated_checksum))
if checksum_match:
if options.verbose:
if options.checksum == "":
- print "Ignoring checksum"
+ print("Ignoring checksum")
else:
- print "Checksum OK"
+ print("Checksum OK")
try:
extract_path = downloader.extract_images_archive(temp_images_dest, print_progress=options.verbose)
if options.verbose:
- print "Image archive extracted to: %s" % (extract_path)
+ print("Image archive extracted to: %s" % (extract_path))
downloader.install_images(extract_path, images_dir, options.keep, print_progress=options.verbose)
if options.verbose:
- print "Cleaning up temp location: %s" % (extract_path)
+ print("Cleaning up temp location: %s" % (extract_path))
shutil.rmtree(extract_path)
- print
- print "Images successfully installed to: %s" % (images_dir)
- except Exception, e:
- print "Failed to install image archive: %s" % (e)
- print "This is usually a permissions problem."
- print "Please check your file system access rights and try again."
+ print("\nImages successfully installed to: %s" % (images_dir))
+ except Exception as e:
+ print("Failed to install image archive: %s" % (e))
+ print("This is usually a permissions problem.")
+ print("Please check your file system access rights and try again.")
if options.verbose:
traceback.print_exc()
else:
- print "You can run this again with the '--verbose' flag to see more information"
- print "If the problem persists, please email the output to: %s" % (_CONTACT)
+ print("You can run this again with the '--verbose' flag to see more information")
+ print("If the problem persists, please email the output to: %s" % (_CONTACT))
else:
- print "Checksum of downloaded file is not correct (not installing - see options to override)"
- print "Expected: %s" % (options.checksum)
- print "Calculated: %s" % (calculated_checksum)
- print "Please try downloading again."
- print "If the problem persists, please email the output to: %s" % (_CONTACT)
+ print("Checksum of downloaded file is not correct (not installing - see options to override)")
+ print("Expected: %s" % (options.checksum))
+ print("Calculated: %s" % (calculated_checksum))
+ print("Please try downloading again.")
+ print("If the problem persists, please email the output to: %s" % (_CONTACT))
except KeyboardInterrupt:
- print
- print "Cancelled at user request"
- except Exception, e:
- print "Downloader raised an unhandled exception: %s" % (e)
+ print("\nCancelled at user request")
+ except Exception as e:
+ print("Downloader raised an unhandled exception: %s" % (e))
if options.verbose:
traceback.print_exc()
else:
- print "You can run this again with the '--verbose' flag to see more information"
- print "If the problem persists, please email the output to: %s" % (_CONTACT)
+ print("You can run this again with the '--verbose' flag to see more information")
+ print("If the problem persists, please email the output to: %s" % (_CONTACT))
return 1
return 0
diff --git a/host/utils/usrp_n2xx_net_burner.py b/host/utils/usrp_n2xx_net_burner.py
index 8f16de501..5605b0028 100755
--- a/host/utils/usrp_n2xx_net_burner.py
+++ b/host/utils/usrp_n2xx_net_burner.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2010-2011 Ettus Research LLC
+# Copyright 2010-2011,2015 Ettus Research LLC
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -91,6 +91,45 @@ def seq():
return _seq
########################################################################
+# print equivalent uhd_image_loader command
+########################################################################
+def print_image_loader_warning(fw, fpga, reset, safe, addr):
+
+ # Newline + indent
+ if platform.system() == "Windows":
+ nl = " ^\n "
+ else:
+ nl = " \\\n "
+
+ # Generate uhd_image_loader command based on given arguments
+ uhd_image_loader = "uhd_image_loader --args=\"type=usrp2,addr={0}".format(addr)
+ if reset:
+ uhd_image_loader += ",reset"
+ if safe:
+ uhd_image_loader += ",overwrite-safe"
+ uhd_image_loader += "\""
+
+ if fw:
+ uhd_image_loader += "{0}--fw-path=\"{1}\"".format(nl, fw)
+ else:
+ uhd_image_loader += "{0}--no-fw".format(nl)
+
+ if fpga:
+ uhd_image_loader += "{0}--fpga-path=\"{1}\"".format(nl, fpga)
+ else:
+ uhd_image_loader += "{0}--no-fpga".format(nl)
+
+ print("")
+ print("************************************************************************************************")
+ print("WARNING: This utility will be removed in an upcoming version of UHD. In the future, use")
+ print(" this command:")
+ print("")
+ print(uhd_image_loader)
+ print("")
+ print("************************************************************************************************")
+ print("")
+
+########################################################################
# helper functions
########################################################################
def unpack_flash_args_fmt(s):
@@ -234,6 +273,7 @@ def enumerate_devices():
class burner_socket(object):
def __init__(self, addr, quiet):
self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ self._addr = addr
self._quiet = quiet
self._sock.settimeout(UDP_TIMEOUT)
self._sock.connect((addr, UDP_FW_UPDATE_PORT))
@@ -284,6 +324,8 @@ class burner_socket(object):
return (self.memory_size_bytes, self.sector_size_bytes)
def burn_fw(self, fw, fpga, reset, safe, check_rev=True):
+ print_image_loader_warning(fw, fpga, reset, safe, self._addr)
+
(flash_size, sector_size) = self.get_flash_info()
hw_rev = self.get_hw_rev()
@@ -501,7 +543,12 @@ if __name__=='__main__':
if options.overwrite_safe and not options.read:
print("Are you REALLY, REALLY sure you want to overwrite the safe image? This is ALMOST ALWAYS a terrible idea.")
print("If your image is faulty, your USRP2+ will become a brick until reprogrammed via JTAG.")
- response = raw_input("""Type "yes" to continue, or anything else to quit: """)
+
+ python_major_version = int(platform.python_version_tuple()[0])
+ if python_major_version > 2:
+ response = input("""Type "yes" to continue, or anything else to quit: """)
+ else:
+ response = raw_input("""Type "yes" to continue, or anything else to quit: """)
if response != "yes": sys.exit(0)
burner = burner_socket(addr=options.addr,quiet=False)
diff --git a/host/utils/usrp_n2xx_simple_net_burner.cpp b/host/utils/usrp_n2xx_simple_net_burner.cpp
index 642e9a407..b105e9cb6 100644
--- a/host/utils/usrp_n2xx_simple_net_burner.cpp
+++ b/host/utils/usrp_n2xx_simple_net_burner.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2012-2014 Ettus Research LLC
+// Copyright 2012-2015 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -184,6 +184,59 @@ void list_usrps(){
/***********************************************************************
* Find USRP N2XX with specified IP address and return type
**********************************************************************/
+void print_image_loader_warning(const std::string &fw_path,
+ const std::string &fpga_path,
+ const po::variables_map &vm){
+
+ // Newline + indent
+ #ifdef UHD_PLATFORM_WIN32
+ const std::string nl = " ^\n ";
+ #else
+ const std::string nl = " \\\n ";
+ #endif
+
+ std::string uhd_image_loader = str(boost::format("uhd_image_loader --args=\"type=usrp2,addr=%s")
+ % vm["addr"].as<std::string>());
+ if(vm.count("auto-reboot") > 0)
+ uhd_image_loader += ",reset";
+ if(vm.count("overwrite-safe") > 0)
+ uhd_image_loader += ",overwrite-safe";
+ if(vm.count("dont-check-rev") > 0)
+ uhd_image_loader += ",dont-check-rev";
+
+ uhd_image_loader += "\"";
+
+ if(vm.count("no-fw") == 0){
+ uhd_image_loader += str(boost::format("%s--fw-path=\"%s\"")
+ % nl % fw_path);
+ }
+ else{
+ uhd_image_loader += str(boost::format("%s--no-fw")
+ % nl);
+ }
+
+ if(vm.count("no-fpga") == 0){
+ uhd_image_loader += str(boost::format("%s--fpga-path=\"%s\"")
+ % nl % fpga_path);
+ }
+ else{
+ uhd_image_loader += str(boost::format("%s--no-fpga")
+ % nl);
+ }
+
+ std::cout << "************************************************************************************************" << std::endl
+ << "WARNING: This utility will be removed in an upcoming version of UHD. In the future, use" << std::endl
+ << " this command:" << std::endl
+ << std::endl
+ << uhd_image_loader << std::endl
+ << std::endl
+ << "************************************************************************************************" << std::endl
+ << std::endl;
+}
+
+/***********************************************************************
+ * Find USRP N2XX with specified IP address and return type
+ **********************************************************************/
boost::uint32_t find_usrp(udp_simple::sptr udp_transport, bool check_rev){
boost::uint32_t hw_rev;
bool found_it = false;
@@ -627,6 +680,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
fw_image_size = read_fw_image(fw_path);
}
+ print_image_loader_warning(fw_path, fpga_path, vm);
+
std::cout << "Will burn the following images:" << std::endl;
if(burn_fw) std::cout << boost::format(" * Firmware: %s\n") % fw_path;
if(burn_fpga) std::cout << boost::format(" * FPGA: %s\n") % fpga_path;
diff --git a/host/utils/usrp_x3xx_fpga_burner.cpp b/host/utils/usrp_x3xx_fpga_burner.cpp
index 3c6225531..704b291be 100644
--- a/host/utils/usrp_x3xx_fpga_burner.cpp
+++ b/host/utils/usrp_x3xx_fpga_burner.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2013-2014 Ettus Research LLC
+// Copyright 2013-2015 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -54,7 +54,7 @@ extern "C" {
}
#define X300_FPGA_BIN_SIZE_BYTES 15877916
-#define X300_FPGA_BIT_MAX_SIZE_BYTES 15878022
+#define X300_FPGA_BIT_MAX_SIZE_BYTES 15878032
#define X300_FPGA_PROG_UDP_PORT 49157
#define X300_FLASH_SECTOR_SIZE 131072
#define X300_PACKET_SIZE_BYTES 256
@@ -195,6 +195,71 @@ void extract_from_lvbitx(std::string lvbitx_path, std::vector<char> &bitstream){
bitstream.swap(decoded_bitstream);
}
+void print_image_loader_warning(const std::string &fpga_path, const po::variables_map &vm){
+
+ // Newline + indent
+ #ifdef UHD_PLATFORM_WIN32
+ const std::string nl = " ^\n ";
+ #else
+ const std::string nl = " \\\n ";
+ #endif
+
+ // Generate equivalent uhd_image_loader command
+ std::string uhd_image_loader = "uhd_image_loader --args=\"type=x300";
+
+ if(vm.count("addr") > 0){
+ uhd_image_loader += str(boost::format(",addr=%s")
+ % vm["addr"].as<std::string>());
+
+ if(vm.count("configure") > 0){
+ uhd_image_loader += ",configure";
+ }
+
+ if(vm.count("verify") > 0){
+ uhd_image_loader += ",verify";
+ }
+ }
+ else{
+ uhd_image_loader += str(boost::format(",resource=%s")
+ % vm["resource"].as<std::string>());
+
+ /*
+ * Since we have a default value, vm.count("rpc-port") will
+ * always be > 0, so only add the option if a different port
+ * is given.
+ */
+ if(vm["rpc-port"].as<std::string>() != "5444"){
+ uhd_image_loader += str(boost::format(",rpc-port=%s")
+ % vm["rpc-port"].as<std::string>());
+ }
+ }
+
+ if(vm.count("type") > 0){
+ uhd_image_loader += str(boost::format(",fpga=%s")
+ % vm["type"].as<std::string>());
+ }
+
+ uhd_image_loader += "\"";
+
+ /*
+ * The --type option overrides any given path, so only add an FPGA path
+ * if there was no --type argument.
+ */
+ if(vm.count("type") == 0){
+ uhd_image_loader += str(boost::format("%s--fpga-path=\"%s\"")
+ % nl % fpga_path);
+ }
+
+ std::cout << "************************************************************************************************" << std::endl
+ << "WARNING: This utility will be removed in an upcoming version of UHD. In the future, use" << std::endl
+ << " this command:" << std::endl
+ << std::endl
+ << uhd_image_loader << std::endl
+ << std::endl
+ << "************************************************************************************************" << std::endl
+ << std::endl;
+}
+
void ethernet_burn(udp_simple::sptr udp_transport, std::string fpga_path, bool verify){
boost::uint32_t max_size;
std::vector<char> bitstream;
@@ -479,6 +544,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
throw std::runtime_error("The image filename must end in .bin, .bit, or .lvbitx.");
}
+ print_image_loader_warning(fpga_path, vm);
+
std::signal(SIGINT, &sig_int_handler);
if(vm.count("addr")){
udp_simple::sptr udp_transport = udp_simple::make_connected(ip_addr, BOOST_STRINGIZE(X300_FPGA_PROG_UDP_PORT));