From 8737c550f535b738c0fad703d7302a305ef871d2 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Fri, 31 Jul 2015 17:11:08 -0700 Subject: utils: Updated b2xx_side_channel utility, moved over from tools/ --- host/utils/b2xx_side_channel.py | 272 ++++++++++++++++++++++++++++++++-------- 1 file changed, 223 insertions(+), 49 deletions(-) (limited to 'host/utils') diff --git a/host/utils/b2xx_side_channel.py b/host/utils/b2xx_side_channel.py index 7b1e980eb..070f5684c 100755 --- a/host/utils/b2xx_side_channel.py +++ b/host/utils/b2xx_side_channel.py @@ -16,25 +16,27 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . # +""" +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 pysusb'" + 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) -import serial - VRT_OUT = usb.util.CTRL_TYPE_VENDOR | usb.util.CTRL_OUT VRT_IN = usb.util.CTRL_TYPE_VENDOR | usb.util.CTRL_IN @@ -62,7 +64,7 @@ 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 +COUNTER_MAGIC = 0x10024001 """ typedef struct Counters { int magic; @@ -162,6 +164,10 @@ USB_PHY_ERROR_REGISTERS = [ USB_ERROR_COUNTERS += USB_PHY_ERROR_REGISTERS +PIB_COUNTERS = [ + 'socket_inactive' +] + COUNTERS = [ 'magic', @@ -177,7 +183,13 @@ COUNTERS = [ 'heap_size', - 'resume_count' + '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 = {} @@ -243,6 +255,101 @@ 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: @@ -252,11 +359,11 @@ def _parse_usb_event_log(data): #l += [(USB_EVENTS[0x80][0] + "+%i" % (d & ~0x80), USB_EVENTS[0x80][1])] ltssm_key = (d & ~0x80) ltssm_val = "(unknown)" - if LTSSM_STATES.has_key(ltssm_key): + 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 USB_EVENTS.has_key(d): + elif d in USB_EVENTS: l += [USB_EVENTS[d]] #else: # l += [("?", "?")] @@ -313,8 +420,8 @@ class counter_set(): try: vals = struct.unpack(self._fmt_str, data) self._update(vals) - except Exception, e: - print e + except Exception as e: + print(("While updating counter set '%s':" % self._name), e) def __str__(self): return self.to_string() @@ -346,7 +453,7 @@ class usb_device(): self.timeout = 2000 def open(self, idVendor, idProduct): - print "Finding %04x:%04x..." % (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)) @@ -362,7 +469,7 @@ class usb_device(): #self.dev.set_configuration() # This will throw as device is already claimed - print "Opened %04x:%04x" % (idVendor, idProduct) + 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 @@ -379,40 +486,41 @@ class usb_device(): l = [] try: l = self.dev.ctrl_transfer(VRT_IN, B200_VREQ_GET_USB_SPEED, 0, 0, 1) - except usb.core.USBError, e: + except usb.core.USBError as e: if e.errno == 32: - print e + 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 + print("Operating at USB", self.usb_speed) break else: - print "Retrying..." + print("Retrying...") #if self.usb_speed == 3: # self.max_buffer_size = 512 - print "Max buffer size:", self.max_buffer_size - print + 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 VRQS.has_key(vrt): + if vrt in VRQS: vrt_str += " (%s)" % (VRQS[vrt]) - print "%s: %s" % (vrt_str, str(e)) + 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, e: + 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, e: + except usb.core.USBError as e: self._handle_error(e, vrt) return None @@ -428,7 +536,11 @@ class usb_device(): last = 0 while raw[last] != 0: try: - idx = raw.index(0, last) + 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) @@ -439,8 +551,8 @@ class usb_device(): last = idx + 1 if last >= len(raw): break - except Exception, e: - print e + except Exception as e: + print("Exception while parsing log buffer:", e) break return lines @@ -450,8 +562,8 @@ class usb_device(): return for l in lines: #print l - print "[%05i %05i] %s" % (l[0], self.log_read_count, l[1]) - print + 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) @@ -462,8 +574,8 @@ class usb_device(): def print_counters(self): self.get_counters() - print "[%05i]" % (self.counters_read_count) - print self.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) @@ -480,8 +592,8 @@ class usb_device(): l = self.get_usb_event_log() if len(l) == 0: return - print "\n".join(map(lambda x: ("[%05i] " % (self.usb_event_log_read_count)) + x[0] + ":\t" + x[1], l)) - print + 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 = [ @@ -489,8 +601,8 @@ def run_log(dev, options): (options.counters, dev.print_counters), (options.usb_events, dev.print_usb_event_log) ] - items = filter(lambda x: x[0] > 0, items) - smallest_interval = min(map(lambda x: x[0], items)) + 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) @@ -506,7 +618,7 @@ def run_log(dev, options): if time_now < (time_last + items[i][0]): continue if options.clear_screen and not cleared: - print chr(27) + "[2J" + print(chr(27) + "[2J") cleared = True #print items[i][1] items[i][1]() @@ -535,9 +647,9 @@ def recv_serial_data(ser): data = data[0:-2] if data == "": #print "[Received an empty line]" - print + print() elif data[0] == ' ': - print time_now_str, data[1:] + print(time_now_str, data[1:]) elif data[0] == 'U': data = data[1:] cur_type = 0 @@ -553,20 +665,20 @@ def recv_serial_data(ser): i = ord(c) - ord('A') cur_type = 2 else: - print time_now_str, "[Unknown type: '%s' (0x%02x) in '%s']" % (c, ord(c), data) + 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) + 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] + 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) + 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] @@ -578,11 +690,14 @@ def recv_serial_data(ser): if len(usb_events) > 0: usb_event_log_read_count += 1 l = _parse_usb_event_log(usb_events) - print "\n".join(map(lambda x: time_now_str + ("[%05i] " % (usb_event_log_read_count)) + x[0] + ":\t" + x[1], l)) + 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]") @@ -597,26 +712,34 @@ def main(): 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 + print("Opened", options.tty) + try: recv_serial_data(ser) except KeyboardInterrupt: break except Exception as e: - print 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: @@ -627,17 +750,68 @@ def main(): 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) - pass else: - pass + 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 + print(e) break + return 0 if __name__ == '__main__': -- cgit v1.2.3 From 12cea5a4843722daf9628006cb8b0c0580034aa7 Mon Sep 17 00:00:00 2001 From: Nicholas Corgan Date: Mon, 3 Aug 2015 14:14:15 -0700 Subject: Added NI B2x0 VID/PID pairs to udev rules --- host/utils/uhd-usrp.rules | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'host/utils') diff --git a/host/utils/uhd-usrp.rules b/host/utils/uhd-usrp.rules index 2f5198d64..10d68a290 100644 --- a/host/utils/uhd-usrp.rules +++ b/host/utils/uhd-usrp.rules @@ -1,5 +1,5 @@ # -# Copyright 2011 Ettus Research LLC +# Copyright 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 @@ -23,3 +23,5 @@ SUBSYSTEMS=="usb", ATTRS{idVendor}=="2500", ATTRS{idProduct}=="0002", MODE:="066 #B200 SUBSYSTEMS=="usb", ATTRS{idVendor}=="2500", ATTRS{idProduct}=="0020", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="3923", ATTRS{idProduct}=="7813", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="3923", ATTRS{idProduct}=="7814", MODE:="0666" -- cgit v1.2.3 From bb62ab84fdad6f7cf18ea55d395dfbd7f11ed79d Mon Sep 17 00:00:00 2001 From: Nicholas Corgan Date: Wed, 5 Aug 2015 08:46:28 -0700 Subject: image_loader: force user to specify device * On utility level, force user to use --args=type=foo * In each loader, throw an error if args are ambiguous --- host/include/uhd/image_loader.hpp | 3 +- host/lib/usrp/b200/b200_image_loader.cpp | 33 +++++++-- host/lib/usrp/usrp2/n200_image_loader.cpp | 80 +++++++++++++++------- host/lib/usrp/x300/x300_image_loader.cpp | 32 ++++++--- .../octoclock/octoclock_image_loader.cpp | 48 +++++++++---- host/utils/uhd_image_loader.cpp | 5 ++ 6 files changed, 148 insertions(+), 53 deletions(-) (limited to 'host/utils') diff --git a/host/include/uhd/image_loader.hpp b/host/include/uhd/image_loader.hpp index 8124e7dea..5963c862f 100644 --- a/host/include/uhd/image_loader.hpp +++ b/host/include/uhd/image_loader.hpp @@ -46,8 +46,9 @@ public: * * This function must return true upon the end of a successful image load * or false if no applicable device was found. It may only throw a runtime - * error under one of two conditions: + * error under one of three conditions: * + * * The function finds multiple devices that fit the user's arguments. * * The function has already engaged with a specific device and * something goes wrong. * * The user gives arguments that unambiguously lead to a specific diff --git a/host/lib/usrp/b200/b200_image_loader.cpp b/host/lib/usrp/b200/b200_image_loader.cpp index 87010244c..9eaeeff63 100644 --- a/host/lib/usrp/b200/b200_image_loader.cpp +++ b/host/lib/usrp/b200/b200_image_loader.cpp @@ -40,27 +40,50 @@ static b200_iface::sptr get_b200_iface(const image_loader::image_loader_args_t & bool user_specified){ std::vector dev_handles = get_b200_device_handles(image_loader_args.args); + std::vector applicable_dev_handles; b200_iface::sptr iface; + mboard_eeprom_t eeprom; // Internal use if(dev_handles.size() > 0){ BOOST_FOREACH(usb_device_handle::sptr dev_handle, dev_handles){ if(dev_handle->firmware_loaded()){ iface = b200_iface::make(usb_control::make(dev_handle,0)); - mb_eeprom = mboard_eeprom_t(*iface, "B200"); + eeprom = mboard_eeprom_t(*iface, "B200"); if(user_specified){ if(image_loader_args.args.has_key("serial") and - mb_eeprom.get("serial") != image_loader_args.args.get("serial")){ + eeprom.get("serial") != image_loader_args.args.get("serial")){ continue; } if(image_loader_args.args.has_key("name") and - mb_eeprom.get("name") != image_loader_args.args.get("name")){ + eeprom.get("name") != image_loader_args.args.get("name")){ continue; } - return iface; + applicable_dev_handles.push_back(dev_handle); } - else return iface; // Just return first found + else applicable_dev_handles.push_back(dev_handle); } } + + // At this point, we should have a single B2XX + if(applicable_dev_handles.size() == 1){ + mb_eeprom = eeprom; + return iface; + } + else if(applicable_dev_handles.size() > 1){ + std::string err_msg = "Could not resolve given args to a single B2XX device.\n" + "Applicable devices:\n"; + + BOOST_FOREACH(usb_device_handle::sptr dev_handle, applicable_dev_handles){ + eeprom = mboard_eeprom_t(*b200_iface::make(usb_control::make(dev_handle,0)), "B200"); + err_msg += str(boost::format(" * %s (serial=%s)\n") + % B2X0_STR_NAMES.get(get_b200_type(mb_eeprom), "B2XX") + % mb_eeprom.get("serial")); + } + + err_msg += "\nSpecify one of these devices with the given args to load an image onto it."; + + throw uhd::runtime_error(err_msg); + } } // No applicable devices found, return empty sptr so we can exit diff --git a/host/lib/usrp/usrp2/n200_image_loader.cpp b/host/lib/usrp/usrp2/n200_image_loader.cpp index ce956c22c..29bec8b4a 100644 --- a/host/lib/usrp/usrp2/n200_image_loader.cpp +++ b/host/lib/usrp/usrp2/n200_image_loader.cpp @@ -210,36 +210,62 @@ static uhd::device_addr_t n200_find(const image_loader::image_loader_args_t &ima image_loader_args.args.has_key("name"); uhd::device_addrs_t found = usrp2_find(image_loader_args.args); - if(found.size() > 0){ - uhd::device_addr_t ret = found[0]; - - /* - * Make sure the device found is an N-Series and not a USRP2. A USRP2 - * will not respond to this query. If the user supplied specific - * arguments that led to a USRP2, throw an error. - */ - udp_simple::sptr rev_xport = udp_simple::make_connected( - ret["addr"], - BOOST_STRINGIZE(N200_UDP_FW_UPDATE_PORT) - ); + if(found.size() > 0){ + uhd::device_addrs_t n200_found; + udp_simple::sptr rev_xport; n200_fw_update_data_t pkt_out; boost::uint8_t data_in[udp_simple::mtu]; const n200_fw_update_data_t *pkt_in = reinterpret_cast(data_in); + size_t len = 0; - size_t len = n200_send_and_recv(rev_xport, GET_HW_REV_CMD, &pkt_out, data_in); - if(n200_response_matches(pkt_in, GET_HW_REV_ACK, len)){ - boost::uint32_t rev = ntohl(pkt_in->data.hw_rev); - ret["hw_rev"] = n200_filename_map.get(rev, "n2xx"); - return ret; + /* + * Filter out any USRP2 devices by sending a query over the + * UDP update port. Only N-Series devices will respond to + * this query. If the user supplied specific arguments that + * led to a USRP2, throw an error. + */ + BOOST_FOREACH(const uhd::device_addr_t &dev, found){ + rev_xport = udp_simple::make_connected( + dev.get("addr"), + BOOST_STRINGIZE(N200_UDP_FW_UPDATE_PORT) + ); + + len = n200_send_and_recv(rev_xport, GET_HW_REV_CMD, &pkt_out, data_in); + if(n200_response_matches(pkt_in, GET_HW_REV_ACK, len)){ + boost::uint32_t rev = ntohl(pkt_in->data.hw_rev); + std::string hw_rev = n200_filename_map.get(rev, "n2xx"); + + n200_found.push_back(dev); + n200_found[n200_found.size()-1]["hw_rev"] = hw_rev; + } + else if(len > offsetof(n200_fw_update_data_t, data) and ntohl(pkt_in->id) != GET_HW_REV_ACK){ + throw uhd::runtime_error(str(boost::format("Received invalid reply %d from device.") + % ntohl(pkt_in->id))); + } + else if(user_specified){ + // At this point, we haven't received any response, so assume it's a USRP2 + print_usrp2_error(image_loader_args); + } } - else if(len > offsetof(n200_fw_update_data_t, data) and ntohl(pkt_in->id) != GET_HW_REV_ACK){ - throw uhd::runtime_error(str(boost::format("Received invalid reply %d from device.") - % ntohl(pkt_in->id))); + + // At this point, we should have a single N-Series device + if(n200_found.size() == 1){ + return n200_found[0]; } - else if(user_specified){ - // At this point, we haven't received any response, so assume it's a USRP2 - print_usrp2_error(image_loader_args); + else if(n200_found.size() > 1){ + std::string err_msg = "Could not resolve given args to a single N-Series device.\n" + "Applicable devices:\n"; + + BOOST_FOREACH(const uhd::device_addr_t &dev, n200_found){ + err_msg += str(boost::format("* %s (addr=%s)\n") + % dev.get("hw_rev") + % dev.get("addr")); + } + + err_msg += "\nSpecify one of these devices with the given args to load an image onto it."; + + throw uhd::runtime_error(err_msg); } } @@ -259,7 +285,7 @@ static void n200_validate_firmware_image(n200_session_t &session){ session.max_size = N200_FW_MAX_SIZE_BYTES; if(session.size > session.max_size){ - throw uhd::runtime_error(str(boost::format("The specified FPGA image is too large: %d vs. %d") + throw uhd::runtime_error(str(boost::format("The specified firmware image is too large: %d vs. %d") % session.size % session.max_size)); } @@ -559,11 +585,15 @@ static std::string nice_name(const std::string &fw_rev){ } static bool n200_image_loader(const image_loader::image_loader_args_t &image_loader_args){ + if(!image_loader_args.load_firmware and !image_loader_args.load_fpga){ + return false; + } + // See if any N2x0 with the given args is found // This will throw if specific args lead to a USRP2 n200_session_t session; session.dev_addr = n200_find(image_loader_args); - if(session.dev_addr.size() == 0 or (!image_loader_args.load_firmware and !image_loader_args.load_fpga)){ + if(session.dev_addr.size() == 0){ return false; } diff --git a/host/lib/usrp/x300/x300_image_loader.cpp b/host/lib/usrp/x300/x300_image_loader.cpp index 321309868..9ec8a2e13 100644 --- a/host/lib/usrp/x300/x300_image_loader.cpp +++ b/host/lib/usrp/x300/x300_image_loader.cpp @@ -158,17 +158,31 @@ static void x300_validate_image(x300_session_t &session){ static void x300_setup_session(x300_session_t &session, const device_addr_t &args, const std::string &filepath){ - device_addr_t find_args; - find_args["type"] = "x300"; - if(args.has_key("name")) find_args["name"] = args["name"]; - if(args.has_key("serial")) find_args["serial"] = args["serial"]; - if(args.has_key("ip-addr")) find_args["addr"] = args["ip-addr"]; - else if(args.has_key("resource")) find_args["resource"] = args["resource"]; - device_addrs_t devs = x300_find(args); - session.found = (devs.size() > 0); - if(!session.found) return; + if(devs.size() == 0){ + session.found = false; + return; + } + else if(devs.size() > 1){ + std::string err_msg = "Could not resolve given args to a single X-Series device.\n" + "Applicable devices:\n"; + + BOOST_FOREACH(const uhd::device_addr_t &dev, devs){ + std::string identifier = dev.has_key("addr") ? "addr" + : "resource"; + + err_msg += str(boost::format(" * %s (%s=%s)\n") + % dev.get("product", "X3XX") + % identifier + % dev.get(identifier)); + } + + err_msg += "\nSpecify one of these devices with the given args to load an image onto it."; + + throw uhd::runtime_error(err_msg); + } + session.found = true; session.dev_addr = devs[0]; session.ethernet = session.dev_addr.has_key("addr"); if(session.ethernet){ diff --git a/host/lib/usrp_clock/octoclock/octoclock_image_loader.cpp b/host/lib/usrp_clock/octoclock/octoclock_image_loader.cpp index c88177f0f..e8c50e029 100644 --- a/host/lib/usrp_clock/octoclock/octoclock_image_loader.cpp +++ b/host/lib/usrp_clock/octoclock/octoclock_image_loader.cpp @@ -51,7 +51,7 @@ using namespace uhd::transport; * OctoClock burn session */ typedef struct { - bool valid; + bool found; uhd::device_addr_t dev_addr; std::string given_filepath; std::string actual_filepath; // If using a .hex, this is the converted .bin @@ -113,18 +113,43 @@ static void octoclock_validate_firmware_image(octoclock_session_t &session){ : (session.size / OCTOCLOCK_BLOCK_SIZE); octoclock_calculate_crc(session); - session.valid = true; } static void octoclock_setup_session(octoclock_session_t &session, + const uhd::device_addr_t &args, const std::string &filepath){ + // See if we can find an OctoClock with the given args + device_addrs_t devs = octoclock_find(args); + if(devs.size() == 0){ + session.found = false; + return; + } + else if(devs.size() > 1){ + std::string err_msg = "Could not resolve given args to a single OctoClock device.\n" + "Applicable devices:\n"; + + BOOST_FOREACH(const uhd::device_addr_t &dev, devs){ + std::string name = (dev["type"] == "octoclock") ? str(boost::format("OctoClock r%d") + % dev.get("revision","4")) + : "OctoClock Bootloader"; + err_msg += str(boost::format(" * %s (addr=%s)\n") + % name + % dev.get("addr")); + } + + err_msg += "\nSpecify one of these devices with the given args to load an image onto it."; + + throw uhd::runtime_error(err_msg); + } + + session.dev_addr = devs[0]; + // If no filepath is given, use the default if(filepath == ""){ - session.given_filepath = find_image_path(str(boost::format("octoclock_r%d_fw.hex") - % boost::lexical_cast( - session.dev_addr.get("revision","4") - ))); + session.given_filepath = find_image_path(str(boost::format("octoclock_r%s_fw.hex") + % session.dev_addr.get("revision","4") + )); } else session.given_filepath = filepath; @@ -287,7 +312,7 @@ static void octoclock_verify(octoclock_session_t &session){ } static void octoclock_finalize(octoclock_session_t &session){ - + octoclock_packet_t pkt_out; pkt_out.sequence = htonx(std::rand()); const octoclock_packet_t* pkt_in = reinterpret_cast(session.data_in); @@ -305,15 +330,12 @@ static void octoclock_finalize(octoclock_session_t &session){ } bool octoclock_image_loader(const image_loader::image_loader_args_t &image_loader_args){ - // See if we can find an OctoClock with the given args - device_addrs_t devs = octoclock_find(image_loader_args.args); - if(devs.size() == 0 or !image_loader_args.load_firmware) return false; - octoclock_session_t session; - session.dev_addr = devs[0]; octoclock_setup_session(session, + image_loader_args.args, image_loader_args.firmware_path ); + if(!session.found or !image_loader_args.load_firmware) return false; std::cout << boost::format("Unit: OctoClock (%s)") % session.dev_addr["addr"] @@ -329,7 +351,7 @@ bool octoclock_image_loader(const image_loader::image_loader_args_t &image_loade UHD_STATIC_BLOCK(register_octoclock_image_loader){ std::string recovery_instructions = "Aborting. Your OctoClock firmware is now corrupt. The bootloader\n" - "is functional, but the device will not have functional clock distribution." + "is functional, but the device will not have functional clock distribution.\n" "Run this utility again to restore functionality or refer to:\n\n" "http://files.ettus.com/manual/page_octoclock.html\n\n" "for alternative setups."; diff --git a/host/utils/uhd_image_loader.cpp b/host/utils/uhd_image_loader.cpp index 39efc8f1e..5ea789ee2 100644 --- a/host/utils/uhd_image_loader.cpp +++ b/host/utils/uhd_image_loader.cpp @@ -91,6 +91,11 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ image_loader_args.firmware_path = vm["fw-path"].as(); image_loader_args.fpga_path = vm["fpga-path"].as(); + // Force user to specify a device + if(not image_loader_args.args.has_key("type")){ + throw uhd::runtime_error("You must specify a device type."); + } + // Clean up paths, if given if(image_loader_args.firmware_path != ""){ #ifndef UHD_PLATFORM_WIN32 -- cgit v1.2.3 From 377850c9699331a24650a8bc41142627f3ab4330 Mon Sep 17 00:00:00 2001 From: Nicholas Corgan Date: Mon, 10 Aug 2015 10:25:15 -0700 Subject: e300: added -DE300_FORCE_NETWORK flag to CMake configuration * Fixes building E300 support in native mode on any Linux system with libudev headers * Added E300_NATIVE check to e300_common.cpp * Improved network mode documentation --- host/docs/usrp_e3x0.dox | 16 +++++++++++++++- host/lib/usrp/e300/CMakeLists.txt | 4 ++-- host/lib/usrp/e300/e300_common.cpp | 16 ++++++++++++++++ host/utils/CMakeLists.txt | 4 ++-- 4 files changed, 35 insertions(+), 5 deletions(-) (limited to 'host/utils') diff --git a/host/docs/usrp_e3x0.dox b/host/docs/usrp_e3x0.dox index f34aef229..e6a574a51 100644 --- a/host/docs/usrp_e3x0.dox +++ b/host/docs/usrp_e3x0.dox @@ -134,6 +134,8 @@ which should return 'arm-oe-linux-gnueabi'. $ cmake -DCMAKE_TOOLCHAIN_FILE=/host/cmake/Toolchains/oe-sdk_cross.cmake -DCMAKE_INSTALL_PREFIX=/usr -DENABLE_E300=ON .. $ make +For instructions on building UHD on a PC to interact with your E-Series device, follow these instructions: \ref e3x0_uhd_build + \subsubsection e3x0_sdk_usage_gnuradio Building GNU Radio -# Obtain the gnuradio source code via git. @@ -699,10 +701,22 @@ they can be queried through the API. \subsection e3x0_network_mode Network Mode -Your USRP-E series device can be used in network mode for narrow band signal observation, evaluation and debugging purposes. +Your USRP-E series device can be used in network mode for narrow band signal observation, evaluation and debugging purposes. See the instructions below for how to use network mode. Please note that when compared with normal operation as a standalone device the usable bandwidth is limited and therefore Network Mode is not the recommended mode of operation. +\subsubsection e3x0_uhd_build Building UHD + +To work with your E-Series device in network mode, you will need to build UHD on your PC with extra CMake flags. Assuming you are in the host/build directory, +see below: + + $ cmake -DENABLE_E300=ON -DE300_FORCE_NETWORK=ON .. + $ make + +Once UHD is installed on your device, it will be able to interact with an E-Series device with network mode active (see below). + +\subsubsection e3x0_activating_network Activating Network Mode on the Device + In order to use the device in network mode it is necessary to start the *usrp_e3x0_network_mode* executable on the device. In order to start the executable please log into your device either via SSH or serial console(see \ref e3x0_first_boot) and type diff --git a/host/lib/usrp/e300/CMakeLists.txt b/host/lib/usrp/e300/CMakeLists.txt index 26e34294a..ae817c620 100644 --- a/host/lib/usrp/e300/CMakeLists.txt +++ b/host/lib/usrp/e300/CMakeLists.txt @@ -42,14 +42,14 @@ IF(ENABLE_E300) ${CMAKE_CURRENT_SOURCE_DIR}/e300_remote_codec_ctrl.cpp ) LIBUHD_APPEND_SOURCES(${E300_SOURCES}) - IF(UDEV_FOUND) + IF(UDEV_FOUND AND NOT E300_FORCE_NETWORK) INCLUDE_DIRECTORIES(${UDEV_INCLUDE_DIR}) LIBUHD_APPEND_LIBS(${UDEV_LIBS}) SET_SOURCE_FILES_PROPERTIES( ${E300_SOURCES} PROPERTIES COMPILE_DEFINITIONS "E300_NATIVE=1" ) - ENDIF(UDEV_FOUND) + ENDIF(UDEV_FOUND AND NOT E300_FORCE_NETWORK) IF(ENABLE_GPSD) SET_SOURCE_FILES_PROPERTIES( diff --git a/host/lib/usrp/e300/e300_common.cpp b/host/lib/usrp/e300/e300_common.cpp index 29117e21f..216713bc6 100644 --- a/host/lib/usrp/e300/e300_common.cpp +++ b/host/lib/usrp/e300/e300_common.cpp @@ -29,6 +29,7 @@ #include #include +#ifdef E300_NATIVE namespace uhd { namespace usrp { namespace e300 { namespace common { @@ -90,3 +91,18 @@ UHD_STATIC_BLOCK(register_e300_image_loader) { } }}} + +#else +namespace uhd { namespace usrp { namespace e300 { + +namespace common { + +void load_fpga_image(const std::string&) +{ + throw uhd::assertion_error("load_fpga_image() !E300_NATIVE"); +} + +} + +}}} +#endif diff --git a/host/utils/CMakeLists.txt b/host/utils/CMakeLists.txt index 530bcf087..06bee48cd 100644 --- a/host/utils/CMakeLists.txt +++ b/host/utils/CMakeLists.txt @@ -34,11 +34,11 @@ SET(x3xx_burner_sources ) find_package(UDev) -IF(ENABLE_E300) +IF(ENABLE_E300 AND NOT E300_FORCE_NETWORK) IF(UDEV_FOUND) LIST(APPEND util_runtime_sources usrp_e3x0_network_mode.cpp) ENDIF(UDEV_FOUND) -ENDIF(ENABLE_E300) +ENDIF(ENABLE_E300 AND NOT E300_FORCE_NETWORK) #for each source: build an executable and install FOREACH(util_source ${util_runtime_sources}) -- cgit v1.2.3