From 9e17fbca4ff08df9a0895f0991d2e8d165468376 Mon Sep 17 00:00:00 2001 From: Doug Schaefer Date: Sun, 19 Jun 2016 15:30:34 -0400 Subject: [PATCH] Bug 492006 Add support for using programmers for uploads. Needed by a few boards, Gemma famously. Adds UI to select a programmer for a board and using it if upload.protocol isn't set for the board (same as the Arduino IDE). No support for the Burn Bootloader menu item yet, but we're closer. Change-Id: I5d550b96191fdd1bd18da3daf69bbf7504bfa241 --- .../arduino/core/tests/FullIntegration.java | 29 +++------ .../core/internal/board/ArduinoPlatform.java | 29 ++++++++- .../build/ArduinoBuildConfiguration.java | 59 ++++++++++++++----- .../remote/ArduinoRemoteConnection.java | 15 ++++- .../internal/remote/BoardPropertyControl.java | 35 ++++++++++- 5 files changed, 126 insertions(+), 41 deletions(-) diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core.tests/src/org/eclipse/cdt/arduino/core/tests/FullIntegration.java b/toolchains/arduino/org.eclipse.cdt.arduino.core.tests/src/org/eclipse/cdt/arduino/core/tests/FullIntegration.java index f3b77afba56..fe2e51a3c7d 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core.tests/src/org/eclipse/cdt/arduino/core/tests/FullIntegration.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core.tests/src/org/eclipse/cdt/arduino/core/tests/FullIntegration.java @@ -13,8 +13,8 @@ import java.nio.file.Paths; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; -import java.util.Set; import java.util.Map.Entry; +import java.util.Set; import org.eclipse.cdt.arduino.core.internal.Activator; import org.eclipse.cdt.arduino.core.internal.ArduinoPreferences; @@ -101,25 +101,6 @@ public class FullIntegration { private static void setupSkipUpload() throws Exception { skipUpload = new HashSet<>(); - // missing upload.protocol - skipUpload.add(arduinoManager.getBoard("arduino", "avr", "gemma")); - skipUpload.add(arduinoManager.getBoard("adafruit", "avr", "gemma")); - skipUpload.add(arduinoManager.getBoard("adafruit", "avr", "trinket5")); - skipUpload.add(arduinoManager.getBoard("adafruit", "avr", "trinket3")); - skipUpload.add(arduinoManager.getBoard("ATTinyCore", "avr", "attinyx7")); - skipUpload.add(arduinoManager.getBoard("ATTinyCore", "avr", "attinyx61")); - skipUpload.add(arduinoManager.getBoard("ATTinyCore", "avr", "attinyx8")); - skipUpload.add(arduinoManager.getBoard("ATTinyCore", "avr", "attiny1634")); - skipUpload.add(arduinoManager.getBoard("ATTinyCore", "avr", "attinyx313")); - skipUpload.add(arduinoManager.getBoard("ATTinyCore", "avr", "attinyx5")); - skipUpload.add(arduinoManager.getBoard("ATTinyCore", "avr", "attinyx4")); - skipUpload.add(arduinoManager.getBoard("ATTinyCore", "avr", "attinyx41")); - skipUpload.add(arduinoManager.getBoard("ATTinyCore", "avr", "attiny828")); - skipUpload.add(arduinoManager.getBoard("arduino-tiny-841", "avr", "attiny1634")); - skipUpload.add(arduinoManager.getBoard("arduino-tiny-841", "avr", "attinyx41")); - skipUpload.add(arduinoManager.getBoard("arduino-tiny-841", "avr", "attiny828")); - skipUpload.add(arduinoManager.getBoard("arduino-tiny-841", "avr", "attiny828")); - // usbtiny missing skipUpload.add(arduinoManager.getBoard("adafruit", "avr", "protrinket3")); skipUpload.add(arduinoManager.getBoard("adafruit", "avr", "protrinket5")); @@ -229,6 +210,14 @@ public class FullIntegration { } } + HierarchicalProperties programmers = board.getPlatform().getProgrammers(); + if (programmers != null && programmers.getChildren() != null) { + for (String programmer : programmers.getChildren().keySet()) { + ArduinoRemoteConnection.setProgrammer(workingCopy, programmer); + break; + } + } + connection = workingCopy.save(); return connection.getService(ArduinoRemoteConnection.class); diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoPlatform.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoPlatform.java index 306be570c01..0bf01f5d595 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoPlatform.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoPlatform.java @@ -56,6 +56,7 @@ public class ArduinoPlatform { private ArduinoPackage pkg; private HierarchicalProperties boardsProperties; private LinkedProperties platformProperties; + private HierarchicalProperties programmerProperties; private Map menus = new HashMap<>(); private Map libraries; @@ -198,12 +199,38 @@ public class ArduinoPlatform { platformProperties.load(reader1); } } catch (IOException e) { - throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "Loading platform.txt", e)); //$NON-NLS-1$ + throw Activator.coreException(e); } } return platformProperties; } + public HierarchicalProperties getProgrammers() throws CoreException { + if (programmerProperties == null) { + LinkedProperties props = new LinkedProperties(); + Path programmersTxt = getInstallPath().resolve("programmers.txt"); //$NON-NLS-1$ + if (Files.exists(programmersTxt)) { + try (FileInputStream in = new FileInputStream(programmersTxt.toFile())) { + props.load(in); + programmerProperties = new HierarchicalProperties(props); + } catch (IOException e) { + throw Activator.coreException(e); + } + } else { + // TODO for now, grab the one from the arduino package + ArduinoManager manager = Activator.getService(ArduinoManager.class); + ArduinoPackage arduinoPkg = manager.getPackage("arduino"); + if (arduinoPkg != null) { + ArduinoPlatform arduinoPlat = arduinoPkg.getInstalledPlatform(getArchitecture()); + if (arduinoPlat != null) { + programmerProperties = arduinoPlat.getProgrammers(); + } + } + } + } + return programmerProperties; + } + public Path getInstallPath() { return getPackage().getInstallPath().resolve("hardware").resolve(architecture); //$NON-NLS-1$ } diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfiguration.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfiguration.java index 14262d7de68..52f9d0ae13a 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfiguration.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfiguration.java @@ -83,6 +83,7 @@ public class ArduinoBuildConfiguration extends CBuildConfiguration implements Te private static final String PLATFORM_NAME = "platformName"; //$NON-NLS-1$ private static final String BOARD_NAME = "boardName"; //$NON-NLS-1$ private static final String MENU_QUALIFIER = "menu_"; //$NON-NLS-1$ + private static final String PROGRAMMER = "programmer"; //$NON-NLS-1$ private static ArduinoManager manager = Activator.getService(ArduinoManager.class); @@ -146,22 +147,28 @@ public class ArduinoBuildConfiguration extends CBuildConfiguration implements Te String launchMode, IToolChain toolChain) throws CoreException { this(config, name, target.getBoard(), launchMode, toolChain); + Preferences settings = getSettings(); + // Store the menu settings HierarchicalProperties menus = board.getMenus(); if (menus != null) { - Preferences settings = getSettings(); for (String id : menus.getChildren().keySet()) { String value = target.getMenuValue(id); if (value != null) { settings.put(MENU_QUALIFIER + id, value); } } + } - try { - settings.flush(); - } catch (BackingStoreException e) { - throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "Saving preferences", e)); //$NON-NLS-1$ - } + String programmer = target.getProgrammer(); + if (programmer != null) { + settings.put(PROGRAMMER, programmer); + } + + try { + settings.flush(); + } catch (BackingStoreException e) { + throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "Saving preferences", e)); //$NON-NLS-1$ } } @@ -540,7 +547,9 @@ public class ArduinoBuildConfiguration extends CBuildConfiguration implements Te } public String[] getUploadCommand(String serialPort) throws CoreException { - String toolName = getProperties().getProperty("upload.tool"); //$NON-NLS-1$ + Properties properties = getProperties(); + + String toolName = properties.getProperty("upload.tool"); //$NON-NLS-1$ ArduinoPlatform platform = getBoard().getPlatform(); if (toolName.contains(":")) { //$NON-NLS-1$ String[] segments = toolName.split(":"); //$NON-NLS-1$ @@ -550,8 +559,6 @@ public class ArduinoBuildConfiguration extends CBuildConfiguration implements Te } } - Properties properties = getProperties(); - ArduinoTool uploadTool = platform.getPackage().getLatestTool(toolName); if (uploadTool != null) { properties.putAll(uploadTool.getToolProperties()); @@ -579,14 +586,36 @@ public class ArduinoBuildConfiguration extends CBuildConfiguration implements Te } } - // TODO make this a preference - properties.put("upload.verbose", properties.getProperty("upload.params.verbose", "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - properties.put("upload.verify", properties.getProperty("upload.params.verify", "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + String command; + if (properties.get("upload.protocol") != null) { //$NON-NLS-1$ + // TODO make this a preference + properties.put("upload.verbose", properties.getProperty("upload.params.verbose", "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + properties.put("upload.verify", properties.getProperty("upload.params.verify", "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - // TODO needed this for esptool - properties.put("upload.resetmethod", "ck"); //$NON-NLS-1$ //$NON-NLS-2$ + // TODO needed this for esptool + properties.put("upload.resetmethod", "ck"); //$NON-NLS-1$ //$NON-NLS-2$ + + command = resolveProperty("upload.pattern", properties); //$NON-NLS-1$ + } else { + // use the bootloader + String programmer = getSettings().get(PROGRAMMER, null); + if (programmer != null) { + HierarchicalProperties programmers = board.getPlatform().getProgrammers(); + if (programmers != null) { + HierarchicalProperties programmerProps = programmers.getChild(programmer); + if (programmerProps != null) { + properties.putAll(programmerProps.flatten()); + } + } + } + + // TODO preference + properties.put("program.verbose", properties.getProperty("program.params.verbose", "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + properties.put("program.verify", properties.getProperty("program.params.verify", "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + command = resolveProperty("program.pattern", properties); //$NON-NLS-1$ + } - String command = resolveProperty("upload.pattern", properties); //$NON-NLS-1$ if (command == null) { throw Activator.coreException("Upload command not specified", null); } diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/remote/ArduinoRemoteConnection.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/remote/ArduinoRemoteConnection.java index 30d3ca89230..2ef9e8a01b0 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/remote/ArduinoRemoteConnection.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/remote/ArduinoRemoteConnection.java @@ -40,6 +40,7 @@ public class ArduinoRemoteConnection private static final String PLATFORM_NAME = "arduinoPlatformName"; //$NON-NLS-1$ private static final String BOARD_NAME = "arduinoBoardName"; //$NON-NLS-1$ private static final String MENU_QUALIFIER = "menu_"; //$NON-NLS-1$ + private static final String PROGRAMMER = "programmer"; //$NON-NLS-1$ private final IRemoteConnection remoteConnection; private SerialPort serialPort; @@ -61,19 +62,27 @@ public class ArduinoRemoteConnection ArduinoPackage pkg = platform.getPackage(); workingCopy.setAttribute(PACKAGE_NAME, pkg.getName()); } - + public static void setPortName(IRemoteConnectionWorkingCopy workingCopy, String portName) { workingCopy.setAttribute(PORT_NAME, portName); } - + public static void setMenuValue(IRemoteConnectionWorkingCopy workingCopy, String key, String value) { workingCopy.setAttribute(MENU_QUALIFIER + key, value); } - + + public static void setProgrammer(IRemoteConnectionWorkingCopy workingCopy, String programmer) { + workingCopy.setAttribute(PROGRAMMER, programmer); + } + public String getMenuValue(String key) { return remoteConnection.getAttribute(MENU_QUALIFIER + key); } + public String getProgrammer() { + return remoteConnection.getAttribute(PROGRAMMER); + } + @Override public void connectionChanged(RemoteConnectionChangeEvent event) { if (event.getType() == RemoteConnectionChangeEvent.CONNECTION_REMOVED) { diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/remote/BoardPropertyControl.java b/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/remote/BoardPropertyControl.java index 38362faf463..84ad9ecc3e3 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/remote/BoardPropertyControl.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/remote/BoardPropertyControl.java @@ -17,8 +17,6 @@ import java.util.Map.Entry; import org.eclipse.cdt.arduino.core.internal.HierarchicalProperties; import org.eclipse.cdt.arduino.core.internal.board.ArduinoBoard; import org.eclipse.cdt.arduino.core.internal.board.ArduinoManager; -import org.eclipse.cdt.arduino.core.internal.board.ArduinoPackage; -import org.eclipse.cdt.arduino.core.internal.board.ArduinoPlatform; import org.eclipse.cdt.arduino.core.internal.remote.ArduinoRemoteConnection; import org.eclipse.cdt.arduino.ui.internal.Activator; import org.eclipse.cdt.arduino.ui.internal.Messages; @@ -49,6 +47,9 @@ public class BoardPropertyControl extends Composite { private List listeners = Collections.synchronizedList(new ArrayList()); private List menuControls = new ArrayList<>(); + + private Label programmerLabel; + private Combo programmerCombo; public BoardPropertyControl(Composite parent, int style) { super(parent, style); @@ -158,6 +159,28 @@ public class BoardPropertyControl extends Composite { combo.select(0); } } + + try { + HierarchicalProperties programmers = board.getPlatform().getProgrammers(); + if (programmers != null && programmers.getChildren() != null) { + programmerLabel = new Label(this, SWT.NONE); + programmerLabel.setText("Programmer:"); + + programmerCombo = new Combo(this, SWT.READ_ONLY); + programmerCombo.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + + List ids = new ArrayList<>(); + for (Entry programmer : programmers.getChildren().entrySet()) { + ids.add(programmer.getKey()); + String name = programmer.getValue().getChild("name").getValue(); //$NON-NLS-1$ + programmerCombo.add(name); + } + programmerCombo.setData(ids); + programmerCombo.select(0); + } + } catch (CoreException e) { + Activator.log(e); + } } private void boardChanged() { @@ -169,6 +192,8 @@ public class BoardPropertyControl extends Composite { control.dispose(); } menuControls.clear(); + programmerLabel.dispose(); + programmerCombo.dispose(); board = newBoard; updateBoardMenu(); @@ -205,6 +230,12 @@ public class BoardPropertyControl extends Composite { } } } + + if (programmerCombo != null) { + @SuppressWarnings("unchecked") + String programmer = ((List) programmerCombo.getData()).get(programmerCombo.getSelectionIndex()); + ArduinoRemoteConnection.setProgrammer(workingCopy, programmer); + } } }