From 4bb1d3fc3f01eef7f380c55ca23d8689bc6d3b6b Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Fri, 3 Oct 2014 03:33:00 +0200 Subject: [PATCH] Use built-in Python DFU-util --- usr/openmv-ide.glade | 8 +++- usr/openmv-ide.py | 91 +++++++++++++++++++++++++++++++++----------- usr/openmv.py | 35 +++++------------ 3 files changed, 84 insertions(+), 50 deletions(-) diff --git a/usr/openmv-ide.glade b/usr/openmv-ide.glade index 7b8f0262d..f0002929f 100644 --- a/usr/openmv-ide.glade +++ b/usr/openmv-ide.glade @@ -55,6 +55,7 @@ False 5 Update Firmware + True center-on-parent True dialog @@ -107,12 +108,15 @@ - + + True False + True + True - True + False 1 diff --git a/usr/openmv-ide.py b/usr/openmv-ide.py index 15b350024..361616b98 100755 --- a/usr/openmv-ide.py +++ b/usr/openmv-ide.py @@ -1,28 +1,30 @@ #!/usr/bin/env python +import pydfu +import openmv import sys, os, os.path -import gtk -import gtksourceview2 as gtksourceview +from time import sleep +import gtk, gtksourceview2 as gtksourceview import gio -import pango import gobject import vte import serial -from time import sleep import usb.core import usb.util import numpy as np -import openmv from os.path import expanduser -import subprocess + UI_PATH =os.path.dirname(os.path.realpath(__file__))+"/openmv-ide.glade" CONFIG_PATH = expanduser("~")+"/.openmvide.config" EXAMPLE_PATH = os.path.dirname(os.path.realpath(__file__))+"/examples" SCRIPTS_PATH = os.path.dirname(os.path.realpath(__file__))+"/scripts" -FWBIN_PATH = "" +FWBIN_PATH = "/home/mux/src/c/stm32f4/openmv/src/build/openmv.bin" DFU_CMD = "dfu-util -d 0483:df11 -c 1 -i 0 -a 0 -s 0x08000000 -D %s" SCALE =1 +flash_offsets= [0x08000000, 0x08004000, 0x08008000, 0x0800C000, + 0x08010000, 0x08020000, 0x08040000, 0x08060000, + 0x08080000, 0x080A0000, 0x080C0000, 0x080E0000] class OMVGtk: def __init__(self): @@ -146,6 +148,11 @@ class OMVGtk: message.run() message.destroy() + def refresh_gui(self, delay=0.0001, wait=0.0001): + sleep(delay) + gtk.main_iteration_do(block=False) + sleep(wait) + def connect(self): self.terminal = self.builder.get_object('terminal') try: @@ -218,16 +225,54 @@ class OMVGtk: dialog.destroy() + # Fake multitasking :P + def fwupdate_task(self, state): + if (state["init"]): + pydfu.init() + state["init"]=False + state["erase"]=True + state["bar"].set_text("Erasing...") + return True + elif (state["erase"]): + page = state["page"] + total = len(flash_offsets) + pydfu.page_erase(flash_offsets[page]) + page +=1 + state["bar"].set_fraction(page/float(total)) + if (page == total): + state["erase"] = False + state["write"] = True + state["bar"].set_text("Uploading...") + state["page"] = page + return True + elif (state["write"]): + buf = state["buf"] + xfer_bytes = state["xfer_bytes"] + xfer_total = state["xfer_total"] + + # Send chunk + chunk = min (64, xfer_total-xfer_bytes) + pydfu.write_page(buf[xfer_bytes:xfer_bytes+chunk], xfer_bytes) + + xfer_bytes += chunk + state["xfer_bytes"] = xfer_bytes + state["bar"].set_fraction(xfer_bytes/float(xfer_total)) + + if (xfer_bytes == xfer_total): + pydfu.exit_dfu() + state["dialog"].hide() + return False + + return True + def fwupdate_clicked(self, widget): if (self.connected): dialog = self.builder.get_object("fw_dialog") fw_entry = self.builder.get_object("fw_entry") - spinner = self.builder.get_object("fw_spinner") + fw_progress = self.builder.get_object("fw_progressbar") ok_button = self.builder.get_object("fw_ok_button") cancel_button = self.builder.get_object("fw_cancel_button") - spinner.stop() - spinner.set_visible(False) ok_button.set_sensitive(True) cancel_button.set_sensitive(True) dialog.set_transient_for(self.window); @@ -238,24 +283,24 @@ class OMVGtk: if dialog.run() == gtk.RESPONSE_OK: ok_button.set_sensitive(False) cancel_button.set_sensitive(False) - spinner.set_visible(True) - spinner.start() + fw_progress.set_text("") + fw_progress.set_fraction(0.0) + + with open(fw_entry.get_text(), 'r') as f: + buf= f.read() + + state={"init":True, "erase":False, "write":False, + "page":0, "buf":buf, "bar":fw_progress, "dialog":dialog, + "xfer_bytes":0, "xfer_total":len(buf)} # call dfu-util openmv.enter_dfu() sleep(1.0) + gobject.gobject.idle_add(self.fwupdate_task, state); - dfu_util = subprocess.Popen(DFU_CMD%fw_entry.get_text(), shell=True, stdout=subprocess.PIPE) - - while dfu_util.poll() == None and gtk.events_pending(): - gtk.main_iteration() - - if (dfu_util.returncode): - self.show_message_dialog(gtk.MESSAGE_ERROR, "Failed to update firmware\n") - - openmv.exit_dfu() - - dialog.hide() +# try: +# except Exception as e: +# self.show_message_dialog(gtk.MESSAGE_ERROR, "Failed to update firmware%s"%(e)) def reset_clicked(self, widget): if (self.connected): diff --git a/usr/openmv.py b/usr/openmv.py index a514c9a6a..17ab5fd57 100755 --- a/usr/openmv.py +++ b/usr/openmv.py @@ -1,14 +1,20 @@ #!/usr/bin/env python -import sys +# This file is part of the OpenMV project. +# Copyright (c) 2013/2014 Ibrahim Abdelkader +# This work is licensed under the MIT license, see the file LICENSE for details. +# +# Openmv module. + +import struct +import sys,time import usb.core import usb.util -import struct +import pydfu import numpy as np from PIL import Image -import time -import StringIO __dev = None + # VID/PID __VID=0xf055 __PID=0x9800 @@ -59,7 +65,6 @@ def init(): __dev.set_interface_altsetting(__INTERFACE, __ALTSETTING) def release(): - global __dev try: # Release device usb.util.dispose_resources(dev) @@ -83,20 +88,16 @@ def fb_to_arr(buff, bpp): return np.column_stack((r,g,b)) def fb_size(): - global __dev # read fb header buf = __dev.ctrl_transfer(0xC1, __USBDBG_FRAME_SIZE, 0, __INTERFACE, __FB_HDR_SIZE, __TIMEOUT) size = struct.unpack("III", buf) return size def fb_lock(): - global __dev buf = __dev.ctrl_transfer(0xC1, __USBDBG_FRAME_LOCK, 0, __INTERFACE, 1, __TIMEOUT) return struct.unpack("B", buf)[0] def fb_dump(): - global __dev - if (fb_lock() == 0): return None @@ -161,22 +162,6 @@ def enter_dfu(): except: pass -#See app note AN3156 -def exit_dfu(): - timeout = 1000 - dev = usb.core.find(idVendor=0x0483, idProduct=0xdf11) - - # Claim DFU interface - usb.util.claim_interface(dev, 0) - - # Send DNLOAD with 0 length to exit DFU - dev.ctrl_transfer(0x21, 0x01, 0, 0, None, timeout) - # Execute last command - dev.ctrl_transfer(0xA1, 0x03, 0, 0, 6, timeout) - - # Release device - usb.util.dispose_resources(dev) - def reset(): try: # This will timeout.