/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
AvrdudeUploader - uploader implementation using avrdude
Part of the Wiring project - http://wiring.org.co
Copyright (c) 2004-05
Hernando Barragan
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 2 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, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
$Id$
*/
package processing.app.debug;
import processing.app.Base;
import processing.app.Preferences;
import processing.app.Serial;
import java.io.*;
import java.util.*;
import java.util.zip.*;
import javax.swing.*;
import jssc.*;
public class AvrdudeUploader extends Uploader {
public AvrdudeUploader() {
}
// XXX: add support for uploading sketches using a programmer
public boolean uploadUsingPreferences(String buildPath, String className, boolean verbose)
throws RunnerException {
this.verbose = verbose;
Map<String, String> boardPreferences = Base.getBoardPreferences();
String uploadUsing = boardPreferences.get("upload.using");
if (uploadUsing == null) {
// fall back on global preference
uploadUsing = Preferences.get("upload.using");
}
if (uploadUsing.equals("bootloader")) {
return uploadViaBootloader(buildPath, className);
} else {
Target t;
if (uploadUsing.indexOf(':') == -1) {
t = Base.getTarget(); // the current target (associated with the board)
} else {
String targetName = uploadUsing.substring(0, uploadUsing.indexOf(':'));
t = Base.targetsTable.get(targetName);
uploadUsing = uploadUsing.substring(uploadUsing.indexOf(':') + 1);
}
Collection params = getProgrammerCommands(t, uploadUsing);
params.add("-Uflash:w:" + buildPath + File.separator + className + ".hex:i");
return avrdude(params);
}
}
private boolean uploadViaBootloader(String buildPath, String className)
throws RunnerException {
Map<String, String> boardPreferences = Base.getBoardPreferences();
List commandDownloader = new ArrayList();
String protocol = boardPreferences.get("upload.protocol");
// avrdude wants "stk500v1" to distinguish it from stk500v2
if (protocol.equals("stk500"))
protocol = "stk500v1";
commandDownloader.add("-c" + protocol);
commandDownloader.add(
"-P" + (Base.isWindows() ? "\\\\.\\" : "") + Preferences.get("serial.port"));
commandDownloader.add(
"-b" + Integer.parseInt(boardPreferences.get("upload.speed")));
commandDownloader.add("-D"); // don't erase
commandDownloader.add("-Uflash:w:" + buildPath + File.separator + className + ".hex:i");
if (boardPreferences.get("upload.disable_flushing") == null ||
boardPreferences.get("upload.disable_flushing").toLowerCase().equals("false")) {
flushSerialBuffer();
}
return avrdude(commandDownloader);
}
public boolean burnBootloader(String targetName, String programmer) throws RunnerException {
return burnBootloader(getProgrammerCommands(Base.targetsTable.get(targetName), programmer));
}
private Collection getProgrammerCommands(Target target, String programmer) {
Map<String, String> programmerPreferences = target.getProgrammers().get(programmer);
List params = new ArrayList();
params.add("-c" + programmerPreferences.get("protocol"));
if ("usb".equals(programmerPreferences.get("communication"))) {
params.add("-Pusb");
} else if ("serial".equals(programmerPreferences.get("communication"))) {
params.add("-P" + (Base.isWindows() ? "\\\\.\\" : "") + Preferences.get("serial.port"));
if (programmerPreferences.get("speed") != null) {
params.add("-b" + Integer.parseInt(programmerPreferences.get("speed")));
}
}
// XXX: add support for specifying the port address for parallel
// programmers, although avrdude has a default that works in most cases.
if (programmerPreferences.get("force") != null &&
programmerPreferences.get("force").toLowerCase().equals("true"))
params.add("-F");
if (programmerPreferences.get("delay") != null)
params.add("-i" + programmerPreferences.get("delay"));
return params;
}
protected boolean burnBootloader(Collection params)
throws RunnerException {
Map<String, String> boardPreferences = Base.getBoardPreferences();
List fuses = new ArrayList();
fuses.add("-e"); // erase the chip
fuses.add("-Ulock:w:" + boardPreferences.get("bootloader.unlock_bits") + ":m");
if (boardPreferences.get("bootloader.extended_fuses") != null)
fuses.add("-Uefuse:w:" + boardPreferences.get("bootloader.extended_fuses") + ":m");
fuses.add("-Uhfuse:w:" + boardPreferences.get("bootloader.high_fuses") + ":m");
fuses.add("-Ulfuse:w:" + boardPreferences.get("bootloader.low_fuses") + ":m");
fuses.add("-xsnooze=3000");
if (!avrdude(params, fuses))
return false;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
Target t;
String bootloaderPath = boardPreferences.get("bootloader.path");
if (bootloaderPath.indexOf(':') == -1) {
t = Base.getTarget(); // the current target (associated with the board)
} else {
String targetName = bootloaderPath.substring(0, bootloaderPath.indexOf(':'));
t = Base.targetsTable.get(targetName);
bootloaderPath = bootloaderPath.substring(bootloaderPath.indexOf(':') + 1);
}
File bootloadersFile = new File(t.getFolder(), "bootloaders");
File bootloaderFile = new File(bootloadersFile, bootloaderPath);
bootloaderPath = bootloaderFile.getAbsolutePath();
List bootloader = new ArrayList();
bootloader.add("-Uflash:w:" + bootloaderPath + File.separator +
boardPreferences.get("bootloader.file") + ":i");
bootloader.add("-Ulock:w:" + boardPreferences.get("bootloader.lock_bits") + ":m");
bootloader.add("-xsnooze=3000");
return avrdude(params, bootloader);
}
public boolean avrdude(Collection p1, Collection p2) throws RunnerException {
ArrayList p = new ArrayList(p1);
p.addAll(p2);
return avrdude(p);
}
public boolean avrdude(Collection params) throws RunnerException {
List commandDownloader = new ArrayList();
commandDownloader.add("avrdude");
// Point avrdude at its config file since it's in a non-standard location.
if (Base.isLinux()) {
// ???: is it better to have Linux users install avrdude themselves, in
// a way that it can find its own configuration file?
//commandDownloader.add("-C" + Base.getHardwarePath() + "/tools/avr/bin/avrdude.conf");
commandDownloader.add("-C" + Base.getAvrBasePath() + "avrdude.conf");
} else {
//commandDownloader.add("-C" + Base.getHardwarePath() + "/tools/avr/bin/avrdude.conf");
commandDownloader.add("-C" + Base.getAvrBasePath() + "avrdude.conf");
}
if (verbose || Preferences.getBoolean("upload.verbose")) {
commandDownloader.add("-v");
commandDownloader.add("-v");
commandDownloader.add("-v");
commandDownloader.add("-v");
} else {
commandDownloader.add("-q");
commandDownloader.add("-q");
}
commandDownloader.add("-p" + Base.getBoardPreferences().get("build.mcu"));
commandDownloader.addAll(params);
return executeUploadCommand(commandDownloader);
}
}