diff --git a/app/src/cc/arduino/packages/Uploader.java b/app/src/cc/arduino/packages/Uploader.java index e8e38edfe..012a18418 100644 --- a/app/src/cc/arduino/packages/Uploader.java +++ b/app/src/cc/arduino/packages/Uploader.java @@ -102,8 +102,8 @@ public abstract class Uploader implements MessageConsumer { System.out.println(); } Process process = ProcessUtils.exec(command); - new MessageSiphon(process.getInputStream(), this); - new MessageSiphon(process.getErrorStream(), this); + new MessageSiphon(process.getInputStream(), this, 100); + new MessageSiphon(process.getErrorStream(), this, 100); // wait for the process to finish. result = process.waitFor(); diff --git a/app/src/processing/app/debug/MessageSiphon.java b/app/src/processing/app/debug/MessageSiphon.java index 26901c3f4..c9abf0ea7 100644 --- a/app/src/processing/app/debug/MessageSiphon.java +++ b/app/src/processing/app/debug/MessageSiphon.java @@ -23,9 +23,9 @@ package processing.app.debug; -import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.Reader; import java.net.SocketException; /** @@ -33,16 +33,25 @@ import java.net.SocketException; */ public class MessageSiphon implements Runnable { - private final BufferedReader streamReader; + private final Reader streamReader; private final MessageConsumer consumer; private Thread thread; private boolean canRun; + // Data is processed line-by-line if possible, but if this is non-zero + // then a partial line is also processed if no line end is received + // within this many milliseconds. + private int lineTimeout; public MessageSiphon(InputStream stream, MessageConsumer consumer) { - this.streamReader = new BufferedReader(new InputStreamReader(stream)); + this(stream, consumer, 0); + } + + public MessageSiphon(InputStream stream, MessageConsumer consumer, int lineTimeout) { + this.streamReader = new InputStreamReader(stream); this.consumer = consumer; this.canRun = true; + this.lineTimeout = lineTimeout; thread = new Thread(this); // don't set priority too low, otherwise exceptions won't @@ -59,12 +68,46 @@ public class MessageSiphon implements Runnable { // (effectively sleeping the thread) until new data comes in. // when the program is finally done, null will come through. // - String currentLine; - while (canRun && (currentLine = streamReader.readLine()) != null) { - // \n is added again because readLine() strips it out - //EditorConsole.systemOut.println("messaging in"); - consumer.message(currentLine + "\n"); - //EditorConsole.systemOut.println("messaging out"); + StringBuilder currentLine = new StringBuilder(); + long lineStartTime = 0; + while (canRun) { + // First, try to read as many characters as possible. Take care + // not to block when: + // 1. lineTimeout is nonzero, and + // 2. we have some characters buffered already + while (lineTimeout == 0 || currentLine.length() == 0 || streamReader.ready()) { + int c = streamReader.read(); + if (c == -1) + return; // EOF + if (!canRun) + return; + + // Keep track of the line start time + if (currentLine.length() == 0) + lineStartTime = System.nanoTime(); + + // Store the character line + currentLine.append((char)c); + + if (c == '\n') { + // We read a full line, pass it on + consumer.message(currentLine.toString()); + currentLine.setLength(0); + } + } + + // No more characters available. Wait until lineTimeout + // milliseconds have passed since the start of the line and then + // try reading again. If the time has already passed, then just + // pass on the characters read so far. + long passed = (System.nanoTime() - lineStartTime) / 1000; + if (passed < this.lineTimeout) { + Thread.sleep(this.lineTimeout - passed); + continue; + } + + consumer.message(currentLine.toString()); + currentLine.setLength(0); } //EditorConsole.systemOut.println("messaging thread done"); } catch (NullPointerException npe) { diff --git a/build/shared/revisions.txt b/build/shared/revisions.txt index b4b8ed5ac..f44ee3456 100644 --- a/build/shared/revisions.txt +++ b/build/shared/revisions.txt @@ -5,6 +5,7 @@ ARDUINO 1.5.9 * Sketch build process: fixed full rebuild on windows even if not needed * Sketch build process: core.a rebuild only if needed (Matthijs Kooijman) * Updated AStyle formatter to v2.04: http://astyle.sourceforge.net/notes.html +* Improved avrdude verbose upload (Matthijs Kooijman) [core] * sam: added -MMD flag to let gcc produce dependency files (full rebuild on Arduino Due is now triggered only if needed) diff --git a/hardware/arduino/avr/platform.txt b/hardware/arduino/avr/platform.txt index 9a2565fe6..95c2d3c8a 100644 --- a/hardware/arduino/avr/platform.txt +++ b/hardware/arduino/avr/platform.txt @@ -80,19 +80,19 @@ recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).* tools.avrdude.cmd.path={runtime.ide.path}/hardware/tools/avr/bin/avrdude tools.avrdude.config.path={runtime.ide.path}/hardware/tools/avr/etc/avrdude.conf -tools.avrdude.upload.params.verbose=-v -v -v -v +tools.avrdude.upload.params.verbose=-v tools.avrdude.upload.params.quiet=-q -q tools.avrdude.upload.pattern="{cmd.path}" "-C{config.path}" {upload.verbose} -p{build.mcu} -c{upload.protocol} -P{serial.port} -b{upload.speed} -D "-Uflash:w:{build.path}/{build.project_name}.hex:i" -tools.avrdude.program.params.verbose=-v -v -v -v +tools.avrdude.program.params.verbose=-v tools.avrdude.program.params.quiet=-q -q tools.avrdude.program.pattern="{cmd.path}" "-C{config.path}" {program.verbose} -p{build.mcu} -c{protocol} {program.extra_params} "-Uflash:w:{build.path}/{build.project_name}.hex:i" -tools.avrdude.erase.params.verbose=-v -v -v -v +tools.avrdude.erase.params.verbose=-v tools.avrdude.erase.params.quiet=-q -q tools.avrdude.erase.pattern="{cmd.path}" "-C{config.path}" {erase.verbose} -p{build.mcu} -c{protocol} {program.extra_params} -e -Ulock:w:{bootloader.unlock_bits}:m -Uefuse:w:{bootloader.extended_fuses}:m -Uhfuse:w:{bootloader.high_fuses}:m -Ulfuse:w:{bootloader.low_fuses}:m -tools.avrdude.bootloader.params.verbose=-v -v -v -v +tools.avrdude.bootloader.params.verbose=-v tools.avrdude.bootloader.params.quiet=-q -q tools.avrdude.bootloader.pattern="{cmd.path}" "-C{config.path}" {bootloader.verbose} -p{build.mcu} -c{protocol} {program.extra_params} "-Uflash:w:{runtime.platform.path}/bootloaders/{bootloader.file}:i" -Ulock:w:{bootloader.lock_bits}:m