From 60f8e10bf941c6efee0a183e047d08b3b7fc966d Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Fri, 24 Feb 2012 17:30:29 +0100 Subject: [PATCH] Reviewed IDE upload procedure for Leonardo bootloader --- app/src/processing/app/Serial.java | 13 +- .../processing/app/debug/AvrdudeUploader.java | 126 +++++++++--------- 2 files changed, 66 insertions(+), 73 deletions(-) diff --git a/app/src/processing/app/Serial.java b/app/src/processing/app/Serial.java index 54ae7d9d8..14c0933c0 100755 --- a/app/src/processing/app/Serial.java +++ b/app/src/processing/app/Serial.java @@ -117,7 +117,7 @@ public class Serial implements SerialPortEventListener { } } catch (PortInUseException e) { throw new SerialException( - I18n.format(_("Serial port ''{0}'' already in use. Try quiting any programs that may be using it."), iname) + I18n.format(_("Serial port ''{0}'' already in use. Try quitting any programs that may be using it."), iname) ); } catch (Exception e) { throw new SerialException( @@ -553,10 +553,11 @@ public class Serial implements SerialPortEventListener { * it may be because the DLL doesn't have its exec bit set. * Why the hell that'd be the case, who knows. */ - static public String[] list() { - Vector list = new Vector(); + static public List list() { + List list = new ArrayList(); try { //System.err.println("trying"); + @SuppressWarnings("unchecked") Enumeration portList = CommPortIdentifier.getPortIdentifiers(); //System.err.println("got port list"); while (portList.hasMoreElements()) { @@ -566,7 +567,7 @@ public class Serial implements SerialPortEventListener { if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) { String name = portId.getName(); - list.addElement(name); + list.add(name); } } @@ -579,9 +580,7 @@ public class Serial implements SerialPortEventListener { errorMessage("ports", e); } //System.err.println("move out"); - String outgoing[] = new String[list.size()]; - list.copyInto(outgoing); - return outgoing; + return list; } diff --git a/app/src/processing/app/debug/AvrdudeUploader.java b/app/src/processing/app/debug/AvrdudeUploader.java index e1c342c7b..6fef20f69 100755 --- a/app/src/processing/app/debug/AvrdudeUploader.java +++ b/app/src/processing/app/debug/AvrdudeUploader.java @@ -77,75 +77,69 @@ public class AvrdudeUploader extends Uploader { if (protocol.equals("stk500")) protocol = "stk500v1"; - // need to do a little dance for Leonardo and derivatives: - // open then close the port at the magic baudrate (usually 1200 bps) first to signal to the - // sketch that it should reset into bootloader. after doing this wait a moment for the - // bootloader to enumerate. On Windows, also must deal with the fact that the COM port number - // changes from bootloader to sketch. - String leonardoUploadPort = null; - if (boardPreferences.get("bootloader.path").equals("caterina_LUFA")) { - try { - long startTime = System.currentTimeMillis(); - String portsBeforeReenum[] = Serial.list(); - Serial.touchPort(Preferences.get("serial.port"), 1200); - if (Base.isWindows()) { - // Windows has a complicated relationship with CDC devices. Have to deal with - // devices being slow to disconnect, slow to connect, and the fact that COM numbers - // change from bootloader to sketch. To find the bootloader port we scan the list - // of reported ports continuously, waiting for the selected port to disappear, then - // waiting for a new port to appear. Have to have long delays between calls to - // Serial.list() on Windows otherwise rxtx causes a bluescreen error. - - // Wait for the port to disappear from the list... - long timeout = 0; - while (true == Arrays.asList(Serial.list()).contains(Preferences.get("serial.port")) && ((timeout = (System.currentTimeMillis() - startTime)) < 4000)) { - Thread.sleep(1000); - } - System.out.println("first timeout: " + timeout); - - Thread.sleep(1000); - - // ...and wait for a port, any port to appear. - while ((portsBeforeReenum.length != Serial.list().length) && ((timeout = (System.currentTimeMillis() - startTime)) < 8000)) { - Thread.sleep(1000); - } - System.out.println("second timeout: " + timeout); - - // Figure out which port is new. - String portsAfterReenum[] = Serial.list(); - for (String port : portsAfterReenum) { - if (!Arrays.asList(portsBeforeReenum).contains(port)) - leonardoUploadPort = port; - } - System.out.println("found leo: " + leonardoUploadPort); - } else { - // Reenumeration is much faster and less complicated on *nix: - // After touching the port wait for it to disappear (timeout on this operation in - // case the port is either not a Leonardo, is a Leonardo with no sketch loaded, - // or is a Leonardo that has already been manually reset). Then wait for the same - // port to reappear in the list and proceed. - - // Wait for the port to disappear from the list... - while (true == Arrays.asList(Serial.list()).contains(Preferences.get("serial.port")) && (System.currentTimeMillis() - startTime < 4000)) { - Thread.sleep(10); - } - // ...and wait for the same-named port to come back. - while (false == Arrays.asList(Serial.list()).contains(Preferences.get("serial.port")) && (System.currentTimeMillis() - startTime < 8000)) { - Thread.sleep(10); - } - } - } catch (SerialException ex) { - } catch (InterruptedException ex) { } + String uploadPort = Preferences.get("serial.port"); + + // need to do a little dance for Leonardo and derivatives: + // open then close the port at the magic baudrate (usually 1200 bps) first + // to signal to the sketch that it should reset into bootloader. after doing + // this wait a moment for the bootloader to enumerate. On Windows, also must + // deal with the fact that the COM port number changes from bootloader to + // sketch. + if (boardPreferences.get("bootloader.path").equals("caterina_LUFA")) { + String caterinaUploadPort = null; + try { + // Toggle 1200 bps on selected serial port to force board reset. + List before = Serial.list(); + if (before.contains(uploadPort)) { + if (verbose) + System.out + .println(_("Forcing reset using 1200bps open/close on port ") + + uploadPort); + Serial.touchPort(uploadPort, 1200); + } + + // Wait for a port to appear on the list + long timeout = System.currentTimeMillis() + 10000; + while (System.currentTimeMillis() < timeout) { + List now = Serial.list(); + List diff = new ArrayList(now); + diff.removeAll(before); + System.out.print("{"); + for (String p : before) + System.out.print(p+","); + System.out.print("} / {"); + for (String p : now) + System.out.print(p+","); + System.out.print("} => {"); + for (String p : diff) + System.out.print(p+","); + System.out.println("}"); + if (diff.size() > 0) { + caterinaUploadPort = diff.get(0); + System.out.println("found leo: " + caterinaUploadPort); + break; + } + + // Keep track of port that disappears + before = now; + Thread.sleep(500); + } + + if (caterinaUploadPort == null) + // Something happened while detecting port + return false; + + uploadPort = caterinaUploadPort; + } catch (SerialException ex) { + return false; + } catch (InterruptedException ex) { + return false; + } } commandDownloader.add("-c" + protocol); - if (null == leonardoUploadPort) { - commandDownloader.add( - "-P" + (Base.isWindows() ? "\\\\.\\" : "") + Preferences.get("serial.port")); - } else { - commandDownloader.add( - "-P" + (Base.isWindows() ? "\\\\.\\" : "") + leonardoUploadPort); - } + commandDownloader.add("-P" + (Base.isWindows() ? "\\\\.\\" : "") + + uploadPort); commandDownloader.add( "-b" + Integer.parseInt(boardPreferences.get("upload.speed"))); commandDownloader.add("-D"); // don't erase