summaryrefslogtreecommitdiffstats
path: root/host/utils
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2011-04-19 17:47:36 -0700
committerJosh Blum <josh@joshknows.com>2011-04-19 17:47:36 -0700
commitfdee3ba82b997c709e6822aa000df8adb61c56a5 (patch)
treeed566f55ef024fd2a45d053a719010e1b2c49366 /host/utils
parentee424d797fc37a8c3c2a82a58218bf1e85456226 (diff)
parent290bb75de236cb53c54bb4599cc2dde924f9800e (diff)
downloaduhd-fdee3ba82b997c709e6822aa000df8adb61c56a5.tar.gz
uhd-fdee3ba82b997c709e6822aa000df8adb61c56a5.tar.bz2
uhd-fdee3ba82b997c709e6822aa000df8adb61c56a5.zip
Merge branch 'master' into next
Conflicts: fpga/usrp2/top/u2plus/Makefile.N200
Diffstat (limited to 'host/utils')
-rw-r--r--host/utils/CMakeLists.txt6
-rwxr-xr-xhost/utils/usrp2_card_burner.py44
-rwxr-xr-xhost/utils/usrp2_card_burner_gui.py87
-rwxr-xr-xhost/utils/usrp2_recovery.py12
-rwxr-xr-xhost/utils/usrp_n2xx_net_burner.py151
-rwxr-xr-xhost/utils/usrp_n2xx_net_burner_gui.py196
6 files changed, 351 insertions, 145 deletions
diff --git a/host/utils/CMakeLists.txt b/host/utils/CMakeLists.txt
index 53527c03d..98b5d41fb 100644
--- a/host/utils/CMakeLists.txt
+++ b/host/utils/CMakeLists.txt
@@ -28,7 +28,7 @@ FOREACH(util_source ${util_runtime_sources})
GET_FILENAME_COMPONENT(util_name ${util_source} NAME_WE)
ADD_EXECUTABLE(${util_name} ${util_source})
TARGET_LINK_LIBRARIES(${util_name} uhd)
- INSTALL(TARGETS ${util_name} RUNTIME DESTINATION ${RUNTIME_DIR})
+ INSTALL(TARGETS ${util_name} RUNTIME DESTINATION ${RUNTIME_DIR} COMPONENT utilities)
ENDFOREACH(util_source)
########################################################################
@@ -50,7 +50,7 @@ FOREACH(util_source ${util_share_sources})
GET_FILENAME_COMPONENT(util_name ${util_source} NAME_WE)
ADD_EXECUTABLE(${util_name} ${util_source})
TARGET_LINK_LIBRARIES(${util_name} uhd)
- INSTALL(TARGETS ${util_name} RUNTIME DESTINATION ${PKG_DATA_DIR}/utils)
+ INSTALL(TARGETS ${util_name} RUNTIME DESTINATION ${PKG_DATA_DIR}/utils COMPONENT utilities)
ENDFOREACH(util_source)
IF(ENABLE_USRP2)
@@ -59,6 +59,8 @@ IF(ENABLE_USRP2)
usrp2_card_burner.py
usrp2_card_burner_gui.py
usrp_n2xx_net_burner.py
+ usrp_n2xx_net_burner_gui.py
DESTINATION ${PKG_DATA_DIR}/utils
+ COMPONENT utilities
)
ENDIF(ENABLE_USRP2)
diff --git a/host/utils/usrp2_card_burner.py b/host/utils/usrp2_card_burner.py
index 1db5e59ce..741c7e3e1 100755
--- a/host/utils/usrp2_card_burner.py
+++ b/host/utils/usrp2_card_burner.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2010 Ettus Research LLC
+# Copyright 2010-2011 Ettus Research LLC
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -19,7 +19,11 @@
import platform
import tempfile
import subprocess
-import urllib
+try:
+ import urllib.request
+except ImportError:
+ import urllib
+ urllib.request = urllib
import optparse
import math
import os
@@ -46,16 +50,16 @@ def command(*args):
stderr=subprocess.STDOUT,
)
ret = p.wait()
- verbose = p.stdout.read()
- if ret != 0: raise Exception, verbose
+ verbose = p.stdout.read().decode('ascii')
+ if ret != 0: raise Exception(verbose)
return verbose
def get_dd_path():
if platform.system() == 'Windows':
dd_path = os.path.join(tempfile.gettempdir(), 'dd.exe')
if not os.path.exists(dd_path):
- print 'Downloading dd.exe to %s'%dd_path
- dd_bin = urllib.urlopen('http://www.ettus.com/downloads/dd.exe').read()
+ print('Downloading dd.exe to %s'%dd_path)
+ dd_bin = urllib.request.urlopen('http://www.ettus.com/downloads/dd.exe').read()
open(dd_path, 'wb').write(dd_bin)
return dd_path
return 'dd'
@@ -97,14 +101,14 @@ def get_raw_device_hints():
if key in info: return extract_info_value(info, key)
return info.splitlines()[0].strip()
- return sorted(set(map(extract_info_name, filter(is_info_valid, get_info_list(command(get_dd_path(), '--list'))))))
+ return sorted(set(map(extract_info_name, list(filter(is_info_valid, get_info_list(command(get_dd_path(), '--list')))))))
####################################################################
# Platform Linux: parse procfs /proc/partitions
####################################################################
if platform.system() == 'Linux':
devs = list()
- try: output = open('/proc/partitions', 'r').read()
+ try: output = open('/proc/partitions', 'r').read().decode('ascii')
except: return devs
for line in output.splitlines():
try:
@@ -120,15 +124,15 @@ def get_raw_device_hints():
# Platform Mac OS X: parse diskutil list and info commands
####################################################################
if platform.system() == 'Darwin':
- devs = map(lambda d: d.split()[0], filter(lambda l: l.startswith('/dev'), command('diskutil', 'list').splitlines()))
+ devs = [d.split()[0] for d in [l for l in command('diskutil', 'list').splitlines() if l.startswith('/dev')]]
def output_to_info(output):
- return dict([map(str.strip, pair.lower().split(':')) for pair in filter(lambda l: ':' in l, output.splitlines())])
+ return dict([list(map(str.strip, pair.lower().split(':'))) for pair in [l for l in output.splitlines() if ':' in l]])
def is_dev_valid(dev):
info = output_to_info(command('diskutil', 'info', dev))
try:
- if info.has_key('internal'): assert info['internal'] == 'no'
- if info.has_key('ejectable'): assert info['ejectable'] == 'yes'
- if info.has_key('total size'):
+ if 'internal' in info: assert info['internal'] == 'no'
+ if 'ejectable' in info: assert info['ejectable'] == 'yes'
+ if 'total size' in info:
size_match = re.match('^.*\((\d+)\s*bytes\).*$', info['total size'])
if size_match: assert int(size_match.groups()[0]) <= MAX_SD_CARD_SIZE
return True
@@ -175,8 +179,8 @@ def write_image(image_file, device_file, offset):
img_data = open(image_file, 'rb').read()
count = int_ceil_div(len(img_data), SECTOR_SIZE)
pad_len = SECTOR_SIZE*count - len(img_data)
- pad_str = ''.join([chr(0)]*pad_len) #zero-padding
- open(tmp_file, 'wb').write(img_data + pad_str)
+ padding = bytes(b'\x00')*pad_len #zero-padding
+ open(tmp_file, 'wb').write(img_data + padding)
#execute a dd subprocess
verbose = command(
@@ -196,7 +200,7 @@ def write_image(image_file, device_file, offset):
def write_and_verify(image_file, device_file, offset):
if os.path.getsize(image_file) > MAX_FILE_SIZE:
- raise Exception, 'Image file larger than %d bytes!'%MAX_FILE_SIZE
+ raise Exception('Image file larger than %d bytes!'%MAX_FILE_SIZE)
return '%s\n%s'%(
write_image(
image_file=image_file,
@@ -231,8 +235,8 @@ def get_options():
(options, args) = parser.parse_args()
if options.list:
- print 'Possible raw devices:'
- print ' ' + '\n '.join(get_raw_device_hints())
+ print('Possible raw devices:')
+ print(' ' + '\n '.join(get_raw_device_hints()))
exit()
return options
@@ -242,5 +246,5 @@ def get_options():
########################################################################
if __name__=='__main__':
options = get_options()
- if not options.dev: raise Exception, 'no raw device path specified'
- print burn_sd_card(dev=options.dev, fw=options.fw, fpga=options.fpga)
+ if not options.dev: raise Exception('no raw device path specified')
+ print(burn_sd_card(dev=options.dev, fw=options.fw, fpga=options.fpga))
diff --git a/host/utils/usrp2_card_burner_gui.py b/host/utils/usrp2_card_burner_gui.py
index 58b7a514a..2941629b9 100755
--- a/host/utils/usrp2_card_burner_gui.py
+++ b/host/utils/usrp2_card_burner_gui.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2010 Ettus Research LLC
+# Copyright 2010-2011 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
@@ -17,10 +17,17 @@
#
import usrp2_card_burner #import implementation
-import Tkinter, tkFileDialog, tkFont, tkMessageBox
+try:
+ import tkinter, tkinter.filedialog, tkinter.font, tkinter.messagebox
+except ImportError:
+ import tkFileDialog, tkFont, tkMessageBox
+ import Tkinter as tkinter
+ tkinter.filedialog = tkFileDialog
+ tkinter.font = tkFont
+ tkinter.messagebox = tkMessageBox
import os
-class BinFileEntry(Tkinter.Frame):
+class BinFileEntry(tkinter.Frame):
"""
Simple file entry widget for getting the file path of bin files.
Combines a label, entry, and button with file dialog callback.
@@ -28,15 +35,15 @@ class BinFileEntry(Tkinter.Frame):
def __init__(self, root, what, def_path=''):
self._what = what
- Tkinter.Frame.__init__(self, root)
- Tkinter.Label(self, text=what+":").pack(side=Tkinter.LEFT)
- self._entry = Tkinter.Entry(self, width=50)
- self._entry.insert(Tkinter.END, def_path)
- self._entry.pack(side=Tkinter.LEFT)
- Tkinter.Button(self, text="...", command=self._button_cb).pack(side=Tkinter.LEFT)
+ tkinter.Frame.__init__(self, root)
+ tkinter.Label(self, text=what+":").pack(side=tkinter.LEFT)
+ self._entry = tkinter.Entry(self, width=50)
+ self._entry.insert(tkinter.END, def_path)
+ self._entry.pack(side=tkinter.LEFT)
+ tkinter.Button(self, text="...", command=self._button_cb).pack(side=tkinter.LEFT)
def _button_cb(self):
- filename = tkFileDialog.askopenfilename(
+ filename = tkinter.filedialog.askopenfilename(
parent=self,
filetypes=[('bin files', '*.bin'), ('all files', '*.*')],
title="Select bin file for %s"%self._what,
@@ -45,65 +52,65 @@ class BinFileEntry(Tkinter.Frame):
# open file on your own
if filename:
- self._entry.delete(0, Tkinter.END)
+ self._entry.delete(0, tkinter.END)
self._entry.insert(0, filename)
def get_filename(self):
return self._entry.get()
-class DeviceEntryWidget(Tkinter.Frame):
+class DeviceEntryWidget(tkinter.Frame):
"""
Simple entry widget for getting the raw device name.
Combines a label, entry, and helpful text box with hints.
"""
def __init__(self, root, text=''):
- Tkinter.Frame.__init__(self, root)
+ tkinter.Frame.__init__(self, root)
- Tkinter.Button(self, text="Rescan for Devices", command=self._reload_cb).pack()
+ tkinter.Button(self, text="Rescan for Devices", command=self._reload_cb).pack()
- self._hints = Tkinter.Listbox(self)
+ self._hints = tkinter.Listbox(self)
self._hints.bind("<<ListboxSelect>>", self._listbox_cb)
self._reload_cb()
- self._hints.pack(expand=Tkinter.YES, fill=Tkinter.X)
+ self._hints.pack(expand=tkinter.YES, fill=tkinter.X)
- frame = Tkinter.Frame(self)
+ frame = tkinter.Frame(self)
frame.pack()
- Tkinter.Label(frame, text="Raw Device:").pack(side=Tkinter.LEFT)
- self._entry = Tkinter.Entry(frame, width=50)
- self._entry.insert(Tkinter.END, text)
- self._entry.pack(side=Tkinter.LEFT)
+ tkinter.Label(frame, text="Raw Device:").pack(side=tkinter.LEFT)
+ self._entry = tkinter.Entry(frame, width=50)
+ self._entry.insert(tkinter.END, text)
+ self._entry.pack(side=tkinter.LEFT)
def _reload_cb(self):
- self._hints.delete(0, Tkinter.END)
+ self._hints.delete(0, tkinter.END)
for hint in usrp2_card_burner.get_raw_device_hints():
- self._hints.insert(Tkinter.END, hint)
+ self._hints.insert(tkinter.END, hint)
def _listbox_cb(self, event):
try:
sel = self._hints.get(self._hints.curselection()[0])
- self._entry.delete(0, Tkinter.END)
+ self._entry.delete(0, tkinter.END)
self._entry.insert(0, sel)
- except Exception, e: print e
+ except Exception as e: print(e)
def get_devname(self):
return self._entry.get()
-class SectionLabel(Tkinter.Label):
+class SectionLabel(tkinter.Label):
"""
Make a text label with bold font.
"""
def __init__(self, root, text):
- Tkinter.Label.__init__(self, root, text=text)
+ tkinter.Label.__init__(self, root, text=text)
#set the font bold
- f = tkFont.Font(font=self['font'])
+ f = tkinter.font.Font(font=self['font'])
f['weight'] = 'bold'
self['font'] = f.name
-class USRP2CardBurnerApp(Tkinter.Frame):
+class USRP2CardBurnerApp(tkinter.Frame):
"""
The top level gui application for the usrp2 sd card burner.
Creates entry widgets and button with callback to write images.
@@ -111,7 +118,7 @@ class USRP2CardBurnerApp(Tkinter.Frame):
def __init__(self, root, dev, fw, fpga):
- Tkinter.Frame.__init__(self, root)
+ tkinter.Frame.__init__(self, root)
#pack the file entry widgets
SectionLabel(self, text="Select Images").pack(pady=5)
@@ -127,8 +134,8 @@ class USRP2CardBurnerApp(Tkinter.Frame):
#the do it button
SectionLabel(self, text="").pack(pady=5)
- Tkinter.Label(self, text="Warning! This tool can overwrite your hard drive. Use with caution.").pack()
- Tkinter.Button(self, text="Burn SD Card", command=self._burn).pack()
+ tkinter.Label(self, text="Warning! This tool can overwrite your hard drive. Use with caution.").pack()
+ tkinter.Button(self, text="Burn SD Card", command=self._burn).pack()
def _burn(self):
#grab strings from the gui
@@ -138,31 +145,31 @@ class USRP2CardBurnerApp(Tkinter.Frame):
#check input
if not dev:
- tkMessageBox.showerror('Error:', 'No device specified!')
+ tkinter.messagebox.showerror('Error:', 'No device specified!')
return
if not fw and not fpga:
- tkMessageBox.showerror('Error:', 'No images specified!')
+ tkinter.messagebox.showerror('Error:', 'No images specified!')
return
if fw and not os.path.exists(fw):
- tkMessageBox.showerror('Error:', 'Firmware image not found!')
+ tkinter.messagebox.showerror('Error:', 'Firmware image not found!')
return
if fpga and not os.path.exists(fpga):
- tkMessageBox.showerror('Error:', 'FPGA image not found!')
+ tkinter.messagebox.showerror('Error:', 'FPGA image not found!')
return
#burn the sd card
try:
verbose = usrp2_card_burner.burn_sd_card(dev=dev, fw=fw, fpga=fpga)
- tkMessageBox.showinfo('Verbose:', verbose)
- except Exception, e:
- tkMessageBox.showerror('Verbose:', 'Error: %s'%str(e))
+ tkinter.messagebox.showinfo('Verbose:', verbose)
+ except Exception as e:
+ tkinter.messagebox.showerror('Verbose:', 'Error: %s'%str(e))
########################################################################
# main
########################################################################
if __name__=='__main__':
options = usrp2_card_burner.get_options()
- root = Tkinter.Tk()
+ root = tkinter.Tk()
root.title('USRP2 SD Card Burner')
USRP2CardBurnerApp(root, dev=options.dev, fw=options.fw, fpga=options.fpga).pack()
root.mainloop()
diff --git a/host/utils/usrp2_recovery.py b/host/utils/usrp2_recovery.py
index 5654e93d3..c7578d3a0 100755
--- a/host/utils/usrp2_recovery.py
+++ b/host/utils/usrp2_recovery.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2010 Ettus Research LLC
+# Copyright 2010-2011 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
@@ -39,7 +39,7 @@ RECOVERY_ETHERTYPE = 0xbeee
IP_RECOVERY_CODE = 'addr'
def mac_addr_repr_to_binary_string(mac_addr):
- return ''.join(map(lambda x: chr(int(x, 16)), mac_addr.split(':')))
+ return ''.join([chr(int(x, 16)) for x in mac_addr.split(':')])
if __name__ == '__main__':
parser = optparse.OptionParser(usage='usage: %prog [options]\n'+__doc__)
@@ -48,12 +48,12 @@ if __name__ == '__main__':
(options, args) = parser.parse_args()
#create the raw socket
- print "Opening raw socket on interface:", options.ifc
+ print("Opening raw socket on interface:", options.ifc)
soc = socket.socket(socket.PF_PACKET, socket.SOCK_RAW)
soc.bind((options.ifc, RECOVERY_ETHERTYPE))
#create the recovery packet
- print "Loading packet with ip address:", options.new_ip
+ print("Loading packet with ip address:", options.new_ip)
packet = struct.pack(
'!6s6sH4s4s',
mac_addr_repr_to_binary_string(BCAST_MAC_ADDR),
@@ -63,6 +63,6 @@ if __name__ == '__main__':
socket.inet_aton(options.new_ip),
)
- print "Sending packet (%d bytes)"%len(packet)
+ print("Sending packet (%d bytes)"%len(packet))
soc.send(packet)
- print "Done"
+ print("Done")
diff --git a/host/utils/usrp_n2xx_net_burner.py b/host/utils/usrp_n2xx_net_burner.py
index 6fdc9df20..0b64f2008 100755
--- a/host/utils/usrp_n2xx_net_burner.py
+++ b/host/utils/usrp_n2xx_net_burner.py
@@ -92,7 +92,7 @@ def unpack_flash_info_fmt(s):
def unpack_flash_ip_fmt(s):
return struct.unpack(FLASH_IP_FMT, s) #(proto_ver, pktid, seq, ip_addr)
-def pack_flash_args_fmt(proto_ver, pktid, seq, flash_addr, length, data):
+def pack_flash_args_fmt(proto_ver, pktid, seq, flash_addr, length, data=bytes()):
return struct.pack(FLASH_ARGS_FMT, proto_ver, pktid, seq, flash_addr, length, data)
def pack_flash_info_fmt(proto_ver, pktid, seq, sector_size_bytes, memory_size_bytes):
@@ -100,69 +100,60 @@ def pack_flash_info_fmt(proto_ver, pktid, seq, sector_size_bytes, memory_size_by
def is_valid_fpga_image(fpga_image):
for i in range(0,63):
- if ord(fpga_image[i]) == 0xFF:
- continue
- if ord(fpga_image[i]) == 0xAA and ord(fpga_image[i+1]) == 0x99:
- return 1
-
- return 0
+ if fpga_image[i:i+1] == bytes(b'\xFF'): continue
+ if fpga_image[i:i+2] == bytes(b'\xAA\x99'): return True
+ return False
def is_valid_fw_image(fw_image):
- for i in range(0,4):
- if ord(fw_image[i]) != 0x0B:
- return 0;
-
- return 1
+ return fw_image[:4] == bytes(b'\x0B\x0B\x0B\x0B')
########################################################################
# Burner class, holds a socket and send/recv routines
########################################################################
class burner_socket(object):
- def __init__(self, ip):
+ def __init__(self, addr):
self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self._sock.settimeout(UDP_TIMEOUT)
- self._sock.connect((ip, UDP_FW_UPDATE_PORT))
-
- def send_and_recv(self, pkt):
- try: self._sock.send(pkt)
- except Exception, e:
- print e
- sys.exit(1)
+ self._sock.connect((addr, UDP_FW_UPDATE_PORT))
+ self.set_callbacks(lambda *a: None, lambda *a: None)
+ self.init_update() #check that the device is there
- try: recv_pkt = self._sock.recv(UDP_MAX_XFER_BYTES)
- except Exception, e:
- print e
- sys.exit(1)
+ def set_callbacks(self, progress_cb, status_cb):
+ self._progress_cb = progress_cb
+ self._status_cb = status_cb
- return recv_pkt
+ def send_and_recv(self, pkt):
+ self._sock.send(pkt)
+ return self._sock.recv(UDP_MAX_XFER_BYTES)
#just here to validate comms
def init_update(self):
- out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_OHAI_LOL, seq(), 0, 0, "")
- in_pkt = self.send_and_recv(out_pkt)
+ out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_OHAI_LOL, seq(), 0, 0)
+ try: in_pkt = self.send_and_recv(out_pkt)
+ except socket.timeout: raise Exception("No response from device")
(proto_ver, pktid, rxseq, ip_addr) = unpack_flash_ip_fmt(in_pkt)
if pktid == update_id_t.USRP2_FW_UPDATE_ID_OHAI_OMG:
- print "USRP2P found."
+ print("USRP-N2XX found.")
else:
- raise Exception, "Invalid reply received from device."
+ raise Exception("Invalid reply received from device.")
# print "Incoming:\n\tVer: %i\n\tID: %c\n\tSeq: %i\n\tIP: %i\n" % (proto_ver, chr(pktid), rxseq, ip_addr)
def get_flash_info(self):
- out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_WATS_TEH_FLASH_INFO_LOL, seq(), 0, 0, "")
+ out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_WATS_TEH_FLASH_INFO_LOL, seq(), 0, 0)
in_pkt = self.send_and_recv(out_pkt)
(proto_ver, pktid, rxseq, sector_size_bytes, memory_size_bytes) = unpack_flash_info_fmt(in_pkt)
if pktid != update_id_t.USRP2_FW_UPDATE_ID_HERES_TEH_FLASH_INFO_OMG:
- raise Exception, "Invalid reply %c from device." % (chr(pktid))
+ raise Exception("Invalid reply %c from device." % (chr(pktid)))
return (memory_size_bytes, sector_size_bytes)
def burn_fw(self, fw, fpga, reset, safe):
(flash_size, sector_size) = self.get_flash_info()
- print "Flash size: %i\nSector size: %i\n\n" % (flash_size, sector_size)
+ print("Flash size: %i\nSector size: %i\n\n" % (flash_size, sector_size))
if fpga:
if safe: image_location = SAFE_FPGA_IMAGE_LOCATION_ADDR
@@ -172,20 +163,18 @@ class burner_socket(object):
fpga_image = fpga_file.read()
if len(fpga_image) > FPGA_IMAGE_SIZE_BYTES:
- print "Error: FPGA image file too large."
- return 0
+ raise Exception("Error: FPGA image file too large.")
if not is_valid_fpga_image(fpga_image):
- print "Error: Invalid FPGA image file."
- return 0
+ raise Exception("Error: Invalid FPGA image file.")
- print "Begin FPGA write: this should take about 1 minute..."
+ print("Begin FPGA write: this should take about 1 minute...")
start_time = time.time()
self.erase_image(image_location, FPGA_IMAGE_SIZE_BYTES)
self.write_image(fpga_image, image_location)
self.verify_image(fpga_image, image_location)
- print "Time elapsed: %f seconds"%(time.time() - start_time)
- print "\n\n"
+ print("Time elapsed: %f seconds"%(time.time() - start_time))
+ print("\n\n")
if fw:
if safe: image_location = SAFE_FW_IMAGE_LOCATION_ADDR
@@ -195,88 +184,91 @@ class burner_socket(object):
fw_image = fw_file.read()
if len(fw_image) > FW_IMAGE_SIZE_BYTES:
- print "Error: Firmware image file too large."
- return 0
+ raise Exception("Error: Firmware image file too large.")
if not is_valid_fw_image(fw_image):
- print "Error: Invalid firmware image file."
- return 0
+ raise Exception("Error: Invalid firmware image file.")
- print "Begin firmware write: this should take about 1 second..."
+ print("Begin firmware write: this should take about 1 second...")
start_time = time.time()
self.erase_image(image_location, FW_IMAGE_SIZE_BYTES)
self.write_image(fw_image, image_location)
self.verify_image(fw_image, image_location)
- print "Time elapsed: %f seconds"%(time.time() - start_time)
- print "\n\n"
+ print("Time elapsed: %f seconds"%(time.time() - start_time))
+ print("\n\n")
if reset: self.reset_usrp()
def write_image(self, image, addr):
- print "Writing image"
+ print("Writing image")
+ self._status_cb("Writing")
+ writedata = image
#we split the image into smaller (256B) bits and send them down the wire
- while image:
- out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_WRITE_TEH_FLASHES_LOL, seq(), addr, FLASH_DATA_PACKET_SIZE, image[:FLASH_DATA_PACKET_SIZE])
+ while writedata:
+ out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_WRITE_TEH_FLASHES_LOL, seq(), addr, FLASH_DATA_PACKET_SIZE, writedata[:FLASH_DATA_PACKET_SIZE])
in_pkt = self.send_and_recv(out_pkt)
(proto_ver, pktid, rxseq, flash_addr, rxlength, data) = unpack_flash_args_fmt(in_pkt)
if pktid != update_id_t.USRP2_FW_UPDATE_ID_WROTE_TEH_FLASHES_OMG:
- raise Exception, "Invalid reply %c from device." % (chr(pktid))
+ raise Exception("Invalid reply %c from device." % (chr(pktid)))
- image = image[FLASH_DATA_PACKET_SIZE:]
+ writedata = writedata[FLASH_DATA_PACKET_SIZE:]
addr += FLASH_DATA_PACKET_SIZE
+ self._progress_cb(float(len(image)-len(writedata))/len(image))
def verify_image(self, image, addr):
- print "Verifying data"
+ print("Verifying data")
+ self._status_cb("Verifying")
readsize = len(image)
- readdata = str()
+ readdata = bytes()
while readsize > 0:
if readsize < FLASH_DATA_PACKET_SIZE: thisreadsize = readsize
else: thisreadsize = FLASH_DATA_PACKET_SIZE
- out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_READ_TEH_FLASHES_LOL, seq(), addr, thisreadsize, "")
+ out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_READ_TEH_FLASHES_LOL, seq(), addr, thisreadsize)
in_pkt = self.send_and_recv(out_pkt)
(proto_ver, pktid, rxseq, flash_addr, rxlength, data) = unpack_flash_args_fmt(in_pkt)
if pktid != update_id_t.USRP2_FW_UPDATE_ID_KK_READ_TEH_FLASHES_OMG:
- raise Exception, "Invalid reply %c from device." % (chr(pktid))
+ raise Exception("Invalid reply %c from device." % (chr(pktid)))
readdata += data[:thisreadsize]
readsize -= FLASH_DATA_PACKET_SIZE
addr += FLASH_DATA_PACKET_SIZE
+ self._progress_cb(float(len(readdata))/len(image))
- print "Read back %i bytes" % len(readdata)
+ print("Read back %i bytes" % len(readdata))
# print readdata
# for i in range(256, 512):
# print "out: %i in: %i" % (ord(image[i]), ord(readdata[i]))
if readdata != image:
- print "Verify failed. Image did not write correctly."
+ raise Exception("Verify failed. Image did not write correctly.")
else:
- print "Success."
+ print("Success.")
def read_image(self, image, size, addr):
- print "Reading image"
+ print("Reading image")
readsize = size
readdata = str()
while readsize > 0:
if readsize < FLASH_DATA_PACKET_SIZE: thisreadsize = readsize
else: thisreadsize = FLASH_DATA_PACKET_SIZE
- out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_READ_TEH_FLASHES_LOL, seq(), addr, thisreadsize, "")
+ out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_READ_TEH_FLASHES_LOL, seq(), addr, thisreadsize)
in_pkt = self.send_and_recv(out_pkt)
(proto_ver, pktid, rxseq, flash_addr, rxlength, data) = unpack_flash_args_fmt(in_pkt)
if pktid != update_id_t.USRP2_FW_UPDATE_ID_KK_READ_TEH_FLASHES_OMG:
- raise Exception, "Invalid reply %c from device." % (chr(pktid))
+ raise Exception("Invalid reply %c from device." % (chr(pktid)))
readdata += data[:thisreadsize]
readsize -= FLASH_DATA_PACKET_SIZE
addr += FLASH_DATA_PACKET_SIZE
- print "Read back %i bytes" % len(readdata)
+ print("Read back %i bytes" % len(readdata))
#write to disk
f = open(image, 'w')
@@ -284,35 +276,40 @@ class burner_socket(object):
f.close()
def reset_usrp(self):
- out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_RESET_MAH_COMPUTORZ_LOL, seq(), 0, 0, "")
- in_pkt = self.send_and_recv(out_pkt)
+ out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_RESET_MAH_COMPUTORZ_LOL, seq(), 0, 0)
+ try: in_pkt = self.send_and_recv(out_pkt)
+ except socket.timeout: return
(proto_ver, pktid, rxseq, flash_addr, rxlength, data) = unpack_flash_args_fmt(in_pkt)
if pktid == update_id_t.USRP2_FW_UPDATE_ID_RESETTIN_TEH_COMPUTORZ_OMG:
- raise Exception, "Device failed to reset."
+ raise Exception("Device failed to reset.")
def erase_image(self, addr, length):
+ self._status_cb("Erasing")
#get flash info first
- out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_ERASE_TEH_FLASHES_LOL, seq(), addr, length, "")
+ out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_ERASE_TEH_FLASHES_LOL, seq(), addr, length)
in_pkt = self.send_and_recv(out_pkt)
(proto_ver, pktid, rxseq, flash_addr, rxlength, data) = unpack_flash_args_fmt(in_pkt)
if pktid != update_id_t.USRP2_FW_UPDATE_ID_ERASING_TEH_FLASHES_OMG:
- raise Exception, "Invalid reply %c from device." % (chr(pktid))
+ raise Exception("Invalid reply %c from device." % (chr(pktid)))
- print "Erasing %i bytes at %i" % (length, addr)
+ print("Erasing %i bytes at %i" % (length, addr))
+ start_time = time.time()
#now wait for it to finish
while(True):
- out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_R_U_DONE_ERASING_LOL, seq(), 0, 0, "")
+ out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_R_U_DONE_ERASING_LOL, seq(), 0, 0)
in_pkt = self.send_and_recv(out_pkt)
(proto_ver, pktid, rxseq, flash_addr, rxlength, data) = unpack_flash_args_fmt(in_pkt)
if pktid == update_id_t.USRP2_FW_UPDATE_ID_IM_DONE_ERASING_OMG: break
elif pktid != update_id_t.USRP2_FW_UPDATE_ID_NOPE_NOT_DONE_ERASING_OMG:
- raise Exception, "Invalid reply %c from device." % (chr(pktid))
+ raise Exception("Invalid reply %c from device." % (chr(pktid)))
+ time.sleep(0.01) #decrease network overhead by waiting a bit before polling
+ self._progress_cb(min(1.0, (time.time() - start_time)/(length/80e3)))
########################################################################
@@ -320,7 +317,7 @@ class burner_socket(object):
########################################################################
def get_options():
parser = optparse.OptionParser()
- parser.add_option("--ip", type="string", help="USRP2P firmware address", default='')
+ parser.add_option("--addr", type="string", help="USRP-N2XX device address", default='')
parser.add_option("--fw", type="string", help="firmware image path (optional)", default='')
parser.add_option("--fpga", type="string", help="fpga image path (optional)", default='')
parser.add_option("--reset", action="store_true", help="reset the device after writing", default=False)
@@ -335,23 +332,23 @@ def get_options():
########################################################################
if __name__=='__main__':
options = get_options()
- if not options.ip: raise Exception, 'no ip address specified'
+ if not options.addr: raise Exception('no address specified')
- if not options.fpga and not options.fw and not options.reset: raise Exception, 'Must specify either a firmware image or FPGA image, and/or reset.'
+ if not options.fpga and not options.fw and not options.reset: raise Exception('Must specify either a firmware image or FPGA image, and/or reset.')
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: """)
+ response = input("""Type "yes" to continue, or anything else to quit: """)
if response != "yes": sys.exit(0)
- burner = burner_socket(ip=options.ip)
+ burner = burner_socket(addr=options.addr)
if options.read:
if options.fw:
file = options.fw
if os.path.isfile(file):
- response = raw_input("File already exists -- overwrite? (y/n) ")
+ response = input("File already exists -- overwrite? (y/n) ")
if response != "y": sys.exit(0)
size = FW_IMAGE_SIZE_BYTES
addr = SAFE_FW_IMAGE_LOCATION_ADDR if options.overwrite_safe else PROD_FW_IMAGE_LOCATION_ADDR
@@ -360,7 +357,7 @@ if __name__=='__main__':
if options.fpga:
file = options.fpga
if os.path.isfile(file):
- response = raw_input("File already exists -- overwrite? (y/n) ")
+ response = input("File already exists -- overwrite? (y/n) ")
if response != "y": sys.exit(0)
size = FPGA_IMAGE_SIZE_BYTES
addr = SAFE_FPGA_IMAGE_LOCATION_ADDR if options.overwrite_safe else PROD_FPGA_IMAGE_LOCATION_ADDR
diff --git a/host/utils/usrp_n2xx_net_burner_gui.py b/host/utils/usrp_n2xx_net_burner_gui.py
new file mode 100755
index 000000000..3b414a918
--- /dev/null
+++ b/host/utils/usrp_n2xx_net_burner_gui.py
@@ -0,0 +1,196 @@
+#!/usr/bin/env python
+#
+# Copyright 2011 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/>.
+#
+
+import usrp_n2xx_net_burner #import implementation
+try:
+ import tkinter, tkinter.filedialog, tkinter.font, tkinter.messagebox
+except ImportError:
+ import tkFileDialog, tkFont, tkMessageBox
+ import Tkinter as tkinter
+ tkinter.filedialog = tkFileDialog
+ tkinter.font = tkFont
+ tkinter.messagebox = tkMessageBox
+import os
+
+class BinFileEntry(tkinter.Frame):
+ """
+ Simple file entry widget for getting the file path of bin files.
+ Combines a label, entry, and button with file dialog callback.
+ """
+
+ def __init__(self, root, what, def_path=''):
+ self._what = what
+ tkinter.Frame.__init__(self, root)
+ tkinter.Label(self, text=what+":").pack(side=tkinter.LEFT)
+ self._entry = tkinter.Entry(self, width=50)
+ self._entry.insert(tkinter.END, def_path)
+ self._entry.pack(side=tkinter.LEFT)
+ tkinter.Button(self, text="...", command=self._button_cb).pack(side=tkinter.LEFT)
+
+ def _button_cb(self):
+ filename = tkinter.filedialog.askopenfilename(
+ parent=self,
+ filetypes=[('bin files', '*.bin'), ('all files', '*.*')],
+ title="Select bin file for %s"%self._what,
+ initialdir=os.path.dirname(self.get_filename()),
+ )
+
+ # open file on your own
+ if filename:
+ self._entry.delete(0, tkinter.END)
+ self._entry.insert(0, filename)
+
+ def get_filename(self):
+ return self._entry.get()
+
+class ProgressBar(tkinter.Canvas):
+ """
+ A simple implementation of a progress bar.
+ Draws rectangle that fills from left to right.
+ """
+
+ def __init__(self, root, width=500, height=20):
+ self._width = width
+ self._height = height
+ tkinter.Canvas.__init__(self, root, relief="sunken", borderwidth=2, width=self._width-2, height=self._height-2)
+ self._last_fill_pixels = None
+ self.set(0.0)
+
+ def set(self, frac):
+ """
+ Update the progress where fraction is between 0.0 and 1.0
+ """
+ #determine the number of pixels to draw
+ fill_pixels = int(round(self._width*frac))
+ if fill_pixels == self._last_fill_pixels: return
+ self._last_fill_pixels = fill_pixels
+
+ #draw a rectangle representing the progress
+ if frac: self.create_rectangle(0, 0, fill_pixels, self._height, fill="#357EC7")
+ else: self.create_rectangle(0, 0, self._width, self._height, fill="#E8E8E8")
+
+class SectionLabel(tkinter.Label):
+ """
+ Make a text label with bold font.
+ """
+
+ def __init__(self, root, text):
+ tkinter.Label.__init__(self, root, text=text)
+
+ #set the font bold
+ f = tkinter.font.Font(font=self['font'])
+ f['weight'] = 'bold'
+ self['font'] = f.name
+
+class USRPN2XXNetBurnerApp(tkinter.Frame):
+ """
+ The top level gui application for the usrp-n2xx network burner.
+ Creates entry widgets and button with callback to write images.
+ """
+
+ def __init__(self, root, addr, fw, fpga):
+
+ tkinter.Frame.__init__(self, root)
+
+ #pack the file entry widgets
+ SectionLabel(self, text="Select Images").pack(pady=5)
+ self._fw_img_entry = BinFileEntry(self, "Firmware Image", def_path=fw)
+ self._fw_img_entry.pack()
+ self._fpga_img_entry = BinFileEntry(self, "FPGA Image", def_path=fpga)
+ self._fpga_img_entry.pack()
+
+ #pack the destination entry widget
+ SectionLabel(self, text="Select Address").pack(pady=5)
+ self._addr_entry = tkinter.Entry(self, width=30)
+ self._addr_entry.insert(tkinter.END, addr)
+ self._addr_entry.pack()
+
+ #the do it button
+ SectionLabel(self, text="").pack(pady=5)
+ button = tkinter.Button(self, text="Burn Images", command=self._burn)
+ self._enable_input = lambda: button.configure(state=tkinter.NORMAL)
+ self._disable_input = lambda: button.configure(state=tkinter.DISABLED)
+ button.pack()
+
+ #a progress bar to monitor the status
+ progress_frame = tkinter.Frame(self)
+ progress_frame.pack()
+ self._status = tkinter.StringVar()
+ tkinter.Label(progress_frame, textvariable=self._status).pack(side=tkinter.LEFT)
+ self._pbar = ProgressBar(progress_frame)
+ self._pbar.pack(side=tkinter.RIGHT, expand=True)
+
+ def _burn(self):
+ self._disable_input()
+
+ #grab strings from the gui
+ fw = self._fw_img_entry.get_filename()
+ fpga = self._fpga_img_entry.get_filename()
+ addr = self._addr_entry.get()
+
+ #check input
+ if not addr:
+ tkinter.messagebox.showerror('Error:', 'No address specified!')
+ return
+ if not fw and not fpga:
+ tkinter.messagebox.showerror('Error:', 'No images specified!')
+ return
+ if fw and not os.path.exists(fw):
+ tkinter.messagebox.showerror('Error:', 'Firmware image not found!')
+ return
+ if fpga and not os.path.exists(fpga):
+ tkinter.messagebox.showerror('Error:', 'FPGA image not found!')
+ return
+
+ try:
+ #make a new burner object and attempt the burner operation
+ burner = usrp_n2xx_net_burner.burner_socket(addr=addr)
+
+ for (image_type, fw_img, fpga_img) in (('FPGA', '', fpga), ('Firmware', fw, '')):
+ #setup callbacks that update the gui
+ def status_cb(status):
+ self._pbar.set(0.0) #status change, reset the progress
+ self._status.set("%s %s "%(status.title(), image_type))
+ self.update()
+ def progress_cb(progress):
+ self._pbar.set(progress)
+ self.update()
+ burner.set_callbacks(progress_cb=progress_cb, status_cb=status_cb)
+ burner.burn_fw(fw=fw_img, fpga=fpga_img, reset=False, safe=False)
+
+ if tkinter.messagebox.askyesno("Burn was successful!", "Reset the device?"):
+ burner.reset_usrp()
+
+ except Exception as e:
+ tkinter.messagebox.showerror('Verbose:', 'Error: %s'%str(e))
+
+ #reset the progress bar
+ self._pbar.set(0.0)
+ self._status.set("")
+ self._enable_input()
+
+########################################################################
+# main
+########################################################################
+if __name__=='__main__':
+ options = usrp_n2xx_net_burner.get_options()
+ root = tkinter.Tk()
+ root.title('USRP-N2XX Net Burner')
+ USRPN2XXNetBurnerApp(root, addr=options.addr, fw=options.fw, fpga=options.fpga).pack()
+ root.mainloop()
+ exit()