From e1faf02deb990077856328a83fec3aa6edc5b5d0 Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Tue, 22 Feb 2011 22:25:04 -0500 Subject: [PATCH 01/33] Removing hardcoded CPU speed from Wire library. Replacing CPU_FREQ with F_CPU. --- libraries/Wire/utility/twi.c | 2 +- libraries/Wire/utility/twi.h | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/libraries/Wire/utility/twi.c b/libraries/Wire/utility/twi.c index 236878c4a..9d7280743 100644 --- a/libraries/Wire/utility/twi.c +++ b/libraries/Wire/utility/twi.c @@ -79,7 +79,7 @@ void twi_init(void) // initialize twi prescaler and bit rate cbi(TWSR, TWPS0); cbi(TWSR, TWPS1); - TWBR = ((CPU_FREQ / TWI_FREQ) - 16) / 2; + TWBR = ((F_CPU / TWI_FREQ) - 16) / 2; /* twi bit rate formula from atmega128 manual pg 204 SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR)) diff --git a/libraries/Wire/utility/twi.h b/libraries/Wire/utility/twi.h index 1258d8d38..71471c6ae 100755 --- a/libraries/Wire/utility/twi.h +++ b/libraries/Wire/utility/twi.h @@ -24,10 +24,6 @@ //#define ATMEGA8 - #ifndef CPU_FREQ - #define CPU_FREQ 16000000L - #endif - #ifndef TWI_FREQ #define TWI_FREQ 100000L #endif From b4f2bd9761b5036d7b287b08007886c04f0279e9 Mon Sep 17 00:00:00 2001 From: Tom Igoe Date: Thu, 24 Feb 2011 09:34:08 -0500 Subject: [PATCH 02/33] updated addresses for Pachube.com in Ethernet examples --- libraries/Ethernet/examples/PachubeClient/PachubeClient.pde | 4 ++-- .../examples/PachubeClientString/PachubeClientString.pde | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/Ethernet/examples/PachubeClient/PachubeClient.pde b/libraries/Ethernet/examples/PachubeClient/PachubeClient.pde index fe94541e1..406c7d17f 100644 --- a/libraries/Ethernet/examples/PachubeClient/PachubeClient.pde +++ b/libraries/Ethernet/examples/PachubeClient/PachubeClient.pde @@ -28,7 +28,7 @@ byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; // assign an IP address for the controller: byte ip[] = { - 192,169,1,20 }; + 192,168,1,20 }; byte gateway[] = { 192,168,1,1}; byte subnet[] = { @@ -36,7 +36,7 @@ byte subnet[] = { // The address of the server you want to connect to (pachube.com): byte server[] = { - 209,40,205,190 }; + 173,203,98,29 }; // initialize the library instance: Client client(server, 80); diff --git a/libraries/Ethernet/examples/PachubeClientString/PachubeClientString.pde b/libraries/Ethernet/examples/PachubeClientString/PachubeClientString.pde index 225823ac1..d49301620 100644 --- a/libraries/Ethernet/examples/PachubeClientString/PachubeClientString.pde +++ b/libraries/Ethernet/examples/PachubeClientString/PachubeClientString.pde @@ -30,7 +30,7 @@ byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; // assign an IP address for the controller: byte ip[] = { - 192,169,1,20 }; + 192,168,1,20 }; byte gateway[] = { 192,168,1,1}; byte subnet[] = { @@ -38,7 +38,7 @@ byte subnet[] = { // The address of the server you want to connect to (pachube.com): byte server[] = { - 209,40,205,190 }; + 173,203,98,29 }; // initialize the library instance: Client client(server, 80); From 896b1a48a1fcd89f624a6b8ae7880fcd7c990615 Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Fri, 25 Feb 2011 18:23:34 -0500 Subject: [PATCH 03/33] Revert "Merge branch 'new-extension' of git@github.com:arduino/Arduino" This reverts commit 42fa932cebb23b62bece52392548f6526fc4d563, reversing changes made to a7352b894f258c7b2e8087d735f1a4aa8e765ea0. See: http://www.kernel.org/pub/software/scm/git/docs/howto/revert-a-faulty-merge.txt for information on how to merge the branch in later. --- app/src/processing/app/Base.java | 28 +- app/src/processing/app/Editor.java | 121 +-- app/src/processing/app/EditorToolbar.java | 22 +- app/src/processing/app/Preferences.java | 21 - app/src/processing/app/Sketch.java | 28 +- .../processing/app/debug/AvrdudeUploader.java | 43 +- app/src/processing/app/debug/Uploader.java | 4 +- app/src/processing/app/windows/Platform.java | 10 +- build/macosx/template.app/Contents/Info.plist | 8 +- .../template.app/Contents/Resources/pde.icns | Bin 95100 -> 42258 bytes build/shared/lib/about.jpg | Bin 106594 -> 115730 bytes build/shared/lib/preferences.txt | 2 - build/shared/lib/theme/buttons.gif | Bin 3331 -> 2739 bytes build/shared/lib/theme/resize.gif | Bin 73 -> 869 bytes build/shared/lib/theme/tab-sel-left.gif | Bin 73 -> 832 bytes build/shared/lib/theme/tab-sel-menu.gif | Bin 114 -> 891 bytes build/shared/lib/theme/tab-sel-mid.gif | Bin 54 -> 830 bytes build/shared/lib/theme/tab-sel-right.gif | Bin 87 -> 834 bytes build/shared/lib/theme/tab-unsel-left.gif | Bin 73 -> 844 bytes build/shared/lib/theme/tab-unsel-menu.gif | Bin 114 -> 896 bytes build/shared/lib/theme/tab-unsel-mid.gif | Bin 54 -> 828 bytes build/shared/lib/theme/tab-unsel-right.gif | Bin 73 -> 842 bytes build/shared/lib/theme/theme.txt | 28 +- build/windows/launcher/about.bmp | Bin 468054 -> 382854 bytes libraries/SoftwareSerial/SoftwareSerial.cpp | 761 ++++++------------ libraries/SoftwareSerial/SoftwareSerial.h | 169 ++-- .../SoftwareSerialExample.pde | 21 - .../TwoPortRXExample/TwoPortRXExample.pde | 50 -- libraries/SoftwareSerial/icrmacros.h | 69 -- libraries/SoftwareSerial/keywords.txt | 15 +- 30 files changed, 396 insertions(+), 1004 deletions(-) mode change 100644 => 100755 build/shared/lib/about.jpg delete mode 100755 libraries/SoftwareSerial/examples/SoftwareSerialExample/SoftwareSerialExample.pde delete mode 100755 libraries/SoftwareSerial/examples/TwoPortRXExample/TwoPortRXExample.pde delete mode 100755 libraries/SoftwareSerial/icrmacros.h mode change 100755 => 100644 libraries/SoftwareSerial/keywords.txt diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 69255abfd..0dba54f30 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -545,7 +545,7 @@ public class Base { newbieDir.mkdirs(); // Make an empty pde file - File newbieFile = new File(newbieDir, newbieName + ".ino"); + File newbieFile = new File(newbieDir, newbieName + ".pde"); new FileOutputStream(newbieFile); // create the file return newbieFile.getAbsolutePath(); } @@ -637,8 +637,7 @@ public class Base { public boolean accept(File dir, String name) { // TODO this doesn't seem to ever be used. AWESOME. //System.out.println("check filter on " + dir + " " + name); - return name.toLowerCase().endsWith(".ino") - || name.toLowerCase().endsWith(".pde"); + return name.toLowerCase().endsWith(".pde"); } }); @@ -1017,28 +1016,22 @@ public class Base { } - public void rebuildProgrammerMenu(JMenu menu) { - //System.out.println("rebuilding programmer menu"); + public void rebuildBurnBootloaderMenu(JMenu menu) { + //System.out.println("rebuilding burn bootloader menu"); menu.removeAll(); - ButtonGroup group = new ButtonGroup(); for (Target target : targetsTable.values()) { for (String programmer : target.getProgrammers().keySet()) { AbstractAction action = new AbstractAction( - target.getProgrammers().get(programmer).get("name")) { + "w/ " + target.getProgrammers().get(programmer).get("name")) { public void actionPerformed(ActionEvent actionevent) { - Preferences.set("programmer", getValue("target") + ":" + - getValue("programmer")); + activeEditor.handleBurnBootloader((String) getValue("target"), + (String) getValue("programmer")); } }; action.putValue("target", target.getName()); action.putValue("programmer", programmer); - JMenuItem item = new JRadioButtonMenuItem(action); - if (Preferences.get("programmer").equals(target.getName() + ":" + - programmer)) { - item.setSelected(true); - } - group.add(item); + JMenuItem item = new JMenuItem(action); menu.add(item); } } @@ -1098,10 +1091,7 @@ public class Base { File subfolder = new File(folder, list[i]); if (!subfolder.isDirectory()) continue; - File entry = new File(subfolder, list[i] + ".ino"); - if (!entry.exists() && (new File(subfolder, list[i] + ".pde")).exists()) { - entry = new File(subfolder, list[i] + ".pde"); - } + File entry = new File(subfolder, list[i] + ".pde"); // if a .pde file of the same prefix as the folder exists.. if (entry.exists()) { //String sanityCheck = sanitizedName(list[i]); diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java index 33f1fc855..3d8bd405b 100644 --- a/app/src/processing/app/Editor.java +++ b/app/src/processing/app/Editor.java @@ -538,7 +538,7 @@ public class Editor extends JFrame implements RunnerListener { }); fileMenu.add(saveAsMenuItem); - item = newJMenuItem("Upload", 'U'); + item = newJMenuItem("Upload to I/O Board", 'U'); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { handleExport(false); @@ -546,13 +546,13 @@ public class Editor extends JFrame implements RunnerListener { }); fileMenu.add(item); - item = newJMenuItemShift("Upload Using Programmer", 'U'); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleExport(true); - } - }); - fileMenu.add(item); +// item = newJMenuItemShift("Upload to I/O Board (verbose)", 'U'); +// item.addActionListener(new ActionListener() { +// public void actionPerformed(ActionEvent e) { +// handleExport(true); +// } +// }); +// fileMenu.add(item); fileMenu.addSeparator(); @@ -618,13 +618,13 @@ public class Editor extends JFrame implements RunnerListener { // }); // sketchMenu.add(item); -// item = new JMenuItem("Stop"); -// item.addActionListener(new ActionListener() { -// public void actionPerformed(ActionEvent e) { -// handleStop(); -// } -// }); -// sketchMenu.add(item); + item = new JMenuItem("Stop"); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + handleStop(); + } + }); + sketchMenu.add(item); sketchMenu.addSeparator(); @@ -693,20 +693,12 @@ public class Editor extends JFrame implements RunnerListener { serialMenu = new JMenu("Serial Port"); populateSerialMenu(); menu.add(serialMenu); - + menu.addSeparator(); - - JMenu programmerMenu = new JMenu("Programmer"); - base.rebuildProgrammerMenu(programmerMenu); - menu.add(programmerMenu); - item = new JMenuItem("Burn Bootloader"); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleBurnBootloader(); - } - }); - menu.add(item); + JMenu bootloaderMenu = new JMenu("Burn Bootloader"); + base.rebuildBurnBootloaderMenu(bootloaderMenu); + menu.add(bootloaderMenu); menu.addMenuListener(new MenuListener() { public void menuCanceled(MenuEvent e) {} @@ -997,8 +989,8 @@ public class Editor extends JFrame implements RunnerListener { //serialMenu.addSeparator(); //serialMenu.add(item); } - - + + protected JMenu buildHelpMenu() { // To deal with a Mac OS X 10.5 bug, add an extra space after the name // so that the OS doesn't try to insert its slow help menu. @@ -1895,12 +1887,12 @@ public class Editor extends JFrame implements RunnerListener { * Implements Sketch → Stop, or pressing Stop on the toolbar. */ public void handleStop() { // called by menu or buttons -// toolbar.activate(EditorToolbar.STOP); + toolbar.activate(EditorToolbar.STOP); internalCloseRunner(); toolbar.deactivate(EditorToolbar.RUN); -// toolbar.deactivate(EditorToolbar.STOP); + toolbar.deactivate(EditorToolbar.STOP); // focus the PDE again after quitting presentation mode [toxi 030903] toFront(); @@ -2040,65 +2032,14 @@ public class Editor extends JFrame implements RunnerListener { * modifications (if any) to the previous sketch need to be saved. */ protected boolean handleOpenInternal(String path) { - // rename .pde files to .ino - File[] oldFiles = (new File(path)).getParentFile().listFiles(new FilenameFilter() { - public boolean accept(File dir, String name) { - return (name.toLowerCase().endsWith(".pde")); - } - }); - - if (oldFiles != null && oldFiles.length > 0) { - if (!Preferences.getBoolean("editor.update_extension")) { - Object[] options = { "OK", "Cancel" }; - String prompt = - "In Arduino 1.0, the file extension for sketches changed\n" + - "from \".pde\" to \".ino\". This version of the software only\n" + - "supports the new extension. Rename the files in this sketch\n" + - "(and future sketches) and continue?"; - - int result = JOptionPane.showOptionDialog(this, - prompt, - "New extension", - JOptionPane.YES_NO_OPTION, - JOptionPane.QUESTION_MESSAGE, - null, - options, - options[0]); - if (result != JOptionPane.YES_OPTION) { - return false; - } - - Preferences.setBoolean("editor.update_extension", true); - } - - for (int i = 0; i < oldFiles.length; i++) { - String oldPath = oldFiles[i].getPath(); - File newFile = new File(oldPath.substring(0, oldPath.length() - 4) + ".ino"); - try { - Base.copyFile(oldFiles[i], newFile); - } catch (IOException e) { - Base.showWarning("Error", "Could not copy to a proper location.", e); - return false; - } - - // remove the original file, so user doesn't get confused - oldFiles[i].delete(); - - // update with the new path - if (oldFiles[i].compareTo(new File(path)) == 0) { - path = newFile.getAbsolutePath(); - } - } - } - // check to make sure that this .pde file is // in a folder of the same name File file = new File(path); File parentFile = new File(file.getParent()); String parentName = parentFile.getName(); - String pdeName = parentName + ".ino"; + String pdeName = parentName + ".pde"; File altFile = new File(file.getParent(), pdeName); - + if (pdeName.equals(file.getName())) { // no beef with this guy @@ -2108,10 +2049,10 @@ public class Editor extends JFrame implements RunnerListener { path = altFile.getAbsolutePath(); //System.out.println("found alt file in same folder"); - } else if (!path.endsWith(".ino")) { + } else if (!path.endsWith(".pde")) { Base.showWarning("Bad file selected", "Processing can only open its own sketches\n" + - "and other files ending in .ino", null); + "and other files ending in .pde", null); return false; } else { @@ -2330,13 +2271,13 @@ public class Editor extends JFrame implements RunnerListener { * Made synchronized to (hopefully) avoid problems of people * hitting export twice, quickly, and horking things up. */ - synchronized public void handleExport(final boolean usingProgrammer) { + synchronized public void handleExport(final boolean verbose) { //if (!handleExportCheckModified()) return; toolbar.activate(EditorToolbar.EXPORT); console.clear(); statusNotice("Uploading to I/O Board..."); - new Thread(usingProgrammer ? exportAppHandler : exportHandler).start(); + new Thread(verbose ? exportAppHandler : exportHandler).start(); } // DAM: in Arduino, this is upload @@ -2454,14 +2395,14 @@ public class Editor extends JFrame implements RunnerListener { } - protected void handleBurnBootloader() { + protected void handleBurnBootloader(final String target, final String programmer) { console.clear(); statusNotice("Burning bootloader to I/O Board (this may take a minute)..."); SwingUtilities.invokeLater(new Runnable() { public void run() { try { Uploader uploader = new AvrdudeUploader(); - if (uploader.burnBootloader()) { + if (uploader.burnBootloader(target, programmer)) { statusNotice("Done burning bootloader."); } else { statusError("Error while burning bootloader."); diff --git a/app/src/processing/app/EditorToolbar.java b/app/src/processing/app/EditorToolbar.java index 9d7a5fc13..74ef71f94 100644 --- a/app/src/processing/app/EditorToolbar.java +++ b/app/src/processing/app/EditorToolbar.java @@ -37,12 +37,12 @@ public class EditorToolbar extends JComponent implements MouseInputListener, Key /** Rollover titles for each button. */ static final String title[] = { - "Verify", "Upload", "New", "Open", "Save", "Serial Monitor" + "Verify", "Stop", "New", "Open", "Save", "Upload", "Serial Monitor" }; /** Titles for each button when the shift key is pressed. */ static final String titleShift[] = { - "Verify", "Upload Using Programmer", "New Editor Window", "Open in Another Window", "Save", "Serial Monitor" + "Verify (w/ Verbose Output)", "Stop", "New Editor Window", "Open in Another Window", "Save", "Upload (w/ Verbose Output)", "Serial Monitor" }; static final int BUTTON_COUNT = title.length; @@ -57,13 +57,14 @@ public class EditorToolbar extends JComponent implements MouseInputListener, Key static final int RUN = 0; - static final int EXPORT = 1; + static final int STOP = 1; static final int NEW = 2; static final int OPEN = 3; static final int SAVE = 4; + static final int EXPORT = 5; - static final int SERIAL = 5; + static final int SERIAL = 6; static final int INACTIVE = 0; static final int ROLLOVER = 1; @@ -104,10 +105,11 @@ public class EditorToolbar extends JComponent implements MouseInputListener, Key //which[buttonCount++] = NOTHING; which[buttonCount++] = RUN; - which[buttonCount++] = EXPORT; + which[buttonCount++] = STOP; which[buttonCount++] = NEW; which[buttonCount++] = OPEN; which[buttonCount++] = SAVE; + which[buttonCount++] = EXPORT; which[buttonCount++] = SERIAL; currentRollover = -1; @@ -310,13 +312,13 @@ public class EditorToolbar extends JComponent implements MouseInputListener, Key switch (sel) { case RUN: - editor.handleRun(false); + editor.handleRun(e.isShiftDown()); + break; + + case STOP: + editor.handleStop(); break; -// case STOP: -// editor.handleStop(); -// break; -// case OPEN: popup = menu.getPopupMenu(); popup.show(EditorToolbar.this, x, y); diff --git a/app/src/processing/app/Preferences.java b/app/src/processing/app/Preferences.java index 4dd15c041..ffc63f7ae 100644 --- a/app/src/processing/app/Preferences.java +++ b/app/src/processing/app/Preferences.java @@ -113,8 +113,6 @@ public class Preferences { JTextField sketchbookLocationField; JCheckBox exportSeparateBox; - JCheckBox verboseCompilationBox; - JCheckBox verboseUploadBox; JCheckBox deletePreviousBox; JCheckBox externalEditorBox; JCheckBox memoryOverrideBox; @@ -281,21 +279,6 @@ public class Preferences { top += d.height + GUI_BETWEEN; - // Show verbose output during: [ ] compilation [ ] upload - - box = Box.createHorizontalBox(); - label = new JLabel("Show verbose output during: "); - box.add(label); - verboseCompilationBox = new JCheckBox("compilation "); - box.add(verboseCompilationBox); - verboseUploadBox = new JCheckBox("upload"); - box.add(verboseUploadBox); - pain.add(box); - d = box.getPreferredSize(); - box.setBounds(left, top, d.width, d.height); - top += d.height + GUI_BETWEEN; - - // [ ] Delete previous applet or application folder on export deletePreviousBox = @@ -478,8 +461,6 @@ public class Preferences { */ protected void applyFrame() { // put each of the settings into the table - setBoolean("build.verbose", verboseCompilationBox.isSelected()); - setBoolean("upload.verbose", verboseUploadBox.isSelected()); setBoolean("export.delete_target_folder", deletePreviousBox.isSelected()); @@ -535,8 +516,6 @@ public class Preferences { this.editor = editor; // set all settings entry boxes to their actual status - verboseCompilationBox.setSelected(getBoolean("build.verbose")); - verboseUploadBox.setSelected(getBoolean("upload.verbose")); deletePreviousBox. setSelected(getBoolean("export.delete_target_folder")); diff --git a/app/src/processing/app/Sketch.java b/app/src/processing/app/Sketch.java index 22e2aa591..801067c5e 100644 --- a/app/src/processing/app/Sketch.java +++ b/app/src/processing/app/Sketch.java @@ -315,7 +315,7 @@ public class Sketch { renamingCode = true; String prompt = (currentIndex == 0) ? "New name for sketch:" : "New name for file:"; - String oldName = (current.isExtension("ino")) ? + String oldName = (current.isExtension("pde")) ? current.getPrettyName() : current.getFileName(); editor.status.edit(prompt, oldName); } @@ -495,7 +495,7 @@ public class Sketch { } // if successful, set base properties for the sketch - File newMainFile = new File(newFolder, newName + ".ino"); + File newMainFile = new File(newFolder, newName + ".pde"); String newMainFilePath = newMainFile.getAbsolutePath(); // having saved everything and renamed the folder and the main .pde, @@ -860,7 +860,7 @@ public class Sketch { } // save the main tab with its new name - File newFile = new File(newFolder, newName + ".ino"); + File newFile = new File(newFolder, newName + ".pde"); code[0].saveAs(newFile); editor.handleOpenUnchecked(newFile.getPath(), @@ -1261,7 +1261,7 @@ public class Sketch { StringBuffer bigCode = new StringBuffer(); int bigCount = 0; for (SketchCode sc : code) { - if (sc.isExtension("ino")) { + if (sc.isExtension("pde")) { sc.setPreprocOffset(bigCount); bigCode.append(sc.getProgram()); bigCode.append('\n'); @@ -1357,7 +1357,7 @@ public class Sketch { } // sc.setPreprocName(filename); - } else if (sc.isExtension("ino")) { + } else if (sc.isExtension("pde")) { // The compiler and runner will need this to have a proper offset sc.addPreprocOffset(headerOffset); } @@ -1386,7 +1386,7 @@ public class Sketch { // SketchCode errorCode = null; // if (filename.equals(appletJavaFile)) { // for (SketchCode code : getCode()) { -// if (code.isExtension("ino")) { +// if (code.isExtension("pde")) { // if (line >= code.getPreprocOffset()) { // errorCode = code; // } @@ -1520,15 +1520,15 @@ public class Sketch { } - protected boolean exportApplet(boolean usingProgrammer) throws Exception { - return exportApplet(tempBuildFolder.getAbsolutePath(), usingProgrammer); + protected boolean exportApplet(boolean verbose) throws Exception { + return exportApplet(tempBuildFolder.getAbsolutePath(), verbose); } /** * Handle export to applet. */ - public boolean exportApplet(String appletPath, boolean usingProgrammer) + public boolean exportApplet(String appletPath, boolean verbose) throws RunnerException, IOException, SerialException { // Make sure the user didn't hide the sketch folder @@ -1565,7 +1565,7 @@ public class Sketch { // return false; // } - upload(appletFolder.getPath(), foundName, usingProgrammer); + upload(appletFolder.getPath(), foundName, verbose); return true; } @@ -1592,7 +1592,7 @@ public class Sketch { } - protected String upload(String buildPath, String suggestedClassName, boolean usingProgrammer) + protected String upload(String buildPath, String suggestedClassName, boolean verbose) throws RunnerException, SerialException { Uploader uploader; @@ -1602,7 +1602,7 @@ public class Sketch { uploader = new AvrdudeUploader(); boolean success = uploader.uploadUsingPreferences(buildPath, suggestedClassName, - usingProgrammer); + verbose); return success ? suggestedClassName : null; } @@ -1791,7 +1791,7 @@ public class Sketch { * Returns the default extension for this editor setup. */ public String getDefaultExtension() { - return "ino"; + return "pde"; } @@ -1799,7 +1799,7 @@ public class Sketch { * Returns a String[] array of proper extensions. */ public String[] getExtensions() { - return new String[] { "ino", "c", "cpp", "h" }; + return new String[] { "pde", "c", "cpp", "h" }; } diff --git a/app/src/processing/app/debug/AvrdudeUploader.java b/app/src/processing/app/debug/AvrdudeUploader.java index a30f56614..97ef91a20 100755 --- a/app/src/processing/app/debug/AvrdudeUploader.java +++ b/app/src/processing/app/debug/AvrdudeUploader.java @@ -42,28 +42,33 @@ public class AvrdudeUploader extends Uploader { public AvrdudeUploader() { } - public boolean uploadUsingPreferences(String buildPath, String className, boolean usingProgrammer) + // XXX: add support for uploading sketches using a programmer + public boolean uploadUsingPreferences(String buildPath, String className, boolean verbose) throws RunnerException, SerialException { this.verbose = verbose; Map 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 no protocol is specified for this board, assume it lacks a - // bootloader and upload using the selected programmer. - if (usingProgrammer || boardPreferences.get("upload.protocol") == null) { - String programmer = Preferences.get("programmer"); - Target target = Base.getTarget(); - - if (programmer.indexOf(":") != -1) { - target = Base.targetsTable.get(programmer.substring(0, programmer.indexOf(":"))); - programmer = programmer.substring(programmer.indexOf(":") + 1); + 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(target, programmer); + + Collection params = getProgrammerCommands(t, uploadUsing); params.add("-Uflash:w:" + buildPath + File.separator + className + ".hex:i"); return avrdude(params); } - - return uploadViaBootloader(buildPath, className); } private boolean uploadViaBootloader(String buildPath, String className) @@ -91,14 +96,8 @@ public class AvrdudeUploader extends Uploader { return avrdude(commandDownloader); } - public boolean burnBootloader() throws RunnerException { - String programmer = Preferences.get("programmer"); - Target target = Base.getTarget(); - if (programmer.indexOf(":") != -1) { - target = Base.targetsTable.get(programmer.substring(0, programmer.indexOf(":"))); - programmer = programmer.substring(programmer.indexOf(":") + 1); - } - return burnBootloader(getProgrammerCommands(target, programmer)); + public boolean burnBootloader(String targetName, String programmer) throws RunnerException { + return burnBootloader(getProgrammerCommands(Base.targetsTable.get(targetName), programmer)); } private Collection getProgrammerCommands(Target target, String programmer) { diff --git a/app/src/processing/app/debug/Uploader.java b/app/src/processing/app/debug/Uploader.java index 03d8f2f30..16e3d33d8 100755 --- a/app/src/processing/app/debug/Uploader.java +++ b/app/src/processing/app/debug/Uploader.java @@ -64,10 +64,10 @@ public abstract class Uploader implements MessageConsumer { public Uploader() { } - public abstract boolean uploadUsingPreferences(String buildPath, String className, boolean usingProgrammer) + public abstract boolean uploadUsingPreferences(String buildPath, String className, boolean verbose) throws RunnerException, SerialException; - public abstract boolean burnBootloader() throws RunnerException; + public abstract boolean burnBootloader(String target, String programmer) throws RunnerException; protected void flushSerialBuffer() throws RunnerException, SerialException { // Cleanup the serial buffer diff --git a/app/src/processing/app/windows/Platform.java b/app/src/processing/app/windows/Platform.java index 5afe4db13..63e76145a 100644 --- a/app/src/processing/app/windows/Platform.java +++ b/app/src/processing/app/windows/Platform.java @@ -44,8 +44,8 @@ public class Platform extends processing.app.Platform { static final String openCommand = System.getProperty("user.dir").replace('/', '\\') + - "\\arduino.exe \"%1\""; - static final String DOC = "Arduino.Document"; + "\\processing.exe \"%1\""; + static final String DOC = "Processing.Document"; public void init(Base base) { super.init(base); @@ -86,13 +86,13 @@ public class Platform extends processing.app.Platform { */ protected void setAssociations() throws UnsupportedEncodingException { if (Registry.createKey(REGISTRY_ROOT_KEY.CLASSES_ROOT, - "", ".ino") && + "", ".pde") && Registry.setStringValue(REGISTRY_ROOT_KEY.CLASSES_ROOT, - ".ino", "", DOC) && + ".pde", "", DOC) && Registry.createKey(REGISTRY_ROOT_KEY.CLASSES_ROOT, "", DOC) && Registry.setStringValue(REGISTRY_ROOT_KEY.CLASSES_ROOT, DOC, "", - "Arduino Source Code") && + "Processing Source Code") && Registry.createKey(REGISTRY_ROOT_KEY.CLASSES_ROOT, DOC, "shell") && diff --git a/build/macosx/template.app/Contents/Info.plist b/build/macosx/template.app/Contents/Info.plist index fbf778b0f..f9dc41c24 100755 --- a/build/macosx/template.app/Contents/Info.plist +++ b/build/macosx/template.app/Contents/Info.plist @@ -35,15 +35,13 @@ CFBundleTypeExtensions - ino - c - cpp - h + pde + java CFBundleTypeIconFile pde.icns CFBundleTypeName - Arduino Source File + Processing Source File CFBundleTypeMIMETypes text/plain diff --git a/build/macosx/template.app/Contents/Resources/pde.icns b/build/macosx/template.app/Contents/Resources/pde.icns index d3862982c4325632a08f042694b12bf1d9abc5ba..214b19877ae38e580adf5e2466aceaa6f6b798a6 100644 GIT binary patch literal 42258 zcmeHwcXS)qnePCknk8AbWI1tc$ zaZy%sx1>P_NP-~126l=C?7fp933h@MdnZ`H27)9i(F=+9-2o{UiB+IwXF1>qxO2a9 z%XbUrH$Uj|8}D7ku%y$M-?;jB7>4~+^0efX;HARUXs70d&&Be zbF&xN`2mKJjxM>(mJ1e(kHvDq^?q(yy*gQ#bU7%X_Lvv$L!-{wVE$jk-o_U8gOE!3&9W`<+>lSw%f`Ej^n!Urqn25e!}Al^k3m3hY>5)k zBE_LJ?K~2&m{$zwwJ2@1XK_*q14cbc+nsI$v%?l6cIr6hq&SY*?KT^JQ%i3mWm*vo`ktSh9Yd7#jcQ&UmOjk1qVvowQ5x z^!l_b`>}QTF4wm=q+i^S{>l3E(!~wwUqBiL>7CGO;lc%2E36iad7~gK2tiXC|wXWu)6$veRAcbB?23l%0AF_}~ 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 Ze8jT{SUj{dc036kWX~Uj-MhYd{C^CIlIj2e literal 95100 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 k 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 MK7C@;Hhr)EAA}0i@c;k- diff --git a/build/shared/lib/about.jpg b/build/shared/lib/about.jpg old mode 100644 new mode 100755 index 0b168bba1b7c1b899af157c11291a9bcd15023fe..90afdb08b193f4f77b8233fd1b4ac01e5b68d6b7 GIT binary patch literal 115730 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 z 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 W11DM5O4u2^wDCT)ddTu~>i+;6c+36( literal 106594 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 diff --git a/build/shared/lib/theme/resize.gif b/build/shared/lib/theme/resize.gif index ed31c0ad89d7657af6e833651b49ad9b0b9d6bc4..59d21d90991428c7078ff6e7ff65f904442a0232 100644 GIT binary patch literal 869 zcmchWu}ju*5XK*09TW_r93wOpDw?{GBqs;WAc9(3T8_4w8xs@}T3WhIof~Xyl$MD5 z1A=I4Xq1+4x<2>)Bf8;*``z7h&-2{(-QL-{zy4xD3;HWnM^;6ZS6P)h%dCt_ue3^a zF|r~myuvEfy`JS!?&Vgl9@k(Wu2r{D3CY*a0U5qY&1BL7GWu!GpzM1Fb$$ zcT*-O#KkZYeXJ!j_2Xz?$Gy8aPS`e&t90)$x?LaM_2{spk1!NA(jeV889W+zK=T~9 z66T?aRWnastt?Ge7N=JGcfzCO<9~>yiczm*Uc;)ll$KU5S*4|xOe=~pU^^dK+>(B1~diiJh+xzbuZ|~iFdXxv# I(-S@T2Us3wq4=Vun+B9V`9YLyfX2!?QV@wQr6q(CRsh)nLP!+e0Bi)M za*ppJ;_6wp$1~&mzI^?Ba(cO^t=^@csP62JZg*?4s;=ycE_Z2)S)JJ#o$l21Ms;LI zbhtw^>S|{@+HMP^R<*JfEw@O(1{y4e>DKI-$f~Gvm1ZqjW@S{mQp18`WJOfCLPLsP zXF19)3yzGIvJ@qk*a~aFAPq}sQDZUKK!e4wM$qI$WI9u$kF{hG8P3qig#|@N+G(L4 zQuL-G b07s!qW$xLU>OYweG^WW`&UzTiz+epkw)h$C diff --git a/build/shared/lib/theme/tab-sel-menu.gif b/build/shared/lib/theme/tab-sel-menu.gif index 3b213f4a77943268c4209bd87c9ef36253a4d777..eabde568a377ecde71218e59be6f776d27cbcfd6 100644 GIT binary patch literal 891 zcmchWJ8PF=48>2?p*m?@1^v_FP(&(OyewKo|4t$<3Ket-euCoQqJmXiyi9=#UOG9o zo2w{NFpF-kegiKco#HRghcMF{lAN4#^1K%>T{wB_)&WiQSE`PziYl+NDs`4w8I@jX zmFi+-MO1i&Rj7MC%cI=Otz127Sr%npW@Q4Yl%*(n$x0+(0}U3#bgTDtM5bq2rg|+| zM22TrhMEOMk91GBbTuh@Ez&&A(ga6FQ<3tNrPvB(ghyC} zS|4l4+`}zgEf*FP&BH8AsD~82ArDyydH4ZMrm+M4kU$}<0fRIwX@v)i!3G*EwR2r2 zC(K=KB>GrOX67b*MJ_BTy3B=-IE?}Dq8+1Ai(dlwz4 S{u8`uCv&XkUvOn&um%9b=PNV- diff --git a/build/shared/lib/theme/tab-sel-mid.gif b/build/shared/lib/theme/tab-sel-mid.gif index 4bd19a0c3b161c5348805d92ea17d1987c5e57a2..e6df0889061c5ad730356870fe8dadad484f7cf5 100644 GIT binary patch literal 830 zcmchWF-~1k3`7Ts0y;zs%@-Y_n+BAgkkpiEXe^dNnov_(LJ?#IpCv$=6y89xktmgO zd>4VMXW1UljPLvS>GJ&IW>*{im3pGOvpc%ot;wpovMajWr7320W@mJ|Q_~yOksZ#b5&s7Q-4rlM|8YOpQL)l0{@VLn9X!6dh@&g?dQQ zn~IcE$iok4GL0SRhXe{?4H%?hNh>^93^veUX`GufIpGM6k?3PBnH?6sA{Q1ELk{61 zPGbPPXvb*OVkLe+lWFXL6M|6)Yrr7QB(&hcVz7bMoM^f!lM~`%7>PdCl3DXO#@BW4 zDXtTa&Fd=DyNn*!mv=L|?3g1gg@d$6&rKGO0bbBN2d;#9Xkyjo_S^Ntcitl3?-`qa tyF1b!oz2quC$x8@m;K|b?bGYm--oAPer=zB-XENNe!P15@ph*V{{bxKT0sB+ literal 54 zcmZ?wbhEHbWMNQbXkcLY|Np=E!ljBoSs2(E{xj$>00Bsbfr+=Le5{)-0I$} H&0q}xrgacx diff --git a/build/shared/lib/theme/tab-sel-right.gif b/build/shared/lib/theme/tab-sel-right.gif index 4ceb3ed808e7c914c14b07092a09ddc7aaa4d3cf..be24960a7c146e668e0657d3805e406b3e075d4d 100644 GIT binary patch literal 834 zcmchWF-o3c5QHc2Be6?q5s;r$0gJ#ihV)TGN-touw|RJu~bf?{MvRJcMz zie6_q$}S6zjFz$#C70L=Yrr54OK4GJG1x$Z#jr-uGrOW`~8Z$b|*P zkVE*0(-;6R+A$inScxCdWEwl*gkTiH8ZbyR2`zZA7;K<5Cz@``6 z@pavMitB`9^Sa9PE~Cfw<=u=fJLU*W;UF#2bCbnmfEP5+fh%Dinpm~{_WktY7jKd8 z{~6oo%`53q2eWkk3BBIe?e5#--&cRm|K06=z5j6i_s5%eUoMYtZytW`z2DjB(+igM BT73Wj literal 87 zcmZ?wbhEHbWMNQbSj52a|NsAg|Nj5`|NqgaFAqO`iQRKRY~fPzg-aEGvM{hS{AbW% r00NL&24>-4^4CI)K&`U58T diff --git a/build/shared/lib/theme/tab-unsel-left.gif b/build/shared/lib/theme/tab-unsel-left.gif index cdc98861ff71de9dca40913060bbcb39286dd7e3..6ed8391d26ea7dbb039261fe82d1cf64245f3721 100644 GIT binary patch literal 844 zcmchWv1*oK426%-q1A3373CiVm!Gp#x)cVw)x}ANT!3`z zRfto3@?M0QzL4bPoRjx^`Rc{t)6*So^hfH6>dx-ycDE+0>dLO@a+ju<)tQ~q=}t{= zR7ZA1hdVT*u6DMg?Y2N_RV!Q3a*G6Ppuu98Zq1&FtcogEY1WcuRz{^OH7qDbRz!s> zG^FTtmZR*l;K*nxOHp!(t*{0R(y)XUH5P*nG*}F41WisvrZYAASW6a>;S7yjSWtAN zofhgLMQ?3cH z@BbN_zdLuN8$Fq&^G|5^vA*p+IJv(1@&5Pq-kUF%x5ppuJ$ij{vc3QO{9ya``>*Z0 NpPwH-ySu-uqklLoT`>Rv literal 73 zcmZ?wbhEHbWMNQbn8?83yM4F&=AG)xSBo!Ps`!(Ift}$$gAM}_faDpNq~`Rm)HGx| bz)|Q@nR~XT`cLKqjcKx#vmS;rFjxZs8p;2c3U%`ZH$g7Ccy+L3QHq0udMkooz=DDVS1b4dR9bM*Q6eIig3_%8 zhmMN1w310DS8;K4Qm6RK^C8Uigd`{Docy1w3s=rxxP4e-{g$dDtD?%QtV*3_Rz{^) zTBW)eSrHXpVHN6L&+;huaw}JlT9!qbmsy!WDrG53Ua}Gi*g%8DFx~1s9g*pomZ@G# z7Lnl@mZ4@r(Ief{EnQ8DUW+tOvoyhx(Nv^7Whu788Zb!15?a()3^veUF{~EUIpGl& zq1MM*GWT!`SIdP3Me{HV6Y3#FZ^%OyLLPoVlWFWgKO|5HYrr54OIqQd}akQ_)y}LM^ux%c$(!GPx?fT$dj}CV95e9{gG?4C_3_Kcm zfaW=HCCoz;tHyVid5C=c=NSLpKO=q9+1}g#gk~4DdGPpj(CWDq e?>?WuxO4r_{nbxvr^l1U&+pd1z8&owY5pHd^LD}j literal 114 zcmZ?wbhEHb6l73jSj52KyM4Fw=I#2c*NZP)%1~CtP*B2%*PsE38(2z_y}?R3K}19014Ow< zl*)X5hls1+vOS&|zyIdz_2t$5MqB-rdZN0sJG$Mi$*Q`tE4tjJDQ0zMXLPz#(;L;1 z9ns+q&8VxL?P$9#kXqHsR8)-z#z>ewBW&Fuz}W`Xu2tr6XIeRi9XhnS@Sr? z*LCkHt`m;U>nhW`j2_pQcQd-|m?JEOgS1G`O%{&IxJ?Vk}EJw5g-^Gar6dnrYAt)a)1uQ zJs4E@9{+T43-OcyEe6u@$@ouB7{z^Sj-P!H#=+@guh6P1u+2tr} zNYNWv;fkmb92qTT$)zZ<71n@38kW$a#$vF628&^hpvehmMy5s|Ysu_%q&0G3K{1>W z8A3gz=uJ5lDdgb?G?~T@^g{xLum%j$u%s0pECw5Bur$t1nVbk)VT)4Plw*OzxQy6l)EEQN!#NY70cj{#oLJO{3Xd1zvlKi_VzKk*j% ze#qGV+dPtf>-j95e?m{rba(jl_5R1t5BK}+#rOBOuWpW>`Q!Q3$*(WRvHSD(+v)D> J@#6!%{116VTx9?N literal 73 zcmZ?wbhEHbWMNQbn8?83yM4F&=AG)xSBo!Ps`!(Ift}$$gAM}_faDpNq~`Rm6i;H1 b;bCs#`nYx1=lPA%9(~Kg7cI9CVXy`O4=@(3 diff --git a/build/shared/lib/theme/theme.txt b/build/shared/lib/theme/theme.txt index a0889e64a..d3404179c 100644 --- a/build/shared/lib/theme/theme.txt +++ b/build/shared/lib/theme/theme.txt @@ -1,35 +1,35 @@ # GUI - STATUS -status.notice.fgcolor = #002325 -status.notice.bgcolor = #17A1A5 -status.error.fgcolor = #FFFFFF -status.error.bgcolor = #E34C00 +status.notice.fgcolor = #000000 +status.notice.bgcolor = #54919e +status.error.fgcolor = #ffffff +status.error.bgcolor = #662000 status.edit.fgcolor = #000000 -status.edit.bgcolor = #F1B500 +status.edit.bgcolor = #cc9900 status.font = SansSerif,plain,12 # GUI - TABS # settings for the tabs at the top # (tab images are stored in the lib/theme folder) -header.bgcolor = #17A1A5 -header.text.selected.color = #005B5B -header.text.unselected.color = #007e82 +header.bgcolor = #216886 +header.text.selected.color = #1a1a00 +header.text.unselected.color = #ffffff header.text.font = SansSerif,plain,12 # GUI - CONSOLE console.font = Monospaced,plain,11 console.font.macosx = Monaco,plain,10 console.color = #000000 -console.output.color = #eeeeee -console.error.color = #E34C00 +console.output.color = #cccccc +console.error.color = #ff3000 # GUI - BUTTONS -buttons.bgcolor = #006468 +buttons.bgcolor = #044f6f buttons.status.font = SansSerif,plain,12 buttons.status.color = #ffffff -# GUI - LINESTATUS -linestatus.color = #17A1A5 -linestatus.bgcolor = #006468 +# GUI - LINESTATUS +linestatus.color = #ffffff +linestatus.bgcolor = #044f6f # EDITOR - DETAILS diff --git a/build/windows/launcher/about.bmp b/build/windows/launcher/about.bmp index 19b6904b84be4dfd735f717af5fb7b3a689fa704..c8eceac06d0020ef6439eaea893f9084d61f2ade 100755 GIT binary patch literal 382854 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 literal 468054 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⋘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

    c|E=&|M)3!w?EW#(OPnWW?$GlcxhE@3c10RB2s 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

    3c z1=j@Ek=ki#|xB{Ch(pSW=^~FnOrVx1!gG#oLNb~ z2vgClj+T^Jra;hmIZ{aB06W9)2vtK)$F#EMgt|~dXNQp&+KuL(Vb&g@4402JSG6eX zqm@u4OM?(OLcZG+i)Kv6ZytHfs>`t>BIl>CGSGo8?>{%WX)qZl zq9&|{8hT6tJuzsphG#2riV=aMiBm-%po}5Jj0}&+F0gSyH?Pyi3%HeLcfe>g;r)@c ziox$|JM#Z+@9})qSU6y0UAdqG0jxy(mCrr-GZ#G$K`>`Y?|^gcIG6pGzzh9-ZQ3_4 zO?QqLL=DhHW^R}rs{4#W$?1$O?ZYkg!QN+a7gxuO5I~qq>Hc-3`-2z-6l68b>BhpO zS>T0s;ebnpfn-Gv92E?XKsTpcJPk@0M5_SR#tDzy4+h)C3jya~@|ad(gp?VDRo+|0Qz`b&9)sxE?D=hu8LcXGftSLZK1@axPg#XE1Hq9j<{5<>Tr}R|S;Q!c2 zXgtCHh33?F0sTk~nvdiLS>?yJN(0XLC#@Yhvr@4IAcBmDD8m5@l*ypNp35CmI)+2~ zQ8=QflLZm{Z=}%U4nTd`>@p3!R~|z(ssi(c|DKg3I_N~8Vva1Jl-@PiJEYl1SPdMb z5H1ik*mekmU?VUGDJ9Xv3ml0%ix)f}>Ckz<^U7#`aB={A>;j_6#ET!?whM<6k?8a8 zXC@I5YfWk*m+-+soN@Z{o?CI}_8!lP7t#gN;A18zjf>Snjh$+^H6wI;L7i^kg>+KV z;)Oo0lLvV5C{jR};{{Pb29w4O<{(XYV$HJ9G$K-=97^P*rHoKn%U)Q8Yv>+)Zu*fF z9RF<&nQkvkFunqMr$B0}!ZW9x7aAXR_Tf}DMnU0-W-r)%nvTG=WQi}jD=D3&PDfq<(&JOI(0BnEMgY>4_Bb`lpt=Ih zwi;9n{P$Mdi9Ux8K=tE4zBa*SQivmL(x@S8*1EH(&>jJ_7ae?9^Hd^D6`(V60bY1BxaG&5bUZWH5e&)5GdEytZdTQ^k=ZXtphs2Rry8I`g zC#aPDk>p2mTctr3BSc8cPfw9N*wh94Gs3_N)hlaYh9&_)gw6{?e9&Dx95M0&RKlt7 z9}MZfqX0Iv=YtR>tPpg{MVN~&h(^PANST7b}`|sQyDK?_-TC~#GMsy z^4b=)QmBnnhk9w|D^%K*nUqZWzn*0*Dl9C-l~Qt1j*^s} z^pcBQynsA?u7PwYnG37Jl>~~-l^jp=WhQDI+U1Mom(t3S!Exluo6(UQ<-$t2O6wE- z>*S|tbkL0jP62$`2(zssypWVEwUF*da*LAHkYB~Nq^ zCu&bYdwR+=h>BY&dnGv-VfWEAuRBap_Cl_W=O;3$av=iKL6jj5*$c^XltE=IXTLpyWmt7!<;PyOp2`#}}{>@G?OYTJP+=G;t#U4(tAk`ABPtFC^mp zYTWtnh|k&K_vu*I0eA~D+|-8c*4Uh9Gk^taX|*^Jq@0hr9g!v zepYQI2p)0u^Z)@uz&y%I*)b_VTD56Uq~S=(TuYk!rZ5jP*&w~1)Hauwj$ER5enUdP0 z(kK;r=u6%J1eQEAO%ZV5<<9GlTyxA{t@??z!(% z=UjIGcOD7U>-*_{quh1Vzgpnz2mYP<>B0llEAH%8!LTIeZ5A(t5h@i;^ubaD0KW<8W$sp$HRYze^+8&A zL22g&I3is;TrkRL=*7_l?b|T2oX;f~{~IsZa0o`Nk`@G|%!rE1$`p%!2HQK{#uf-K zq(DI{SCu?o8#EU3D;&_aMN;7o`{);+gxqjJ19OuLjL@#?afFGX78lknm;mEl>QP7K zN?&6rH6_QdG2hkPRea%Sk|wKuf>B5rY5e2T2512FyQdkDMoC&`g4<6UZ)l)07gp$8 zP<6I{qKmP8Knn-N41!hHLSg8y{16bSe?*m|SdG`HPgn{gzz$dq zm=6E~nzK}6p>C-8u+&9XDApBwlJLq79JuG2RU7C{QeJx%j#E=)pc~d^hfBBvzHu^qT zf5i*27ifxlWn143k|rIuQaZ)5>0E~zyI5q*hjd1IVuY9pHHs_zr;mdG?%*C4_DM?W z{+$9wlqk3eu#CKbCg3xUR42^oCPo!YVbT!~M>$ym_7OaDVWy;xyuh_%Z6b~VkR=zG zBXCNAuuNYEK@H<2d6=22dJV-3iv~hH()d}Zc6_!mYh@X$YCZrxR?@zQPLw@sx}?79 zv7S;QfG_#d>A=hS1Lc5h=J3Fe0vbA#?1p)bV1nI48 z^OX8*Rmg%Pm>-Z∋CmgVLxU~E60|GJU34X4Fr+4 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 -#include -#include "WConstants.h" -#include "pins_arduino.h" -#include "SoftwareSerial.h" -#include "icrmacros.h" -// -// Lookup table -// -typedef struct _DELAY_TABLE -{ - long baud; - unsigned short rx_delay_centering; - unsigned short rx_delay_intrabit; - unsigned short rx_delay_stopbit; - unsigned short tx_delay; -} DELAY_TABLE; - -#if F_CPU == 16000000 - -static const DELAY_TABLE PROGMEM table[] = -{ - // baud rxcenter rxintra rxstop tx - { 115200, 1, 17, 17, 12, }, - { 57600, 10, 37, 37, 33, }, - { 38400, 25, 57, 57, 54, }, - { 31250, 31, 70, 70, 68, }, - { 28800, 34, 77, 77, 74, }, - { 19200, 54, 117, 117, 114, }, - { 14400, 74, 156, 156, 153, }, - { 9600, 114, 236, 236, 233, }, - { 4800, 233, 474, 474, 471, }, - { 2400, 471, 950, 950, 947, }, - { 1200, 947, 1902, 1902, 1899, }, - { 300, 3804, 7617, 7617, 7614, }, -}; - -const int XMIT_START_ADJUSTMENT = 5; - -#elif F_CPU == 8000000 - -static const DELAY_TABLE table[] PROGMEM = -{ - // baud rxcenter rxintra rxstop tx - { 115200, 1, 5, 5, 3, }, - { 57600, 1, 15, 15, 13, }, - { 38400, 2, 25, 26, 23, }, - { 31250, 7, 32, 33, 29, }, - { 28800, 11, 35, 35, 32, }, - { 19200, 20, 55, 55, 52, }, - { 14400, 30, 75, 75, 72, }, - { 9600, 50, 114, 114, 112, }, - { 4800, 110, 233, 233, 230, }, - { 2400, 229, 472, 472, 469, }, - { 1200, 467, 948, 948, 945, }, - { 300, 1895, 3805, 3805, 3802, }, -}; - -const int XMIT_START_ADJUSTMENT = 4; - -#elif F_CPU == 20000000 - -// 20MHz support courtesy of the good people at macegr.com. -// Thanks, Garrett! - -static const DELAY_TABLE PROGMEM table[] = -{ - // baud rxcenter rxintra rxstop tx - { 115200, 3, 21, 21, 18, }, - { 57600, 20, 43, 43, 41, }, - { 38400, 37, 73, 73, 70, }, - { 31250, 45, 89, 89, 88, }, - { 28800, 46, 98, 98, 95, }, - { 19200, 71, 148, 148, 145, }, - { 14400, 96, 197, 197, 194, }, - { 9600, 146, 297, 297, 294, }, - { 4800, 296, 595, 595, 592, }, - { 2400, 592, 1189, 1189, 1186, }, - { 1200, 1187, 2379, 2379, 2376, }, - { 300, 4759, 9523, 9523, 9520, }, -}; - -const int XMIT_START_ADJUSTMENT = 6; - -#else - -#error This version of SoftwareSerial supports only 20, 16 and 8MHz processors - -#endif - -// -// Statics -// -SoftwareSerial *SoftwareSerial::active_object = 0; -char SoftwareSerial::_receive_buffer[_SS_MAX_RX_BUFF]; -volatile uint8_t SoftwareSerial::_receive_buffer_tail = 0; -volatile uint8_t SoftwareSerial::_receive_buffer_head = 0; - -// -// Debugging -// -// This function generates a brief pulse -// for debugging or measuring on an oscilloscope. -inline void DebugPulse(uint8_t pin, uint8_t count) -{ -#if _DEBUG - volatile uint8_t *pport = portOutputRegister(digitalPinToPort(pin)); - - uint8_t val = *pport; - while (count--) - { - *pport = val | digitalPinToBitMask(pin); - *pport = val; - } -#endif -} - -// -// Private methods -// - -/* static */ -inline void SoftwareSerial::tunedDelay(uint16_t delay) { - uint8_t tmp=0; - - asm volatile("sbiw %0, 0x01 \n\t" - "ldi %1, 0xFF \n\t" - "cpi %A0, 0xFF \n\t" - "cpc %B0, %1 \n\t" - "brne .-10 \n\t" - : "+r" (delay), "+a" (tmp) - : "0" (delay) - ); -} - -// This function sets the current object as the "listening" -// one and returns true if it replaces another -bool SoftwareSerial::listen() -{ - if (active_object != this) - { - _buffer_overflow = false; - uint8_t oldSREG = SREG; - cli(); - _receive_buffer_head = _receive_buffer_tail = 0; - active_object = this; - SREG = oldSREG; - return true; - } - - return false; -} - -// -// The receive routine called by the interrupt handler -// -void SoftwareSerial::recv() -{ - -#if GCC_VERSION < 40302 -// Work-around for avr-gcc 4.3.0 OSX version bug -// Preserve the registers that the compiler misses -// (courtesy of Arduino forum user *etracer*) - asm volatile( - "push r18 \n\t" - "push r19 \n\t" - "push r20 \n\t" - "push r21 \n\t" - "push r22 \n\t" - "push r23 \n\t" - "push r26 \n\t" - "push r27 \n\t" - ::); -#endif - - uint8_t d = 0; - - // If RX line is high, then we don't see any start bit - // so interrupt is probably not for us - if (_inverse_logic ? rx_pin_read() : !rx_pin_read()) - { - // Wait approximately 1/2 of a bit width to "center" the sample - tunedDelay(_rx_delay_centering); - DebugPulse(_DEBUG_PIN2, 1); - - // Read each of the 8 bits - for (uint8_t i=0x1; i; i <<= 1) - { - tunedDelay(_rx_delay_intrabit); - DebugPulse(_DEBUG_PIN2, 1); - uint8_t noti = ~i; - if (rx_pin_read()) - d |= i; - else // else clause added to ensure function timing is ~balanced - d &= noti; - } - - // skip the stop bit - tunedDelay(_rx_delay_stopbit); - DebugPulse(_DEBUG_PIN2, 1); - - if (_inverse_logic) - d = ~d; - - // if buffer full, set the overflow flag and return - if ((_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF != _receive_buffer_head) - { - // save new data in buffer: tail points to where byte goes - _receive_buffer[_receive_buffer_tail] = d; // save new byte - _receive_buffer_tail = (_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF; - } - else - { -#if _DEBUG // for scope: pulse pin as overflow indictator - DebugPulse(_DEBUG_PIN1, 1); -#endif - _buffer_overflow = true; - } - } - -#if GCC_VERSION < 40302 -// Work-around for avr-gcc 4.3.0 OSX version bug -// Restore the registers that the compiler misses - asm volatile( - "pop r27 \n\t" - "pop r26 \n\t" - "pop r23 \n\t" - "pop r22 \n\t" - "pop r21 \n\t" - "pop r20 \n\t" - "pop r19 \n\t" - "pop r18 \n\t" - ::); -#endif -} - -void SoftwareSerial::tx_pin_write(uint8_t pin_state) -{ - if (pin_state == LOW) - *_transmitPortRegister &= ~_transmitBitMask; - else - *_transmitPortRegister |= _transmitBitMask; -} - -uint8_t SoftwareSerial::rx_pin_read() -{ - return *_receivePortRegister & _receiveBitMask; -} - -// -// Interrupt handling -// - -/* static */ -inline void SoftwareSerial::handle_interrupt() -{ - if (active_object) - { - active_object->recv(); - } -} - -#if defined(PCINT0_vect) -ISR(PCINT0_vect) -{ - SoftwareSerial::handle_interrupt(); -} -#endif - -#if defined(PCINT1_vect) -ISR(PCINT1_vect) -{ - SoftwareSerial::handle_interrupt(); -} -#endif - -#if defined(PCINT2_vect) -ISR(PCINT2_vect) -{ - SoftwareSerial::handle_interrupt(); -} -#endif - -#if defined(PCINT3_vect) -ISR(PCINT3_vect) -{ - SoftwareSerial::handle_interrupt(); -} -#endif - -// -// Constructor -// -SoftwareSerial::SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic /* = false */) : - _rx_delay_centering(0), - _rx_delay_intrabit(0), - _rx_delay_stopbit(0), - _tx_delay(0), - _buffer_overflow(false), - _inverse_logic(inverse_logic) -{ - setTX(transmitPin); - setRX(receivePin); -} - -// -// Destructor -// -SoftwareSerial::~SoftwareSerial() -{ - end(); -} - -void SoftwareSerial::setTX(uint8_t tx) -{ - pinMode(tx, OUTPUT); - digitalWrite(tx, HIGH); - _transmitBitMask = digitalPinToBitMask(tx); - uint8_t port = digitalPinToPort(tx); - _transmitPortRegister = portOutputRegister(port); -} - -void SoftwareSerial::setRX(uint8_t rx) -{ - pinMode(rx, INPUT); - if (!_inverse_logic) - digitalWrite(rx, HIGH); // pullup for normal logic! - _receivePin = rx; - _receiveBitMask = digitalPinToBitMask(rx); - uint8_t port = digitalPinToPort(rx); - _receivePortRegister = portInputRegister(port); -} - -// -// Public methods -// - -void SoftwareSerial::begin(long speed) -{ - _rx_delay_centering = _rx_delay_intrabit = _rx_delay_stopbit = _tx_delay = 0; - - for (unsigned i=0; i 0) { + buf[i++] = n % base; + n /= base; + } + + for (; i > 0; i--) + print((char) (buf[i - 1] < 10 ? '0' + buf[i - 1] : 'A' + buf[i - 1] - 10)); +} diff --git a/libraries/SoftwareSerial/SoftwareSerial.h b/libraries/SoftwareSerial/SoftwareSerial.h index d7cea594d..95753fc09 100755 --- a/libraries/SoftwareSerial/SoftwareSerial.h +++ b/libraries/SoftwareSerial/SoftwareSerial.h @@ -1,113 +1,56 @@ -/* -SoftwareSerial.h (formerly NewSoftSerial.h) - -Multi-instance software serial library for Arduino/Wiring --- Interrupt-driven receive and other improvements by ladyada - (http://ladyada.net) --- Tuning, circular buffer, derivation from class Print/Stream, - multi-instance support, porting to 8MHz processors, - various optimizations, PROGMEM delay tables, inverse logic and - direct port writing by Mikal Hart (http://www.arduiniana.org) --- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com) --- 20MHz processor support by Garrett Mace (http://www.macetech.com) --- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/) - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library 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 -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -The latest version of this library can always be found at -http://arduiniana.org. -*/ - -#ifndef SoftwareSerial_h -#define SoftwareSerial_h - -#include -#include - -/****************************************************************************** -* Definitions -******************************************************************************/ - -#define _SS_MAX_RX_BUFF 64 // RX buffer size -#define _SS_VERSION 11 // software version of this library -#ifndef GCC_VERSION -#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) -#endif - -class SoftwareSerial : public Stream -{ -private: - // per object data - uint8_t _receivePin; - uint8_t _receiveBitMask; - volatile uint8_t *_receivePortRegister; - uint8_t _transmitBitMask; - volatile uint8_t *_transmitPortRegister; - - uint16_t _rx_delay_centering; - uint16_t _rx_delay_intrabit; - uint16_t _rx_delay_stopbit; - uint16_t _tx_delay; - - uint16_t _buffer_overflow:1; - uint16_t _inverse_logic:1; - - // static data - static char _receive_buffer[_SS_MAX_RX_BUFF]; - static volatile uint8_t _receive_buffer_tail; - static volatile uint8_t _receive_buffer_head; - static SoftwareSerial *active_object; - - // private methods - void recv(); - uint8_t rx_pin_read(); - void tx_pin_write(uint8_t pin_state); - void setTX(uint8_t transmitPin); - void setRX(uint8_t receivePin); - - // private static method for timing - static inline void tunedDelay(uint16_t delay); - -public: - // public methods - SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic = false); - ~SoftwareSerial(); - void begin(long speed); - bool listen(); - void end(); - bool is_listening() { return this == active_object; } - bool overflow() { bool ret = _buffer_overflow; _buffer_overflow = false; return ret; } - static int library_version() { return _SS_VERSION; } - static void enable_timer0(bool enable); - int peek(); - - virtual void write(uint8_t byte); - virtual int read(); - virtual int available(); - virtual void flush(); - - // public only for easy access by interrupt handlers - static inline void handle_interrupt(); -}; - -// Arduino 0012 workaround -#undef int -#undef char -#undef long -#undef byte -#undef float -#undef abs -#undef round - -#endif +/* + SoftwareSerial.h - Software serial library + Copyright (c) 2006 David A. Mellis. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef SoftwareSerial_h +#define SoftwareSerial_h + +#include + +class SoftwareSerial +{ + private: + uint8_t _receivePin; + uint8_t _transmitPin; + long _baudRate; + int _bitPeriod; + void printNumber(unsigned long, uint8_t); + public: + SoftwareSerial(uint8_t, uint8_t); + void begin(long); + int read(); + void print(char); + void print(const char[]); + void print(uint8_t); + void print(int); + void print(unsigned int); + void print(long); + void print(unsigned long); + void print(long, int); + void println(void); + void println(char); + void println(const char[]); + void println(uint8_t); + void println(int); + void println(long); + void println(unsigned long); + void println(long, int); +}; + +#endif + diff --git a/libraries/SoftwareSerial/examples/SoftwareSerialExample/SoftwareSerialExample.pde b/libraries/SoftwareSerial/examples/SoftwareSerialExample/SoftwareSerialExample.pde deleted file mode 100755 index fe9f89146..000000000 --- a/libraries/SoftwareSerial/examples/SoftwareSerialExample/SoftwareSerialExample.pde +++ /dev/null @@ -1,21 +0,0 @@ -#include - -SoftwareSerial mySerial(2, 3); - -void setup() -{ - Serial.begin(57600); - Serial.println("Goodnight moon!"); - - // set the data rate for the SoftwareSerial port - mySerial.begin(4800); - mySerial.println("Hello, world?"); -} - -void loop() // run over and over -{ - if (mySerial.available()) - Serial.print((char)mySerial.read()); - if (Serial.available()) - mySerial.print((char)Serial.read()); -} diff --git a/libraries/SoftwareSerial/examples/TwoPortRXExample/TwoPortRXExample.pde b/libraries/SoftwareSerial/examples/TwoPortRXExample/TwoPortRXExample.pde deleted file mode 100755 index 1db4536de..000000000 --- a/libraries/SoftwareSerial/examples/TwoPortRXExample/TwoPortRXExample.pde +++ /dev/null @@ -1,50 +0,0 @@ -#include - -SoftwareSerial ss(2, 3); -SoftwareSerial ss2(4, 5); - -/* This sample shows how to correctly process received data - on two different "soft" serial ports. Here we listen on - the first port (ss) until we receive a '?' character. Then - we begin listening on the other soft port. -*/ - -void setup() -{ - // Start the HW serial port - Serial.begin(57600); - - // Start each soft serial port - ss.begin(4800); - ss2.begin(4800); - - // By default, the most recently "begun" port is listening. - // We want to listen on ss, so let's explicitly select it. - ss.listen(); - - // Simply wait for a ? character to come down the pipe - Serial.println("Data from the first port: "); - char c = 0; - do - if (ss.available()) - { - c = (char)ss.read(); - Serial.print(c); - } - while (c != '?'); - - // Now listen on the second port - ss2.listen(); - - Serial.println("Data from the second port: "); -} - -void loop() -{ - if (ss2.available()) - { - char c = (char)ss2.read(); - Serial.print(c); - } -} - diff --git a/libraries/SoftwareSerial/icrmacros.h b/libraries/SoftwareSerial/icrmacros.h deleted file mode 100755 index b29f6ffd5..000000000 --- a/libraries/SoftwareSerial/icrmacros.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -icrmacros.h - -A place to put useful ICR (interrupt change register) macros - -If you want to support non-Arduino processors you can extend or replace -this file. - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library 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 -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -The latest version of this library can always be found at -http://arduiniana.org. -*/ - -// Abstractions for maximum portability between processors -// These are macros to associate pins to pin change interrupts -#if !defined(digitalPinToPCICR) // Courtesy Paul Stoffregen - -#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) - -#define digitalPinToPCICR(p) (((p) >= 0 && (p) <= 21) ? (&PCICR) : ((uint8_t *)0)) -#define digitalPinToPCICRbit(p) (((p) <= 7) ? 2 : (((p) <= 13) ? 0 : 1)) -#define digitalPinToPCMSK(p) (((p) <= 7) ? (&PCMSK2) : (((p) <= 13) ? (&PCMSK0) : (((p) <= 21) ? (&PCMSK1) : ((uint8_t *)0)))) -#define digitalPinToPCMSKbit(p) (((p) <= 7) ? (p) : (((p) <= 13) ? ((p) - 8) : ((p) - 14))) - -#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) -// Specifically for the Arduino Mega 2560 (or 1280 on the original Arduino Mega) -// A majority of the pins are NOT PCINTs, SO BE WARNED (i.e. you cannot use them as receive pins) -// Only pins available for RECEIVE (TRANSMIT can be on any pin): -// (I've deliberately left out pin mapping to the Hardware USARTs - seems senseless to me) -// Pins: 10, 11, 12, 13, 50, 51, 52, 53, 62, 63, 64, 65, 66, 67, 68, 69 - -#define digitalPinToPCICR(p) ( (((p) >= 10) && ((p) <= 13)) || \ - (((p) >= 50) && ((p) <= 53)) || \ - (((p) >= 62) && ((p) <= 69)) ? (&PCICR) : ((uint8_t *)0) ) - -#define digitalPinToPCICRbit(p) ( (((p) >= 10) && ((p) <= 13)) || (((p) >= 50) && ((p) <= 53)) ? 0 : \ - ( (((p) >= 62) && ((p) <= 69)) ? 2 : \ - 0 ) ) - -#define digitalPinToPCMSK(p) ( (((p) >= 10) && ((p) <= 13)) || (((p) >= 50) && ((p) <= 53)) ? (&PCMSK0) : \ - ( (((p) >= 62) && ((p) <= 69)) ? (&PCMSK2) : \ - ((uint8_t *)0) ) ) - -#define digitalPinToPCMSKbit(p) ( (((p) >= 10) && ((p) <= 13)) ? ((p) - 6) : \ - ( ((p) == 50) ? 3 : \ - ( ((p) == 51) ? 2 : \ - ( ((p) == 52) ? 1 : \ - ( ((p) ==53) ? 0 : \ - ( (((p) >= 62) && ((p) <= 69)) ? ((p) - 62) : \ - 0 ) ) ) ) ) ) - -#else -#error This processor is not supported by SoftwareSerial -#endif -#endif - diff --git a/libraries/SoftwareSerial/keywords.txt b/libraries/SoftwareSerial/keywords.txt old mode 100755 new mode 100644 index 2ed9642e5..de5a74c77 --- a/libraries/SoftwareSerial/keywords.txt +++ b/libraries/SoftwareSerial/keywords.txt @@ -1,28 +1,17 @@ ####################################### -# Syntax Coloring Map for NewSoftSerial +# Syntax Coloring Map For Ultrasound ####################################### ####################################### # Datatypes (KEYWORD1) ####################################### -NewSoftSerial KEYWORD1 +SoftwareSerial KEYWORD1 ####################################### # Methods and Functions (KEYWORD2) ####################################### -begin KEYWORD2 -end KEYWORD2 -read KEYWORD2 -available KEYWORD2 -is_listening KEYWORD2 -overflow KEYWORD2 -library_version KEYWORD2 -enable_timer0 KEYWORD2 -flush KEYWORD2 -listen KEYWORD2 - ####################################### # Constants (LITERAL1) ####################################### From 13e3ba87e3b89910be202de1a8b65c23add2d1b8 Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Fri, 25 Feb 2011 18:36:46 -0500 Subject: [PATCH 04/33] Small optimization in HardwareSerial. begin(long) -> begin(unsigned long) --- hardware/arduino/cores/arduino/HardwareSerial.cpp | 2 +- hardware/arduino/cores/arduino/HardwareSerial.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hardware/arduino/cores/arduino/HardwareSerial.cpp b/hardware/arduino/cores/arduino/HardwareSerial.cpp index 4397efb7e..38e87c49f 100644 --- a/hardware/arduino/cores/arduino/HardwareSerial.cpp +++ b/hardware/arduino/cores/arduino/HardwareSerial.cpp @@ -191,7 +191,7 @@ HardwareSerial::HardwareSerial(ring_buffer *rx_buffer, // Public Methods ////////////////////////////////////////////////////////////// -void HardwareSerial::begin(long baud) +void HardwareSerial::begin(unsigned long baud) { uint16_t baud_setting; bool use_u2x = true; diff --git a/hardware/arduino/cores/arduino/HardwareSerial.h b/hardware/arduino/cores/arduino/HardwareSerial.h index 3efa775f8..9dc67c4c9 100644 --- a/hardware/arduino/cores/arduino/HardwareSerial.h +++ b/hardware/arduino/cores/arduino/HardwareSerial.h @@ -48,7 +48,7 @@ class HardwareSerial : public Stream volatile uint8_t *ucsra, volatile uint8_t *ucsrb, volatile uint8_t *udr, uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x); - void begin(long); + void begin(unsigned long); void end(); virtual int available(void); virtual int peek(void); From e031022a68f641439ebdc0abf533bab38ad9bcd6 Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Fri, 25 Feb 2011 18:44:43 -0500 Subject: [PATCH 05/33] Removing O_SYNC from FILE_WRITE mode for the SD File class. --- libraries/SD/SD.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/SD/SD.h b/libraries/SD/SD.h index 2c5c323a8..d1e53debc 100644 --- a/libraries/SD/SD.h +++ b/libraries/SD/SD.h @@ -21,7 +21,7 @@ #include #define FILE_READ O_READ -#define FILE_WRITE (O_READ | O_WRITE | O_CREAT | O_SYNC) +#define FILE_WRITE (O_READ | O_WRITE | O_CREAT) class File : public Stream { public: From 6739f20bbf7b3a200239ef877961688cbadee3cb Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Sat, 26 Feb 2011 13:57:41 -0500 Subject: [PATCH 06/33] Modifying examples to use Serial.write() instead of Serial.print(BYTE). --- .../examples/4.Communication/ASCIITable/ASCIITable.pde | 2 +- build/shared/examples/4.Communication/MIDI/Midi.pde | 6 +++--- .../4.Communication/MultiSerialMega/MultiSerialMega.pde | 2 +- .../SerialCallResponse/SerialCallResponse.pde | 8 ++++---- libraries/Firmata/examples/EchoString/EchoString.pde | 8 ++++---- .../examples/TextDirection/TextDirection.pde | 2 +- libraries/LiquidCrystal/examples/setCursor/setCursor.pde | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/build/shared/examples/4.Communication/ASCIITable/ASCIITable.pde b/build/shared/examples/4.Communication/ASCIITable/ASCIITable.pde index 3678836b3..c92b0d023 100644 --- a/build/shared/examples/4.Communication/ASCIITable/ASCIITable.pde +++ b/build/shared/examples/4.Communication/ASCIITable/ASCIITable.pde @@ -38,7 +38,7 @@ void loop() // prints value unaltered, i.e. the raw binary version of the // byte. The serial monitor interprets all bytes as // ASCII, so 33, the first number, will show up as '!' - Serial.print(thisByte, BYTE); + Serial.write(thisByte); Serial.print(", dec: "); // prints value as string as an ASCII-encoded decimal (base 10). diff --git a/build/shared/examples/4.Communication/MIDI/Midi.pde b/build/shared/examples/4.Communication/MIDI/Midi.pde index 3d34a18cc..cdeaeea11 100644 --- a/build/shared/examples/4.Communication/MIDI/Midi.pde +++ b/build/shared/examples/4.Communication/MIDI/Midi.pde @@ -42,8 +42,8 @@ void loop() { // plays a MIDI note. Doesn't check to see that // cmd is greater than 127, or that data values are less than 127: void noteOn(int cmd, int pitch, int velocity) { - Serial.print(cmd, BYTE); - Serial.print(pitch, BYTE); - Serial.print(velocity, BYTE); + Serial.write(cmd); + Serial.write(pitch); + Serial.write(velocity); } diff --git a/build/shared/examples/4.Communication/MultiSerialMega/MultiSerialMega.pde b/build/shared/examples/4.Communication/MultiSerialMega/MultiSerialMega.pde index 788bc908e..684e305bb 100644 --- a/build/shared/examples/4.Communication/MultiSerialMega/MultiSerialMega.pde +++ b/build/shared/examples/4.Communication/MultiSerialMega/MultiSerialMega.pde @@ -28,6 +28,6 @@ void loop() { // read from port 1, send to port 0: if (Serial1.available()) { int inByte = Serial1.read(); - Serial.print(inByte, BYTE); + Serial.write(inByte); } } diff --git a/build/shared/examples/4.Communication/SerialCallResponse/SerialCallResponse.pde b/build/shared/examples/4.Communication/SerialCallResponse/SerialCallResponse.pde index 6f56d9891..e3565152a 100644 --- a/build/shared/examples/4.Communication/SerialCallResponse/SerialCallResponse.pde +++ b/build/shared/examples/4.Communication/SerialCallResponse/SerialCallResponse.pde @@ -52,15 +52,15 @@ void loop() // read switch, map it to 0 or 255L thirdSensor = map(digitalRead(2), 0, 1, 0, 255); // send sensor values: - Serial.print(firstSensor, BYTE); - Serial.print(secondSensor, BYTE); - Serial.print(thirdSensor, BYTE); + Serial.write(firstSensor); + Serial.write(secondSensor); + Serial.write(thirdSensor); } } void establishContact() { while (Serial.available() <= 0) { - Serial.print('A', BYTE); // send a capital A + Serial.print('A'); // send a capital A delay(300); } } diff --git a/libraries/Firmata/examples/EchoString/EchoString.pde b/libraries/Firmata/examples/EchoString/EchoString.pde index 6559ae1c6..e5c4e6fe5 100644 --- a/libraries/Firmata/examples/EchoString/EchoString.pde +++ b/libraries/Firmata/examples/EchoString/EchoString.pde @@ -14,12 +14,12 @@ void stringCallback(char *myString) void sysexCallback(byte command, byte argc, byte*argv) { - Serial.print(START_SYSEX, BYTE); - Serial.print(command, BYTE); + Serial.write(START_SYSEX); + Serial.write(command); for(byte i=0; i Date: Tue, 1 Mar 2011 07:13:18 -0500 Subject: [PATCH 07/33] Added CardInfo example to SD libary examples --- libraries/SD/examples/CardInfo/CardInfo.pde | 108 ++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 libraries/SD/examples/CardInfo/CardInfo.pde diff --git a/libraries/SD/examples/CardInfo/CardInfo.pde b/libraries/SD/examples/CardInfo/CardInfo.pde new file mode 100644 index 000000000..f81e21d17 --- /dev/null +++ b/libraries/SD/examples/CardInfo/CardInfo.pde @@ -0,0 +1,108 @@ +/* + SD card test + + This example shows how use the utility libraries on which the' + SD library is based in order to get info about your SD card. + Very useful for testing a card when you're not sure whether its working or not. + + The circuit: + * SD card attached to SPI bus as follows: + ** MOSI - pin 11 on Arduino Uno/Duemilanove/Diecimila + ** MISO - pin 12 on Arduino Uno/Duemilanove/Diecimila + ** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila + ** CS - depends on your SD card shield or module + + + created 28 Mar 2011 + by Limor Fried + */ + // include the SD library: +#include + +// set up variables using the SD utility library functions: +Sd2Card card; +SdVolume volume; +SdFile root; + +// change this to match your SD shield or module; +// Arduino Ethernet shield: pin 4 +// Adafruit SD shields and modules: pin 10 +// Sparkfun SD shield: pin 8 +const int chipSelect = 8; + +void setup() +{ + Serial.begin(9600); + Serial.print("\nInitializing SD card..."); + // On the Ethernet Shield, CS is pin 4. It's set as an output by default. + // Note that even if it's not used as the CS pin, the hardware SS pin + // (10 on most Arduino boards, 53 on the Mega) must be left as an output + // or the SD library functions will not work. + pinMode(10, OUTPUT); // change this to 53 on a mega + + + // we'll use the initialization code from the utility libraries + // since we're just testing if the card is working! + if (!card.init(SPI_HALF_SPEED, chipSelect)) { + Serial.println("initialization failed. Things to check:"); + Serial.println("* is a card is inserted?"); + Serial.println("* Is your wiring correct?"); + Serial.println("* did you change the chipSelect pin to match your shield or module?"); + return; + } else { + Serial.println("Wiring is correct and a card is present."); + } + + // print the type of card + Serial.print("\nCard type: "); + switch(card.type()) { + case SD_CARD_TYPE_SD1: + Serial.println("SD1"); + break; + case SD_CARD_TYPE_SD2: + Serial.println("SD2"); + break; + case SD_CARD_TYPE_SDHC: + Serial.println("SDHC"); + break; + default: + Serial.println("Unknown"); + } + + // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32 + if (!volume.init(card)) { + Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card"); + return; + } + + + // print the type and size of the first FAT-type volume + long volumesize; + Serial.print("\nVolume type is FAT"); + Serial.println(volume.fatType(), DEC); + Serial.println(); + + volumesize = volume.blocksPerCluster(); // clusters are collections of blocks + volumesize *= volume.clusterCount(); // we'll have a lot of clusters + volumesize *= 512; // SD card blocks are always 512 bytes + Serial.print("Volume size (bytes): "); + Serial.println(volumesize); + Serial.print("Volume size (Kbytes): "); + volumesize /= 1024; + Serial.println(volumesize); + Serial.print("Volume size (Mbytes): "); + volumesize /= 1024; + Serial.println(volumesize); + + + Serial.println("\nFiles found on the card (name, date and size in bytes): "); + root.openRoot(volume); + + // list all files in the card with date and size + root.ls(LS_R | LS_DATE | LS_SIZE); +} + + +void loop(void) { + +} From d59fcb8eed1d06c21309cb36c6906867a9a15124 Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Thu, 3 Mar 2011 22:56:20 -0500 Subject: [PATCH 08/33] Fixing warnings (David H. Lynch Jr). --- hardware/arduino/cores/arduino/Print.cpp | 2 +- hardware/arduino/cores/arduino/WString.h | 2 +- hardware/arduino/cores/arduino/pins_arduino.c | 84 +++++++++---------- libraries/Ethernet/utility/socket.cpp | 1 - libraries/Ethernet/utility/w5100.cpp | 4 +- libraries/SD/File.cpp | 2 +- 6 files changed, 47 insertions(+), 48 deletions(-) diff --git a/hardware/arduino/cores/arduino/Print.cpp b/hardware/arduino/cores/arduino/Print.cpp index 4ee556dd8..fd689423a 100755 --- a/hardware/arduino/cores/arduino/Print.cpp +++ b/hardware/arduino/cores/arduino/Print.cpp @@ -45,7 +45,7 @@ void Print::write(const uint8_t *buffer, size_t size) void Print::print(const String &s) { - for (int i = 0; i < s.length(); i++) { + for (unsigned int i = 0; i < s.length(); i++) { write(s[i]); } } diff --git a/hardware/arduino/cores/arduino/WString.h b/hardware/arduino/cores/arduino/WString.h index cadddb947..56faf9a48 100644 --- a/hardware/arduino/cores/arduino/WString.h +++ b/hardware/arduino/cores/arduino/WString.h @@ -67,7 +67,7 @@ class String int lastIndexOf( char ch, unsigned int fromIndex ) const; int lastIndexOf( const String &str ) const; int lastIndexOf( const String &str, unsigned int fromIndex ) const; - const unsigned int length( ) const { return _length; } + unsigned int length( ) const { return _length; } void setCharAt(unsigned int index, const char ch); unsigned char startsWith( const String &prefix ) const; unsigned char startsWith( const String &prefix, unsigned int toffset ) const; diff --git a/hardware/arduino/cores/arduino/pins_arduino.c b/hardware/arduino/cores/arduino/pins_arduino.c index 0c816e94d..62e10ad15 100755 --- a/hardware/arduino/cores/arduino/pins_arduino.c +++ b/hardware/arduino/cores/arduino/pins_arduino.c @@ -81,50 +81,50 @@ #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) const uint16_t PROGMEM port_to_mode_PGM[] = { NOT_A_PORT, - &DDRA, - &DDRB, - &DDRC, - &DDRD, - &DDRE, - &DDRF, - &DDRG, - &DDRH, + (uint16_t) &DDRA, + (uint16_t) &DDRB, + (uint16_t) &DDRC, + (uint16_t) &DDRD, + (uint16_t) &DDRE, + (uint16_t) &DDRF, + (uint16_t) &DDRG, + (uint16_t) &DDRH, NOT_A_PORT, - &DDRJ, - &DDRK, - &DDRL, + (uint16_t) &DDRJ, + (uint16_t) &DDRK, + (uint16_t) &DDRL, }; const uint16_t PROGMEM port_to_output_PGM[] = { NOT_A_PORT, - &PORTA, - &PORTB, - &PORTC, - &PORTD, - &PORTE, - &PORTF, - &PORTG, - &PORTH, + (uint16_t) &PORTA, + (uint16_t) &PORTB, + (uint16_t) &PORTC, + (uint16_t) &PORTD, + (uint16_t) &PORTE, + (uint16_t) &PORTF, + (uint16_t) &PORTG, + (uint16_t) &PORTH, NOT_A_PORT, - &PORTJ, - &PORTK, - &PORTL, + (uint16_t) &PORTJ, + (uint16_t) &PORTK, + (uint16_t) &PORTL, }; const uint16_t PROGMEM port_to_input_PGM[] = { NOT_A_PIN, - &PINA, - &PINB, - &PINC, - &PIND, - &PINE, - &PINF, - &PING, - &PINH, + (uint16_t) &PINA, + (uint16_t) &PINB, + (uint16_t) &PINC, + (uint16_t) &PIND, + (uint16_t) &PINE, + (uint16_t) &PINF, + (uint16_t) &PING, + (uint16_t) &PINH, NOT_A_PIN, - &PINJ, - &PINK, - &PINL, + (uint16_t) &PINJ, + (uint16_t) &PINK, + (uint16_t) &PINL, }; const uint8_t PROGMEM digital_pin_to_port_PGM[] = { @@ -358,25 +358,25 @@ const uint8_t PROGMEM digital_pin_to_timer_PGM[] = { const uint16_t PROGMEM port_to_mode_PGM[] = { NOT_A_PORT, NOT_A_PORT, - &DDRB, - &DDRC, - &DDRD, + (uint16_t) &DDRB, + (uint16_t) &DDRC, + (uint16_t) &DDRD, }; const uint16_t PROGMEM port_to_output_PGM[] = { NOT_A_PORT, NOT_A_PORT, - &PORTB, - &PORTC, - &PORTD, + (uint16_t) &PORTB, + (uint16_t) &PORTC, + (uint16_t) &PORTD, }; const uint16_t PROGMEM port_to_input_PGM[] = { NOT_A_PORT, NOT_A_PORT, - &PINB, - &PINC, - &PIND, + (uint16_t) &PINB, + (uint16_t) &PINC, + (uint16_t) &PIND, }; const uint8_t PROGMEM digital_pin_to_port_PGM[] = { diff --git a/libraries/Ethernet/utility/socket.cpp b/libraries/Ethernet/utility/socket.cpp index cad54a5e3..f9f4bb190 100644 --- a/libraries/Ethernet/utility/socket.cpp +++ b/libraries/Ethernet/utility/socket.cpp @@ -9,7 +9,6 @@ static uint16_t local_port; */ uint8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag) { - uint8_t ret; if ((protocol == SnMR::TCP) || (protocol == SnMR::UDP) || (protocol == SnMR::IPRAW) || (protocol == SnMR::MACRAW) || (protocol == SnMR::PPPOE)) { close(s); diff --git a/libraries/Ethernet/utility/w5100.cpp b/libraries/Ethernet/utility/w5100.cpp index aaf3071f7..03aca0846 100644 --- a/libraries/Ethernet/utility/w5100.cpp +++ b/libraries/Ethernet/utility/w5100.cpp @@ -134,7 +134,7 @@ uint8_t W5100Class::write(uint16_t _addr, uint8_t _data) uint16_t W5100Class::write(uint16_t _addr, uint8_t *_buf, uint16_t _len) { - for (int i=0; i<_len; i++) + for (uint16_t i=0; i<_len; i++) { setSS(); SPI.transfer(0xF0); @@ -160,7 +160,7 @@ uint8_t W5100Class::read(uint16_t _addr) uint16_t W5100Class::read(uint16_t _addr, uint8_t *_buf, uint16_t _len) { - for (int i=0; i<_len; i++) + for (uint16_t i=0; i<_len; i++) { setSS(); SPI.transfer(0x0F); diff --git a/libraries/SD/File.cpp b/libraries/SD/File.cpp index ded622c85..b93466ec1 100644 --- a/libraries/SD/File.cpp +++ b/libraries/SD/File.cpp @@ -27,7 +27,7 @@ void File::write(const uint8_t *buf, size_t size) { } int File::peek() { - char c = SD.file.read(); + int c = SD.file.read(); if (c != -1) SD.file.seekCur(-1); return c; } From df00d3e5f34a194869b7f901ef22f4da2fa5ffd9 Mon Sep 17 00:00:00 2001 From: Tom Igoe Date: Wed, 16 Mar 2011 13:53:39 -0400 Subject: [PATCH 09/33] changed CS pin on CardInfo example to make it consistent with other SD examples --- libraries/SD/examples/CardInfo/CardInfo.pde | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libraries/SD/examples/CardInfo/CardInfo.pde b/libraries/SD/examples/CardInfo/CardInfo.pde index f81e21d17..7abfd33e4 100644 --- a/libraries/SD/examples/CardInfo/CardInfo.pde +++ b/libraries/SD/examples/CardInfo/CardInfo.pde @@ -10,11 +10,14 @@ ** MOSI - pin 11 on Arduino Uno/Duemilanove/Diecimila ** MISO - pin 12 on Arduino Uno/Duemilanove/Diecimila ** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila - ** CS - depends on your SD card shield or module + ** CS - depends on your SD card shield or module. + Pin 4 used here for consistency with other Arduino examples created 28 Mar 2011 by Limor Fried + modified 16 Mar 2011 + by Tom Igoe */ // include the SD library: #include @@ -28,7 +31,7 @@ SdFile root; // Arduino Ethernet shield: pin 4 // Adafruit SD shields and modules: pin 10 // Sparkfun SD shield: pin 8 -const int chipSelect = 8; +const int chipSelect = 4; void setup() { From fcb66ddccd2b21ef7cb3585b0b25222719a1daea Mon Sep 17 00:00:00 2001 From: Tom Igoe Date: Mon, 21 Mar 2011 12:27:18 -0400 Subject: [PATCH 10/33] Added example to demonstrate LiquidCrystal chreateChar() function --- .../CustomCharacter/CustomCharacter.pde | 138 ++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 libraries/LiquidCrystal/examples/CustomCharacter/CustomCharacter.pde diff --git a/libraries/LiquidCrystal/examples/CustomCharacter/CustomCharacter.pde b/libraries/LiquidCrystal/examples/CustomCharacter/CustomCharacter.pde new file mode 100644 index 000000000..d3ce47924 --- /dev/null +++ b/libraries/LiquidCrystal/examples/CustomCharacter/CustomCharacter.pde @@ -0,0 +1,138 @@ +/* + LiquidCrystal Library - Custom Characters + + Demonstrates how to add custom characters on an LCD display. + The LiquidCrystal library works with all LCD displays that are + compatible with the Hitachi HD44780 driver. There are many of + them out there, and you can usually tell them by the 16-pin interface. + + This sketch prints "I Arduino!" and a little dancing man + to the LCD. + + The circuit: + * LCD RS pin to digital pin 12 + * LCD Enable pin to digital pin 11 + * LCD D4 pin to digital pin 5 + * LCD D5 pin to digital pin 4 + * LCD D6 pin to digital pin 3 + * LCD D7 pin to digital pin 2 + * LCD R/W pin to ground + * 10K potentiometer: + * ends to +5V and ground + * wiper to LCD VO pin (pin 3) + * 10K poterntiometer on pin A0 + + created21 Mar 2011 + by Tom Igoe + Based on Adafruit's example at + https://github.com/adafruit/SPI_VFD/blob/master/examples/createChar/createChar.pde + + This example code is in the public domain. + http://www.arduino.cc/en/Tutorial/LiquidCrystal + + Also useful: + http://icontexto.com/charactercreator/ + + */ + +// include the library code: +#include + +// initialize the library with the numbers of the interface pins +LiquidCrystal lcd(12, 11, 5, 4, 3, 2); + +// make some custom characters: +byte heart[8] = { + 0b00000, + 0b01010, + 0b11111, + 0b11111, + 0b11111, + 0b01110, + 0b00100, + 0b00000 +}; + +byte smiley[8] = { + 0b00000, + 0b00000, + 0b01010, + 0b00000, + 0b00000, + 0b10001, + 0b01110, + 0b00000 +}; + +byte frownie[8] = { + 0b00000, + 0b00000, + 0b01010, + 0b00000, + 0b00000, + 0b00000, + 0b01110, + 0b10001 +}; + +byte armsDown[8] = { + 0b00100, + 0b01010, + 0b00100, + 0b00100, + 0b01110, + 0b10101, + 0b00100, + 0b01010 +}; + +byte armsUp[8] = { + 0b00100, + 0b01010, + 0b00100, + 0b10101, + 0b01110, + 0b00100, + 0b00100, + 0b01010 +}; +void setup() { + // create a new character + lcd.createChar(0, heart); + // create a new character + lcd.createChar(1, smiley); + // create a new character + lcd.createChar(2, frownie); + // create a new character + lcd.createChar(3, armsDown); + // create a new character + lcd.createChar(4, armsUp); + + // set up the lcd's number of columns and rows: + lcd.begin(16, 2); + // Print a message to the lcd. + lcd.print("I "); + lcd.write(0); + lcd.print(" Arduino! "); + lcd.write(1); + +} + +void loop() { + // read the potentiometer on A0: + int sensorReading = analogRead(A0); + // map the result to 200 - 1000: + int delayTime = map(sensorReading, 0, 1023, 200, 1000); + // set the cursor to the bottom row, 5th position: + lcd.setCursor(4, 1); + // draw the little man, arms down: + lcd.write(3); + delay(delayTime); + lcd.setCursor(4, 1); + // draw him arms up: + lcd.write(4); + delay(delayTime); +} + + + From db64d2fc323219c3487947aa28bee07385c96a67 Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Sat, 14 May 2011 12:25:39 -0400 Subject: [PATCH 11/33] Fixing 300 baud communication for serial. Because UBBR is only 12 bits, we were overflowing it at 300 baud because of the use of the U2X bit. Now we turn off U2X if it would yield a UBBR value that would overflow. Note that this breaks 300 baud communication with the computer on the Uno and Mega 2560 because the 8U2 USB-serial firmware has this same bug (and previously they cancelled each other out). Since, however, it seems more likely that people will need to use 300 baud to communicate with other (legacy) hardware than with the computer, I'm making this change. Issue for 8U2 firmware bug: http://code.google.com/p/arduino/issues/detail?id=542 http://code.google.com/p/arduino/issues/detail?id=522 --- hardware/arduino/cores/arduino/HardwareSerial.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hardware/arduino/cores/arduino/HardwareSerial.cpp b/hardware/arduino/cores/arduino/HardwareSerial.cpp index 38e87c49f..b5dba1e4a 100644 --- a/hardware/arduino/cores/arduino/HardwareSerial.cpp +++ b/hardware/arduino/cores/arduino/HardwareSerial.cpp @@ -204,6 +204,8 @@ void HardwareSerial::begin(unsigned long baud) use_u2x = false; } #endif + +try_again: if (use_u2x) { *_ucsra = 1 << _u2x; @@ -212,6 +214,12 @@ void HardwareSerial::begin(unsigned long baud) *_ucsra = 0; baud_setting = (F_CPU / 8 / baud - 1) / 2; } + + if ((baud_setting > 4095) && use_u2x) + { + use_u2x = false; + goto try_again; + } // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register) *_ubrrh = baud_setting >> 8; From ceddbf960fc2799cde62baaeb1279a5691066137 Mon Sep 17 00:00:00 2001 From: Tom Igoe Date: Sat, 21 May 2011 09:58:52 -0400 Subject: [PATCH 12/33] Added SerialEvent() example --- .../SerialEvent/SerialEvent.ino | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 build/shared/examples/4.Communication/SerialEvent/SerialEvent.ino diff --git a/build/shared/examples/4.Communication/SerialEvent/SerialEvent.ino b/build/shared/examples/4.Communication/SerialEvent/SerialEvent.ino new file mode 100644 index 000000000..2f3f917e5 --- /dev/null +++ b/build/shared/examples/4.Communication/SerialEvent/SerialEvent.ino @@ -0,0 +1,57 @@ +/* + Serial Event example + + When new serial data arrives, this sketch adds it to a String. + When a newline is received, the loop prints the string and + clears it. + + A good test for this is to try it with a GPS receiver + that sends out NMEA 0183 sentences. + + Created 9 May 2011 + by Tom Igoe + + This example code is in the public domain. + + http://www.arduino.cc/en/Tutorial/SerialEvent + + */ + +String inputString = ""; // a string to hold incoming data +boolean stringComplete = false; // whether the string is complete + +void setup() { + // initialize serial: + Serial.begin(9600); + // reserve 200 bytes for the inputString: + inputString.reserve(200); +} + +void loop() { + // print the string when a newline arrives: + if (stringComplete) { + Serial.println(inputString); + // clear the string: + inputString = ""; + stringComplete = false; + } +} + +/* + SerialEvent occurs whenever a new byte comes in the + hardware serial RX. Don't do complex things here, as thge + processor halts the regular program to run this routine: + */ +void serialEvent() { + // get the new byte: + char inChar = (char)Serial.read(); + // add it to the inputString: + inputString += inChar; + // if the incoming character is a newline, set a flag + // so the main loop can do something about it: + if (inChar == '\n') { + stringComplete = true; + } +} + + From 4519e4b6a8d7988551bae35298f2cfdb8ef1d288 Mon Sep 17 00:00:00 2001 From: Tom Igoe Date: Sat, 21 May 2011 09:59:23 -0400 Subject: [PATCH 13/33] Added DHCP-based chat server example --- .../DhcpChatServer/DhcpChatServer.ino | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 libraries/Ethernet/examples/DhcpChatServer/DhcpChatServer.ino diff --git a/libraries/Ethernet/examples/DhcpChatServer/DhcpChatServer.ino b/libraries/Ethernet/examples/DhcpChatServer/DhcpChatServer.ino new file mode 100644 index 000000000..c3e581387 --- /dev/null +++ b/libraries/Ethernet/examples/DhcpChatServer/DhcpChatServer.ino @@ -0,0 +1,80 @@ +/* + DHCP Chat Server + + A simple server that distributes any incoming messages to all + connected clients. To use telnet to your device's IP address and type. + You can see the client's input in the serial monitor as well. + Using an Arduino Wiznet Ethernet shield. + + THis version attempts to get an IP address using DHCP + + Circuit: + * Ethernet shield attached to pins 10, 11, 12, 13 + + created 21 May 2011 + by Tom Igoe + Based on ChatServer example by David A. Mellis + + */ + +#include +#include + +// Enter a MAC address and IP address for your controller below. +// The IP address will be dependent on your local network. +// gateway and subnet are optional: +byte mac[] = { + 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 }; +IPAddress ip(192,168,1, 177); +IPAddress gateway(192,168,1, 1); +IPAddress subnet(255, 255, 0, 0); + +// telnet defaults to port 23 +Server server(23); +boolean gotAMessage = false; // whether or not you got a message from the client yet + +void setup() { + // open the serial port + Serial.begin(9600); + // start the Ethernet connection: + Serial.println("Trying to get an IP address using DHCP"); + if (Ethernet.begin(mac) == 0) { + Serial.println("Failed to configure Ethernet using DHCP"); + // initialize the ethernet device not using DHCP: + Ethernet.begin(mac, ip, gateway, subnet); + } + // print your local IP address: + Serial.print("My IP address: "); + ip = Ethernet.localIP(); + for (byte thisByte = 0; thisByte < 4; thisByte++) { + // print the value of each byte of the IP address: + Serial.print(ip[thisByte], DEC); + Serial.print("."); + } + Serial.println(); + // start listening for clients + server.begin(); + +} + +void loop() { + // wait for a new client: + Client client = server.available(); + + // when the client sends the first byte, say hello: + if (client) { + if (!gotAMessage) { + Serial.println("We have a new client"); + client.println("Hello, client!"); + gotAMessage = true; + } + + // read the bytes incoming from the client: + char thisChar = client.read(); + // echo the bytes back to the client: + server.write(thisChar); + // echo the bytes to the server as well: + Serial.print(thisChar); + } +} + From 1110407690b1ad88bb7f1e510139fe39618b6c61 Mon Sep 17 00:00:00 2001 From: Tom Igoe Date: Sat, 21 May 2011 10:00:12 -0400 Subject: [PATCH 14/33] Added SoftwareSerial Two Port Receive example --- .../TwoPortReceive/TwoPortReceive.ino | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 libraries/SoftwareSerial/examples/TwoPortReceive/TwoPortReceive.ino diff --git a/libraries/SoftwareSerial/examples/TwoPortReceive/TwoPortReceive.ino b/libraries/SoftwareSerial/examples/TwoPortReceive/TwoPortReceive.ino new file mode 100644 index 000000000..e870c6fc1 --- /dev/null +++ b/libraries/SoftwareSerial/examples/TwoPortReceive/TwoPortReceive.ino @@ -0,0 +1,78 @@ +/* + Software serial multple serial test + + Receives from the two software serial ports, + sends to the hardware serial port. + + In order to listen on a software port, you call port.listen(). + When using two software serial ports, you have to switch ports + by listen()ing on each one in turn. Pick a logical time to switch + ports, like the end of an expected transmission, or when the + buffer is empty. This example switches ports when there is nothing + more to read from a port + + The circuit: + Two devices which communicate serially are needed. + * First serial device's TX attached to digital pin 2, RX to pin 3 + * Second serial device's TX attached to digital pin 4, RX to pin 5 + + created 18 Apr. 2011 + by Tom Igoe + based on Mikal Hart's twoPortRXExample + + This example code is in the public domain. + + */ + +#include +// software serial #1: TX = digital pin 2, RX = digital pin 3 +SoftwareSerial portOne(2, 3); + +// software serial #2: TX = digital pin 4, RX = digital pin 5 +SoftwareSerial portTwo(4, 5); + +void setup() +{ + // Start the hardware serial port + Serial.begin(9600); + + // Start each software serial port + portOne.begin(9600); + portTwo.begin(9600); +} + +void loop() +{ + // By default, the last intialized port is listening. + // when you want to listen on a port, explicitly select it: + portOne.listen(); + Serial.println("Data from port one:"); + // while there is data coming in, read it + // and send to the hardware serial port: + while (portOne.available() > 0) { + char inByte = portOne.read(); + Serial.write(inByte); + } + + // blank line to separate data from the two ports: + Serial.println(); + + // Now listen on the second port + portTwo.listen(); + // while there is data coming in, read it + // and send to the hardware serial port: + Serial.println("Data from port two:"); + while (portTwo.available() > 0) { + char inByte = portTwo.read(); + Serial.write(inByte); + } + + // blank line to separate data from the two ports: + Serial.println(); +} + + + + + + From 2f0d9d650a14b503458e08ed43e86bead3b132ea Mon Sep 17 00:00:00 2001 From: Tom Igoe Date: Sat, 21 May 2011 10:00:37 -0400 Subject: [PATCH 15/33] Added DHCP and DNS-based Twitter client for Ethernet library --- .../examples/TwitterClient/TwitterClient.ino | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 libraries/Ethernet/examples/TwitterClient/TwitterClient.ino diff --git a/libraries/Ethernet/examples/TwitterClient/TwitterClient.ino b/libraries/Ethernet/examples/TwitterClient/TwitterClient.ino new file mode 100644 index 000000000..39ff53222 --- /dev/null +++ b/libraries/Ethernet/examples/TwitterClient/TwitterClient.ino @@ -0,0 +1,124 @@ +/* + Twitter Client with Strings + + This sketch connects to Twitter using an Ethernet shield. It parses the XML + returned, and looks for this is a tweet + + You can use the Arduino Ethernet shield, or the Adafruit Ethernet shield, + either one will work, as long as it's got a Wiznet Ethernet module on board. + + This example uses the DHCP routines in the Ethernet library which is part of the + Arduino core from version 1.0 beta 1 + + This example uses the String library, which is part of the Arduino core from + version 0019. + + Circuit: + * Ethernet shield attached to pins 10, 11, 12, 13 + + created 21 May 2011 + by Tom Igoe + + This code is in the public domain. + + */ +#include +#include + + +// Enter a MAC address and IP address for your controller below. +// The IP address will be dependent on your local network: +byte mac[] = { + 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x01 }; +IPAddress ip(192,168,1,20); + +// initialize the library instance: +Client client; + +const int requestInterval = 60000; // delay between requests + +char serverName[] = "api.twitter.com"; // twitter URL + +boolean requested; // whether you've made a request since connecting +long lastAttemptTime = 0; // last time you connected to the server, in milliseconds + +String currentLine = ""; // string to hold the text from server +String tweet = ""; // string to hold the tweet +boolean readingTweet = false; // if you're currently reading the tweet + +void setup() { + // reserve space for the strings: + currentLine.reserve(256); + tweet.reserve(150); + +// initialize serial: + Serial.begin(9600); + // attempt a DHCP connection: + if (!Ethernet.begin(mac)) { + // if DHCP fails, start with a hard-coded address: + Ethernet.begin(mac, ip); + } + // connect to Twitter: + connectToServer(); +} + + + +void loop() +{ + if (client.connected()) { + if (client.available()) { + // read incoming bytes: + char inChar = client.read(); + + // add incoming byte to end of line: + currentLine += inChar; + + // if you get a newline, clear the line: + if (inChar == '\n') { + currentLine = ""; + } + // if the current line ends with , it will + // be followed by the tweet: + if ( currentLine.endsWith("")) { + // tweet is beginning. Clear the tweet string: + readingTweet = true; + tweet = ""; + } + // if you're currently reading the bytes of a tweet, + // add them to the tweet String: + if (readingTweet) { + if (inChar != '<') { + tweet += inChar; + } + else { + // if you got a "<" character, + // you've reached the end of the tweet: + readingTweet = false; + Serial.println(tweet); + // close the connection to the server: + client.stop(); + } + } + } + } + else if (millis() - lastAttemptTime > requestInterval) { + // if you're not connected, and two minutes have passed since + // your last connection, then attempt to connect again: + connectToServer(); + } +} + +void connectToServer() { + // attempt to connect, and wait a millisecond: + Serial.println("connecting to server..."); + if (client.connect(serverName, 80)) { + Serial.println("making HTTP request..."); + // make HTTP GET request to twitter: + client.println("GET /1/statuses/user_timeline.xml?screen_name=arduino&count=1 HTTP/1.1"); + client.println("HOST: api.twitter.com"); + client.println(); + } + // note the time of this connect attempt: + lastAttemptTime = millis(); +} From eabc471876b97c62497c476fee2800a0b7e88ba9 Mon Sep 17 00:00:00 2001 From: Tom Igoe Date: Sat, 21 May 2011 10:01:03 -0400 Subject: [PATCH 16/33] Updated DHCP Address printer for Ethernet library --- .../DhcpAddressPrinter/DhcpAddressPrinter.ino | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 libraries/Ethernet/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino diff --git a/libraries/Ethernet/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino b/libraries/Ethernet/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino new file mode 100644 index 000000000..8701568c0 --- /dev/null +++ b/libraries/Ethernet/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino @@ -0,0 +1,54 @@ +/* + DHCP-based IP printer + + This sketch uses the DHCP extensions to the Ethernet library + to get an IP address via DHCP and print the address obtained. + using an Arduino Wiznet Ethernet shield. + + Circuit: + * Ethernet shield attached to pins 10, 11, 12, 13 + + created 12 April 2011 + by Tom Igoe + + */ + +#include +#include + +// Enter a MAC address for your controller below. +// Newer Ethernet shields have a MAC address printed on a sticker on the shield +byte mac[] = { + 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 }; + +// Initialize the Ethernet client library +// with the IP address and port of the server +// that you want to connect to (port 80 is default for HTTP): +Client client; + +void setup() { + // start the serial library: + Serial.begin(9600); + // start the Ethernet connection: + Serial.println("Trying to get an IP address using DHCP");z + if (Ethernet.begin(mac) == 0) { + Serial.println("Failed to configure Ethernet using DHCP"); + // no point in carrying on, so do nothing forevermore: + while(true); + } + // print your local IP address: + Serial.print("My IP address: "); + IPAddress myIPAddress = Ethernet.localIP(); + for (byte thisByte = 0; thisByte < 4; thisByte++) { + // print the value of each byte of the IP address: + Serial.print(myIPAddress[thisByte], DEC); + Serial.print("."); + } + Serial.println(); +} + +void loop() { + +} + + From b18ce9a0174da5222bfbf46f1eb3de2f544f42c9 Mon Sep 17 00:00:00 2001 From: Tom Igoe Date: Sat, 21 May 2011 10:25:53 -0400 Subject: [PATCH 17/33] updated twitter client for Ethernet --- libraries/Ethernet/examples/TwitterClient/TwitterClient.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/Ethernet/examples/TwitterClient/TwitterClient.ino b/libraries/Ethernet/examples/TwitterClient/TwitterClient.ino index 39ff53222..399e76bc3 100644 --- a/libraries/Ethernet/examples/TwitterClient/TwitterClient.ino +++ b/libraries/Ethernet/examples/TwitterClient/TwitterClient.ino @@ -121,4 +121,4 @@ void connectToServer() { } // note the time of this connect attempt: lastAttemptTime = millis(); -} +} From 665ae33e885e6990f7760c46840e1e7d3c60d669 Mon Sep 17 00:00:00 2001 From: Tom Igoe Date: Tue, 24 May 2011 13:35:36 -0400 Subject: [PATCH 18/33] removing new-extension branch examples from master branch --- .../SerialEvent/SerialEvent.ino | 57 -------- .../DhcpAddressPrinter/DhcpAddressPrinter.ino | 54 -------- .../DhcpChatServer/DhcpChatServer.ino | 80 ----------- .../examples/TwitterClient/TwitterClient.ino | 124 ------------------ .../TwoPortReceive/TwoPortReceive.ino | 78 ----------- 5 files changed, 393 deletions(-) delete mode 100644 build/shared/examples/4.Communication/SerialEvent/SerialEvent.ino delete mode 100644 libraries/Ethernet/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino delete mode 100644 libraries/Ethernet/examples/DhcpChatServer/DhcpChatServer.ino delete mode 100644 libraries/Ethernet/examples/TwitterClient/TwitterClient.ino delete mode 100644 libraries/SoftwareSerial/examples/TwoPortReceive/TwoPortReceive.ino diff --git a/build/shared/examples/4.Communication/SerialEvent/SerialEvent.ino b/build/shared/examples/4.Communication/SerialEvent/SerialEvent.ino deleted file mode 100644 index 2f3f917e5..000000000 --- a/build/shared/examples/4.Communication/SerialEvent/SerialEvent.ino +++ /dev/null @@ -1,57 +0,0 @@ -/* - Serial Event example - - When new serial data arrives, this sketch adds it to a String. - When a newline is received, the loop prints the string and - clears it. - - A good test for this is to try it with a GPS receiver - that sends out NMEA 0183 sentences. - - Created 9 May 2011 - by Tom Igoe - - This example code is in the public domain. - - http://www.arduino.cc/en/Tutorial/SerialEvent - - */ - -String inputString = ""; // a string to hold incoming data -boolean stringComplete = false; // whether the string is complete - -void setup() { - // initialize serial: - Serial.begin(9600); - // reserve 200 bytes for the inputString: - inputString.reserve(200); -} - -void loop() { - // print the string when a newline arrives: - if (stringComplete) { - Serial.println(inputString); - // clear the string: - inputString = ""; - stringComplete = false; - } -} - -/* - SerialEvent occurs whenever a new byte comes in the - hardware serial RX. Don't do complex things here, as thge - processor halts the regular program to run this routine: - */ -void serialEvent() { - // get the new byte: - char inChar = (char)Serial.read(); - // add it to the inputString: - inputString += inChar; - // if the incoming character is a newline, set a flag - // so the main loop can do something about it: - if (inChar == '\n') { - stringComplete = true; - } -} - - diff --git a/libraries/Ethernet/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino b/libraries/Ethernet/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino deleted file mode 100644 index 8701568c0..000000000 --- a/libraries/Ethernet/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino +++ /dev/null @@ -1,54 +0,0 @@ -/* - DHCP-based IP printer - - This sketch uses the DHCP extensions to the Ethernet library - to get an IP address via DHCP and print the address obtained. - using an Arduino Wiznet Ethernet shield. - - Circuit: - * Ethernet shield attached to pins 10, 11, 12, 13 - - created 12 April 2011 - by Tom Igoe - - */ - -#include -#include - -// Enter a MAC address for your controller below. -// Newer Ethernet shields have a MAC address printed on a sticker on the shield -byte mac[] = { - 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 }; - -// Initialize the Ethernet client library -// with the IP address and port of the server -// that you want to connect to (port 80 is default for HTTP): -Client client; - -void setup() { - // start the serial library: - Serial.begin(9600); - // start the Ethernet connection: - Serial.println("Trying to get an IP address using DHCP");z - if (Ethernet.begin(mac) == 0) { - Serial.println("Failed to configure Ethernet using DHCP"); - // no point in carrying on, so do nothing forevermore: - while(true); - } - // print your local IP address: - Serial.print("My IP address: "); - IPAddress myIPAddress = Ethernet.localIP(); - for (byte thisByte = 0; thisByte < 4; thisByte++) { - // print the value of each byte of the IP address: - Serial.print(myIPAddress[thisByte], DEC); - Serial.print("."); - } - Serial.println(); -} - -void loop() { - -} - - diff --git a/libraries/Ethernet/examples/DhcpChatServer/DhcpChatServer.ino b/libraries/Ethernet/examples/DhcpChatServer/DhcpChatServer.ino deleted file mode 100644 index c3e581387..000000000 --- a/libraries/Ethernet/examples/DhcpChatServer/DhcpChatServer.ino +++ /dev/null @@ -1,80 +0,0 @@ -/* - DHCP Chat Server - - A simple server that distributes any incoming messages to all - connected clients. To use telnet to your device's IP address and type. - You can see the client's input in the serial monitor as well. - Using an Arduino Wiznet Ethernet shield. - - THis version attempts to get an IP address using DHCP - - Circuit: - * Ethernet shield attached to pins 10, 11, 12, 13 - - created 21 May 2011 - by Tom Igoe - Based on ChatServer example by David A. Mellis - - */ - -#include -#include - -// Enter a MAC address and IP address for your controller below. -// The IP address will be dependent on your local network. -// gateway and subnet are optional: -byte mac[] = { - 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 }; -IPAddress ip(192,168,1, 177); -IPAddress gateway(192,168,1, 1); -IPAddress subnet(255, 255, 0, 0); - -// telnet defaults to port 23 -Server server(23); -boolean gotAMessage = false; // whether or not you got a message from the client yet - -void setup() { - // open the serial port - Serial.begin(9600); - // start the Ethernet connection: - Serial.println("Trying to get an IP address using DHCP"); - if (Ethernet.begin(mac) == 0) { - Serial.println("Failed to configure Ethernet using DHCP"); - // initialize the ethernet device not using DHCP: - Ethernet.begin(mac, ip, gateway, subnet); - } - // print your local IP address: - Serial.print("My IP address: "); - ip = Ethernet.localIP(); - for (byte thisByte = 0; thisByte < 4; thisByte++) { - // print the value of each byte of the IP address: - Serial.print(ip[thisByte], DEC); - Serial.print("."); - } - Serial.println(); - // start listening for clients - server.begin(); - -} - -void loop() { - // wait for a new client: - Client client = server.available(); - - // when the client sends the first byte, say hello: - if (client) { - if (!gotAMessage) { - Serial.println("We have a new client"); - client.println("Hello, client!"); - gotAMessage = true; - } - - // read the bytes incoming from the client: - char thisChar = client.read(); - // echo the bytes back to the client: - server.write(thisChar); - // echo the bytes to the server as well: - Serial.print(thisChar); - } -} - diff --git a/libraries/Ethernet/examples/TwitterClient/TwitterClient.ino b/libraries/Ethernet/examples/TwitterClient/TwitterClient.ino deleted file mode 100644 index 399e76bc3..000000000 --- a/libraries/Ethernet/examples/TwitterClient/TwitterClient.ino +++ /dev/null @@ -1,124 +0,0 @@ -/* - Twitter Client with Strings - - This sketch connects to Twitter using an Ethernet shield. It parses the XML - returned, and looks for this is a tweet - - You can use the Arduino Ethernet shield, or the Adafruit Ethernet shield, - either one will work, as long as it's got a Wiznet Ethernet module on board. - - This example uses the DHCP routines in the Ethernet library which is part of the - Arduino core from version 1.0 beta 1 - - This example uses the String library, which is part of the Arduino core from - version 0019. - - Circuit: - * Ethernet shield attached to pins 10, 11, 12, 13 - - created 21 May 2011 - by Tom Igoe - - This code is in the public domain. - - */ -#include -#include - - -// Enter a MAC address and IP address for your controller below. -// The IP address will be dependent on your local network: -byte mac[] = { - 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x01 }; -IPAddress ip(192,168,1,20); - -// initialize the library instance: -Client client; - -const int requestInterval = 60000; // delay between requests - -char serverName[] = "api.twitter.com"; // twitter URL - -boolean requested; // whether you've made a request since connecting -long lastAttemptTime = 0; // last time you connected to the server, in milliseconds - -String currentLine = ""; // string to hold the text from server -String tweet = ""; // string to hold the tweet -boolean readingTweet = false; // if you're currently reading the tweet - -void setup() { - // reserve space for the strings: - currentLine.reserve(256); - tweet.reserve(150); - -// initialize serial: - Serial.begin(9600); - // attempt a DHCP connection: - if (!Ethernet.begin(mac)) { - // if DHCP fails, start with a hard-coded address: - Ethernet.begin(mac, ip); - } - // connect to Twitter: - connectToServer(); -} - - - -void loop() -{ - if (client.connected()) { - if (client.available()) { - // read incoming bytes: - char inChar = client.read(); - - // add incoming byte to end of line: - currentLine += inChar; - - // if you get a newline, clear the line: - if (inChar == '\n') { - currentLine = ""; - } - // if the current line ends with , it will - // be followed by the tweet: - if ( currentLine.endsWith("")) { - // tweet is beginning. Clear the tweet string: - readingTweet = true; - tweet = ""; - } - // if you're currently reading the bytes of a tweet, - // add them to the tweet String: - if (readingTweet) { - if (inChar != '<') { - tweet += inChar; - } - else { - // if you got a "<" character, - // you've reached the end of the tweet: - readingTweet = false; - Serial.println(tweet); - // close the connection to the server: - client.stop(); - } - } - } - } - else if (millis() - lastAttemptTime > requestInterval) { - // if you're not connected, and two minutes have passed since - // your last connection, then attempt to connect again: - connectToServer(); - } -} - -void connectToServer() { - // attempt to connect, and wait a millisecond: - Serial.println("connecting to server..."); - if (client.connect(serverName, 80)) { - Serial.println("making HTTP request..."); - // make HTTP GET request to twitter: - client.println("GET /1/statuses/user_timeline.xml?screen_name=arduino&count=1 HTTP/1.1"); - client.println("HOST: api.twitter.com"); - client.println(); - } - // note the time of this connect attempt: - lastAttemptTime = millis(); -} diff --git a/libraries/SoftwareSerial/examples/TwoPortReceive/TwoPortReceive.ino b/libraries/SoftwareSerial/examples/TwoPortReceive/TwoPortReceive.ino deleted file mode 100644 index e870c6fc1..000000000 --- a/libraries/SoftwareSerial/examples/TwoPortReceive/TwoPortReceive.ino +++ /dev/null @@ -1,78 +0,0 @@ -/* - Software serial multple serial test - - Receives from the two software serial ports, - sends to the hardware serial port. - - In order to listen on a software port, you call port.listen(). - When using two software serial ports, you have to switch ports - by listen()ing on each one in turn. Pick a logical time to switch - ports, like the end of an expected transmission, or when the - buffer is empty. This example switches ports when there is nothing - more to read from a port - - The circuit: - Two devices which communicate serially are needed. - * First serial device's TX attached to digital pin 2, RX to pin 3 - * Second serial device's TX attached to digital pin 4, RX to pin 5 - - created 18 Apr. 2011 - by Tom Igoe - based on Mikal Hart's twoPortRXExample - - This example code is in the public domain. - - */ - -#include -// software serial #1: TX = digital pin 2, RX = digital pin 3 -SoftwareSerial portOne(2, 3); - -// software serial #2: TX = digital pin 4, RX = digital pin 5 -SoftwareSerial portTwo(4, 5); - -void setup() -{ - // Start the hardware serial port - Serial.begin(9600); - - // Start each software serial port - portOne.begin(9600); - portTwo.begin(9600); -} - -void loop() -{ - // By default, the last intialized port is listening. - // when you want to listen on a port, explicitly select it: - portOne.listen(); - Serial.println("Data from port one:"); - // while there is data coming in, read it - // and send to the hardware serial port: - while (portOne.available() > 0) { - char inByte = portOne.read(); - Serial.write(inByte); - } - - // blank line to separate data from the two ports: - Serial.println(); - - // Now listen on the second port - portTwo.listen(); - // while there is data coming in, read it - // and send to the hardware serial port: - Serial.println("Data from port two:"); - while (portTwo.available() > 0) { - char inByte = portTwo.read(); - Serial.write(inByte); - } - - // blank line to separate data from the two ports: - Serial.println(); -} - - - - - - From 2d2ed324b48e709f59a002cb274ed60bb0ebc911 Mon Sep 17 00:00:00 2001 From: WestfW Date: Thu, 9 Jun 2011 22:36:05 -0700 Subject: [PATCH 19/33] Makefile modification to allow building optiboot in more environments. Allows building within the Arduino Source tree, and within the Arduino IDE tree, as well as using CrossPack on Mac. Adds README.TXT to track arduino-specific changes (and documents the new build options.) This addresses Arduino issue: http://code.google.com/p/arduino/issues/detail?id=487 And optiboot issue http://code.google.com/p/optiboot/issues/detail?id=1 (which can be thought of as a subset of the Arduno issue.) Note that the binaries produced after these Makefile changes (using any of the compile environments) are identical to those produced by the crosspack-20100115 environment on a Mac. --- .../arduino/bootloaders/optiboot/Makefile | 77 +++++++++++++++++-- .../arduino/bootloaders/optiboot/README.TXT | 55 +++++++++++++ hardware/arduino/bootloaders/optiboot/omake | 2 + .../arduino/bootloaders/optiboot/omake.bat | 1 + .../optiboot/optiboot_atmega328.lst | 22 +++--- 5 files changed, 138 insertions(+), 19 deletions(-) create mode 100644 hardware/arduino/bootloaders/optiboot/README.TXT create mode 100644 hardware/arduino/bootloaders/optiboot/omake create mode 100644 hardware/arduino/bootloaders/optiboot/omake.bat diff --git a/hardware/arduino/bootloaders/optiboot/Makefile b/hardware/arduino/bootloaders/optiboot/Makefile index 0fd600501..92f9c61f9 100644 --- a/hardware/arduino/bootloaders/optiboot/Makefile +++ b/hardware/arduino/bootloaders/optiboot/Makefile @@ -19,6 +19,17 @@ # program name should not be changed... PROGRAM = optiboot +# The default behavior is to build using tools that are in the users +# current path variables, but we can also build using an installed +# Arduino user IDE setup, or the Arduino source tree. +# Uncomment this next lines to build within the arduino environment, +# using the arduino-included avrgcc toolset (mac and pc) +# ENV ?= arduino +# ENV ?= arduinodev +# OS ?= macosx +# OS ?= windows + + # enter the parameters for the avrdude isp tool ISPTOOL = stk500v2 ISPPORT = usb @@ -27,6 +38,50 @@ ISPSPEED = -b 115200 MCU_TARGET = atmega168 LDSECTION = --section-start=.text=0x3e00 +# Build environments +# Start of some ugly makefile-isms to allow optiboot to be built +# in several different environments. See the README.TXT file for +# details. + +# default +fixpath = $(1) + +ifeq ($(ENV), arduino) +# For Arduino, we assume that we're connected to the optiboot directory +# included with the arduino distribution, which means that the full set +# of avr-tools are "right up there" in standard places. +TOOLROOT = ../../../tools +GCCROOT = $(TOOLROOT)/avr/bin/ +AVRDUDE_CONF = -C$(TOOLROOT)/avr/etc/avrdude.conf + +ifeq ($(OS), windows) +# On windows, SOME of the tool paths will need to have backslashes instead +# of forward slashes (because they use windows cmd.exe for execution instead +# of a unix/mingw shell?) +fixpath = $(subst /,\,$1) +endif + +else ifeq ($(ENV), arduinodev) +# Arduino IDE source code environment. Use the unpacked compilers created +# by the build (you'll need to do "ant build" first.) +ifeq ($(OS), macosx) +TOOLROOT = ../../../../build/macosx/work/Arduino.app/Contents/Resources/Java/hardware/tools +endif +ifeq ($(OS), windows) +TOOLROOT = ../../../../build/windows/work/hardware/tools +endif + +GCCROOT = $(TOOLROOT)/avr/bin/ +AVRDUDE_CONF = -C$(TOOLROOT)/avr/etc/avrdude.conf + +else +GCCROOT = +AVRDUDE_CONF = +endif +# +# End of build environment code. + + # the efuse should really be 0xf8; since, however, only the lower # three bits of that byte are used on the atmega168, avrdude gets # confused if you specify 1's for the higher bits, see: @@ -37,10 +92,13 @@ LDSECTION = --section-start=.text=0x3e00 # lock it), but since the high two bits of the lock byte are # unused, avrdude would get confused. -ISPFUSES = avrdude -c $(ISPTOOL) -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \ --e -u -U lock:w:0x3f:m -U efuse:w:0x$(EFUSE):m -U hfuse:w:0x$(HFUSE):m -U lfuse:w:0x$(LFUSE):m -ISPFLASH = avrdude -c $(ISPTOOL) -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \ --U flash:w:$(PROGRAM)_$(TARGET).hex -U lock:w:0x0f:m +ISPFUSES = $(GCCROOT)avrdude $(AVRDUDE_CONF) -c $(ISPTOOL) \ + -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \ + -e -u -U lock:w:0x3f:m -U efuse:w:0x$(EFUSE):m \ + -U hfuse:w:0x$(HFUSE):m -U lfuse:w:0x$(LFUSE):m +ISPFLASH = $(GCCROOT)avrdude $(AVRDUDE_CONF) -c $(ISPTOOL) \ + -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \ + -U flash:w:$(PROGRAM)_$(TARGET).hex -U lock:w:0x0f:m STK500 = "C:\Program Files\Atmel\AVR Tools\STK500\Stk500.exe" STK500-1 = $(STK500) -e -d$(MCU_TARGET) -pf -vf -if$(PROGRAM)_$(TARGET).hex \ @@ -53,15 +111,17 @@ OPTIMIZE = -Os -fno-inline-small-functions -fno-split-wide-types -mshort-calls DEFS = LIBS = -CC = avr-gcc +CC = $(GCCROOT)avr-gcc # Override is only needed by avr-lib build system. override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) -DF_CPU=$(AVR_FREQ) $(DEFS) -override LDFLAGS = -Wl,$(LDSECTION) -Wl,--relax -nostartfiles +override LDFLAGS = -Wl,$(LDSECTION) -Wl,--relax -Wl,--gc-sections -nostartfiles -nostdlib -OBJCOPY = avr-objcopy -OBJDUMP = avr-objdump +OBJCOPY = $(GCCROOT)avr-objcopy +OBJDUMP = $(call fixpath,$(GCCROOT)avr-objdump) + +SIZE = $(GCCROOT)avr-size # 20MHz clocked platforms # @@ -222,6 +282,7 @@ isp-stk500: $(PROGRAM)_$(TARGET).hex %.elf: $(OBJ) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) + $(SIZE) $@ clean: rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex diff --git a/hardware/arduino/bootloaders/optiboot/README.TXT b/hardware/arduino/bootloaders/optiboot/README.TXT new file mode 100644 index 000000000..9a68e2343 --- /dev/null +++ b/hardware/arduino/bootloaders/optiboot/README.TXT @@ -0,0 +1,55 @@ +This directory contains the Optiboot small bootloader for AVR +microcontrollers, somewhat modified specifically for the Arduino +environment. + +Optiboot is more fully described here: http://code.google.com/p/optiboot/ +and is the work of Peter Knight (aka Cathedrow), building on work of Jason P +Kyle, Spiff, and Ladyada. Arduino-specific modification are by Bill +Westfield (aka WestfW) + +Arduino-specific issues are tracked as part of the Arduino project +at http://code.google.com/p/arduino + + +------------------------------------------------------------ +Building optiboot for Arduino. + +Production builds of optiboot for Arduino are done on a Mac in "unix mode" +using CrossPack-AVR-20100115. CrossPack tracks WINAVR (for windows), which +is just a package of avr-gcc and related utilities, so similar builds should +work on Windows or Linux systems. + +One of the Arduino-specific changes is modifications to the makefile to +allow building optiboot using only the tools installed as part of the +Arduino environment, or the Arduino source development tree. All three +build procedures should yield identical binaries (.hex files) (although +this may change if compiler versions drift apart between CrossPack and +the Arduino IDE.) + + +Building optiboot in the arduino IDE install. + +Work in the .../hardware/arduino/bootloaders/optiboot/ and use the +"omake " command, which just generates a command that uses +the arduino-included "make" utility with a command like: + make OS=windows ENV=arduino +or make OS=macosx ENV=arduino +On windows, this assumes you're using the windows command shell. If +you're using a cygwin or mingw shell, or have one of those in your +path, the build will probably break due to slash vs backslash issues. +On a Mac, if you have the developer tools installed, you can use the +Apple-supplied version of make. +The makefile uses relative paths ("../../../tools/" and such) to find +the programs it needs, so you need to work in the existing optiboot +directory (or something created at the same "level") for it to work. + + +Building optiboot in the arduino source development install. + +In this case, there is no special shell script, and you're assumed to +have "make" installed somewhere in your path. +Build the Arduino source ("ant build") to unpack the tools into the +expected directory. +Work in Arduino/hardware/arduino/bootloaders/optiboot and use + make OS=windows ENV=arduinodev +or make OS=macosx ENV=arduinodev diff --git a/hardware/arduino/bootloaders/optiboot/omake b/hardware/arduino/bootloaders/optiboot/omake new file mode 100644 index 000000000..cc7c6bc29 --- /dev/null +++ b/hardware/arduino/bootloaders/optiboot/omake @@ -0,0 +1,2 @@ +echo ../../../tools/avr/bin/make OS=macosx ENV=arduino $* +../../../tools/avr/bin/make OS=macosx ENV=arduino $* diff --git a/hardware/arduino/bootloaders/optiboot/omake.bat b/hardware/arduino/bootloaders/optiboot/omake.bat new file mode 100644 index 000000000..f6815dacc --- /dev/null +++ b/hardware/arduino/bootloaders/optiboot/omake.bat @@ -0,0 +1 @@ +..\..\..\tools\avr\utils\bin\make OS=windows ENV=arduino %* diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.lst b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.lst index dd879dcd1..104799ff2 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.lst @@ -13,15 +13,15 @@ Idx Name Size VMA LMA File off Algn CONTENTS, READONLY, DEBUGGING 4 .debug_abbrev 00000196 00000000 00000000 0000053d 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_line 000003db 00000000 00000000 000006d3 2**0 + 5 .debug_line 0000043f 00000000 00000000 000006d3 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_frame 00000090 00000000 00000000 00000ab0 2**2 + 6 .debug_frame 00000090 00000000 00000000 00000b14 2**2 CONTENTS, READONLY, DEBUGGING - 7 .debug_str 00000124 00000000 00000000 00000b40 2**0 + 7 .debug_str 00000136 00000000 00000000 00000ba4 2**0 CONTENTS, READONLY, DEBUGGING - 8 .debug_loc 000001d1 00000000 00000000 00000c64 2**0 + 8 .debug_loc 000001d1 00000000 00000000 00000cda 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_ranges 00000068 00000000 00000000 00000e35 2**0 + 9 .debug_ranges 00000068 00000000 00000000 00000eab 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: @@ -153,7 +153,7 @@ void watchdogReset() { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); 7e5e: 81 e0 ldi r24, 0x01 ; 1 - 7e60: be d0 rcall .+380 ; 0x7fde + 7e60: be d0 rcall .+380 ; 0x7fde putch(0x03); 7e62: 83 e0 ldi r24, 0x03 ; 3 7e64: 24 c0 rjmp .+72 ; 0x7eae @@ -172,7 +172,7 @@ void watchdogReset() { // SET DEVICE EXT is ignored getNch(5); 7e72: 85 e0 ldi r24, 0x05 ; 5 - 7e74: b4 d0 rcall .+360 ; 0x7fde + 7e74: b4 d0 rcall .+360 ; 0x7fde 7e76: 8a c0 rjmp .+276 ; 0x7f8c } else if(ch == STK_LOAD_ADDRESS) { @@ -206,7 +206,7 @@ void watchdogReset() { // UNIVERSAL command is ignored getNch(4); 7ea8: 84 e0 ldi r24, 0x04 ; 4 - 7eaa: 99 d0 rcall .+306 ; 0x7fde + 7eaa: 99 d0 rcall .+306 ; 0x7fde putch(0x00); 7eac: 80 e0 ldi r24, 0x00 ; 0 7eae: 71 d0 rcall .+226 ; 0x7f92 @@ -503,6 +503,8 @@ void verifySpace() { 7fda: 84 e1 ldi r24, 0x14 ; 20 } 7fdc: da cf rjmp .-76 ; 0x7f92 + +00007fde : ::[count] "M" (UART_B_VALUE) ); } @@ -511,12 +513,10 @@ void verifySpace() { void getNch(uint8_t count) { 7fde: 1f 93 push r17 7fe0: 18 2f mov r17, r24 - -00007fe2 : do getch(); while (--count); 7fe2: df df rcall .-66 ; 0x7fa2 7fe4: 11 50 subi r17, 0x01 ; 1 - 7fe6: e9 f7 brne .-6 ; 0x7fe2 + 7fe6: e9 f7 brne .-6 ; 0x7fe2 verifySpace(); 7fe8: f4 df rcall .-24 ; 0x7fd2 } From 6840b77643a75b850d48bed80c578da484e6559f Mon Sep 17 00:00:00 2001 From: WestfW Date: Thu, 9 Jun 2011 22:57:27 -0700 Subject: [PATCH 20/33] http://code.google.com/p/arduino/issues/detail?id=517 Remove the trailing comments when setting fuse values for the various *_isp targets, so that they won't cause avrdude errors. This was done the same way as in the optiboot source tree: http://code.google.com/p/optiboot/issues/detail?id=17 http://code.google.com/p/optiboot/source/detail?r=005fb033fc08c551b2f86f7c90c5db21549b3f20 --- .../arduino/bootloaders/optiboot/Makefile | 81 ++++++++++++------- 1 file changed, 54 insertions(+), 27 deletions(-) diff --git a/hardware/arduino/bootloaders/optiboot/Makefile b/hardware/arduino/bootloaders/optiboot/Makefile index 92f9c61f9..0f8d09e9d 100644 --- a/hardware/arduino/bootloaders/optiboot/Makefile +++ b/hardware/arduino/bootloaders/optiboot/Makefile @@ -136,9 +136,12 @@ pro20: $(PROGRAM)_pro_20mhz.lst pro20_isp: pro20 pro20_isp: TARGET = pro_20mhz -pro20_isp: HFUSE = DD # 2.7V brownout -pro20_isp: LFUSE = C6 # Full swing xtal (20MHz) 258CK/14CK+4.1ms -pro20_isp: EFUSE = 02 # 512 byte boot +# 2.7V brownout +pro20_isp: HFUSE = DD +# Full swing xtal (20MHz) 258CK/14CK+4.1ms +pro20_isp: LFUSE = C6 +# 512 byte boot +pro20_isp: EFUSE = 02 pro20_isp: isp # 16MHz clocked platforms @@ -154,9 +157,12 @@ pro16: $(PROGRAM)_pro_16MHz.lst pro16_isp: pro16 pro16_isp: TARGET = pro_16MHz -pro16_isp: HFUSE = DD # 2.7V brownout -pro16_isp: LFUSE = C6 # Full swing xtal (20MHz) 258CK/14CK+4.1ms -pro16_isp: EFUSE = 02 # 512 byte boot +# 2.7V brownout +pro16_isp: HFUSE = DD +# Full swing xtal (20MHz) 258CK/14CK+4.1ms +pro16_isp: LFUSE = C6 +# 512 byte boot +pro16_isp: EFUSE = 02 pro16_isp: isp # Diecimila and NG use identical bootloaders @@ -169,9 +175,12 @@ diecimila: $(PROGRAM)_diecimila.lst diecimila_isp: diecimila diecimila_isp: TARGET = diecimila -diecimila_isp: HFUSE = DD # 2.7V brownout -diecimila_isp: LFUSE = FF # Low power xtal (16MHz) 16KCK/14CK+65ms -diecimila_isp: EFUSE = 02 # 512 byte boot +# 2.7V brownout +diecimila_isp: HFUSE = DD +# Low power xtal (16MHz) 16KCK/14CK+65ms +diecimila_isp: LFUSE = FF +# 512 byte boot +diecimila_isp: EFUSE = 02 diecimila_isp: isp atmega328: TARGET = atmega328 @@ -185,9 +194,12 @@ atmega328: $(PROGRAM)_atmega328.lst atmega328_isp: atmega328 atmega328_isp: TARGET = atmega328 atmega328_isp: MCU_TARGET = atmega328p -atmega328_isp: HFUSE = DE # 512 byte boot -atmega328_isp: LFUSE = FF # Low power xtal (16MHz) 16KCK/14CK+65ms -atmega328_isp: EFUSE = 05 # 2.7V brownout +# 512 byte boot +atmega328_isp: HFUSE = DE +# Low power xtal (16MHz) 16KCK/14CK+65ms +atmega328_isp: LFUSE = FF +# 2.7V brownout +atmega328_isp: EFUSE = 05 atmega328_isp: isp # 8MHz clocked platforms @@ -203,9 +215,12 @@ lilypad: $(PROGRAM)_lilypad.lst lilypad_isp: lilypad lilypad_isp: TARGET = lilypad -lilypad_isp: HFUSE = DD # 2.7V brownout -lilypad_isp: LFUSE = E2 # Internal 8MHz osc (8MHz) Slow rising power -lilypad_isp: EFUSE = 02 # 512 byte boot +# 2.7V brownout +lilypad_isp: HFUSE = DD +# Internal 8MHz osc (8MHz) Slow rising power +lilypad_isp: LFUSE = E2 +# 512 byte boot +lilypad_isp: EFUSE = 02 lilypad_isp: isp lilypad_resonator: TARGET = lilypad_resonator @@ -216,9 +231,12 @@ lilypad_resonator: $(PROGRAM)_lilypad_resonator.lst lilypad_resonator_isp: lilypad_resonator lilypad_resonator_isp: TARGET = lilypad_resonator -lilypad_resonator_isp: HFUSE = DD # 2.7V brownout -lilypad_resonator_isp: LFUSE = C6 # Full swing xtal (20MHz) 258CK/14CK+4.1ms -lilypad_resonator_isp: EFUSE = 02 # 512 byte boot +# 2.7V brownout +lilypad_resonator_isp: HFUSE = DD +# Full swing xtal (20MHz) 258CK/14CK+4.1ms +lilypad_resonator_isp: LFUSE = C6 +# 512 byte boot +lilypad_resonator_isp: EFUSE = 02 lilypad_resonator_isp: isp pro8: TARGET = pro_8MHz @@ -229,9 +247,12 @@ pro8: $(PROGRAM)_pro_8MHz.lst pro8_isp: pro8 pro8_isp: TARGET = pro_8MHz -pro8_isp: HFUSE = DD # 2.7V brownout -pro8_isp: LFUSE = C6 # Full swing xtal (20MHz) 258CK/14CK+4.1ms -pro8_isp: EFUSE = 02 # 512 byte boot +# 2.7V brownout +pro8_isp: HFUSE = DD +# Full swing xtal (20MHz) 258CK/14CK+4.1ms +pro8_isp: LFUSE = C6 +# 512 byte boot +pro8_isp: EFUSE = 02 pro8_isp: isp atmega328_pro8: TARGET = atmega328_pro_8MHz @@ -245,9 +266,12 @@ atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.lst atmega328_pro8_isp: atmega328_pro8 atmega328_pro8_isp: TARGET = atmega328_pro_8MHz atmega328_pro8_isp: MCU_TARGET = atmega328p -atmega328_pro8_isp: HFUSE = DE # 512 byte boot -atmega328_pro8_isp: LFUSE = FF # Low power xtal (16MHz) 16KCK/14CK+65ms -atmega328_pro8_isp: EFUSE = 05 # 2.7V brownout +# 512 byte boot +atmega328_pro8_isp: HFUSE = DE +# Low power xtal (16MHz) 16KCK/14CK+65ms +atmega328_pro8_isp: LFUSE = FF +# 2.7V brownout +atmega328_pro8_isp: EFUSE = 05 atmega328_pro8_isp: isp # 1MHz clocked platforms @@ -267,9 +291,12 @@ luminet: $(PROGRAM)_luminet.lst luminet_isp: luminet luminet_isp: TARGET = luminet luminet_isp: MCU_TARGET = attiny84 -luminet_isp: HFUSE = DF # Brownout disabled -luminet_isp: LFUSE = 62 # 1MHz internal oscillator, slowly rising power -luminet_isp: EFUSE = FE # Self-programming enable +# Brownout disabled +luminet_isp: HFUSE = DF +# 1MHz internal oscillator, slowly rising power +luminet_isp: LFUSE = 62 +# Self-programming enable +luminet_isp: EFUSE = FE luminet_isp: isp isp: $(TARGET) From e2812ef91cc1489527827dcd14c843f3b3244f36 Mon Sep 17 00:00:00 2001 From: WestfW Date: Fri, 10 Jun 2011 16:17:13 -0700 Subject: [PATCH 21/33] This is a relatively significant edit that brings the Arduino copy of optiboot up-to-date with the optiboot source repository as of Jun-2011 (the last changes made in the optiboot repository were in Oct-2010) This adds support for several plaforms, fixes the "30k bug", and refactors the source to have separate stk500.h, boot.h, and pin_defs.h These are the arduino opticode issues fixed: http://code.google.com/p/arduino/issues/detail?id=380 optiboot has problems upload sketches bigger than 30 KB http://code.google.com/p/arduino/issues/detail?id=556 update optiboot to the point of the latest optiboot project sources. These are issues that had been solved in the optiboot source aready: http://code.google.com/p/arduino/issues/detail?id=364 optiboot leaves timer1 configured when starting app, breaks PWM on pin 9 and 10. (fixed with a workaround in arduino core.) aka http://code.google.com/p/optiboot/source/detail?r=c778fbe72df6ac13ef730c25283358c3c970f73e Support for ATmega8 and mega88. Fix fuse settings for mega168 _ISP targets Additional new platforms (mega, sanguino) http://code.google.com/p/optiboot/issues/detail?id=26 Set R1 to 0 (already in arduino code) http://code.google.com/p/optiboot/issues/detail?id=36&can=1 Fails to build correctly for mega88 After this commit, the only differences between the Arduino optiboot.c and the optiboot repository optiboot.c are cosmetic. --- .../arduino/bootloaders/optiboot/Makefile | 125 ++- hardware/arduino/bootloaders/optiboot/boot.h | 848 ++++++++++++++++++ .../arduino/bootloaders/optiboot/optiboot.c | 298 +++--- .../optiboot/optiboot_atmega328.hex | 59 +- .../optiboot/optiboot_atmega328.lst | 492 +++++----- .../optiboot/optiboot_atmega328_pro_8MHz.hex | 63 +- .../optiboot/optiboot_atmega328_pro_8MHz.lst | 544 +++++------ .../optiboot/optiboot_diecimila.hex | 63 +- .../optiboot/optiboot_diecimila.lst | 544 +++++------ .../bootloaders/optiboot/optiboot_lilypad.hex | 62 +- .../bootloaders/optiboot/optiboot_lilypad.lst | 537 +++++------ .../optiboot/optiboot_lilypad_resonator.hex | 62 +- .../optiboot/optiboot_lilypad_resonator.lst | 537 +++++------ .../bootloaders/optiboot/optiboot_luminet.hex | 80 +- .../bootloaders/optiboot/optiboot_luminet.lst | 668 +++++++------- .../optiboot/optiboot_pro_16MHz.hex | 63 +- .../optiboot/optiboot_pro_16MHz.lst | 544 +++++------ .../optiboot/optiboot_pro_20mhz.hex | 63 +- .../optiboot/optiboot_pro_20mhz.lst | 544 +++++------ .../optiboot/optiboot_pro_8MHz.hex | 62 +- .../optiboot/optiboot_pro_8MHz.lst | 537 +++++------ .../arduino/bootloaders/optiboot/pin_defs.h | 79 ++ .../arduino/bootloaders/optiboot/stk500.h | 39 + 23 files changed, 4149 insertions(+), 2764 deletions(-) create mode 100644 hardware/arduino/bootloaders/optiboot/boot.h create mode 100644 hardware/arduino/bootloaders/optiboot/pin_defs.h create mode 100644 hardware/arduino/bootloaders/optiboot/stk500.h diff --git a/hardware/arduino/bootloaders/optiboot/Makefile b/hardware/arduino/bootloaders/optiboot/Makefile index 0f8d09e9d..88cb9a20d 100644 --- a/hardware/arduino/bootloaders/optiboot/Makefile +++ b/hardware/arduino/bootloaders/optiboot/Makefile @@ -123,12 +123,23 @@ OBJDUMP = $(call fixpath,$(GCCROOT)avr-objdump) SIZE = $(GCCROOT)avr-size +# Test platforms +# Virtual boot block test +virboot328: TARGET = atmega328 +virboot328: MCU_TARGET = atmega328p +virboot328: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' '-DVIRTUAL_BOOT' +virboot328: AVR_FREQ = 16000000L +virboot328: LDSECTION = --section-start=.text=0x7e00 +virboot328: $(PROGRAM)_atmega328.hex +virboot328: $(PROGRAM)_atmega328.lst + # 20MHz clocked platforms # # These are capable of 230400 baud, or 115200 baud on PC (Arduino Avrdude issue) # pro20: TARGET = pro_20mhz +pro20: MCU_TARGET = atmega168 pro20: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' pro20: AVR_FREQ = 20000000L pro20: $(PROGRAM)_pro_20mhz.hex @@ -141,7 +152,7 @@ pro20_isp: HFUSE = DD # Full swing xtal (20MHz) 258CK/14CK+4.1ms pro20_isp: LFUSE = C6 # 512 byte boot -pro20_isp: EFUSE = 02 +pro20_isp: EFUSE = 04 pro20_isp: isp # 16MHz clocked platforms @@ -150,6 +161,7 @@ pro20_isp: isp # pro16: TARGET = pro_16MHz +pro16: MCU_TARGET = atmega168 pro16: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' pro16: AVR_FREQ = 16000000L pro16: $(PROGRAM)_pro_16MHz.hex @@ -162,12 +174,13 @@ pro16_isp: HFUSE = DD # Full swing xtal (20MHz) 258CK/14CK+4.1ms pro16_isp: LFUSE = C6 # 512 byte boot -pro16_isp: EFUSE = 02 +pro16_isp: EFUSE = 04 pro16_isp: isp # Diecimila and NG use identical bootloaders # diecimila: TARGET = diecimila +diecimila: MCU_TARGET = atmega168 diecimila: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' diecimila: AVR_FREQ = 16000000L diecimila: $(PROGRAM)_diecimila.hex @@ -180,7 +193,7 @@ diecimila_isp: HFUSE = DD # Low power xtal (16MHz) 16KCK/14CK+65ms diecimila_isp: LFUSE = FF # 512 byte boot -diecimila_isp: EFUSE = 02 +diecimila_isp: EFUSE = 04 diecimila_isp: isp atmega328: TARGET = atmega328 @@ -194,7 +207,7 @@ atmega328: $(PROGRAM)_atmega328.lst atmega328_isp: atmega328 atmega328_isp: TARGET = atmega328 atmega328_isp: MCU_TARGET = atmega328p -# 512 byte boot +# 512 byte boot, SPIEN atmega328_isp: HFUSE = DE # Low power xtal (16MHz) 16KCK/14CK+65ms atmega328_isp: LFUSE = FF @@ -202,13 +215,96 @@ atmega328_isp: LFUSE = FF atmega328_isp: EFUSE = 05 atmega328_isp: isp +# Sanguino has a minimum boot size of 1024 bytes, so enable extra functions +# +sanguino: TARGET = atmega644p +sanguino: MCU_TARGET = atmega644p +sanguino: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' '-DBIGBOOT' +sanguino: AVR_FREQ = 16000000L +sanguino: LDSECTION = --section-start=.text=0xfc00 +sanguino: $(PROGRAM)_atmega644p.hex +sanguino: $(PROGRAM)_atmega644p.lst + +sanguino_isp: sanguino +sanguino_isp: TARGET = atmega644p +sanguino_isp: MCU_TARGET = atmega644p +# 1024 byte boot +sanguino_isp: HFUSE = DE +# Low power xtal (16MHz) 16KCK/14CK+65ms +sanguino_isp: LFUSE = FF +# 2.7V brownout +sanguino_isp: EFUSE = 05 +sanguino_isp: isp + +# Mega has a minimum boot size of 1024 bytes, so enable extra functions +#mega: TARGET = atmega1280 +mega: MCU_TARGET = atmega1280 +mega: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' '-DBIGBOOT' +mega: AVR_FREQ = 16000000L +mega: LDSECTION = --section-start=.text=0x1fc00 +mega: $(PROGRAM)_atmega1280.hex +mega: $(PROGRAM)_atmega1280.lst + +mega_isp: mega +mega_isp: TARGET = atmega1280 +mega_isp: MCU_TARGET = atmega1280 +# 1024 byte boot +mega_isp: HFUSE = DE +# Low power xtal (16MHz) 16KCK/14CK+65ms +mega_isp: LFUSE = FF +# 2.7V brownout +mega_isp: EFUSE = 05 +mega_isp: isp + +# ATmega8 +# +atmega8: TARGET = atmega8 +atmega8: MCU_TARGET = atmega8 +atmega8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' +atmega8: AVR_FREQ = 16000000L +atmega8: LDSECTION = --section-start=.text=0x1e00 +atmega8: $(PROGRAM)_atmega8.hex +atmega8: $(PROGRAM)_atmega8.lst + +atmega8_isp: atmega8 +atmega8_isp: TARGET = atmega8 +atmega8_isp: MCU_TARGET = atmega8 +# SPIEN, CKOPT, Bootsize=512B +atmega8_isp: HFUSE = CC +# 2.7V brownout, Low power xtal (16MHz) 16KCK/14CK+65ms +atmega8_isp: LFUSE = BF +atmega8_isp: isp + +# ATmega88 +# +atmega88: TARGET = atmega88 +atmega88: MCU_TARGET = atmega88 +atmega88: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' +atmega88: AVR_FREQ = 16000000L +atmega88: LDSECTION = --section-start=.text=0x1e00 +atmega88: $(PROGRAM)_atmega88.hex +atmega88: $(PROGRAM)_atmega88.lst + +atmega88_isp: atmega88 +atmega88_isp: TARGET = atmega88 +atmega88_isp: MCU_TARGET = atmega88 +# 2.7V brownout +atmega88_isp: HFUSE = DD +# Low power xtal (16MHz) 16KCK/14CK+65ms +atemga88_isp: LFUSE = FF +# 512 byte boot +atmega88_isp: EFUSE = 04 +atmega88_isp: isp + + # 8MHz clocked platforms # # These are capable of 115200 baud # lilypad: TARGET = lilypad -lilypad: CFLAGS += '-DLED_START_FLASHES=3' '-DSOFT_UART' '-DBAUD_RATE=115200' +lilypad: MCU_TARGET = atmega168 +lilypad: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' lilypad: AVR_FREQ = 8000000L lilypad: $(PROGRAM)_lilypad.hex lilypad: $(PROGRAM)_lilypad.lst @@ -220,11 +316,12 @@ lilypad_isp: HFUSE = DD # Internal 8MHz osc (8MHz) Slow rising power lilypad_isp: LFUSE = E2 # 512 byte boot -lilypad_isp: EFUSE = 02 +lilypad_isp: EFUSE = 04 lilypad_isp: isp lilypad_resonator: TARGET = lilypad_resonator -lilypad_resonator: CFLAGS += '-DLED_START_FLASHES=3' '-DSOFT_UART' '-DBAUD_RATE=115200' +lilypad_resonator: MCU_TARGET = atmega168 +lilypad_resonator: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' lilypad_resonator: AVR_FREQ = 8000000L lilypad_resonator: $(PROGRAM)_lilypad_resonator.hex lilypad_resonator: $(PROGRAM)_lilypad_resonator.lst @@ -236,11 +333,12 @@ lilypad_resonator_isp: HFUSE = DD # Full swing xtal (20MHz) 258CK/14CK+4.1ms lilypad_resonator_isp: LFUSE = C6 # 512 byte boot -lilypad_resonator_isp: EFUSE = 02 +lilypad_resonator_isp: EFUSE = 04 lilypad_resonator_isp: isp pro8: TARGET = pro_8MHz -pro8: CFLAGS += '-DLED_START_FLASHES=3' '-DSOFT_UART' '-DBAUD_RATE=115200' +pro8: MCU_TARGET = atmega168 +pro8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' pro8: AVR_FREQ = 8000000L pro8: $(PROGRAM)_pro_8MHz.hex pro8: $(PROGRAM)_pro_8MHz.lst @@ -252,7 +350,7 @@ pro8_isp: HFUSE = DD # Full swing xtal (20MHz) 258CK/14CK+4.1ms pro8_isp: LFUSE = C6 # 512 byte boot -pro8_isp: EFUSE = 02 +pro8_isp: EFUSE = 04 pro8_isp: isp atmega328_pro8: TARGET = atmega328_pro_8MHz @@ -266,7 +364,7 @@ atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.lst atmega328_pro8_isp: atmega328_pro8 atmega328_pro8_isp: TARGET = atmega328_pro_8MHz atmega328_pro8_isp: MCU_TARGET = atmega328p -# 512 byte boot +# 512 byte boot, SPIEN atmega328_pro8_isp: HFUSE = DE # Low power xtal (16MHz) 16KCK/14CK+65ms atmega328_pro8_isp: LFUSE = FF @@ -299,6 +397,11 @@ luminet_isp: LFUSE = 62 luminet_isp: EFUSE = FE luminet_isp: isp +# +# Generic build instructions +# +# + isp: $(TARGET) $(ISPFUSES) $(ISPFLASH) diff --git a/hardware/arduino/bootloaders/optiboot/boot.h b/hardware/arduino/bootloaders/optiboot/boot.h new file mode 100644 index 000000000..2639cd859 --- /dev/null +++ b/hardware/arduino/bootloaders/optiboot/boot.h @@ -0,0 +1,848 @@ +/* Modified to use out for SPM access +** Peter Knight, Optiboot project http://optiboot.googlecode.com +** +** Todo: Tidy up +** +** "_short" routines execute 1 cycle faster and use 1 less word of flash +** by using "out" instruction instead of "sts". +** +** Additional elpm variants that trust the value of RAMPZ +*/ + +/* Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 Eric B. Weddington + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of the copyright holders nor the names of + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. */ + +/* $Id: boot.h,v 1.27.2.3 2008/09/30 13:58:48 arcanum Exp $ */ + +#ifndef _AVR_BOOT_H_ +#define _AVR_BOOT_H_ 1 + +/** \file */ +/** \defgroup avr_boot : Bootloader Support Utilities + \code + #include + #include + \endcode + + The macros in this module provide a C language interface to the + bootloader support functionality of certain AVR processors. These + macros are designed to work with all sizes of flash memory. + + Global interrupts are not automatically disabled for these macros. It + is left up to the programmer to do this. See the code example below. + Also see the processor datasheet for caveats on having global interrupts + enabled during writing of the Flash. + + \note Not all AVR processors provide bootloader support. See your + processor datasheet to see if it provides bootloader support. + + \todo From email with Marek: On smaller devices (all except ATmega64/128), + __SPM_REG is in the I/O space, accessible with the shorter "in" and "out" + instructions - since the boot loader has a limited size, this could be an + important optimization. + + \par API Usage Example + The following code shows typical usage of the boot API. + + \code + #include + #include + #include + + void boot_program_page (uint32_t page, uint8_t *buf) + { + uint16_t i; + uint8_t sreg; + + // Disable interrupts. + + sreg = SREG; + cli(); + + eeprom_busy_wait (); + + boot_page_erase (page); + boot_spm_busy_wait (); // Wait until the memory is erased. + + for (i=0; i +#include +#include +#include + +/* Check for SPM Control Register in processor. */ +#if defined (SPMCSR) +# define __SPM_REG SPMCSR +#elif defined (SPMCR) +# define __SPM_REG SPMCR +#else +# error AVR processor does not provide bootloader support! +#endif + + +/* Check for SPM Enable bit. */ +#if defined(SPMEN) +# define __SPM_ENABLE SPMEN +#elif defined(SELFPRGEN) +# define __SPM_ENABLE SELFPRGEN +#else +# error Cannot find SPM Enable bit definition! +#endif + +/** \ingroup avr_boot + \def BOOTLOADER_SECTION + + Used to declare a function or variable to be placed into a + new section called .bootloader. This section and its contents + can then be relocated to any address (such as the bootloader + NRWW area) at link-time. */ + +#define BOOTLOADER_SECTION __attribute__ ((section (".bootloader"))) + +/* Create common bit definitions. */ +#ifdef ASB +#define __COMMON_ASB ASB +#else +#define __COMMON_ASB RWWSB +#endif + +#ifdef ASRE +#define __COMMON_ASRE ASRE +#else +#define __COMMON_ASRE RWWSRE +#endif + +/* Define the bit positions of the Boot Lock Bits. */ + +#define BLB12 5 +#define BLB11 4 +#define BLB02 3 +#define BLB01 2 + +/** \ingroup avr_boot + \def boot_spm_interrupt_enable() + Enable the SPM interrupt. */ + +#define boot_spm_interrupt_enable() (__SPM_REG |= (uint8_t)_BV(SPMIE)) + +/** \ingroup avr_boot + \def boot_spm_interrupt_disable() + Disable the SPM interrupt. */ + +#define boot_spm_interrupt_disable() (__SPM_REG &= (uint8_t)~_BV(SPMIE)) + +/** \ingroup avr_boot + \def boot_is_spm_interrupt() + Check if the SPM interrupt is enabled. */ + +#define boot_is_spm_interrupt() (__SPM_REG & (uint8_t)_BV(SPMIE)) + +/** \ingroup avr_boot + \def boot_rww_busy() + Check if the RWW section is busy. */ + +#define boot_rww_busy() (__SPM_REG & (uint8_t)_BV(__COMMON_ASB)) + +/** \ingroup avr_boot + \def boot_spm_busy() + Check if the SPM instruction is busy. */ + +#define boot_spm_busy() (__SPM_REG & (uint8_t)_BV(__SPM_ENABLE)) + +/** \ingroup avr_boot + \def boot_spm_busy_wait() + Wait while the SPM instruction is busy. */ + +#define boot_spm_busy_wait() do{}while(boot_spm_busy()) + +#define __BOOT_PAGE_ERASE (_BV(__SPM_ENABLE) | _BV(PGERS)) +#define __BOOT_PAGE_WRITE (_BV(__SPM_ENABLE) | _BV(PGWRT)) +#define __BOOT_PAGE_FILL _BV(__SPM_ENABLE) +#define __BOOT_RWW_ENABLE (_BV(__SPM_ENABLE) | _BV(__COMMON_ASRE)) +#define __BOOT_LOCK_BITS_SET (_BV(__SPM_ENABLE) | _BV(BLBSET)) + +#define __boot_page_fill_short(address, data) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "movw r0, %3\n\t" \ + "out %0, %1\n\t" \ + "spm\n\t" \ + "clr r1\n\t" \ + : \ + : "i" (_SFR_IO_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_PAGE_FILL), \ + "z" ((uint16_t)address), \ + "r" ((uint16_t)data) \ + : "r0" \ + ); \ +})) + +#define __boot_page_fill_normal(address, data) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "movw r0, %3\n\t" \ + "sts %0, %1\n\t" \ + "spm\n\t" \ + "clr r1\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_PAGE_FILL), \ + "z" ((uint16_t)address), \ + "r" ((uint16_t)data) \ + : "r0" \ + ); \ +})) + +#define __boot_page_fill_alternate(address, data)\ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "movw r0, %3\n\t" \ + "sts %0, %1\n\t" \ + "spm\n\t" \ + ".word 0xffff\n\t" \ + "nop\n\t" \ + "clr r1\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_PAGE_FILL), \ + "z" ((uint16_t)address), \ + "r" ((uint16_t)data) \ + : "r0" \ + ); \ +})) + +#define __boot_page_fill_extended(address, data) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "movw r0, %4\n\t" \ + "movw r30, %A3\n\t" \ + "sts %1, %C3\n\t" \ + "sts %0, %2\n\t" \ + "spm\n\t" \ + "clr r1\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "i" (_SFR_MEM_ADDR(RAMPZ)), \ + "r" ((uint8_t)__BOOT_PAGE_FILL), \ + "r" ((uint32_t)address), \ + "r" ((uint16_t)data) \ + : "r0", "r30", "r31" \ + ); \ +})) + +#define __boot_page_fill_extended_short(address, data) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "movw r0, %4\n\t" \ + "movw r30, %A3\n\t" \ + "out %1, %C3\n\t" \ + "out %0, %2\n\t" \ + "spm\n\t" \ + "clr r1\n\t" \ + : \ + : "i" (_SFR_IO_ADDR(__SPM_REG)), \ + "i" (_SFR_IO_ADDR(RAMPZ)), \ + "r" ((uint8_t)__BOOT_PAGE_FILL), \ + "r" ((uint32_t)address), \ + "r" ((uint16_t)data) \ + : "r0", "r30", "r31" \ + ); \ +})) + +#define __boot_page_erase_short(address) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "out %0, %1\n\t" \ + "spm\n\t" \ + : \ + : "i" (_SFR_IO_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_PAGE_ERASE), \ + "z" ((uint16_t)address) \ + ); \ +})) + + +#define __boot_page_erase_normal(address) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "sts %0, %1\n\t" \ + "spm\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_PAGE_ERASE), \ + "z" ((uint16_t)address) \ + ); \ +})) + +#define __boot_page_erase_alternate(address) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "sts %0, %1\n\t" \ + "spm\n\t" \ + ".word 0xffff\n\t" \ + "nop\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_PAGE_ERASE), \ + "z" ((uint16_t)address) \ + ); \ +})) + +#define __boot_page_erase_extended(address) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "movw r30, %A3\n\t" \ + "sts %1, %C3\n\t" \ + "sts %0, %2\n\t" \ + "spm\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "i" (_SFR_MEM_ADDR(RAMPZ)), \ + "r" ((uint8_t)__BOOT_PAGE_ERASE), \ + "r" ((uint32_t)address) \ + : "r30", "r31" \ + ); \ +})) +#define __boot_page_erase_extended_short(address) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "movw r30, %A3\n\t" \ + "out %1, %C3\n\t" \ + "out %0, %2\n\t" \ + "spm\n\t" \ + : \ + : "i" (_SFR_IO_ADDR(__SPM_REG)), \ + "i" (_SFR_IO_ADDR(RAMPZ)), \ + "r" ((uint8_t)__BOOT_PAGE_ERASE), \ + "r" ((uint32_t)address) \ + : "r30", "r31" \ + ); \ +})) + +#define __boot_page_write_short(address) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "out %0, %1\n\t" \ + "spm\n\t" \ + : \ + : "i" (_SFR_IO_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_PAGE_WRITE), \ + "z" ((uint16_t)address) \ + ); \ +})) + +#define __boot_page_write_normal(address) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "sts %0, %1\n\t" \ + "spm\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_PAGE_WRITE), \ + "z" ((uint16_t)address) \ + ); \ +})) + +#define __boot_page_write_alternate(address) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "sts %0, %1\n\t" \ + "spm\n\t" \ + ".word 0xffff\n\t" \ + "nop\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_PAGE_WRITE), \ + "z" ((uint16_t)address) \ + ); \ +})) + +#define __boot_page_write_extended(address) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "movw r30, %A3\n\t" \ + "sts %1, %C3\n\t" \ + "sts %0, %2\n\t" \ + "spm\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "i" (_SFR_MEM_ADDR(RAMPZ)), \ + "r" ((uint8_t)__BOOT_PAGE_WRITE), \ + "r" ((uint32_t)address) \ + : "r30", "r31" \ + ); \ +})) +#define __boot_page_write_extended_short(address) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "movw r30, %A3\n\t" \ + "out %1, %C3\n\t" \ + "out %0, %2\n\t" \ + "spm\n\t" \ + : \ + : "i" (_SFR_IO_ADDR(__SPM_REG)), \ + "i" (_SFR_IO_ADDR(RAMPZ)), \ + "r" ((uint8_t)__BOOT_PAGE_WRITE), \ + "r" ((uint32_t)address) \ + : "r30", "r31" \ + ); \ +})) + +#define __boot_rww_enable_short() \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "out %0, %1\n\t" \ + "spm\n\t" \ + : \ + : "i" (_SFR_IO_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_RWW_ENABLE) \ + ); \ +})) + +#define __boot_rww_enable() \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "sts %0, %1\n\t" \ + "spm\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_RWW_ENABLE) \ + ); \ +})) + +#define __boot_rww_enable_alternate() \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "sts %0, %1\n\t" \ + "spm\n\t" \ + ".word 0xffff\n\t" \ + "nop\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_RWW_ENABLE) \ + ); \ +})) + +/* From the mega16/mega128 data sheets (maybe others): + + Bits by SPM To set the Boot Loader Lock bits, write the desired data to + R0, write "X0001001" to SPMCR and execute SPM within four clock cycles + after writing SPMCR. The only accessible Lock bits are the Boot Lock bits + that may prevent the Application and Boot Loader section from any + software update by the MCU. + + If bits 5..2 in R0 are cleared (zero), the corresponding Boot Lock bit + will be programmed if an SPM instruction is executed within four cycles + after BLBSET and SPMEN (or SELFPRGEN) are set in SPMCR. The Z-pointer is + don't care during this operation, but for future compatibility it is + recommended to load the Z-pointer with $0001 (same as used for reading the + Lock bits). For future compatibility It is also recommended to set bits 7, + 6, 1, and 0 in R0 to 1 when writing the Lock bits. When programming the + Lock bits the entire Flash can be read during the operation. */ + +#define __boot_lock_bits_set_short(lock_bits) \ +(__extension__({ \ + uint8_t value = (uint8_t)(~(lock_bits)); \ + __asm__ __volatile__ \ + ( \ + "ldi r30, 1\n\t" \ + "ldi r31, 0\n\t" \ + "mov r0, %2\n\t" \ + "out %0, %1\n\t" \ + "spm\n\t" \ + : \ + : "i" (_SFR_IO_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_LOCK_BITS_SET), \ + "r" (value) \ + : "r0", "r30", "r31" \ + ); \ +})) + +#define __boot_lock_bits_set(lock_bits) \ +(__extension__({ \ + uint8_t value = (uint8_t)(~(lock_bits)); \ + __asm__ __volatile__ \ + ( \ + "ldi r30, 1\n\t" \ + "ldi r31, 0\n\t" \ + "mov r0, %2\n\t" \ + "sts %0, %1\n\t" \ + "spm\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_LOCK_BITS_SET), \ + "r" (value) \ + : "r0", "r30", "r31" \ + ); \ +})) + +#define __boot_lock_bits_set_alternate(lock_bits) \ +(__extension__({ \ + uint8_t value = (uint8_t)(~(lock_bits)); \ + __asm__ __volatile__ \ + ( \ + "ldi r30, 1\n\t" \ + "ldi r31, 0\n\t" \ + "mov r0, %2\n\t" \ + "sts %0, %1\n\t" \ + "spm\n\t" \ + ".word 0xffff\n\t" \ + "nop\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_LOCK_BITS_SET), \ + "r" (value) \ + : "r0", "r30", "r31" \ + ); \ +})) + +/* + Reading lock and fuse bits: + + Similarly to writing the lock bits above, set BLBSET and SPMEN (or + SELFPRGEN) bits in __SPMREG, and then (within four clock cycles) issue an + LPM instruction. + + Z address: contents: + 0x0000 low fuse bits + 0x0001 lock bits + 0x0002 extended fuse bits + 0x0003 high fuse bits + + Sounds confusing, doesn't it? + + Unlike the macros in pgmspace.h, no need to care for non-enhanced + cores here as these old cores do not provide SPM support anyway. + */ + +/** \ingroup avr_boot + \def GET_LOW_FUSE_BITS + address to read the low fuse bits, using boot_lock_fuse_bits_get + */ +#define GET_LOW_FUSE_BITS (0x0000) +/** \ingroup avr_boot + \def GET_LOCK_BITS + address to read the lock bits, using boot_lock_fuse_bits_get + */ +#define GET_LOCK_BITS (0x0001) +/** \ingroup avr_boot + \def GET_EXTENDED_FUSE_BITS + address to read the extended fuse bits, using boot_lock_fuse_bits_get + */ +#define GET_EXTENDED_FUSE_BITS (0x0002) +/** \ingroup avr_boot + \def GET_HIGH_FUSE_BITS + address to read the high fuse bits, using boot_lock_fuse_bits_get + */ +#define GET_HIGH_FUSE_BITS (0x0003) + +/** \ingroup avr_boot + \def boot_lock_fuse_bits_get(address) + + Read the lock or fuse bits at \c address. + + Parameter \c address can be any of GET_LOW_FUSE_BITS, + GET_LOCK_BITS, GET_EXTENDED_FUSE_BITS, or GET_HIGH_FUSE_BITS. + + \note The lock and fuse bits returned are the physical values, + i.e. a bit returned as 0 means the corresponding fuse or lock bit + is programmed. + */ +#define boot_lock_fuse_bits_get_short(address) \ +(__extension__({ \ + uint8_t __result; \ + __asm__ __volatile__ \ + ( \ + "ldi r30, %3\n\t" \ + "ldi r31, 0\n\t" \ + "out %1, %2\n\t" \ + "lpm %0, Z\n\t" \ + : "=r" (__result) \ + : "i" (_SFR_IO_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_LOCK_BITS_SET), \ + "M" (address) \ + : "r0", "r30", "r31" \ + ); \ + __result; \ +})) + +#define boot_lock_fuse_bits_get(address) \ +(__extension__({ \ + uint8_t __result; \ + __asm__ __volatile__ \ + ( \ + "ldi r30, %3\n\t" \ + "ldi r31, 0\n\t" \ + "sts %1, %2\n\t" \ + "lpm %0, Z\n\t" \ + : "=r" (__result) \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_LOCK_BITS_SET), \ + "M" (address) \ + : "r0", "r30", "r31" \ + ); \ + __result; \ +})) + +/** \ingroup avr_boot + \def boot_signature_byte_get(address) + + Read the Signature Row byte at \c address. For some MCU types, + this function can also retrieve the factory-stored oscillator + calibration bytes. + + Parameter \c address can be 0-0x1f as documented by the datasheet. + \note The values are MCU type dependent. +*/ + +#define __BOOT_SIGROW_READ (_BV(__SPM_ENABLE) | _BV(SIGRD)) + +#define boot_signature_byte_get_short(addr) \ +(__extension__({ \ + uint16_t __addr16 = (uint16_t)(addr); \ + uint8_t __result; \ + __asm__ __volatile__ \ + ( \ + "out %1, %2\n\t" \ + "lpm %0, Z" "\n\t" \ + : "=r" (__result) \ + : "i" (_SFR_IO_ADDR(__SPM_REG)), \ + "r" ((uint8_t) __BOOT_SIGROW_READ), \ + "z" (__addr16) \ + ); \ + __result; \ +})) + +#define boot_signature_byte_get(addr) \ +(__extension__({ \ + uint16_t __addr16 = (uint16_t)(addr); \ + uint8_t __result; \ + __asm__ __volatile__ \ + ( \ + "sts %1, %2\n\t" \ + "lpm %0, Z" "\n\t" \ + : "=r" (__result) \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t) __BOOT_SIGROW_READ), \ + "z" (__addr16) \ + ); \ + __result; \ +})) + +/** \ingroup avr_boot + \def boot_page_fill(address, data) + + Fill the bootloader temporary page buffer for flash + address with data word. + + \note The address is a byte address. The data is a word. The AVR + writes data to the buffer a word at a time, but addresses the buffer + per byte! So, increment your address by 2 between calls, and send 2 + data bytes in a word format! The LSB of the data is written to the lower + address; the MSB of the data is written to the higher address.*/ + +/** \ingroup avr_boot + \def boot_page_erase(address) + + Erase the flash page that contains address. + + \note address is a byte address in flash, not a word address. */ + +/** \ingroup avr_boot + \def boot_page_write(address) + + Write the bootloader temporary page buffer + to flash page that contains address. + + \note address is a byte address in flash, not a word address. */ + +/** \ingroup avr_boot + \def boot_rww_enable() + + Enable the Read-While-Write memory section. */ + +/** \ingroup avr_boot + \def boot_lock_bits_set(lock_bits) + + Set the bootloader lock bits. + + \param lock_bits A mask of which Boot Loader Lock Bits to set. + + \note In this context, a 'set bit' will be written to a zero value. + Note also that only BLBxx bits can be programmed by this command. + + For example, to disallow the SPM instruction from writing to the Boot + Loader memory section of flash, you would use this macro as such: + + \code + boot_lock_bits_set (_BV (BLB11)); + \endcode + + \note Like any lock bits, the Boot Loader Lock Bits, once set, + cannot be cleared again except by a chip erase which will in turn + also erase the boot loader itself. */ + +/* Normal versions of the macros use 16-bit addresses. + Extended versions of the macros use 32-bit addresses. + Alternate versions of the macros use 16-bit addresses and require special + instruction sequences after LPM. + + FLASHEND is defined in the ioXXXX.h file. + USHRT_MAX is defined in . */ + +#if defined(__AVR_ATmega161__) || defined(__AVR_ATmega163__) \ + || defined(__AVR_ATmega323__) + +/* Alternate: ATmega161/163/323 and 16 bit address */ +#define boot_page_fill(address, data) __boot_page_fill_alternate(address, data) +#define boot_page_erase(address) __boot_page_erase_alternate(address) +#define boot_page_write(address) __boot_page_write_alternate(address) +#define boot_rww_enable() __boot_rww_enable_alternate() +#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_alternate(lock_bits) + +#elif (FLASHEND > USHRT_MAX) + +/* Extended: >16 bit address */ +#define boot_page_fill(address, data) __boot_page_fill_extended_short(address, data) +#define boot_page_erase(address) __boot_page_erase_extended_short(address) +#define boot_page_write(address) __boot_page_write_extended_short(address) +#define boot_rww_enable() __boot_rww_enable_short() +#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_short(lock_bits) + +#else + +/* Normal: 16 bit address */ +#define boot_page_fill(address, data) __boot_page_fill_short(address, data) +#define boot_page_erase(address) __boot_page_erase_short(address) +#define boot_page_write(address) __boot_page_write_short(address) +#define boot_rww_enable() __boot_rww_enable_short() +#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_short(lock_bits) + +#endif + +/** \ingroup avr_boot + + Same as boot_page_fill() except it waits for eeprom and spm operations to + complete before filling the page. */ + +#define boot_page_fill_safe(address, data) \ +do { \ + boot_spm_busy_wait(); \ + eeprom_busy_wait(); \ + boot_page_fill(address, data); \ +} while (0) + +/** \ingroup avr_boot + + Same as boot_page_erase() except it waits for eeprom and spm operations to + complete before erasing the page. */ + +#define boot_page_erase_safe(address) \ +do { \ + boot_spm_busy_wait(); \ + eeprom_busy_wait(); \ + boot_page_erase (address); \ +} while (0) + +/** \ingroup avr_boot + + Same as boot_page_write() except it waits for eeprom and spm operations to + complete before writing the page. */ + +#define boot_page_write_safe(address) \ +do { \ + boot_spm_busy_wait(); \ + eeprom_busy_wait(); \ + boot_page_write (address); \ +} while (0) + +/** \ingroup avr_boot + + Same as boot_rww_enable() except waits for eeprom and spm operations to + complete before enabling the RWW mameory. */ + +#define boot_rww_enable_safe() \ +do { \ + boot_spm_busy_wait(); \ + eeprom_busy_wait(); \ + boot_rww_enable(); \ +} while (0) + +/** \ingroup avr_boot + + Same as boot_lock_bits_set() except waits for eeprom and spm operations to + complete before setting the lock bits. */ + +#define boot_lock_bits_set_safe(lock_bits) \ +do { \ + boot_spm_busy_wait(); \ + eeprom_busy_wait(); \ + boot_lock_bits_set (lock_bits); \ +} while (0) + +#endif /* _AVR_BOOT_H_ */ diff --git a/hardware/arduino/bootloaders/optiboot/optiboot.c b/hardware/arduino/bootloaders/optiboot/optiboot.c index c7d817a61..4b4a10a80 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot.c +++ b/hardware/arduino/bootloaders/optiboot/optiboot.c @@ -1,6 +1,11 @@ /**********************************************************/ /* Optiboot bootloader for Arduino */ /* */ +/* http://optiboot.googlecode.com */ +/* */ +/* Arduino-maintained version : See README.TXT */ +/* http://code.google.com/p/arduino/ */ +/* */ /* Heavily optimised bootloader that is faster and */ /* smaller than the Arduino standard bootloader */ /* */ @@ -10,6 +15,8 @@ /* Higher baud rate speeds up programming */ /* Written almost entirely in C */ /* Customisable timeout with accurate timeconstant */ +/* Optional virtual UART. No hardware UART required. */ +/* Optional virtual boot partition for devices without. */ /* */ /* What you lose: */ /* Implements a skeleton STK500 protocol which is */ @@ -18,12 +25,19 @@ /* High baud rate breaks compatibility with standard */ /* Arduino flash settings */ /* */ -/* Currently supports: */ -/* ATmega168 based devices (Diecimila etc) */ +/* Fully supported: */ +/* ATmega168 based devices (Diecimila etc) */ /* ATmega328P based devices (Duemilanove etc) */ /* */ +/* Alpha test */ +/* ATmega1280 based devices (Arduino Mega) */ +/* */ +/* Work in progress: */ +/* ATmega644P based devices (Sanguino) */ +/* ATtiny84 based devices (Luminet) */ +/* */ /* Does not support: */ -/* ATmega1280 based devices (eg. Mega) */ +/* USB based devices (eg. Teensy) */ /* */ /* Assumptions: */ /* The code makes several assumptions that reduce the */ @@ -64,102 +78,85 @@ /* */ /**********************************************************/ + +/**********************************************************/ +/* */ +/* Optional defines: */ +/* */ +/**********************************************************/ +/* */ +/* BIG_BOOT: */ +/* Build a 1k bootloader, not 512 bytes. This turns on */ +/* extra functionality. */ +/* */ +/* BAUD_RATE: */ +/* Set bootloader baud rate. */ +/* */ +/* LUDICROUS_SPEED: */ +/* 230400 baud :-) */ +/* */ +/* SOFT_UART: */ +/* Use AVR305 soft-UART instead of hardware UART. */ +/* */ +/* LED_START_FLASHES: */ +/* Number of LED flashes on bootup. */ +/* */ +/* LED_DATA_FLASH: */ +/* Flash LED when transferring data. For boards without */ +/* TX or RX LEDs, or for people who like blinky lights. */ +/* */ +/* SUPPORT_EEPROM: */ +/* Support reading and writing from EEPROM. This is not */ +/* used by Arduino, so off by default. */ +/* */ +/* TIMEOUT_MS: */ +/* Bootloader timeout period, in milliseconds. */ +/* 500,1000,2000,4000,8000 supported. */ +/* */ +/**********************************************************/ + #include #include #include -#include -//#define LED_DATA_FLASH +// uses sts instructions, but this version uses out instructions +// This saves cycles and program memory. +#include "boot.h" + + +// We don't use as those routines have interrupt overhead we don't need. + +#include "pin_defs.h" +#include "stk500.h" #ifndef LED_START_FLASHES #define LED_START_FLASHES 0 #endif -/* Build-time variables */ -/* BAUD_RATE Programming baud rate */ -/* LED_NO_FLASHES Number of LED flashes on boot */ -/* FLASH_TIME_MS Duration of each LED flash */ -/* BOOT_TIMEOUT_MS Serial port wait time before exiting bootloader */ +#ifdef LUDICROUS_SPEED +#define BAUD_RATE 230400L +#endif -/* set the UART baud rate */ +/* set the UART baud rate defaults */ #ifndef BAUD_RATE -#define BAUD_RATE 19200 -#endif - -#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) -/* Onboard LED is connected to pin PB5 in Arduino NG, Diecimila, and Duemilanove */ -#define LED_DDR DDRB -#define LED_PORT PORTB -#define LED_PIN PINB -#define LED PINB5 - -/* Ports for soft UART */ -#ifdef SOFT_UART -#define UART_PORT PORTD -#define UART_PIN PIND -#define UART_DDR DDRD -#define UART_TX_BIT 1 -#define UART_RX_BIT 0 +#if F_CPU >= 8000000L +#define BAUD_RATE 115200L // Highest rate Avrdude win32 will support +#elsif F_CPU >= 1000000L +#define BAUD_RATE 9600L // 19200 also supported, but with significant error +#elsif F_CPU >= 128000L +#define BAUD_RATE 4800L // Good for 128kHz internal RC +#else +#define BAUD_RATE 1200L // Good even at 32768Hz #endif #endif -#if defined(__AVR_ATtiny84__) -/* Onboard LED is connected to pin PB5 in Arduino NG, Diecimila, and Duemilanove */ -#define LED_DDR DDRA -#define LED_PORT PORTA -#define LED_PIN PINA -#define LED PINA4 - -/* Ports for soft UART - left port only for now*/ -#ifdef SOFT_UART -#define UART_PORT PORTA -#define UART_PIN PINA -#define UART_DDR DDRA -#define UART_TX_BIT 2 -#define UART_RX_BIT 3 +/* Switch in soft UART for hard baud rates */ +#if (F_CPU/BAUD_RATE) > 280 // > 57600 for 16MHz +#ifndef SOFT_UART +#define SOFT_UART #endif #endif -/* STK500 constants list, from AVRDUDE */ -#define STK_OK 0x10 -#define STK_FAILED 0x11 // Not used -#define STK_UNKNOWN 0x12 // Not used -#define STK_NODEVICE 0x13 // Not used -#define STK_INSYNC 0x14 // ' ' -#define STK_NOSYNC 0x15 // Not used -#define ADC_CHANNEL_ERROR 0x16 // Not used -#define ADC_MEASURE_OK 0x17 // Not used -#define PWM_CHANNEL_ERROR 0x18 // Not used -#define PWM_ADJUST_OK 0x19 // Not used -#define CRC_EOP 0x20 // 'SPACE' -#define STK_GET_SYNC 0x30 // '0' -#define STK_GET_SIGN_ON 0x31 // '1' -#define STK_SET_PARAMETER 0x40 // '@' -#define STK_GET_PARAMETER 0x41 // 'A' -#define STK_SET_DEVICE 0x42 // 'B' -#define STK_SET_DEVICE_EXT 0x45 // 'E' -#define STK_ENTER_PROGMODE 0x50 // 'P' -#define STK_LEAVE_PROGMODE 0x51 // 'Q' -#define STK_CHIP_ERASE 0x52 // 'R' -#define STK_CHECK_AUTOINC 0x53 // 'S' -#define STK_LOAD_ADDRESS 0x55 // 'U' -#define STK_UNIVERSAL 0x56 // 'V' -#define STK_PROG_FLASH 0x60 // '`' -#define STK_PROG_DATA 0x61 // 'a' -#define STK_PROG_FUSE 0x62 // 'b' -#define STK_PROG_LOCK 0x63 // 'c' -#define STK_PROG_PAGE 0x64 // 'd' -#define STK_PROG_FUSE_EXT 0x65 // 'e' -#define STK_READ_FLASH 0x70 // 'p' -#define STK_READ_DATA 0x71 // 'q' -#define STK_READ_FUSE 0x72 // 'r' -#define STK_READ_LOCK 0x73 // 's' -#define STK_READ_PAGE 0x74 // 't' -#define STK_READ_SIGN 0x75 // 'u' -#define STK_READ_OSCCAL 0x76 // 'v' -#define STK_READ_FUSE_EXT 0x77 // 'w' -#define STK_READ_OSCCAL_EXT 0x78 // 'x' - /* Watchdog settings */ #define WATCHDOG_OFF (0) #define WATCHDOG_16MS (_BV(WDE)) @@ -170,8 +167,10 @@ #define WATCHDOG_500MS (_BV(WDP2) | _BV(WDP0) | _BV(WDE)) #define WATCHDOG_1S (_BV(WDP2) | _BV(WDP1) | _BV(WDE)) #define WATCHDOG_2S (_BV(WDP2) | _BV(WDP1) | _BV(WDP0) | _BV(WDE)) +#ifndef __AVR_ATmega8__ #define WATCHDOG_4S (_BV(WDE3) | _BV(WDE)) #define WATCHDOG_8S (_BV(WDE3) | _BV(WDE0) | _BV(WDE)) +#endif /* Function Prototypes */ /* The main function is in init9, which removes the interrupt vector table */ @@ -191,18 +190,41 @@ void uartDelay() __attribute__ ((naked)); #endif void appStart() __attribute__ ((naked)); +#if defined(__AVR_ATmega168__) +#define RAMSTART (0x100) +#define NRWWSTART (0x3800) +#elif defined(__AVR_ATmega328P__) +#define RAMSTART (0x100) +#define NRWWSTART (0x7000) +#elif defined (__AVR_ATmega644P__) +#define RAMSTART (0x100) +#define NRWWSTART (0xE000) +#elif defined(__AVR_ATtiny84__) +#define RAMSTART (0x100) +#define NRWWSTART (0x0000) +#elif defined(__AVR_ATmega1280__) +#define RAMSTART (0x200) +#define NRWWSTART (0xE000) +#elif defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__) +#define RAMSTART (0x100) +#define NRWWSTART (0x1800) +#endif + /* C zero initialises all global variables. However, that requires */ /* These definitions are NOT zero initialised, but that doesn't matter */ /* This allows us to drop the zero init code, saving us memory */ -#define buff ((uint8_t*)(0x100)) -#define address (*(uint16_t*)(0x200)) -#define length (*(uint8_t*)(0x202)) +#define buff ((uint8_t*)(RAMSTART)) +#define address (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2)) +#define length (*(uint8_t*)(RAMSTART+SPM_PAGESIZE*2+2)) #ifdef VIRTUAL_BOOT_PARTITION -#define rstVect (*(uint16_t*)(0x204)) -#define wdtVect (*(uint16_t*)(0x206)) +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif + /* main program starts here */ int main(void) { + uint8_t ch; + // After the zero init loop, this is the first code to run. // // This code makes the following assumptions: @@ -212,20 +234,9 @@ int main(void) { // // If not, uncomment the following instructions: // cli(); - // SP=RAMEND; // This is done by hardware reset asm volatile ("clr __zero_reg__"); - - uint8_t ch; - -#if LED_START_FLASHES > 0 - // Set up Timer 1 for timeout counter - TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 -#endif -#ifndef SOFT_UART - UCSR0A = _BV(U2X0); //Double speed mode USART0 - UCSR0B = _BV(RXEN0) | _BV(TXEN0); - UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); - UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); +#ifdef __AVR_ATmega8__ + SP=RAMEND; // This is done by hardware reset #endif // Adaboot no-wait mod @@ -233,8 +244,26 @@ int main(void) { MCUSR = 0; if (!(ch & _BV(EXTRF))) appStart(); +#if LED_START_FLASHES > 0 + // Set up Timer 1 for timeout counter + TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 +#endif +#ifndef SOFT_UART +#ifdef __AVR_ATmega8__ + UCSRA = _BV(U2X); //Double speed mode USART + UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx + UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 + UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); +#else + UCSR0A = _BV(U2X0); //Double speed mode USART0 + UCSR0B = _BV(RXEN0) | _BV(TXEN0); + UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); + UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); +#endif +#endif + // Set up watchdog to trigger after 500ms - watchdogConfig(WATCHDOG_500MS); + watchdogConfig(WATCHDOG_1S); /* Set LED pin as output */ LED_DDR |= _BV(LED); @@ -269,9 +298,15 @@ int main(void) { } else if(ch == STK_LOAD_ADDRESS) { // LOAD ADDRESS - address = getch(); - address = (address & 0xff) | (getch() << 8); - address += address; // Convert from word address to byte address + uint16_t newAddress; + newAddress = getch(); + newAddress = (newAddress & 0xff) | (getch() << 8); +#ifdef RAMPZ + // Transfer top bit to RAMPZ + RAMPZ = (newAddress & 0x8000) ? 1 : 0; +#endif + newAddress += newAddress; // Convert from word address to byte address + address = newAddress; verifySpace(); } else if(ch == STK_UNIVERSAL) { @@ -279,7 +314,7 @@ int main(void) { getNch(4); putch(0x00); } - /* Write memory, length is big endian and is in bytes */ + /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t *bufPtr; @@ -287,14 +322,18 @@ int main(void) { getLen(); - // Immediately start page erase - this will 4.5ms - boot_page_erase((uint16_t)(void*)address); - + // If we are in RWW section, immediately start page erase + if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); while (--length); + // If we are in NRWW section, page erase has to be delayed until now. + // Todo: Take RAMPZ into account + if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + // Read command terminator, start reply verifySpace(); @@ -310,10 +349,10 @@ int main(void) { // Move RESET vector to WDT vector uint16_t vect = buff[0] | (buff[1]<<8); rstVect = vect; - wdtVect = buff[10] | (buff[11]<<8); + wdtVect = buff[8] | (buff[9]<<8); vect -= 4; // Instruction is a relative jump (rjmp), so recalculate. - buff[10] = vect & 0xff; - buff[11] = vect >> 8; + buff[8] = vect & 0xff; + buff[9] = vect >> 8; // Add jump to bootloader at RESET vector buff[0] = 0x7f; @@ -329,12 +368,12 @@ int main(void) { uint16_t a; a = *bufPtr++; a |= (*bufPtr++) << 8; - boot_page_fill((uint16_t)(void*)addrPtr,a); + __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); // Write from programming buffer - boot_page_write((uint16_t)(void*)address); + __boot_page_write_short((uint16_t)(void*)address); boot_spm_busy_wait(); #if defined(RWWSRE) @@ -353,15 +392,27 @@ int main(void) { // Undo vector patch in bottom page so verify passes if (address == 0) ch=rstVect & 0xff; else if (address == 1) ch=rstVect >> 8; - else if (address == 10) ch=wdtVect & 0xff; - else if (address == 11) ch=wdtVect >> 8; + else if (address == 8) ch=wdtVect & 0xff; + else if (address == 9) ch=wdtVect >> 8; else ch = pgm_read_byte_near(address); address++; putch(ch); } while (--length); +#else +#ifdef __AVR_ATmega1280__ +// do putch(pgm_read_byte_near(address++)); +// while (--length); + do { + uint8_t result; + __asm__ ("elpm %0,Z\n":"=r"(result):"z"(address)); + putch(result); + address++; + } + while (--length); #else do putch(pgm_read_byte_near(address++)); while (--length); +#endif #endif } @@ -422,8 +473,12 @@ uint8_t getch(void) { watchdogReset(); #ifdef LED_DATA_FLASH +#ifdef __AVR_ATmega8__ + LED_PORT ^= _BV(LED); +#else LED_PIN |= _BV(LED); #endif +#endif #ifdef SOFT_UART __asm__ __volatile__ ( @@ -455,14 +510,19 @@ uint8_t getch(void) { #endif #ifdef LED_DATA_FLASH +#ifdef __AVR_ATmega8__ + LED_PORT ^= _BV(LED); +#else LED_PIN |= _BV(LED); +#endif #endif return ch; } #ifdef SOFT_UART -//#define UART_B_VALUE (((F_CPU/BAUD_RATE)-23)/6) +// AVR350 equation: #define UART_B_VALUE (((F_CPU/BAUD_RATE)-23)/6) +// Adding 3 to numerator simulates nearest rounding for more accurate baud rates #define UART_B_VALUE (((F_CPU/BAUD_RATE)-20)/6) #if UART_B_VALUE > 255 #error Baud rate too slow for soft UART @@ -495,7 +555,11 @@ void flash_led(uint8_t count) { TCNT1 = -(F_CPU/(1024*16)); TIFR1 = _BV(TOV1); while(!(TIFR1 & _BV(TOV1))); +#ifdef __AVR_ATmega8__ + LED_PORT ^= _BV(LED); +#else LED_PIN |= _BV(LED); +#endif watchdogReset(); } while (--count); } @@ -524,7 +588,7 @@ void appStart() { __asm__ __volatile__ ( #ifdef VIRTUAL_BOOT_PARTITION // Jump to WDT vector - "ldi r30,5\n" + "ldi r30,4\n" "clr r31\n" #else // Jump to RST vector diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.hex b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.hex index e8aa31c4b..72108ee10 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.hex @@ -1,33 +1,34 @@ -:107E0000112485E08093810082E08093C00088E1A6 -:107E10008093C10086E08093C20080E18093C4001B -:107E200084B714BE81FFD0D08DE0C8D0259A86E0FB +:107E0000112484B714BE81FFE6D085E08093810001 +:107E100082E08093C00088E18093C10086E0809377 +:107E2000C20080E18093C4008EE0CFD0259A86E026 :107E300020E33CEF91E0309385002093840096BBD3 :107E4000B09BFECF1D9AA8958150A9F7DD24D3944D -:107E5000A5E0EA2EF1E1FF2EA4D0813421F481E0E7 -:107E6000BED083E024C0823411F484E103C08534A1 -:107E700019F485E0B4D08AC08535A1F492D0082FDA -:107E800010E010930102009300028BD090E0982F35 -:107E90008827802B912B880F991F90930102809344 -:107EA000000273C0863529F484E099D080E071D057 -:107EB0006DC0843609F043C07CD0E0910002F0919F -:107EC000010283E080935700E895C0E0D1E069D0DB -:107ED0008993809102028150809302028823B9F72E -:107EE00078D007B600FCFDCF40910002509101020E -:107EF000A0E0B1E02C9130E011968C91119790E0C8 -:107F0000982F8827822B932B1296FA010C01D0927E -:107F10005700E89511244E5F5F4FF1E0A038BF078E -:107F200049F7E0910002F0910102E0925700E895D4 -:107F300007B600FCFDCFF0925700E89527C08437C4 -:107F4000B9F437D046D0E0910002F09101023196A9 -:107F5000F0930102E09300023197E4918E2F19D043 -:107F600080910202815080930202882361F70EC043 -:107F7000853739F42ED08EE10CD085E90AD08FE018 -:107F800096CF813511F488E019D023D080E101D05B -:107F900063CF982F8091C00085FFFCCF9093C600DF -:107FA0000895A8958091C00087FFFCCF8091C600FE -:107FB0000895F7DFF6DF80930202F3CFE0E6F0E00A -:107FC00098E190838083089580E0F8DFEE27FF2713 -:107FD0000994E7DF803209F0F7DF84E1DACF1F93FD -:0E7FE000182FDFDF1150E9F7F4DF1F9108952D +:107E5000A5E0EA2EF1E1FF2EABD0813421F481E0E0 +:107E6000C5D083E020C0823411F484E103C085349E +:107E700019F485E0BBD091C0853581F499D0082FE5 +:107E800010E096D090E0982F8827802B912B880FB8 +:107E9000991F90930102809300027EC0863529F4D9 +:107EA00084E0A4D080E07CD078C0843609F04EC055 +:107EB00087D0E0910002F091010280E7E030F807FE +:107EC00018F483E087BFE895C0E0D1E071D08993D2 +:107ED000809102028150809302028823B9F7E091D9 +:107EE0000002F091010280E7E030F80718F083E02B +:107EF00087BFE89575D007B600FCFDCF4091000222 +:107F000050910102A0E0B1E02C9130E011968C91EB +:107F1000119790E0982F8827822B932B1296FA01C5 +:107F20000C01D7BEE89511244E5F5F4FF1E0A038F9 +:107F3000BF0751F7E0910002F0910102E7BEE8951A +:107F400007B600FCFDCFF7BEE89527C08437B9F42B +:107F500037D046D0E0910002F09101023196F093C3 +:107F60000102E09300023197E4918E2F19D08091A5 +:107F70000202815080930202882361F70EC0853788 +:107F800039F42ED08EE10CD085E90AD08FE08BCF6A +:107F9000813511F488E019D023D080E101D05CCF85 +:107FA000982F8091C00085FFFCCF9093C600089564 +:107FB000A8958091C00087FFFCCF8091C6000895EE +:107FC000F7DFF6DF80930202F3CFE0E6F0E098E11E +:107FD00090838083089580E0F8DFEE27FF270994DF +:107FE000E7DF803209F0F7DF84E1DACF1F93182F43 +:0C7FF000DFDF1150E9F7F4DF1F91089566 :0400000300007E007B :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.lst b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.lst index 104799ff2..1af4a3c62 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.lst @@ -3,74 +3,79 @@ optiboot_atmega328.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .text 000001ee 00007e00 00007e00 00000054 2**1 + 0 .text 000001fc 00007e00 00007e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .debug_aranges 00000028 00000000 00000000 00000242 2**0 + 1 .debug_aranges 00000028 00000000 00000000 00000250 2**0 CONTENTS, READONLY, DEBUGGING - 2 .debug_pubnames 0000006a 00000000 00000000 0000026a 2**0 + 2 .debug_pubnames 0000006a 00000000 00000000 00000278 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_info 00000269 00000000 00000000 000002d4 2**0 + 3 .debug_info 00000284 00000000 00000000 000002e2 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_abbrev 00000196 00000000 00000000 0000053d 2**0 + 4 .debug_abbrev 000001ae 00000000 00000000 00000566 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_line 0000043f 00000000 00000000 000006d3 2**0 + 5 .debug_line 00000450 00000000 00000000 00000714 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_frame 00000090 00000000 00000000 00000b14 2**2 + 6 .debug_frame 00000090 00000000 00000000 00000b64 2**2 CONTENTS, READONLY, DEBUGGING - 7 .debug_str 00000136 00000000 00000000 00000ba4 2**0 + 7 .debug_str 00000141 00000000 00000000 00000bf4 2**0 CONTENTS, READONLY, DEBUGGING - 8 .debug_loc 000001d1 00000000 00000000 00000cda 2**0 + 8 .debug_loc 000001e1 00000000 00000000 00000d35 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_ranges 00000068 00000000 00000000 00000eab 2**0 + 9 .debug_ranges 00000068 00000000 00000000 00000f16 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: 00007e00

    : -#ifdef VIRTUAL_BOOT_PARTITION -#define rstVect (*(uint16_t*)(0x204)) -#define wdtVect (*(uint16_t*)(0x206)) +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif + /* main program starts here */ int main(void) { 7e00: 11 24 eor r1, r1 - - uint8_t ch; - -#if LED_START_FLASHES > 0 - // Set up Timer 1 for timeout counter - TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 - 7e02: 85 e0 ldi r24, 0x05 ; 5 - 7e04: 80 93 81 00 sts 0x0081, r24 -#endif -#ifndef SOFT_UART - UCSR0A = _BV(U2X0); //Double speed mode USART0 - 7e08: 82 e0 ldi r24, 0x02 ; 2 - 7e0a: 80 93 c0 00 sts 0x00C0, r24 - UCSR0B = _BV(RXEN0) | _BV(TXEN0); - 7e0e: 88 e1 ldi r24, 0x18 ; 24 - 7e10: 80 93 c1 00 sts 0x00C1, r24 - UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); - 7e14: 86 e0 ldi r24, 0x06 ; 6 - 7e16: 80 93 c2 00 sts 0x00C2, r24 - UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); - 7e1a: 80 e1 ldi r24, 0x10 ; 16 - 7e1c: 80 93 c4 00 sts 0x00C4, r24 +#ifdef __AVR_ATmega8__ + SP=RAMEND; // This is done by hardware reset #endif // Adaboot no-wait mod ch = MCUSR; - 7e20: 84 b7 in r24, 0x34 ; 52 + 7e02: 84 b7 in r24, 0x34 ; 52 MCUSR = 0; - 7e22: 14 be out 0x34, r1 ; 52 + 7e04: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); - 7e24: 81 ff sbrs r24, 1 - 7e26: d0 d0 rcall .+416 ; 0x7fc8 + 7e06: 81 ff sbrs r24, 1 + 7e08: e6 d0 rcall .+460 ; 0x7fd6 + +#if LED_START_FLASHES > 0 + // Set up Timer 1 for timeout counter + TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 + 7e0a: 85 e0 ldi r24, 0x05 ; 5 + 7e0c: 80 93 81 00 sts 0x0081, r24 + UCSRA = _BV(U2X); //Double speed mode USART + UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx + UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 + UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); +#else + UCSR0A = _BV(U2X0); //Double speed mode USART0 + 7e10: 82 e0 ldi r24, 0x02 ; 2 + 7e12: 80 93 c0 00 sts 0x00C0, r24 + UCSR0B = _BV(RXEN0) | _BV(TXEN0); + 7e16: 88 e1 ldi r24, 0x18 ; 24 + 7e18: 80 93 c1 00 sts 0x00C1, r24 + UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); + 7e1c: 86 e0 ldi r24, 0x06 ; 6 + 7e1e: 80 93 c2 00 sts 0x00C2, r24 + UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); + 7e22: 80 e1 ldi r24, 0x10 ; 16 + 7e24: 80 93 c4 00 sts 0x00C4, r24 +#endif +#endif // Set up watchdog to trigger after 500ms - watchdogConfig(WATCHDOG_500MS); - 7e28: 8d e0 ldi r24, 0x0D ; 13 - 7e2a: c8 d0 rcall .+400 ; 0x7fbc + watchdogConfig(WATCHDOG_1S); + 7e28: 8e e0 ldi r24, 0x0E ; 14 + 7e2a: cf d0 rcall .+414 ; 0x7fca /* Set LED pin as output */ LED_DDR |= _BV(LED); @@ -99,6 +104,9 @@ void flash_led(uint8_t count) { while(!(TIFR1 & _BV(TOV1))); 7e40: b0 9b sbis 0x16, 0 ; 22 7e42: fe cf rjmp .-4 ; 0x7e40 +#ifdef __AVR_ATmega8__ + LED_PORT ^= _BV(LED); +#else LED_PIN |= _BV(LED); 7e44: 1d 9a sbi 0x03, 5 ; 3 return getch(); @@ -108,10 +116,10 @@ void flash_led(uint8_t count) { void watchdogReset() { __asm__ __volatile__ ( 7e46: a8 95 wdr - TCNT1 = -(F_CPU/(1024*16)); - TIFR1 = _BV(TOV1); - while(!(TIFR1 & _BV(TOV1))); + LED_PORT ^= _BV(LED); +#else LED_PIN |= _BV(LED); +#endif watchdogReset(); } while (--count); 7e48: 81 50 subi r24, 0x01 ; 1 @@ -124,12 +132,12 @@ void watchdogReset() { getNch(1); 7e4c: dd 24 eor r13, r13 7e4e: d3 94 inc r13 - boot_page_fill((uint16_t)(void*)addrPtr,a); + __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); // Write from programming buffer - boot_page_write((uint16_t)(void*)address); + __boot_page_write_short((uint16_t)(void*)address); 7e50: a5 e0 ldi r26, 0x05 ; 5 7e52: ea 2e mov r14, r26 boot_spm_busy_wait(); @@ -145,7 +153,7 @@ void watchdogReset() { for (;;) { /* get character from UART */ ch = getch(); - 7e58: a4 d0 rcall .+328 ; 0x7fa2 + 7e58: ab d0 rcall .+342 ; 0x7fb0 if(ch == STK_GET_PARAMETER) { 7e5a: 81 34 cpi r24, 0x41 ; 65 @@ -153,10 +161,10 @@ void watchdogReset() { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); 7e5e: 81 e0 ldi r24, 0x01 ; 1 - 7e60: be d0 rcall .+380 ; 0x7fde + 7e60: c5 d0 rcall .+394 ; 0x7fec putch(0x03); 7e62: 83 e0 ldi r24, 0x03 ; 3 - 7e64: 24 c0 rjmp .+72 ; 0x7eae + 7e64: 20 c0 rjmp .+64 ; 0x7ea6 } else if(ch == STK_SET_DEVICE) { 7e66: 82 34 cpi r24, 0x42 ; 66 @@ -172,353 +180,375 @@ void watchdogReset() { // SET DEVICE EXT is ignored getNch(5); 7e72: 85 e0 ldi r24, 0x05 ; 5 - 7e74: b4 d0 rcall .+360 ; 0x7fde - 7e76: 8a c0 rjmp .+276 ; 0x7f8c + 7e74: bb d0 rcall .+374 ; 0x7fec + 7e76: 91 c0 rjmp .+290 ; 0x7f9a } else if(ch == STK_LOAD_ADDRESS) { 7e78: 85 35 cpi r24, 0x55 ; 85 - 7e7a: a1 f4 brne .+40 ; 0x7ea4 + 7e7a: 81 f4 brne .+32 ; 0x7e9c // LOAD ADDRESS - address = getch(); - 7e7c: 92 d0 rcall .+292 ; 0x7fa2 + uint16_t newAddress; + newAddress = getch(); + 7e7c: 99 d0 rcall .+306 ; 0x7fb0 + newAddress = (newAddress & 0xff) | (getch() << 8); 7e7e: 08 2f mov r16, r24 7e80: 10 e0 ldi r17, 0x00 ; 0 - 7e82: 10 93 01 02 sts 0x0201, r17 - 7e86: 00 93 00 02 sts 0x0200, r16 - address = (address & 0xff) | (getch() << 8); - 7e8a: 8b d0 rcall .+278 ; 0x7fa2 - 7e8c: 90 e0 ldi r25, 0x00 ; 0 - 7e8e: 98 2f mov r25, r24 - 7e90: 88 27 eor r24, r24 - 7e92: 80 2b or r24, r16 - 7e94: 91 2b or r25, r17 - address += address; // Convert from word address to byte address - 7e96: 88 0f add r24, r24 - 7e98: 99 1f adc r25, r25 - 7e9a: 90 93 01 02 sts 0x0201, r25 - 7e9e: 80 93 00 02 sts 0x0200, r24 - 7ea2: 73 c0 rjmp .+230 ; 0x7f8a + 7e82: 96 d0 rcall .+300 ; 0x7fb0 + 7e84: 90 e0 ldi r25, 0x00 ; 0 + 7e86: 98 2f mov r25, r24 + 7e88: 88 27 eor r24, r24 + 7e8a: 80 2b or r24, r16 + 7e8c: 91 2b or r25, r17 +#ifdef RAMPZ + // Transfer top bit to RAMPZ + RAMPZ = (newAddress & 0x8000) ? 1 : 0; +#endif + newAddress += newAddress; // Convert from word address to byte address + 7e8e: 88 0f add r24, r24 + 7e90: 99 1f adc r25, r25 + address = newAddress; + 7e92: 90 93 01 02 sts 0x0201, r25 + 7e96: 80 93 00 02 sts 0x0200, r24 + 7e9a: 7e c0 rjmp .+252 ; 0x7f98 verifySpace(); } else if(ch == STK_UNIVERSAL) { - 7ea4: 86 35 cpi r24, 0x56 ; 86 - 7ea6: 29 f4 brne .+10 ; 0x7eb2 + 7e9c: 86 35 cpi r24, 0x56 ; 86 + 7e9e: 29 f4 brne .+10 ; 0x7eaa // UNIVERSAL command is ignored getNch(4); - 7ea8: 84 e0 ldi r24, 0x04 ; 4 - 7eaa: 99 d0 rcall .+306 ; 0x7fde + 7ea0: 84 e0 ldi r24, 0x04 ; 4 + 7ea2: a4 d0 rcall .+328 ; 0x7fec putch(0x00); - 7eac: 80 e0 ldi r24, 0x00 ; 0 - 7eae: 71 d0 rcall .+226 ; 0x7f92 - 7eb0: 6d c0 rjmp .+218 ; 0x7f8c + 7ea4: 80 e0 ldi r24, 0x00 ; 0 + 7ea6: 7c d0 rcall .+248 ; 0x7fa0 + 7ea8: 78 c0 rjmp .+240 ; 0x7f9a } - /* Write memory, length is big endian and is in bytes */ + /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { - 7eb2: 84 36 cpi r24, 0x64 ; 100 - 7eb4: 09 f0 breq .+2 ; 0x7eb8 - 7eb6: 43 c0 rjmp .+134 ; 0x7f3e + 7eaa: 84 36 cpi r24, 0x64 ; 100 + 7eac: 09 f0 breq .+2 ; 0x7eb0 + 7eae: 4e c0 rjmp .+156 ; 0x7f4c // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t *bufPtr; uint16_t addrPtr; getLen(); - 7eb8: 7c d0 rcall .+248 ; 0x7fb2 + 7eb0: 87 d0 rcall .+270 ; 0x7fc0 - // Immediately start page erase - this will 4.5ms - boot_page_erase((uint16_t)(void*)address); - 7eba: e0 91 00 02 lds r30, 0x0200 - 7ebe: f0 91 01 02 lds r31, 0x0201 + // If we are in RWW section, immediately start page erase + if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + 7eb2: e0 91 00 02 lds r30, 0x0200 + 7eb6: f0 91 01 02 lds r31, 0x0201 + 7eba: 80 e7 ldi r24, 0x70 ; 112 + 7ebc: e0 30 cpi r30, 0x00 ; 0 + 7ebe: f8 07 cpc r31, r24 + 7ec0: 18 f4 brcc .+6 ; 0x7ec8 7ec2: 83 e0 ldi r24, 0x03 ; 3 - 7ec4: 80 93 57 00 sts 0x0057, r24 - 7ec8: e8 95 spm - 7eca: c0 e0 ldi r28, 0x00 ; 0 - 7ecc: d1 e0 ldi r29, 0x01 ; 1 - + 7ec4: 87 bf out 0x37, r24 ; 55 + 7ec6: e8 95 spm + 7ec8: c0 e0 ldi r28, 0x00 ; 0 + 7eca: d1 e0 ldi r29, 0x01 ; 1 + // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); - 7ece: 69 d0 rcall .+210 ; 0x7fa2 - 7ed0: 89 93 st Y+, r24 + 7ecc: 71 d0 rcall .+226 ; 0x7fb0 + 7ece: 89 93 st Y+, r24 while (--length); - 7ed2: 80 91 02 02 lds r24, 0x0202 - 7ed6: 81 50 subi r24, 0x01 ; 1 - 7ed8: 80 93 02 02 sts 0x0202, r24 - 7edc: 88 23 and r24, r24 - 7ede: b9 f7 brne .-18 ; 0x7ece + 7ed0: 80 91 02 02 lds r24, 0x0202 + 7ed4: 81 50 subi r24, 0x01 ; 1 + 7ed6: 80 93 02 02 sts 0x0202, r24 + 7eda: 88 23 and r24, r24 + 7edc: b9 f7 brne .-18 ; 0x7ecc + + // If we are in NRWW section, page erase has to be delayed until now. + // Todo: Take RAMPZ into account + if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + 7ede: e0 91 00 02 lds r30, 0x0200 + 7ee2: f0 91 01 02 lds r31, 0x0201 + 7ee6: 80 e7 ldi r24, 0x70 ; 112 + 7ee8: e0 30 cpi r30, 0x00 ; 0 + 7eea: f8 07 cpc r31, r24 + 7eec: 18 f0 brcs .+6 ; 0x7ef4 + 7eee: 83 e0 ldi r24, 0x03 ; 3 + 7ef0: 87 bf out 0x37, r24 ; 55 + 7ef2: e8 95 spm // Read command terminator, start reply verifySpace(); - 7ee0: 78 d0 rcall .+240 ; 0x7fd2 + 7ef4: 75 d0 rcall .+234 ; 0x7fe0 // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); - 7ee2: 07 b6 in r0, 0x37 ; 55 - 7ee4: 00 fc sbrc r0, 0 - 7ee6: fd cf rjmp .-6 ; 0x7ee2 + 7ef6: 07 b6 in r0, 0x37 ; 55 + 7ef8: 00 fc sbrc r0, 0 + 7efa: fd cf rjmp .-6 ; 0x7ef6 } #endif // Copy buffer into programming buffer bufPtr = buff; addrPtr = (uint16_t)(void*)address; - 7ee8: 40 91 00 02 lds r20, 0x0200 - 7eec: 50 91 01 02 lds r21, 0x0201 - 7ef0: a0 e0 ldi r26, 0x00 ; 0 - 7ef2: b1 e0 ldi r27, 0x01 ; 1 + 7efc: 40 91 00 02 lds r20, 0x0200 + 7f00: 50 91 01 02 lds r21, 0x0201 + 7f04: a0 e0 ldi r26, 0x00 ; 0 + 7f06: b1 e0 ldi r27, 0x01 ; 1 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; - 7ef4: 2c 91 ld r18, X - 7ef6: 30 e0 ldi r19, 0x00 ; 0 + 7f08: 2c 91 ld r18, X + 7f0a: 30 e0 ldi r19, 0x00 ; 0 a |= (*bufPtr++) << 8; - 7ef8: 11 96 adiw r26, 0x01 ; 1 - 7efa: 8c 91 ld r24, X - 7efc: 11 97 sbiw r26, 0x01 ; 1 - 7efe: 90 e0 ldi r25, 0x00 ; 0 - 7f00: 98 2f mov r25, r24 - 7f02: 88 27 eor r24, r24 - 7f04: 82 2b or r24, r18 - 7f06: 93 2b or r25, r19 -#ifdef VIRTUAL_BOOT_PARTITION -#define rstVect (*(uint16_t*)(0x204)) -#define wdtVect (*(uint16_t*)(0x206)) + 7f0c: 11 96 adiw r26, 0x01 ; 1 + 7f0e: 8c 91 ld r24, X + 7f10: 11 97 sbiw r26, 0x01 ; 1 + 7f12: 90 e0 ldi r25, 0x00 ; 0 + 7f14: 98 2f mov r25, r24 + 7f16: 88 27 eor r24, r24 + 7f18: 82 2b or r24, r18 + 7f1a: 93 2b or r25, r19 +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif + /* main program starts here */ int main(void) { - 7f08: 12 96 adiw r26, 0x02 ; 2 + 7f1c: 12 96 adiw r26, 0x02 ; 2 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; a |= (*bufPtr++) << 8; - boot_page_fill((uint16_t)(void*)addrPtr,a); - 7f0a: fa 01 movw r30, r20 - 7f0c: 0c 01 movw r0, r24 - 7f0e: d0 92 57 00 sts 0x0057, r13 - 7f12: e8 95 spm - 7f14: 11 24 eor r1, r1 + __boot_page_fill_short((uint16_t)(void*)addrPtr,a); + 7f1e: fa 01 movw r30, r20 + 7f20: 0c 01 movw r0, r24 + 7f22: d7 be out 0x37, r13 ; 55 + 7f24: e8 95 spm + 7f26: 11 24 eor r1, r1 addrPtr += 2; - 7f16: 4e 5f subi r20, 0xFE ; 254 - 7f18: 5f 4f sbci r21, 0xFF ; 255 + 7f28: 4e 5f subi r20, 0xFE ; 254 + 7f2a: 5f 4f sbci r21, 0xFF ; 255 } while (--ch); - 7f1a: f1 e0 ldi r31, 0x01 ; 1 - 7f1c: a0 38 cpi r26, 0x80 ; 128 - 7f1e: bf 07 cpc r27, r31 - 7f20: 49 f7 brne .-46 ; 0x7ef4 + 7f2c: f1 e0 ldi r31, 0x01 ; 1 + 7f2e: a0 38 cpi r26, 0x80 ; 128 + 7f30: bf 07 cpc r27, r31 + 7f32: 51 f7 brne .-44 ; 0x7f08 // Write from programming buffer - boot_page_write((uint16_t)(void*)address); - 7f22: e0 91 00 02 lds r30, 0x0200 - 7f26: f0 91 01 02 lds r31, 0x0201 - 7f2a: e0 92 57 00 sts 0x0057, r14 - 7f2e: e8 95 spm + __boot_page_write_short((uint16_t)(void*)address); + 7f34: e0 91 00 02 lds r30, 0x0200 + 7f38: f0 91 01 02 lds r31, 0x0201 + 7f3c: e7 be out 0x37, r14 ; 55 + 7f3e: e8 95 spm boot_spm_busy_wait(); - 7f30: 07 b6 in r0, 0x37 ; 55 - 7f32: 00 fc sbrc r0, 0 - 7f34: fd cf rjmp .-6 ; 0x7f30 + 7f40: 07 b6 in r0, 0x37 ; 55 + 7f42: 00 fc sbrc r0, 0 + 7f44: fd cf rjmp .-6 ; 0x7f40 #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 7f36: f0 92 57 00 sts 0x0057, r15 - 7f3a: e8 95 spm - 7f3c: 27 c0 rjmp .+78 ; 0x7f8c + 7f46: f7 be out 0x37, r15 ; 55 + 7f48: e8 95 spm + 7f4a: 27 c0 rjmp .+78 ; 0x7f9a #endif } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { - 7f3e: 84 37 cpi r24, 0x74 ; 116 - 7f40: b9 f4 brne .+46 ; 0x7f70 + 7f4c: 84 37 cpi r24, 0x74 ; 116 + 7f4e: b9 f4 brne .+46 ; 0x7f7e // READ PAGE - we only read flash getLen(); - 7f42: 37 d0 rcall .+110 ; 0x7fb2 + 7f50: 37 d0 rcall .+110 ; 0x7fc0 verifySpace(); - 7f44: 46 d0 rcall .+140 ; 0x7fd2 - else ch = pgm_read_byte_near(address); + 7f52: 46 d0 rcall .+140 ; 0x7fe0 + putch(result); address++; - putch(ch); - } while (--length); + } + while (--length); #else do putch(pgm_read_byte_near(address++)); - 7f46: e0 91 00 02 lds r30, 0x0200 - 7f4a: f0 91 01 02 lds r31, 0x0201 - 7f4e: 31 96 adiw r30, 0x01 ; 1 - 7f50: f0 93 01 02 sts 0x0201, r31 - 7f54: e0 93 00 02 sts 0x0200, r30 - 7f58: 31 97 sbiw r30, 0x01 ; 1 - 7f5a: e4 91 lpm r30, Z+ - 7f5c: 8e 2f mov r24, r30 - 7f5e: 19 d0 rcall .+50 ; 0x7f92 + 7f54: e0 91 00 02 lds r30, 0x0200 + 7f58: f0 91 01 02 lds r31, 0x0201 + 7f5c: 31 96 adiw r30, 0x01 ; 1 + 7f5e: f0 93 01 02 sts 0x0201, r31 + 7f62: e0 93 00 02 sts 0x0200, r30 + 7f66: 31 97 sbiw r30, 0x01 ; 1 + 7f68: e4 91 lpm r30, Z+ + 7f6a: 8e 2f mov r24, r30 + 7f6c: 19 d0 rcall .+50 ; 0x7fa0 while (--length); - 7f60: 80 91 02 02 lds r24, 0x0202 - 7f64: 81 50 subi r24, 0x01 ; 1 - 7f66: 80 93 02 02 sts 0x0202, r24 - 7f6a: 88 23 and r24, r24 - 7f6c: 61 f7 brne .-40 ; 0x7f46 - 7f6e: 0e c0 rjmp .+28 ; 0x7f8c + 7f6e: 80 91 02 02 lds r24, 0x0202 + 7f72: 81 50 subi r24, 0x01 ; 1 + 7f74: 80 93 02 02 sts 0x0202, r24 + 7f78: 88 23 and r24, r24 + 7f7a: 61 f7 brne .-40 ; 0x7f54 + 7f7c: 0e c0 rjmp .+28 ; 0x7f9a +#endif #endif } /* Get device signature bytes */ else if(ch == STK_READ_SIGN) { - 7f70: 85 37 cpi r24, 0x75 ; 117 - 7f72: 39 f4 brne .+14 ; 0x7f82 + 7f7e: 85 37 cpi r24, 0x75 ; 117 + 7f80: 39 f4 brne .+14 ; 0x7f90 // READ SIGN - return what Avrdude wants to hear verifySpace(); - 7f74: 2e d0 rcall .+92 ; 0x7fd2 + 7f82: 2e d0 rcall .+92 ; 0x7fe0 putch(SIGNATURE_0); - 7f76: 8e e1 ldi r24, 0x1E ; 30 - 7f78: 0c d0 rcall .+24 ; 0x7f92 + 7f84: 8e e1 ldi r24, 0x1E ; 30 + 7f86: 0c d0 rcall .+24 ; 0x7fa0 putch(SIGNATURE_1); - 7f7a: 85 e9 ldi r24, 0x95 ; 149 - 7f7c: 0a d0 rcall .+20 ; 0x7f92 + 7f88: 85 e9 ldi r24, 0x95 ; 149 + 7f8a: 0a d0 rcall .+20 ; 0x7fa0 putch(SIGNATURE_2); - 7f7e: 8f e0 ldi r24, 0x0F ; 15 - 7f80: 96 cf rjmp .-212 ; 0x7eae + 7f8c: 8f e0 ldi r24, 0x0F ; 15 + 7f8e: 8b cf rjmp .-234 ; 0x7ea6 } else if (ch == 'Q') { - 7f82: 81 35 cpi r24, 0x51 ; 81 - 7f84: 11 f4 brne .+4 ; 0x7f8a + 7f90: 81 35 cpi r24, 0x51 ; 81 + 7f92: 11 f4 brne .+4 ; 0x7f98 // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); - 7f86: 88 e0 ldi r24, 0x08 ; 8 - 7f88: 19 d0 rcall .+50 ; 0x7fbc + 7f94: 88 e0 ldi r24, 0x08 ; 8 + 7f96: 19 d0 rcall .+50 ; 0x7fca verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 7f8a: 23 d0 rcall .+70 ; 0x7fd2 + 7f98: 23 d0 rcall .+70 ; 0x7fe0 } putch(STK_OK); - 7f8c: 80 e1 ldi r24, 0x10 ; 16 - 7f8e: 01 d0 rcall .+2 ; 0x7f92 - 7f90: 63 cf rjmp .-314 ; 0x7e58 + 7f9a: 80 e1 ldi r24, 0x10 ; 16 + 7f9c: 01 d0 rcall .+2 ; 0x7fa0 + 7f9e: 5c cf rjmp .-328 ; 0x7e58 -00007f92 : +00007fa0 : } } void putch(char ch) { - 7f92: 98 2f mov r25, r24 + 7fa0: 98 2f mov r25, r24 #ifndef SOFT_UART while (!(UCSR0A & _BV(UDRE0))); - 7f94: 80 91 c0 00 lds r24, 0x00C0 - 7f98: 85 ff sbrs r24, 5 - 7f9a: fc cf rjmp .-8 ; 0x7f94 + 7fa2: 80 91 c0 00 lds r24, 0x00C0 + 7fa6: 85 ff sbrs r24, 5 + 7fa8: fc cf rjmp .-8 ; 0x7fa2 UDR0 = ch; - 7f9c: 90 93 c6 00 sts 0x00C6, r25 + 7faa: 90 93 c6 00 sts 0x00C6, r25 [uartBit] "I" (UART_TX_BIT) : "r25" ); #endif } - 7fa0: 08 95 ret + 7fae: 08 95 ret -00007fa2 : +00007fb0 : return getch(); } // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 7fa2: a8 95 wdr + 7fb0: a8 95 wdr [uartBit] "I" (UART_RX_BIT) : "r25" ); #else while(!(UCSR0A & _BV(RXC0))); - 7fa4: 80 91 c0 00 lds r24, 0x00C0 - 7fa8: 87 ff sbrs r24, 7 - 7faa: fc cf rjmp .-8 ; 0x7fa4 + 7fb2: 80 91 c0 00 lds r24, 0x00C0 + 7fb6: 87 ff sbrs r24, 7 + 7fb8: fc cf rjmp .-8 ; 0x7fb2 ch = UDR0; - 7fac: 80 91 c6 00 lds r24, 0x00C6 -#ifdef LED_DATA_FLASH + 7fba: 80 91 c6 00 lds r24, 0x00C6 LED_PIN |= _BV(LED); +#endif #endif return ch; } - 7fb0: 08 95 ret + 7fbe: 08 95 ret -00007fb2 : +00007fc0 : } while (--count); } #endif uint8_t getLen() { getch(); - 7fb2: f7 df rcall .-18 ; 0x7fa2 + 7fc0: f7 df rcall .-18 ; 0x7fb0 length = getch(); - 7fb4: f6 df rcall .-20 ; 0x7fa2 - 7fb6: 80 93 02 02 sts 0x0202, r24 + 7fc2: f6 df rcall .-20 ; 0x7fb0 + 7fc4: 80 93 02 02 sts 0x0202, r24 return getch(); } - 7fba: f3 cf rjmp .-26 ; 0x7fa2 + 7fc8: f3 cf rjmp .-26 ; 0x7fb0 -00007fbc : +00007fca : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 7fbc: e0 e6 ldi r30, 0x60 ; 96 - 7fbe: f0 e0 ldi r31, 0x00 ; 0 - 7fc0: 98 e1 ldi r25, 0x18 ; 24 - 7fc2: 90 83 st Z, r25 + 7fca: e0 e6 ldi r30, 0x60 ; 96 + 7fcc: f0 e0 ldi r31, 0x00 ; 0 + 7fce: 98 e1 ldi r25, 0x18 ; 24 + 7fd0: 90 83 st Z, r25 WDTCSR = x; - 7fc4: 80 83 st Z, r24 + 7fd2: 80 83 st Z, r24 } - 7fc6: 08 95 ret + 7fd4: 08 95 ret -00007fc8 : +00007fd6 : void appStart() { watchdogConfig(WATCHDOG_OFF); - 7fc8: 80 e0 ldi r24, 0x00 ; 0 - 7fca: f8 df rcall .-16 ; 0x7fbc + 7fd6: 80 e0 ldi r24, 0x00 ; 0 + 7fd8: f8 df rcall .-16 ; 0x7fca __asm__ __volatile__ ( - 7fcc: ee 27 eor r30, r30 - 7fce: ff 27 eor r31, r31 - 7fd0: 09 94 ijmp + 7fda: ee 27 eor r30, r30 + 7fdc: ff 27 eor r31, r31 + 7fde: 09 94 ijmp -00007fd2 : +00007fe0 : do getch(); while (--count); verifySpace(); } void verifySpace() { if (getch() != CRC_EOP) appStart(); - 7fd2: e7 df rcall .-50 ; 0x7fa2 - 7fd4: 80 32 cpi r24, 0x20 ; 32 - 7fd6: 09 f0 breq .+2 ; 0x7fda - 7fd8: f7 df rcall .-18 ; 0x7fc8 + 7fe0: e7 df rcall .-50 ; 0x7fb0 + 7fe2: 80 32 cpi r24, 0x20 ; 32 + 7fe4: 09 f0 breq .+2 ; 0x7fe8 + 7fe6: f7 df rcall .-18 ; 0x7fd6 putch(STK_INSYNC); - 7fda: 84 e1 ldi r24, 0x14 ; 20 + 7fe8: 84 e1 ldi r24, 0x14 ; 20 } - 7fdc: da cf rjmp .-76 ; 0x7f92 + 7fea: da cf rjmp .-76 ; 0x7fa0 -00007fde : +00007fec : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 7fde: 1f 93 push r17 - 7fe0: 18 2f mov r17, r24 + 7fec: 1f 93 push r17 + 7fee: 18 2f mov r17, r24 do getch(); while (--count); - 7fe2: df df rcall .-66 ; 0x7fa2 - 7fe4: 11 50 subi r17, 0x01 ; 1 - 7fe6: e9 f7 brne .-6 ; 0x7fe2 + 7ff0: df df rcall .-66 ; 0x7fb0 + 7ff2: 11 50 subi r17, 0x01 ; 1 + 7ff4: e9 f7 brne .-6 ; 0x7ff0 verifySpace(); - 7fe8: f4 df rcall .-24 ; 0x7fd2 + 7ff6: f4 df rcall .-24 ; 0x7fe0 } - 7fea: 1f 91 pop r17 - 7fec: 08 95 ret + 7ff8: 1f 91 pop r17 + 7ffa: 08 95 ret diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.hex b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.hex index d6ac145d5..f4a151437 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.hex @@ -1,33 +1,34 @@ -:107E000085E08093810082E08093C00088E18093C8 -:107E1000C10086E08093C20088E08093C40084B7EC -:107E200014BE81FFD0D08DE0C8D0259A86E028E12D -:107E30003EEF91E0309385002093840096BBB09B89 -:107E4000FECF1D9AA8958150A9F7DD24D394A5E013 -:107E5000EA2EF1E1FF2EA4D0813421F481E0BED0DE -:107E600083E024C0823411F484E103C0853419F422 -:107E700085E0B4D08AC08535A1F492D0082F10E0F7 -:107E800010930102009300028BD090E0982F882776 -:107E9000802B912B880F991F9093010280930002F1 -:107EA00073C0863529F484E099D080E071D06DC02C -:107EB000843609F043C07CD0E0910002F0910102C9 -:107EC00083E080935700E895C0E0D1E069D08993C2 -:107ED000809102028150809302028823B9F778D002 -:107EE00007B600FCFDCF4091000250910102A0E0D6 -:107EF000B1E02C9130E011968C91119790E0982F81 -:107F00008827822B932B1296FA010C01D0925700EE -:107F1000E89511244E5F5F4FF1E0A038BF0749F7A5 -:107F2000E0910002F0910102E0925700E89507B657 -:107F300000FCFDCFF0925700E89527C08437B9F4D4 -:107F400037D046D0E0910002F09101023196F093D3 -:107F50000102E09300023197E4918E2F19D08091B5 -:107F60000202815080930202882361F70EC0853798 -:107F700039F42ED08EE10CD085E90AD08FE096CF6F -:107F8000813511F488E019D023D080E101D063CF8E -:107F9000982F8091C00085FFFCCF9093C600089574 -:107FA000A8958091C00087FFFCCF8091C6000895FE -:107FB000F7DFF6DF80930202F3CFE0E6F0E098E12E -:107FC00090838083089580E0F8DFEE27FF270994EF -:107FD000E7DF803209F0F7DF84E1DACF1F93182F53 -:0C7FE000DFDF1150E9F7F4DF1F91089576 +:107E0000112484B714BE81FFE6D085E08093810001 +:107E100082E08093C00088E18093C10086E0809377 +:107E2000C20088E08093C4008EE0CFD0259A86E01F +:107E300028E13EEF91E0309385002093840096BBCB +:107E4000B09BFECF1D9AA8958150A9F7DD24D3944D +:107E5000A5E0EA2EF1E1FF2EABD0813421F481E0E0 +:107E6000C5D083E020C0823411F484E103C085349E +:107E700019F485E0BBD091C0853581F499D0082FE5 +:107E800010E096D090E0982F8827802B912B880FB8 +:107E9000991F90930102809300027EC0863529F4D9 +:107EA00084E0A4D080E07CD078C0843609F04EC055 +:107EB00087D0E0910002F091010280E7E030F807FE +:107EC00018F483E087BFE895C0E0D1E071D08993D2 +:107ED000809102028150809302028823B9F7E091D9 +:107EE0000002F091010280E7E030F80718F083E02B +:107EF00087BFE89575D007B600FCFDCF4091000222 +:107F000050910102A0E0B1E02C9130E011968C91EB +:107F1000119790E0982F8827822B932B1296FA01C5 +:107F20000C01D7BEE89511244E5F5F4FF1E0A038F9 +:107F3000BF0751F7E0910002F0910102E7BEE8951A +:107F400007B600FCFDCFF7BEE89527C08437B9F42B +:107F500037D046D0E0910002F09101023196F093C3 +:107F60000102E09300023197E4918E2F19D08091A5 +:107F70000202815080930202882361F70EC0853788 +:107F800039F42ED08EE10CD085E90AD08FE08BCF6A +:107F9000813511F488E019D023D080E101D05CCF85 +:107FA000982F8091C00085FFFCCF9093C600089564 +:107FB000A8958091C00087FFFCCF8091C6000895EE +:107FC000F7DFF6DF80930202F3CFE0E6F0E098E11E +:107FD00090838083089580E0F8DFEE27FF270994DF +:107FE000E7DF803209F0F7DF84E1DACF1F93182F43 +:0C7FF000DFDF1150E9F7F4DF1F91089566 :0400000300007E007B :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.lst b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.lst index 46eda68c4..4cbcf626e 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.lst @@ -3,237 +3,257 @@ optiboot_atmega328_pro_8MHz.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .text 000001ec 00007e00 00007e00 00000054 2**1 + 0 .text 000001fc 00007e00 00007e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .debug_aranges 00000028 00000000 00000000 00000240 2**0 + 1 .debug_aranges 00000028 00000000 00000000 00000250 2**0 CONTENTS, READONLY, DEBUGGING - 2 .debug_pubnames 0000006a 00000000 00000000 00000268 2**0 + 2 .debug_pubnames 0000006a 00000000 00000000 00000278 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_info 00000269 00000000 00000000 000002d2 2**0 + 3 .debug_info 00000284 00000000 00000000 000002e2 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_abbrev 00000196 00000000 00000000 0000053b 2**0 + 4 .debug_abbrev 000001ae 00000000 00000000 00000566 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_line 000003d3 00000000 00000000 000006d1 2**0 + 5 .debug_line 00000450 00000000 00000000 00000714 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_frame 00000090 00000000 00000000 00000aa4 2**2 + 6 .debug_frame 00000090 00000000 00000000 00000b64 2**2 CONTENTS, READONLY, DEBUGGING - 7 .debug_str 00000135 00000000 00000000 00000b34 2**0 + 7 .debug_str 00000141 00000000 00000000 00000bf4 2**0 CONTENTS, READONLY, DEBUGGING - 8 .debug_loc 000001d1 00000000 00000000 00000c69 2**0 + 8 .debug_loc 000001e1 00000000 00000000 00000d35 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_ranges 00000068 00000000 00000000 00000e3a 2**0 + 9 .debug_ranges 00000068 00000000 00000000 00000f16 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: 00007e00
    : -#ifdef VIRTUAL_BOOT_PARTITION -#define rstVect (*(uint16_t*)(0x204)) -#define wdtVect (*(uint16_t*)(0x206)) +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif + /* main program starts here */ int main(void) { - 7e00: 85 e0 ldi r24, 0x05 ; 5 - 7e02: 80 93 81 00 sts 0x0081, r24 -#if LED_START_FLASHES > 0 - // Set up Timer 1 for timeout counter - TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 -#endif -#ifndef SOFT_UART - UCSR0A = _BV(U2X0); //Double speed mode USART0 - 7e06: 82 e0 ldi r24, 0x02 ; 2 - 7e08: 80 93 c0 00 sts 0x00C0, r24 - UCSR0B = _BV(RXEN0) | _BV(TXEN0); - 7e0c: 88 e1 ldi r24, 0x18 ; 24 - 7e0e: 80 93 c1 00 sts 0x00C1, r24 - UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); - 7e12: 86 e0 ldi r24, 0x06 ; 6 - 7e14: 80 93 c2 00 sts 0x00C2, r24 - UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); - 7e18: 88 e0 ldi r24, 0x08 ; 8 - 7e1a: 80 93 c4 00 sts 0x00C4, r24 + 7e00: 11 24 eor r1, r1 +#ifdef __AVR_ATmega8__ + SP=RAMEND; // This is done by hardware reset #endif // Adaboot no-wait mod ch = MCUSR; - 7e1e: 84 b7 in r24, 0x34 ; 52 + 7e02: 84 b7 in r24, 0x34 ; 52 MCUSR = 0; - 7e20: 14 be out 0x34, r1 ; 52 + 7e04: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); - 7e22: 81 ff sbrs r24, 1 - 7e24: d0 d0 rcall .+416 ; 0x7fc6 + 7e06: 81 ff sbrs r24, 1 + 7e08: e6 d0 rcall .+460 ; 0x7fd6 + +#if LED_START_FLASHES > 0 + // Set up Timer 1 for timeout counter + TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 + 7e0a: 85 e0 ldi r24, 0x05 ; 5 + 7e0c: 80 93 81 00 sts 0x0081, r24 + UCSRA = _BV(U2X); //Double speed mode USART + UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx + UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 + UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); +#else + UCSR0A = _BV(U2X0); //Double speed mode USART0 + 7e10: 82 e0 ldi r24, 0x02 ; 2 + 7e12: 80 93 c0 00 sts 0x00C0, r24 + UCSR0B = _BV(RXEN0) | _BV(TXEN0); + 7e16: 88 e1 ldi r24, 0x18 ; 24 + 7e18: 80 93 c1 00 sts 0x00C1, r24 + UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); + 7e1c: 86 e0 ldi r24, 0x06 ; 6 + 7e1e: 80 93 c2 00 sts 0x00C2, r24 + UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); + 7e22: 88 e0 ldi r24, 0x08 ; 8 + 7e24: 80 93 c4 00 sts 0x00C4, r24 +#endif +#endif // Set up watchdog to trigger after 500ms - watchdogConfig(WATCHDOG_500MS); - 7e26: 8d e0 ldi r24, 0x0D ; 13 - 7e28: c8 d0 rcall .+400 ; 0x7fba + watchdogConfig(WATCHDOG_1S); + 7e28: 8e e0 ldi r24, 0x0E ; 14 + 7e2a: cf d0 rcall .+414 ; 0x7fca /* Set LED pin as output */ LED_DDR |= _BV(LED); - 7e2a: 25 9a sbi 0x04, 5 ; 4 - 7e2c: 86 e0 ldi r24, 0x06 ; 6 + 7e2c: 25 9a sbi 0x04, 5 ; 4 + 7e2e: 86 e0 ldi r24, 0x06 ; 6 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - 7e2e: 28 e1 ldi r18, 0x18 ; 24 - 7e30: 3e ef ldi r19, 0xFE ; 254 + 7e30: 28 e1 ldi r18, 0x18 ; 24 + 7e32: 3e ef ldi r19, 0xFE ; 254 TIFR1 = _BV(TOV1); - 7e32: 91 e0 ldi r25, 0x01 ; 1 + 7e34: 91 e0 ldi r25, 0x01 ; 1 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - 7e34: 30 93 85 00 sts 0x0085, r19 - 7e38: 20 93 84 00 sts 0x0084, r18 + 7e36: 30 93 85 00 sts 0x0085, r19 + 7e3a: 20 93 84 00 sts 0x0084, r18 TIFR1 = _BV(TOV1); - 7e3c: 96 bb out 0x16, r25 ; 22 + 7e3e: 96 bb out 0x16, r25 ; 22 while(!(TIFR1 & _BV(TOV1))); - 7e3e: b0 9b sbis 0x16, 0 ; 22 - 7e40: fe cf rjmp .-4 ; 0x7e3e + 7e40: b0 9b sbis 0x16, 0 ; 22 + 7e42: fe cf rjmp .-4 ; 0x7e40 +#ifdef __AVR_ATmega8__ + LED_PORT ^= _BV(LED); +#else LED_PIN |= _BV(LED); - 7e42: 1d 9a sbi 0x03, 5 ; 3 + 7e44: 1d 9a sbi 0x03, 5 ; 3 return getch(); } // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 7e44: a8 95 wdr - TCNT1 = -(F_CPU/(1024*16)); - TIFR1 = _BV(TOV1); - while(!(TIFR1 & _BV(TOV1))); + 7e46: a8 95 wdr + LED_PORT ^= _BV(LED); +#else LED_PIN |= _BV(LED); +#endif watchdogReset(); } while (--count); - 7e46: 81 50 subi r24, 0x01 ; 1 - 7e48: a9 f7 brne .-22 ; 0x7e34 + 7e48: 81 50 subi r24, 0x01 ; 1 + 7e4a: a9 f7 brne .-22 ; 0x7e36 /* get character from UART */ ch = getch(); if(ch == STK_GET_PARAMETER) { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 7e4a: dd 24 eor r13, r13 - 7e4c: d3 94 inc r13 - boot_page_fill((uint16_t)(void*)addrPtr,a); + 7e4c: dd 24 eor r13, r13 + 7e4e: d3 94 inc r13 + __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); // Write from programming buffer - boot_page_write((uint16_t)(void*)address); - 7e4e: a5 e0 ldi r26, 0x05 ; 5 - 7e50: ea 2e mov r14, r26 + __boot_page_write_short((uint16_t)(void*)address); + 7e50: a5 e0 ldi r26, 0x05 ; 5 + 7e52: ea 2e mov r14, r26 boot_spm_busy_wait(); #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 7e52: f1 e1 ldi r31, 0x11 ; 17 - 7e54: ff 2e mov r15, r31 + 7e54: f1 e1 ldi r31, 0x11 ; 17 + 7e56: ff 2e mov r15, r31 #endif /* Forever loop */ for (;;) { /* get character from UART */ ch = getch(); - 7e56: a4 d0 rcall .+328 ; 0x7fa0 + 7e58: ab d0 rcall .+342 ; 0x7fb0 if(ch == STK_GET_PARAMETER) { - 7e58: 81 34 cpi r24, 0x41 ; 65 - 7e5a: 21 f4 brne .+8 ; 0x7e64 + 7e5a: 81 34 cpi r24, 0x41 ; 65 + 7e5c: 21 f4 brne .+8 ; 0x7e66 // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 7e5c: 81 e0 ldi r24, 0x01 ; 1 - 7e5e: be d0 rcall .+380 ; 0x7fdc + 7e5e: 81 e0 ldi r24, 0x01 ; 1 + 7e60: c5 d0 rcall .+394 ; 0x7fec putch(0x03); - 7e60: 83 e0 ldi r24, 0x03 ; 3 - 7e62: 24 c0 rjmp .+72 ; 0x7eac + 7e62: 83 e0 ldi r24, 0x03 ; 3 + 7e64: 20 c0 rjmp .+64 ; 0x7ea6 } else if(ch == STK_SET_DEVICE) { - 7e64: 82 34 cpi r24, 0x42 ; 66 - 7e66: 11 f4 brne .+4 ; 0x7e6c + 7e66: 82 34 cpi r24, 0x42 ; 66 + 7e68: 11 f4 brne .+4 ; 0x7e6e // SET DEVICE is ignored getNch(20); - 7e68: 84 e1 ldi r24, 0x14 ; 20 - 7e6a: 03 c0 rjmp .+6 ; 0x7e72 + 7e6a: 84 e1 ldi r24, 0x14 ; 20 + 7e6c: 03 c0 rjmp .+6 ; 0x7e74 } else if(ch == STK_SET_DEVICE_EXT) { - 7e6c: 85 34 cpi r24, 0x45 ; 69 - 7e6e: 19 f4 brne .+6 ; 0x7e76 + 7e6e: 85 34 cpi r24, 0x45 ; 69 + 7e70: 19 f4 brne .+6 ; 0x7e78 // SET DEVICE EXT is ignored getNch(5); - 7e70: 85 e0 ldi r24, 0x05 ; 5 - 7e72: b4 d0 rcall .+360 ; 0x7fdc - 7e74: 8a c0 rjmp .+276 ; 0x7f8a + 7e72: 85 e0 ldi r24, 0x05 ; 5 + 7e74: bb d0 rcall .+374 ; 0x7fec + 7e76: 91 c0 rjmp .+290 ; 0x7f9a } else if(ch == STK_LOAD_ADDRESS) { - 7e76: 85 35 cpi r24, 0x55 ; 85 - 7e78: a1 f4 brne .+40 ; 0x7ea2 + 7e78: 85 35 cpi r24, 0x55 ; 85 + 7e7a: 81 f4 brne .+32 ; 0x7e9c // LOAD ADDRESS - address = getch(); - 7e7a: 92 d0 rcall .+292 ; 0x7fa0 - 7e7c: 08 2f mov r16, r24 - 7e7e: 10 e0 ldi r17, 0x00 ; 0 - 7e80: 10 93 01 02 sts 0x0201, r17 - 7e84: 00 93 00 02 sts 0x0200, r16 - address = (address & 0xff) | (getch() << 8); - 7e88: 8b d0 rcall .+278 ; 0x7fa0 - 7e8a: 90 e0 ldi r25, 0x00 ; 0 - 7e8c: 98 2f mov r25, r24 - 7e8e: 88 27 eor r24, r24 - 7e90: 80 2b or r24, r16 - 7e92: 91 2b or r25, r17 - address += address; // Convert from word address to byte address - 7e94: 88 0f add r24, r24 - 7e96: 99 1f adc r25, r25 - 7e98: 90 93 01 02 sts 0x0201, r25 - 7e9c: 80 93 00 02 sts 0x0200, r24 - 7ea0: 73 c0 rjmp .+230 ; 0x7f88 + uint16_t newAddress; + newAddress = getch(); + 7e7c: 99 d0 rcall .+306 ; 0x7fb0 + newAddress = (newAddress & 0xff) | (getch() << 8); + 7e7e: 08 2f mov r16, r24 + 7e80: 10 e0 ldi r17, 0x00 ; 0 + 7e82: 96 d0 rcall .+300 ; 0x7fb0 + 7e84: 90 e0 ldi r25, 0x00 ; 0 + 7e86: 98 2f mov r25, r24 + 7e88: 88 27 eor r24, r24 + 7e8a: 80 2b or r24, r16 + 7e8c: 91 2b or r25, r17 +#ifdef RAMPZ + // Transfer top bit to RAMPZ + RAMPZ = (newAddress & 0x8000) ? 1 : 0; +#endif + newAddress += newAddress; // Convert from word address to byte address + 7e8e: 88 0f add r24, r24 + 7e90: 99 1f adc r25, r25 + address = newAddress; + 7e92: 90 93 01 02 sts 0x0201, r25 + 7e96: 80 93 00 02 sts 0x0200, r24 + 7e9a: 7e c0 rjmp .+252 ; 0x7f98 verifySpace(); } else if(ch == STK_UNIVERSAL) { - 7ea2: 86 35 cpi r24, 0x56 ; 86 - 7ea4: 29 f4 brne .+10 ; 0x7eb0 + 7e9c: 86 35 cpi r24, 0x56 ; 86 + 7e9e: 29 f4 brne .+10 ; 0x7eaa // UNIVERSAL command is ignored getNch(4); - 7ea6: 84 e0 ldi r24, 0x04 ; 4 - 7ea8: 99 d0 rcall .+306 ; 0x7fdc + 7ea0: 84 e0 ldi r24, 0x04 ; 4 + 7ea2: a4 d0 rcall .+328 ; 0x7fec putch(0x00); - 7eaa: 80 e0 ldi r24, 0x00 ; 0 - 7eac: 71 d0 rcall .+226 ; 0x7f90 - 7eae: 6d c0 rjmp .+218 ; 0x7f8a + 7ea4: 80 e0 ldi r24, 0x00 ; 0 + 7ea6: 7c d0 rcall .+248 ; 0x7fa0 + 7ea8: 78 c0 rjmp .+240 ; 0x7f9a } - /* Write memory, length is big endian and is in bytes */ + /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { - 7eb0: 84 36 cpi r24, 0x64 ; 100 - 7eb2: 09 f0 breq .+2 ; 0x7eb6 - 7eb4: 43 c0 rjmp .+134 ; 0x7f3c + 7eaa: 84 36 cpi r24, 0x64 ; 100 + 7eac: 09 f0 breq .+2 ; 0x7eb0 + 7eae: 4e c0 rjmp .+156 ; 0x7f4c // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t *bufPtr; uint16_t addrPtr; getLen(); - 7eb6: 7c d0 rcall .+248 ; 0x7fb0 + 7eb0: 87 d0 rcall .+270 ; 0x7fc0 - // Immediately start page erase - this will 4.5ms - boot_page_erase((uint16_t)(void*)address); - 7eb8: e0 91 00 02 lds r30, 0x0200 - 7ebc: f0 91 01 02 lds r31, 0x0201 - 7ec0: 83 e0 ldi r24, 0x03 ; 3 - 7ec2: 80 93 57 00 sts 0x0057, r24 + // If we are in RWW section, immediately start page erase + if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + 7eb2: e0 91 00 02 lds r30, 0x0200 + 7eb6: f0 91 01 02 lds r31, 0x0201 + 7eba: 80 e7 ldi r24, 0x70 ; 112 + 7ebc: e0 30 cpi r30, 0x00 ; 0 + 7ebe: f8 07 cpc r31, r24 + 7ec0: 18 f4 brcc .+6 ; 0x7ec8 + 7ec2: 83 e0 ldi r24, 0x03 ; 3 + 7ec4: 87 bf out 0x37, r24 ; 55 7ec6: e8 95 spm 7ec8: c0 e0 ldi r28, 0x00 ; 0 7eca: d1 e0 ldi r29, 0x01 ; 1 - + // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); - 7ecc: 69 d0 rcall .+210 ; 0x7fa0 + 7ecc: 71 d0 rcall .+226 ; 0x7fb0 7ece: 89 93 st Y+, r24 while (--length); 7ed0: 80 91 02 02 lds r24, 0x0202 @@ -242,279 +262,293 @@ void watchdogReset() { 7eda: 88 23 and r24, r24 7edc: b9 f7 brne .-18 ; 0x7ecc + // If we are in NRWW section, page erase has to be delayed until now. + // Todo: Take RAMPZ into account + if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + 7ede: e0 91 00 02 lds r30, 0x0200 + 7ee2: f0 91 01 02 lds r31, 0x0201 + 7ee6: 80 e7 ldi r24, 0x70 ; 112 + 7ee8: e0 30 cpi r30, 0x00 ; 0 + 7eea: f8 07 cpc r31, r24 + 7eec: 18 f0 brcs .+6 ; 0x7ef4 + 7eee: 83 e0 ldi r24, 0x03 ; 3 + 7ef0: 87 bf out 0x37, r24 ; 55 + 7ef2: e8 95 spm + // Read command terminator, start reply verifySpace(); - 7ede: 78 d0 rcall .+240 ; 0x7fd0 + 7ef4: 75 d0 rcall .+234 ; 0x7fe0 // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); - 7ee0: 07 b6 in r0, 0x37 ; 55 - 7ee2: 00 fc sbrc r0, 0 - 7ee4: fd cf rjmp .-6 ; 0x7ee0 + 7ef6: 07 b6 in r0, 0x37 ; 55 + 7ef8: 00 fc sbrc r0, 0 + 7efa: fd cf rjmp .-6 ; 0x7ef6 } #endif // Copy buffer into programming buffer bufPtr = buff; addrPtr = (uint16_t)(void*)address; - 7ee6: 40 91 00 02 lds r20, 0x0200 - 7eea: 50 91 01 02 lds r21, 0x0201 - 7eee: a0 e0 ldi r26, 0x00 ; 0 - 7ef0: b1 e0 ldi r27, 0x01 ; 1 + 7efc: 40 91 00 02 lds r20, 0x0200 + 7f00: 50 91 01 02 lds r21, 0x0201 + 7f04: a0 e0 ldi r26, 0x00 ; 0 + 7f06: b1 e0 ldi r27, 0x01 ; 1 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; - 7ef2: 2c 91 ld r18, X - 7ef4: 30 e0 ldi r19, 0x00 ; 0 + 7f08: 2c 91 ld r18, X + 7f0a: 30 e0 ldi r19, 0x00 ; 0 a |= (*bufPtr++) << 8; - 7ef6: 11 96 adiw r26, 0x01 ; 1 - 7ef8: 8c 91 ld r24, X - 7efa: 11 97 sbiw r26, 0x01 ; 1 - 7efc: 90 e0 ldi r25, 0x00 ; 0 - 7efe: 98 2f mov r25, r24 - 7f00: 88 27 eor r24, r24 - 7f02: 82 2b or r24, r18 - 7f04: 93 2b or r25, r19 -#ifdef VIRTUAL_BOOT_PARTITION -#define rstVect (*(uint16_t*)(0x204)) -#define wdtVect (*(uint16_t*)(0x206)) + 7f0c: 11 96 adiw r26, 0x01 ; 1 + 7f0e: 8c 91 ld r24, X + 7f10: 11 97 sbiw r26, 0x01 ; 1 + 7f12: 90 e0 ldi r25, 0x00 ; 0 + 7f14: 98 2f mov r25, r24 + 7f16: 88 27 eor r24, r24 + 7f18: 82 2b or r24, r18 + 7f1a: 93 2b or r25, r19 +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif + /* main program starts here */ int main(void) { - 7f06: 12 96 adiw r26, 0x02 ; 2 + 7f1c: 12 96 adiw r26, 0x02 ; 2 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; a |= (*bufPtr++) << 8; - boot_page_fill((uint16_t)(void*)addrPtr,a); - 7f08: fa 01 movw r30, r20 - 7f0a: 0c 01 movw r0, r24 - 7f0c: d0 92 57 00 sts 0x0057, r13 - 7f10: e8 95 spm - 7f12: 11 24 eor r1, r1 + __boot_page_fill_short((uint16_t)(void*)addrPtr,a); + 7f1e: fa 01 movw r30, r20 + 7f20: 0c 01 movw r0, r24 + 7f22: d7 be out 0x37, r13 ; 55 + 7f24: e8 95 spm + 7f26: 11 24 eor r1, r1 addrPtr += 2; - 7f14: 4e 5f subi r20, 0xFE ; 254 - 7f16: 5f 4f sbci r21, 0xFF ; 255 + 7f28: 4e 5f subi r20, 0xFE ; 254 + 7f2a: 5f 4f sbci r21, 0xFF ; 255 } while (--ch); - 7f18: f1 e0 ldi r31, 0x01 ; 1 - 7f1a: a0 38 cpi r26, 0x80 ; 128 - 7f1c: bf 07 cpc r27, r31 - 7f1e: 49 f7 brne .-46 ; 0x7ef2 + 7f2c: f1 e0 ldi r31, 0x01 ; 1 + 7f2e: a0 38 cpi r26, 0x80 ; 128 + 7f30: bf 07 cpc r27, r31 + 7f32: 51 f7 brne .-44 ; 0x7f08 // Write from programming buffer - boot_page_write((uint16_t)(void*)address); - 7f20: e0 91 00 02 lds r30, 0x0200 - 7f24: f0 91 01 02 lds r31, 0x0201 - 7f28: e0 92 57 00 sts 0x0057, r14 - 7f2c: e8 95 spm + __boot_page_write_short((uint16_t)(void*)address); + 7f34: e0 91 00 02 lds r30, 0x0200 + 7f38: f0 91 01 02 lds r31, 0x0201 + 7f3c: e7 be out 0x37, r14 ; 55 + 7f3e: e8 95 spm boot_spm_busy_wait(); - 7f2e: 07 b6 in r0, 0x37 ; 55 - 7f30: 00 fc sbrc r0, 0 - 7f32: fd cf rjmp .-6 ; 0x7f2e + 7f40: 07 b6 in r0, 0x37 ; 55 + 7f42: 00 fc sbrc r0, 0 + 7f44: fd cf rjmp .-6 ; 0x7f40 #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 7f34: f0 92 57 00 sts 0x0057, r15 - 7f38: e8 95 spm - 7f3a: 27 c0 rjmp .+78 ; 0x7f8a + 7f46: f7 be out 0x37, r15 ; 55 + 7f48: e8 95 spm + 7f4a: 27 c0 rjmp .+78 ; 0x7f9a #endif } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { - 7f3c: 84 37 cpi r24, 0x74 ; 116 - 7f3e: b9 f4 brne .+46 ; 0x7f6e + 7f4c: 84 37 cpi r24, 0x74 ; 116 + 7f4e: b9 f4 brne .+46 ; 0x7f7e // READ PAGE - we only read flash getLen(); - 7f40: 37 d0 rcall .+110 ; 0x7fb0 + 7f50: 37 d0 rcall .+110 ; 0x7fc0 verifySpace(); - 7f42: 46 d0 rcall .+140 ; 0x7fd0 - else ch = pgm_read_byte_near(address); + 7f52: 46 d0 rcall .+140 ; 0x7fe0 + putch(result); address++; - putch(ch); - } while (--length); + } + while (--length); #else do putch(pgm_read_byte_near(address++)); - 7f44: e0 91 00 02 lds r30, 0x0200 - 7f48: f0 91 01 02 lds r31, 0x0201 - 7f4c: 31 96 adiw r30, 0x01 ; 1 - 7f4e: f0 93 01 02 sts 0x0201, r31 - 7f52: e0 93 00 02 sts 0x0200, r30 - 7f56: 31 97 sbiw r30, 0x01 ; 1 - 7f58: e4 91 lpm r30, Z+ - 7f5a: 8e 2f mov r24, r30 - 7f5c: 19 d0 rcall .+50 ; 0x7f90 + 7f54: e0 91 00 02 lds r30, 0x0200 + 7f58: f0 91 01 02 lds r31, 0x0201 + 7f5c: 31 96 adiw r30, 0x01 ; 1 + 7f5e: f0 93 01 02 sts 0x0201, r31 + 7f62: e0 93 00 02 sts 0x0200, r30 + 7f66: 31 97 sbiw r30, 0x01 ; 1 + 7f68: e4 91 lpm r30, Z+ + 7f6a: 8e 2f mov r24, r30 + 7f6c: 19 d0 rcall .+50 ; 0x7fa0 while (--length); - 7f5e: 80 91 02 02 lds r24, 0x0202 - 7f62: 81 50 subi r24, 0x01 ; 1 - 7f64: 80 93 02 02 sts 0x0202, r24 - 7f68: 88 23 and r24, r24 - 7f6a: 61 f7 brne .-40 ; 0x7f44 - 7f6c: 0e c0 rjmp .+28 ; 0x7f8a + 7f6e: 80 91 02 02 lds r24, 0x0202 + 7f72: 81 50 subi r24, 0x01 ; 1 + 7f74: 80 93 02 02 sts 0x0202, r24 + 7f78: 88 23 and r24, r24 + 7f7a: 61 f7 brne .-40 ; 0x7f54 + 7f7c: 0e c0 rjmp .+28 ; 0x7f9a +#endif #endif } /* Get device signature bytes */ else if(ch == STK_READ_SIGN) { - 7f6e: 85 37 cpi r24, 0x75 ; 117 - 7f70: 39 f4 brne .+14 ; 0x7f80 + 7f7e: 85 37 cpi r24, 0x75 ; 117 + 7f80: 39 f4 brne .+14 ; 0x7f90 // READ SIGN - return what Avrdude wants to hear verifySpace(); - 7f72: 2e d0 rcall .+92 ; 0x7fd0 + 7f82: 2e d0 rcall .+92 ; 0x7fe0 putch(SIGNATURE_0); - 7f74: 8e e1 ldi r24, 0x1E ; 30 - 7f76: 0c d0 rcall .+24 ; 0x7f90 + 7f84: 8e e1 ldi r24, 0x1E ; 30 + 7f86: 0c d0 rcall .+24 ; 0x7fa0 putch(SIGNATURE_1); - 7f78: 85 e9 ldi r24, 0x95 ; 149 - 7f7a: 0a d0 rcall .+20 ; 0x7f90 + 7f88: 85 e9 ldi r24, 0x95 ; 149 + 7f8a: 0a d0 rcall .+20 ; 0x7fa0 putch(SIGNATURE_2); - 7f7c: 8f e0 ldi r24, 0x0F ; 15 - 7f7e: 96 cf rjmp .-212 ; 0x7eac + 7f8c: 8f e0 ldi r24, 0x0F ; 15 + 7f8e: 8b cf rjmp .-234 ; 0x7ea6 } else if (ch == 'Q') { - 7f80: 81 35 cpi r24, 0x51 ; 81 - 7f82: 11 f4 brne .+4 ; 0x7f88 + 7f90: 81 35 cpi r24, 0x51 ; 81 + 7f92: 11 f4 brne .+4 ; 0x7f98 // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); - 7f84: 88 e0 ldi r24, 0x08 ; 8 - 7f86: 19 d0 rcall .+50 ; 0x7fba + 7f94: 88 e0 ldi r24, 0x08 ; 8 + 7f96: 19 d0 rcall .+50 ; 0x7fca verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 7f88: 23 d0 rcall .+70 ; 0x7fd0 + 7f98: 23 d0 rcall .+70 ; 0x7fe0 } putch(STK_OK); - 7f8a: 80 e1 ldi r24, 0x10 ; 16 - 7f8c: 01 d0 rcall .+2 ; 0x7f90 - 7f8e: 63 cf rjmp .-314 ; 0x7e56 + 7f9a: 80 e1 ldi r24, 0x10 ; 16 + 7f9c: 01 d0 rcall .+2 ; 0x7fa0 + 7f9e: 5c cf rjmp .-328 ; 0x7e58 -00007f90 : +00007fa0 : } } void putch(char ch) { - 7f90: 98 2f mov r25, r24 + 7fa0: 98 2f mov r25, r24 #ifndef SOFT_UART while (!(UCSR0A & _BV(UDRE0))); - 7f92: 80 91 c0 00 lds r24, 0x00C0 - 7f96: 85 ff sbrs r24, 5 - 7f98: fc cf rjmp .-8 ; 0x7f92 + 7fa2: 80 91 c0 00 lds r24, 0x00C0 + 7fa6: 85 ff sbrs r24, 5 + 7fa8: fc cf rjmp .-8 ; 0x7fa2 UDR0 = ch; - 7f9a: 90 93 c6 00 sts 0x00C6, r25 + 7faa: 90 93 c6 00 sts 0x00C6, r25 [uartBit] "I" (UART_TX_BIT) : "r25" ); #endif } - 7f9e: 08 95 ret + 7fae: 08 95 ret -00007fa0 : +00007fb0 : return getch(); } // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 7fa0: a8 95 wdr + 7fb0: a8 95 wdr [uartBit] "I" (UART_RX_BIT) : "r25" ); #else while(!(UCSR0A & _BV(RXC0))); - 7fa2: 80 91 c0 00 lds r24, 0x00C0 - 7fa6: 87 ff sbrs r24, 7 - 7fa8: fc cf rjmp .-8 ; 0x7fa2 + 7fb2: 80 91 c0 00 lds r24, 0x00C0 + 7fb6: 87 ff sbrs r24, 7 + 7fb8: fc cf rjmp .-8 ; 0x7fb2 ch = UDR0; - 7faa: 80 91 c6 00 lds r24, 0x00C6 -#ifdef LED_DATA_FLASH + 7fba: 80 91 c6 00 lds r24, 0x00C6 LED_PIN |= _BV(LED); +#endif #endif return ch; } - 7fae: 08 95 ret + 7fbe: 08 95 ret -00007fb0 : +00007fc0 : } while (--count); } #endif uint8_t getLen() { getch(); - 7fb0: f7 df rcall .-18 ; 0x7fa0 + 7fc0: f7 df rcall .-18 ; 0x7fb0 length = getch(); - 7fb2: f6 df rcall .-20 ; 0x7fa0 - 7fb4: 80 93 02 02 sts 0x0202, r24 + 7fc2: f6 df rcall .-20 ; 0x7fb0 + 7fc4: 80 93 02 02 sts 0x0202, r24 return getch(); } - 7fb8: f3 cf rjmp .-26 ; 0x7fa0 + 7fc8: f3 cf rjmp .-26 ; 0x7fb0 -00007fba : +00007fca : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 7fba: e0 e6 ldi r30, 0x60 ; 96 - 7fbc: f0 e0 ldi r31, 0x00 ; 0 - 7fbe: 98 e1 ldi r25, 0x18 ; 24 - 7fc0: 90 83 st Z, r25 + 7fca: e0 e6 ldi r30, 0x60 ; 96 + 7fcc: f0 e0 ldi r31, 0x00 ; 0 + 7fce: 98 e1 ldi r25, 0x18 ; 24 + 7fd0: 90 83 st Z, r25 WDTCSR = x; - 7fc2: 80 83 st Z, r24 + 7fd2: 80 83 st Z, r24 } - 7fc4: 08 95 ret + 7fd4: 08 95 ret -00007fc6 : +00007fd6 : void appStart() { watchdogConfig(WATCHDOG_OFF); - 7fc6: 80 e0 ldi r24, 0x00 ; 0 - 7fc8: f8 df rcall .-16 ; 0x7fba + 7fd6: 80 e0 ldi r24, 0x00 ; 0 + 7fd8: f8 df rcall .-16 ; 0x7fca __asm__ __volatile__ ( - 7fca: ee 27 eor r30, r30 - 7fcc: ff 27 eor r31, r31 - 7fce: 09 94 ijmp + 7fda: ee 27 eor r30, r30 + 7fdc: ff 27 eor r31, r31 + 7fde: 09 94 ijmp -00007fd0 : +00007fe0 : do getch(); while (--count); verifySpace(); } void verifySpace() { if (getch() != CRC_EOP) appStart(); - 7fd0: e7 df rcall .-50 ; 0x7fa0 - 7fd2: 80 32 cpi r24, 0x20 ; 32 - 7fd4: 09 f0 breq .+2 ; 0x7fd8 - 7fd6: f7 df rcall .-18 ; 0x7fc6 + 7fe0: e7 df rcall .-50 ; 0x7fb0 + 7fe2: 80 32 cpi r24, 0x20 ; 32 + 7fe4: 09 f0 breq .+2 ; 0x7fe8 + 7fe6: f7 df rcall .-18 ; 0x7fd6 putch(STK_INSYNC); - 7fd8: 84 e1 ldi r24, 0x14 ; 20 + 7fe8: 84 e1 ldi r24, 0x14 ; 20 } - 7fda: da cf rjmp .-76 ; 0x7f90 + 7fea: da cf rjmp .-76 ; 0x7fa0 + +00007fec : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 7fdc: 1f 93 push r17 - 7fde: 18 2f mov r17, r24 - -00007fe0 : + 7fec: 1f 93 push r17 + 7fee: 18 2f mov r17, r24 do getch(); while (--count); - 7fe0: df df rcall .-66 ; 0x7fa0 - 7fe2: 11 50 subi r17, 0x01 ; 1 - 7fe4: e9 f7 brne .-6 ; 0x7fe0 + 7ff0: df df rcall .-66 ; 0x7fb0 + 7ff2: 11 50 subi r17, 0x01 ; 1 + 7ff4: e9 f7 brne .-6 ; 0x7ff0 verifySpace(); - 7fe6: f4 df rcall .-24 ; 0x7fd0 + 7ff6: f4 df rcall .-24 ; 0x7fe0 } - 7fe8: 1f 91 pop r17 - 7fea: 08 95 ret + 7ff8: 1f 91 pop r17 + 7ffa: 08 95 ret diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.hex b/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.hex index 1e9341468..2b4a582a4 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.hex @@ -1,33 +1,34 @@ -:103E000085E08093810082E08093C00088E1809308 -:103E1000C10086E08093C20080E18093C40084B733 -:103E200014BE81FFD0D08DE0C8D0259A86E020E373 -:103E30003CEF91E0309385002093840096BBB09BCB -:103E4000FECF1D9AA8958150A9F7DD24D394A5E053 -:103E5000EA2EF1E1FF2EA4D0813421F481E0BED01E -:103E600083E024C0823411F484E103C0853419F462 -:103E700085E0B4D08AC08535A1F492D0082F10E037 -:103E800010930102009300028BD090E0982F8827B6 -:103E9000802B912B880F991F909301028093000231 -:103EA00073C0863529F484E099D080E071D06DC06C -:103EB000843609F043C07CD0E0910002F091010209 -:103EC00083E080935700E895C0E0D1E069D0899302 -:103ED000809102028150809302028823B9F778D042 -:103EE00007B600FCFDCF4091000250910102A0E016 -:103EF000B1E02C9130E011968C91119790E0982FC1 -:103F00008827822B932B1296FA010C01D09257002E -:103F1000E89511244E5F5F4FF1E0A038BF0749F7E5 -:103F2000E0910002F0910102E0925700E89507B697 -:103F300000FCFDCFF0925700E89527C08437B9F414 -:103F400037D046D0E0910002F09101023196F09313 -:103F50000102E09300023197E4918E2F19D08091F5 -:103F60000202815080930202882361F70EC08537D8 -:103F700039F42ED08EE10CD084E90AD086E096CFB9 -:103F8000813511F488E019D023D080E101D063CFCE -:103F9000982F8091C00085FFFCCF9093C6000895B4 -:103FA000A8958091C00087FFFCCF8091C60008953E -:103FB000F7DFF6DF80930202F3CFE0E6F0E098E16E -:103FC00090838083089580E0F8DFEE27FF2709942F -:103FD000E7DF803209F0F7DF84E1DACF1F93182F93 -:0C3FE000DFDF1150E9F7F4DF1F910895B6 +:103E0000112484B714BE81FFE6D085E08093810041 +:103E100082E08093C00088E18093C10086E08093B7 +:103E2000C20080E18093C4008EE0CFD0259A86E066 +:103E300020E33CEF91E0309385002093840096BB13 +:103E4000B09BFECF1D9AA8958150A9F7DD24D3948D +:103E5000A5E0EA2EF1E1FF2EABD0813421F481E020 +:103E6000C5D083E020C0823411F484E103C08534DE +:103E700019F485E0BBD091C0853581F499D0082F25 +:103E800010E096D090E0982F8827802B912B880FF8 +:103E9000991F90930102809300027EC0863529F419 +:103EA00084E0A4D080E07CD078C0843609F04EC095 +:103EB00087D0E0910002F091010288E3E030F8073A +:103EC00018F483E087BFE895C0E0D1E071D0899312 +:103ED000809102028150809302028823B9F7E09119 +:103EE0000002F091010288E3E030F80718F083E067 +:103EF00087BFE89575D007B600FCFDCF4091000262 +:103F000050910102A0E0B1E02C9130E011968C912B +:103F1000119790E0982F8827822B932B1296FA0105 +:103F20000C01D7BEE89511244E5F5F4FF1E0A03839 +:103F3000BF0751F7E0910002F0910102E7BEE8955A +:103F400007B600FCFDCFF7BEE89527C08437B9F46B +:103F500037D046D0E0910002F09101023196F09303 +:103F60000102E09300023197E4918E2F19D08091E5 +:103F70000202815080930202882361F70EC08537C8 +:103F800039F42ED08EE10CD084E90AD086E08BCFB4 +:103F9000813511F488E019D023D080E101D05CCFC5 +:103FA000982F8091C00085FFFCCF9093C6000895A4 +:103FB000A8958091C00087FFFCCF8091C60008952E +:103FC000F7DFF6DF80930202F3CFE0E6F0E098E15E +:103FD00090838083089580E0F8DFEE27FF2709941F +:103FE000E7DF803209F0F7DF84E1DACF1F93182F83 +:0C3FF000DFDF1150E9F7F4DF1F910895A6 :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.lst b/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.lst index 11218932e..e0a1ecf51 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.lst @@ -3,237 +3,257 @@ optiboot_diecimila.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .text 000001ec 00003e00 00003e00 00000054 2**1 + 0 .text 000001fc 00003e00 00003e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .debug_aranges 00000028 00000000 00000000 00000240 2**0 + 1 .debug_aranges 00000028 00000000 00000000 00000250 2**0 CONTENTS, READONLY, DEBUGGING - 2 .debug_pubnames 0000006a 00000000 00000000 00000268 2**0 + 2 .debug_pubnames 0000006a 00000000 00000000 00000278 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_info 00000269 00000000 00000000 000002d2 2**0 + 3 .debug_info 00000284 00000000 00000000 000002e2 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_abbrev 00000196 00000000 00000000 0000053b 2**0 + 4 .debug_abbrev 000001ae 00000000 00000000 00000566 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_line 000003d3 00000000 00000000 000006d1 2**0 + 5 .debug_line 00000450 00000000 00000000 00000714 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_frame 00000090 00000000 00000000 00000aa4 2**2 + 6 .debug_frame 00000090 00000000 00000000 00000b64 2**2 CONTENTS, READONLY, DEBUGGING - 7 .debug_str 00000135 00000000 00000000 00000b34 2**0 + 7 .debug_str 00000141 00000000 00000000 00000bf4 2**0 CONTENTS, READONLY, DEBUGGING - 8 .debug_loc 000001d1 00000000 00000000 00000c69 2**0 + 8 .debug_loc 000001e1 00000000 00000000 00000d35 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_ranges 00000068 00000000 00000000 00000e3a 2**0 + 9 .debug_ranges 00000068 00000000 00000000 00000f16 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: 00003e00
    : -#ifdef VIRTUAL_BOOT_PARTITION -#define rstVect (*(uint16_t*)(0x204)) -#define wdtVect (*(uint16_t*)(0x206)) +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif + /* main program starts here */ int main(void) { - 3e00: 85 e0 ldi r24, 0x05 ; 5 - 3e02: 80 93 81 00 sts 0x0081, r24 -#if LED_START_FLASHES > 0 - // Set up Timer 1 for timeout counter - TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 -#endif -#ifndef SOFT_UART - UCSR0A = _BV(U2X0); //Double speed mode USART0 - 3e06: 82 e0 ldi r24, 0x02 ; 2 - 3e08: 80 93 c0 00 sts 0x00C0, r24 - UCSR0B = _BV(RXEN0) | _BV(TXEN0); - 3e0c: 88 e1 ldi r24, 0x18 ; 24 - 3e0e: 80 93 c1 00 sts 0x00C1, r24 - UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); - 3e12: 86 e0 ldi r24, 0x06 ; 6 - 3e14: 80 93 c2 00 sts 0x00C2, r24 - UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); - 3e18: 80 e1 ldi r24, 0x10 ; 16 - 3e1a: 80 93 c4 00 sts 0x00C4, r24 + 3e00: 11 24 eor r1, r1 +#ifdef __AVR_ATmega8__ + SP=RAMEND; // This is done by hardware reset #endif // Adaboot no-wait mod ch = MCUSR; - 3e1e: 84 b7 in r24, 0x34 ; 52 + 3e02: 84 b7 in r24, 0x34 ; 52 MCUSR = 0; - 3e20: 14 be out 0x34, r1 ; 52 + 3e04: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); - 3e22: 81 ff sbrs r24, 1 - 3e24: d0 d0 rcall .+416 ; 0x3fc6 + 3e06: 81 ff sbrs r24, 1 + 3e08: e6 d0 rcall .+460 ; 0x3fd6 + +#if LED_START_FLASHES > 0 + // Set up Timer 1 for timeout counter + TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 + 3e0a: 85 e0 ldi r24, 0x05 ; 5 + 3e0c: 80 93 81 00 sts 0x0081, r24 + UCSRA = _BV(U2X); //Double speed mode USART + UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx + UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 + UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); +#else + UCSR0A = _BV(U2X0); //Double speed mode USART0 + 3e10: 82 e0 ldi r24, 0x02 ; 2 + 3e12: 80 93 c0 00 sts 0x00C0, r24 + UCSR0B = _BV(RXEN0) | _BV(TXEN0); + 3e16: 88 e1 ldi r24, 0x18 ; 24 + 3e18: 80 93 c1 00 sts 0x00C1, r24 + UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); + 3e1c: 86 e0 ldi r24, 0x06 ; 6 + 3e1e: 80 93 c2 00 sts 0x00C2, r24 + UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); + 3e22: 80 e1 ldi r24, 0x10 ; 16 + 3e24: 80 93 c4 00 sts 0x00C4, r24 +#endif +#endif // Set up watchdog to trigger after 500ms - watchdogConfig(WATCHDOG_500MS); - 3e26: 8d e0 ldi r24, 0x0D ; 13 - 3e28: c8 d0 rcall .+400 ; 0x3fba + watchdogConfig(WATCHDOG_1S); + 3e28: 8e e0 ldi r24, 0x0E ; 14 + 3e2a: cf d0 rcall .+414 ; 0x3fca /* Set LED pin as output */ LED_DDR |= _BV(LED); - 3e2a: 25 9a sbi 0x04, 5 ; 4 - 3e2c: 86 e0 ldi r24, 0x06 ; 6 + 3e2c: 25 9a sbi 0x04, 5 ; 4 + 3e2e: 86 e0 ldi r24, 0x06 ; 6 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - 3e2e: 20 e3 ldi r18, 0x30 ; 48 - 3e30: 3c ef ldi r19, 0xFC ; 252 + 3e30: 20 e3 ldi r18, 0x30 ; 48 + 3e32: 3c ef ldi r19, 0xFC ; 252 TIFR1 = _BV(TOV1); - 3e32: 91 e0 ldi r25, 0x01 ; 1 + 3e34: 91 e0 ldi r25, 0x01 ; 1 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - 3e34: 30 93 85 00 sts 0x0085, r19 - 3e38: 20 93 84 00 sts 0x0084, r18 + 3e36: 30 93 85 00 sts 0x0085, r19 + 3e3a: 20 93 84 00 sts 0x0084, r18 TIFR1 = _BV(TOV1); - 3e3c: 96 bb out 0x16, r25 ; 22 + 3e3e: 96 bb out 0x16, r25 ; 22 while(!(TIFR1 & _BV(TOV1))); - 3e3e: b0 9b sbis 0x16, 0 ; 22 - 3e40: fe cf rjmp .-4 ; 0x3e3e + 3e40: b0 9b sbis 0x16, 0 ; 22 + 3e42: fe cf rjmp .-4 ; 0x3e40 +#ifdef __AVR_ATmega8__ + LED_PORT ^= _BV(LED); +#else LED_PIN |= _BV(LED); - 3e42: 1d 9a sbi 0x03, 5 ; 3 + 3e44: 1d 9a sbi 0x03, 5 ; 3 return getch(); } // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 3e44: a8 95 wdr - TCNT1 = -(F_CPU/(1024*16)); - TIFR1 = _BV(TOV1); - while(!(TIFR1 & _BV(TOV1))); + 3e46: a8 95 wdr + LED_PORT ^= _BV(LED); +#else LED_PIN |= _BV(LED); +#endif watchdogReset(); } while (--count); - 3e46: 81 50 subi r24, 0x01 ; 1 - 3e48: a9 f7 brne .-22 ; 0x3e34 + 3e48: 81 50 subi r24, 0x01 ; 1 + 3e4a: a9 f7 brne .-22 ; 0x3e36 /* get character from UART */ ch = getch(); if(ch == STK_GET_PARAMETER) { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 3e4a: dd 24 eor r13, r13 - 3e4c: d3 94 inc r13 - boot_page_fill((uint16_t)(void*)addrPtr,a); + 3e4c: dd 24 eor r13, r13 + 3e4e: d3 94 inc r13 + __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); // Write from programming buffer - boot_page_write((uint16_t)(void*)address); - 3e4e: a5 e0 ldi r26, 0x05 ; 5 - 3e50: ea 2e mov r14, r26 + __boot_page_write_short((uint16_t)(void*)address); + 3e50: a5 e0 ldi r26, 0x05 ; 5 + 3e52: ea 2e mov r14, r26 boot_spm_busy_wait(); #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 3e52: f1 e1 ldi r31, 0x11 ; 17 - 3e54: ff 2e mov r15, r31 + 3e54: f1 e1 ldi r31, 0x11 ; 17 + 3e56: ff 2e mov r15, r31 #endif /* Forever loop */ for (;;) { /* get character from UART */ ch = getch(); - 3e56: a4 d0 rcall .+328 ; 0x3fa0 + 3e58: ab d0 rcall .+342 ; 0x3fb0 if(ch == STK_GET_PARAMETER) { - 3e58: 81 34 cpi r24, 0x41 ; 65 - 3e5a: 21 f4 brne .+8 ; 0x3e64 + 3e5a: 81 34 cpi r24, 0x41 ; 65 + 3e5c: 21 f4 brne .+8 ; 0x3e66 // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 3e5c: 81 e0 ldi r24, 0x01 ; 1 - 3e5e: be d0 rcall .+380 ; 0x3fdc + 3e5e: 81 e0 ldi r24, 0x01 ; 1 + 3e60: c5 d0 rcall .+394 ; 0x3fec putch(0x03); - 3e60: 83 e0 ldi r24, 0x03 ; 3 - 3e62: 24 c0 rjmp .+72 ; 0x3eac + 3e62: 83 e0 ldi r24, 0x03 ; 3 + 3e64: 20 c0 rjmp .+64 ; 0x3ea6 } else if(ch == STK_SET_DEVICE) { - 3e64: 82 34 cpi r24, 0x42 ; 66 - 3e66: 11 f4 brne .+4 ; 0x3e6c + 3e66: 82 34 cpi r24, 0x42 ; 66 + 3e68: 11 f4 brne .+4 ; 0x3e6e // SET DEVICE is ignored getNch(20); - 3e68: 84 e1 ldi r24, 0x14 ; 20 - 3e6a: 03 c0 rjmp .+6 ; 0x3e72 + 3e6a: 84 e1 ldi r24, 0x14 ; 20 + 3e6c: 03 c0 rjmp .+6 ; 0x3e74 } else if(ch == STK_SET_DEVICE_EXT) { - 3e6c: 85 34 cpi r24, 0x45 ; 69 - 3e6e: 19 f4 brne .+6 ; 0x3e76 + 3e6e: 85 34 cpi r24, 0x45 ; 69 + 3e70: 19 f4 brne .+6 ; 0x3e78 // SET DEVICE EXT is ignored getNch(5); - 3e70: 85 e0 ldi r24, 0x05 ; 5 - 3e72: b4 d0 rcall .+360 ; 0x3fdc - 3e74: 8a c0 rjmp .+276 ; 0x3f8a + 3e72: 85 e0 ldi r24, 0x05 ; 5 + 3e74: bb d0 rcall .+374 ; 0x3fec + 3e76: 91 c0 rjmp .+290 ; 0x3f9a } else if(ch == STK_LOAD_ADDRESS) { - 3e76: 85 35 cpi r24, 0x55 ; 85 - 3e78: a1 f4 brne .+40 ; 0x3ea2 + 3e78: 85 35 cpi r24, 0x55 ; 85 + 3e7a: 81 f4 brne .+32 ; 0x3e9c // LOAD ADDRESS - address = getch(); - 3e7a: 92 d0 rcall .+292 ; 0x3fa0 - 3e7c: 08 2f mov r16, r24 - 3e7e: 10 e0 ldi r17, 0x00 ; 0 - 3e80: 10 93 01 02 sts 0x0201, r17 - 3e84: 00 93 00 02 sts 0x0200, r16 - address = (address & 0xff) | (getch() << 8); - 3e88: 8b d0 rcall .+278 ; 0x3fa0 - 3e8a: 90 e0 ldi r25, 0x00 ; 0 - 3e8c: 98 2f mov r25, r24 - 3e8e: 88 27 eor r24, r24 - 3e90: 80 2b or r24, r16 - 3e92: 91 2b or r25, r17 - address += address; // Convert from word address to byte address - 3e94: 88 0f add r24, r24 - 3e96: 99 1f adc r25, r25 - 3e98: 90 93 01 02 sts 0x0201, r25 - 3e9c: 80 93 00 02 sts 0x0200, r24 - 3ea0: 73 c0 rjmp .+230 ; 0x3f88 + uint16_t newAddress; + newAddress = getch(); + 3e7c: 99 d0 rcall .+306 ; 0x3fb0 + newAddress = (newAddress & 0xff) | (getch() << 8); + 3e7e: 08 2f mov r16, r24 + 3e80: 10 e0 ldi r17, 0x00 ; 0 + 3e82: 96 d0 rcall .+300 ; 0x3fb0 + 3e84: 90 e0 ldi r25, 0x00 ; 0 + 3e86: 98 2f mov r25, r24 + 3e88: 88 27 eor r24, r24 + 3e8a: 80 2b or r24, r16 + 3e8c: 91 2b or r25, r17 +#ifdef RAMPZ + // Transfer top bit to RAMPZ + RAMPZ = (newAddress & 0x8000) ? 1 : 0; +#endif + newAddress += newAddress; // Convert from word address to byte address + 3e8e: 88 0f add r24, r24 + 3e90: 99 1f adc r25, r25 + address = newAddress; + 3e92: 90 93 01 02 sts 0x0201, r25 + 3e96: 80 93 00 02 sts 0x0200, r24 + 3e9a: 7e c0 rjmp .+252 ; 0x3f98 verifySpace(); } else if(ch == STK_UNIVERSAL) { - 3ea2: 86 35 cpi r24, 0x56 ; 86 - 3ea4: 29 f4 brne .+10 ; 0x3eb0 + 3e9c: 86 35 cpi r24, 0x56 ; 86 + 3e9e: 29 f4 brne .+10 ; 0x3eaa // UNIVERSAL command is ignored getNch(4); - 3ea6: 84 e0 ldi r24, 0x04 ; 4 - 3ea8: 99 d0 rcall .+306 ; 0x3fdc + 3ea0: 84 e0 ldi r24, 0x04 ; 4 + 3ea2: a4 d0 rcall .+328 ; 0x3fec putch(0x00); - 3eaa: 80 e0 ldi r24, 0x00 ; 0 - 3eac: 71 d0 rcall .+226 ; 0x3f90 - 3eae: 6d c0 rjmp .+218 ; 0x3f8a + 3ea4: 80 e0 ldi r24, 0x00 ; 0 + 3ea6: 7c d0 rcall .+248 ; 0x3fa0 + 3ea8: 78 c0 rjmp .+240 ; 0x3f9a } - /* Write memory, length is big endian and is in bytes */ + /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { - 3eb0: 84 36 cpi r24, 0x64 ; 100 - 3eb2: 09 f0 breq .+2 ; 0x3eb6 - 3eb4: 43 c0 rjmp .+134 ; 0x3f3c + 3eaa: 84 36 cpi r24, 0x64 ; 100 + 3eac: 09 f0 breq .+2 ; 0x3eb0 + 3eae: 4e c0 rjmp .+156 ; 0x3f4c // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t *bufPtr; uint16_t addrPtr; getLen(); - 3eb6: 7c d0 rcall .+248 ; 0x3fb0 + 3eb0: 87 d0 rcall .+270 ; 0x3fc0 - // Immediately start page erase - this will 4.5ms - boot_page_erase((uint16_t)(void*)address); - 3eb8: e0 91 00 02 lds r30, 0x0200 - 3ebc: f0 91 01 02 lds r31, 0x0201 - 3ec0: 83 e0 ldi r24, 0x03 ; 3 - 3ec2: 80 93 57 00 sts 0x0057, r24 + // If we are in RWW section, immediately start page erase + if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + 3eb2: e0 91 00 02 lds r30, 0x0200 + 3eb6: f0 91 01 02 lds r31, 0x0201 + 3eba: 88 e3 ldi r24, 0x38 ; 56 + 3ebc: e0 30 cpi r30, 0x00 ; 0 + 3ebe: f8 07 cpc r31, r24 + 3ec0: 18 f4 brcc .+6 ; 0x3ec8 + 3ec2: 83 e0 ldi r24, 0x03 ; 3 + 3ec4: 87 bf out 0x37, r24 ; 55 3ec6: e8 95 spm 3ec8: c0 e0 ldi r28, 0x00 ; 0 3eca: d1 e0 ldi r29, 0x01 ; 1 - + // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); - 3ecc: 69 d0 rcall .+210 ; 0x3fa0 + 3ecc: 71 d0 rcall .+226 ; 0x3fb0 3ece: 89 93 st Y+, r24 while (--length); 3ed0: 80 91 02 02 lds r24, 0x0202 @@ -242,279 +262,293 @@ void watchdogReset() { 3eda: 88 23 and r24, r24 3edc: b9 f7 brne .-18 ; 0x3ecc + // If we are in NRWW section, page erase has to be delayed until now. + // Todo: Take RAMPZ into account + if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + 3ede: e0 91 00 02 lds r30, 0x0200 + 3ee2: f0 91 01 02 lds r31, 0x0201 + 3ee6: 88 e3 ldi r24, 0x38 ; 56 + 3ee8: e0 30 cpi r30, 0x00 ; 0 + 3eea: f8 07 cpc r31, r24 + 3eec: 18 f0 brcs .+6 ; 0x3ef4 + 3eee: 83 e0 ldi r24, 0x03 ; 3 + 3ef0: 87 bf out 0x37, r24 ; 55 + 3ef2: e8 95 spm + // Read command terminator, start reply verifySpace(); - 3ede: 78 d0 rcall .+240 ; 0x3fd0 + 3ef4: 75 d0 rcall .+234 ; 0x3fe0 // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); - 3ee0: 07 b6 in r0, 0x37 ; 55 - 3ee2: 00 fc sbrc r0, 0 - 3ee4: fd cf rjmp .-6 ; 0x3ee0 + 3ef6: 07 b6 in r0, 0x37 ; 55 + 3ef8: 00 fc sbrc r0, 0 + 3efa: fd cf rjmp .-6 ; 0x3ef6 } #endif // Copy buffer into programming buffer bufPtr = buff; addrPtr = (uint16_t)(void*)address; - 3ee6: 40 91 00 02 lds r20, 0x0200 - 3eea: 50 91 01 02 lds r21, 0x0201 - 3eee: a0 e0 ldi r26, 0x00 ; 0 - 3ef0: b1 e0 ldi r27, 0x01 ; 1 + 3efc: 40 91 00 02 lds r20, 0x0200 + 3f00: 50 91 01 02 lds r21, 0x0201 + 3f04: a0 e0 ldi r26, 0x00 ; 0 + 3f06: b1 e0 ldi r27, 0x01 ; 1 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; - 3ef2: 2c 91 ld r18, X - 3ef4: 30 e0 ldi r19, 0x00 ; 0 + 3f08: 2c 91 ld r18, X + 3f0a: 30 e0 ldi r19, 0x00 ; 0 a |= (*bufPtr++) << 8; - 3ef6: 11 96 adiw r26, 0x01 ; 1 - 3ef8: 8c 91 ld r24, X - 3efa: 11 97 sbiw r26, 0x01 ; 1 - 3efc: 90 e0 ldi r25, 0x00 ; 0 - 3efe: 98 2f mov r25, r24 - 3f00: 88 27 eor r24, r24 - 3f02: 82 2b or r24, r18 - 3f04: 93 2b or r25, r19 -#ifdef VIRTUAL_BOOT_PARTITION -#define rstVect (*(uint16_t*)(0x204)) -#define wdtVect (*(uint16_t*)(0x206)) + 3f0c: 11 96 adiw r26, 0x01 ; 1 + 3f0e: 8c 91 ld r24, X + 3f10: 11 97 sbiw r26, 0x01 ; 1 + 3f12: 90 e0 ldi r25, 0x00 ; 0 + 3f14: 98 2f mov r25, r24 + 3f16: 88 27 eor r24, r24 + 3f18: 82 2b or r24, r18 + 3f1a: 93 2b or r25, r19 +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif + /* main program starts here */ int main(void) { - 3f06: 12 96 adiw r26, 0x02 ; 2 + 3f1c: 12 96 adiw r26, 0x02 ; 2 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; a |= (*bufPtr++) << 8; - boot_page_fill((uint16_t)(void*)addrPtr,a); - 3f08: fa 01 movw r30, r20 - 3f0a: 0c 01 movw r0, r24 - 3f0c: d0 92 57 00 sts 0x0057, r13 - 3f10: e8 95 spm - 3f12: 11 24 eor r1, r1 + __boot_page_fill_short((uint16_t)(void*)addrPtr,a); + 3f1e: fa 01 movw r30, r20 + 3f20: 0c 01 movw r0, r24 + 3f22: d7 be out 0x37, r13 ; 55 + 3f24: e8 95 spm + 3f26: 11 24 eor r1, r1 addrPtr += 2; - 3f14: 4e 5f subi r20, 0xFE ; 254 - 3f16: 5f 4f sbci r21, 0xFF ; 255 + 3f28: 4e 5f subi r20, 0xFE ; 254 + 3f2a: 5f 4f sbci r21, 0xFF ; 255 } while (--ch); - 3f18: f1 e0 ldi r31, 0x01 ; 1 - 3f1a: a0 38 cpi r26, 0x80 ; 128 - 3f1c: bf 07 cpc r27, r31 - 3f1e: 49 f7 brne .-46 ; 0x3ef2 + 3f2c: f1 e0 ldi r31, 0x01 ; 1 + 3f2e: a0 38 cpi r26, 0x80 ; 128 + 3f30: bf 07 cpc r27, r31 + 3f32: 51 f7 brne .-44 ; 0x3f08 // Write from programming buffer - boot_page_write((uint16_t)(void*)address); - 3f20: e0 91 00 02 lds r30, 0x0200 - 3f24: f0 91 01 02 lds r31, 0x0201 - 3f28: e0 92 57 00 sts 0x0057, r14 - 3f2c: e8 95 spm + __boot_page_write_short((uint16_t)(void*)address); + 3f34: e0 91 00 02 lds r30, 0x0200 + 3f38: f0 91 01 02 lds r31, 0x0201 + 3f3c: e7 be out 0x37, r14 ; 55 + 3f3e: e8 95 spm boot_spm_busy_wait(); - 3f2e: 07 b6 in r0, 0x37 ; 55 - 3f30: 00 fc sbrc r0, 0 - 3f32: fd cf rjmp .-6 ; 0x3f2e + 3f40: 07 b6 in r0, 0x37 ; 55 + 3f42: 00 fc sbrc r0, 0 + 3f44: fd cf rjmp .-6 ; 0x3f40 #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 3f34: f0 92 57 00 sts 0x0057, r15 - 3f38: e8 95 spm - 3f3a: 27 c0 rjmp .+78 ; 0x3f8a + 3f46: f7 be out 0x37, r15 ; 55 + 3f48: e8 95 spm + 3f4a: 27 c0 rjmp .+78 ; 0x3f9a #endif } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { - 3f3c: 84 37 cpi r24, 0x74 ; 116 - 3f3e: b9 f4 brne .+46 ; 0x3f6e + 3f4c: 84 37 cpi r24, 0x74 ; 116 + 3f4e: b9 f4 brne .+46 ; 0x3f7e // READ PAGE - we only read flash getLen(); - 3f40: 37 d0 rcall .+110 ; 0x3fb0 + 3f50: 37 d0 rcall .+110 ; 0x3fc0 verifySpace(); - 3f42: 46 d0 rcall .+140 ; 0x3fd0 - else ch = pgm_read_byte_near(address); + 3f52: 46 d0 rcall .+140 ; 0x3fe0 + putch(result); address++; - putch(ch); - } while (--length); + } + while (--length); #else do putch(pgm_read_byte_near(address++)); - 3f44: e0 91 00 02 lds r30, 0x0200 - 3f48: f0 91 01 02 lds r31, 0x0201 - 3f4c: 31 96 adiw r30, 0x01 ; 1 - 3f4e: f0 93 01 02 sts 0x0201, r31 - 3f52: e0 93 00 02 sts 0x0200, r30 - 3f56: 31 97 sbiw r30, 0x01 ; 1 - 3f58: e4 91 lpm r30, Z+ - 3f5a: 8e 2f mov r24, r30 - 3f5c: 19 d0 rcall .+50 ; 0x3f90 + 3f54: e0 91 00 02 lds r30, 0x0200 + 3f58: f0 91 01 02 lds r31, 0x0201 + 3f5c: 31 96 adiw r30, 0x01 ; 1 + 3f5e: f0 93 01 02 sts 0x0201, r31 + 3f62: e0 93 00 02 sts 0x0200, r30 + 3f66: 31 97 sbiw r30, 0x01 ; 1 + 3f68: e4 91 lpm r30, Z+ + 3f6a: 8e 2f mov r24, r30 + 3f6c: 19 d0 rcall .+50 ; 0x3fa0 while (--length); - 3f5e: 80 91 02 02 lds r24, 0x0202 - 3f62: 81 50 subi r24, 0x01 ; 1 - 3f64: 80 93 02 02 sts 0x0202, r24 - 3f68: 88 23 and r24, r24 - 3f6a: 61 f7 brne .-40 ; 0x3f44 - 3f6c: 0e c0 rjmp .+28 ; 0x3f8a + 3f6e: 80 91 02 02 lds r24, 0x0202 + 3f72: 81 50 subi r24, 0x01 ; 1 + 3f74: 80 93 02 02 sts 0x0202, r24 + 3f78: 88 23 and r24, r24 + 3f7a: 61 f7 brne .-40 ; 0x3f54 + 3f7c: 0e c0 rjmp .+28 ; 0x3f9a +#endif #endif } /* Get device signature bytes */ else if(ch == STK_READ_SIGN) { - 3f6e: 85 37 cpi r24, 0x75 ; 117 - 3f70: 39 f4 brne .+14 ; 0x3f80 + 3f7e: 85 37 cpi r24, 0x75 ; 117 + 3f80: 39 f4 brne .+14 ; 0x3f90 // READ SIGN - return what Avrdude wants to hear verifySpace(); - 3f72: 2e d0 rcall .+92 ; 0x3fd0 + 3f82: 2e d0 rcall .+92 ; 0x3fe0 putch(SIGNATURE_0); - 3f74: 8e e1 ldi r24, 0x1E ; 30 - 3f76: 0c d0 rcall .+24 ; 0x3f90 + 3f84: 8e e1 ldi r24, 0x1E ; 30 + 3f86: 0c d0 rcall .+24 ; 0x3fa0 putch(SIGNATURE_1); - 3f78: 84 e9 ldi r24, 0x94 ; 148 - 3f7a: 0a d0 rcall .+20 ; 0x3f90 + 3f88: 84 e9 ldi r24, 0x94 ; 148 + 3f8a: 0a d0 rcall .+20 ; 0x3fa0 putch(SIGNATURE_2); - 3f7c: 86 e0 ldi r24, 0x06 ; 6 - 3f7e: 96 cf rjmp .-212 ; 0x3eac + 3f8c: 86 e0 ldi r24, 0x06 ; 6 + 3f8e: 8b cf rjmp .-234 ; 0x3ea6 } else if (ch == 'Q') { - 3f80: 81 35 cpi r24, 0x51 ; 81 - 3f82: 11 f4 brne .+4 ; 0x3f88 + 3f90: 81 35 cpi r24, 0x51 ; 81 + 3f92: 11 f4 brne .+4 ; 0x3f98 // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); - 3f84: 88 e0 ldi r24, 0x08 ; 8 - 3f86: 19 d0 rcall .+50 ; 0x3fba + 3f94: 88 e0 ldi r24, 0x08 ; 8 + 3f96: 19 d0 rcall .+50 ; 0x3fca verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 3f88: 23 d0 rcall .+70 ; 0x3fd0 + 3f98: 23 d0 rcall .+70 ; 0x3fe0 } putch(STK_OK); - 3f8a: 80 e1 ldi r24, 0x10 ; 16 - 3f8c: 01 d0 rcall .+2 ; 0x3f90 - 3f8e: 63 cf rjmp .-314 ; 0x3e56 + 3f9a: 80 e1 ldi r24, 0x10 ; 16 + 3f9c: 01 d0 rcall .+2 ; 0x3fa0 + 3f9e: 5c cf rjmp .-328 ; 0x3e58 -00003f90 : +00003fa0 : } } void putch(char ch) { - 3f90: 98 2f mov r25, r24 + 3fa0: 98 2f mov r25, r24 #ifndef SOFT_UART while (!(UCSR0A & _BV(UDRE0))); - 3f92: 80 91 c0 00 lds r24, 0x00C0 - 3f96: 85 ff sbrs r24, 5 - 3f98: fc cf rjmp .-8 ; 0x3f92 + 3fa2: 80 91 c0 00 lds r24, 0x00C0 + 3fa6: 85 ff sbrs r24, 5 + 3fa8: fc cf rjmp .-8 ; 0x3fa2 UDR0 = ch; - 3f9a: 90 93 c6 00 sts 0x00C6, r25 + 3faa: 90 93 c6 00 sts 0x00C6, r25 [uartBit] "I" (UART_TX_BIT) : "r25" ); #endif } - 3f9e: 08 95 ret + 3fae: 08 95 ret -00003fa0 : +00003fb0 : return getch(); } // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 3fa0: a8 95 wdr + 3fb0: a8 95 wdr [uartBit] "I" (UART_RX_BIT) : "r25" ); #else while(!(UCSR0A & _BV(RXC0))); - 3fa2: 80 91 c0 00 lds r24, 0x00C0 - 3fa6: 87 ff sbrs r24, 7 - 3fa8: fc cf rjmp .-8 ; 0x3fa2 + 3fb2: 80 91 c0 00 lds r24, 0x00C0 + 3fb6: 87 ff sbrs r24, 7 + 3fb8: fc cf rjmp .-8 ; 0x3fb2 ch = UDR0; - 3faa: 80 91 c6 00 lds r24, 0x00C6 -#ifdef LED_DATA_FLASH + 3fba: 80 91 c6 00 lds r24, 0x00C6 LED_PIN |= _BV(LED); +#endif #endif return ch; } - 3fae: 08 95 ret + 3fbe: 08 95 ret -00003fb0 : +00003fc0 : } while (--count); } #endif uint8_t getLen() { getch(); - 3fb0: f7 df rcall .-18 ; 0x3fa0 + 3fc0: f7 df rcall .-18 ; 0x3fb0 length = getch(); - 3fb2: f6 df rcall .-20 ; 0x3fa0 - 3fb4: 80 93 02 02 sts 0x0202, r24 + 3fc2: f6 df rcall .-20 ; 0x3fb0 + 3fc4: 80 93 02 02 sts 0x0202, r24 return getch(); } - 3fb8: f3 cf rjmp .-26 ; 0x3fa0 + 3fc8: f3 cf rjmp .-26 ; 0x3fb0 -00003fba : +00003fca : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 3fba: e0 e6 ldi r30, 0x60 ; 96 - 3fbc: f0 e0 ldi r31, 0x00 ; 0 - 3fbe: 98 e1 ldi r25, 0x18 ; 24 - 3fc0: 90 83 st Z, r25 + 3fca: e0 e6 ldi r30, 0x60 ; 96 + 3fcc: f0 e0 ldi r31, 0x00 ; 0 + 3fce: 98 e1 ldi r25, 0x18 ; 24 + 3fd0: 90 83 st Z, r25 WDTCSR = x; - 3fc2: 80 83 st Z, r24 + 3fd2: 80 83 st Z, r24 } - 3fc4: 08 95 ret + 3fd4: 08 95 ret -00003fc6 : +00003fd6 : void appStart() { watchdogConfig(WATCHDOG_OFF); - 3fc6: 80 e0 ldi r24, 0x00 ; 0 - 3fc8: f8 df rcall .-16 ; 0x3fba + 3fd6: 80 e0 ldi r24, 0x00 ; 0 + 3fd8: f8 df rcall .-16 ; 0x3fca __asm__ __volatile__ ( - 3fca: ee 27 eor r30, r30 - 3fcc: ff 27 eor r31, r31 - 3fce: 09 94 ijmp + 3fda: ee 27 eor r30, r30 + 3fdc: ff 27 eor r31, r31 + 3fde: 09 94 ijmp -00003fd0 : +00003fe0 : do getch(); while (--count); verifySpace(); } void verifySpace() { if (getch() != CRC_EOP) appStart(); - 3fd0: e7 df rcall .-50 ; 0x3fa0 - 3fd2: 80 32 cpi r24, 0x20 ; 32 - 3fd4: 09 f0 breq .+2 ; 0x3fd8 - 3fd6: f7 df rcall .-18 ; 0x3fc6 + 3fe0: e7 df rcall .-50 ; 0x3fb0 + 3fe2: 80 32 cpi r24, 0x20 ; 32 + 3fe4: 09 f0 breq .+2 ; 0x3fe8 + 3fe6: f7 df rcall .-18 ; 0x3fd6 putch(STK_INSYNC); - 3fd8: 84 e1 ldi r24, 0x14 ; 20 + 3fe8: 84 e1 ldi r24, 0x14 ; 20 } - 3fda: da cf rjmp .-76 ; 0x3f90 + 3fea: da cf rjmp .-76 ; 0x3fa0 + +00003fec : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 3fdc: 1f 93 push r17 - 3fde: 18 2f mov r17, r24 - -00003fe0 : + 3fec: 1f 93 push r17 + 3fee: 18 2f mov r17, r24 do getch(); while (--count); - 3fe0: df df rcall .-66 ; 0x3fa0 - 3fe2: 11 50 subi r17, 0x01 ; 1 - 3fe4: e9 f7 brne .-6 ; 0x3fe0 + 3ff0: df df rcall .-66 ; 0x3fb0 + 3ff2: 11 50 subi r17, 0x01 ; 1 + 3ff4: e9 f7 brne .-6 ; 0x3ff0 verifySpace(); - 3fe6: f4 df rcall .-24 ; 0x3fd0 + 3ff6: f4 df rcall .-24 ; 0x3fe0 } - 3fe8: 1f 91 pop r17 - 3fea: 08 95 ret + 3ff8: 1f 91 pop r17 + 3ffa: 08 95 ret diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.hex b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.hex index 9d31a7a18..757928697 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.hex @@ -1,34 +1,34 @@ -:103E000085E08093810084B714BE81FFE4D08DE00B -:103E1000DCD0259A519A86E028E13EEF91E030937C -:103E200085002093840096BBB09BFECF1D9AA89579 -:103E30008150A9F7DD24D394A5E0EA2EF1E1FF2E0D -:103E4000ABD0813421F481E0D1D083E024C082342E -:103E500011F484E103C0853419F485E0C7D08AC029 -:103E60008535A1F499D0082F10E01093010200933A -:103E7000000292D090E0982F8827802B912B880FFA -:103E8000991F909301028093000273C0863529F434 -:103E900084E0ACD080E071D06DC0843609F043C0BE -:103EA0008FD0E0910002F091010283E080935700EF -:103EB000E895C0E0D1E070D08993809102028150F2 -:103EC000809302028823B9F78BD007B600FCFDCFA0 -:103ED0004091000250910102A0E0B1E02C9130E04D -:103EE00011968C91119790E0982F8827822B932B15 -:103EF0001296FA010C01D0925700E89511244E5FFA -:103F00005F4FF1E0A038BF0749F7E0910002F09160 -:103F10000102E0925700E89507B600FCFDCFF09251 -:103F20005700E89527C08437B9F44AD059D0E091BA -:103F30000002F09101023196F0930102E093000239 -:103F40003197E4918E2F19D0809102028150809395 -:103F50000202882361F70EC0853739F441D08EE123 -:103F60000CD084E90AD086E096CF813511F488E040 -:103F70002CD036D080E101D063CF2AE030E08095AC -:103F8000089410F4599802C0599A000015D014D022 -:103F900086952A95B1F70895A89529E030E04899CB -:103FA000FECF0AD009D008D08894489908942A9561 -:103FB00011F08795F7CF089598E09A95F1F7089555 -:103FC000EBDFEADF80930202E7CFE0E6F0E098E182 +:103E0000112484B714BE81FFE6D085E08093810041 +:103E100082E08093C00088E18093C10086E08093B7 +:103E2000C20088E08093C4008EE0CFD0259A86E05F +:103E300028E13EEF91E0309385002093840096BB0B +:103E4000B09BFECF1D9AA8958150A9F7DD24D3948D +:103E5000A5E0EA2EF1E1FF2EABD0813421F481E020 +:103E6000C5D083E020C0823411F484E103C08534DE +:103E700019F485E0BBD091C0853581F499D0082F25 +:103E800010E096D090E0982F8827802B912B880FF8 +:103E9000991F90930102809300027EC0863529F419 +:103EA00084E0A4D080E07CD078C0843609F04EC095 +:103EB00087D0E0910002F091010288E3E030F8073A +:103EC00018F483E087BFE895C0E0D1E071D0899312 +:103ED000809102028150809302028823B9F7E09119 +:103EE0000002F091010288E3E030F80718F083E067 +:103EF00087BFE89575D007B600FCFDCF4091000262 +:103F000050910102A0E0B1E02C9130E011968C912B +:103F1000119790E0982F8827822B932B1296FA0105 +:103F20000C01D7BEE89511244E5F5F4FF1E0A03839 +:103F3000BF0751F7E0910002F0910102E7BEE8955A +:103F400007B600FCFDCFF7BEE89527C08437B9F46B +:103F500037D046D0E0910002F09101023196F09303 +:103F60000102E09300023197E4918E2F19D08091E5 +:103F70000202815080930202882361F70EC08537C8 +:103F800039F42ED08EE10CD084E90AD086E08BCFB4 +:103F9000813511F488E019D023D080E101D05CCFC5 +:103FA000982F8091C00085FFFCCF9093C6000895A4 +:103FB000A8958091C00087FFFCCF8091C60008952E +:103FC000F7DFF6DF80930202F3CFE0E6F0E098E15E :103FD00090838083089580E0F8DFEE27FF2709941F -:103FE000DBDF803209F0F7DF84E1C7CF1F93182FA2 -:0C3FF000D3DF1150E9F7F4DF1F910895B2 +:103FE000E7DF803209F0F7DF84E1DACF1F93182F83 +:0C3FF000DFDF1150E9F7F4DF1F910895A6 :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.lst b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.lst index 0e46bd1a6..cbae2687c 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.lst @@ -7,452 +7,473 @@ Idx Name Size VMA LMA File off Algn CONTENTS, ALLOC, LOAD, READONLY, CODE 1 .debug_aranges 00000028 00000000 00000000 00000250 2**0 CONTENTS, READONLY, DEBUGGING - 2 .debug_pubnames 00000078 00000000 00000000 00000278 2**0 + 2 .debug_pubnames 0000006a 00000000 00000000 00000278 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_info 00000277 00000000 00000000 000002f0 2**0 + 3 .debug_info 00000284 00000000 00000000 000002e2 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_abbrev 00000194 00000000 00000000 00000567 2**0 + 4 .debug_abbrev 000001ae 00000000 00000000 00000566 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_line 000003bb 00000000 00000000 000006fb 2**0 + 5 .debug_line 00000450 00000000 00000000 00000714 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_frame 000000a0 00000000 00000000 00000ab8 2**2 + 6 .debug_frame 00000090 00000000 00000000 00000b64 2**2 CONTENTS, READONLY, DEBUGGING - 7 .debug_str 0000013f 00000000 00000000 00000b58 2**0 + 7 .debug_str 00000141 00000000 00000000 00000bf4 2**0 CONTENTS, READONLY, DEBUGGING - 8 .debug_loc 000001a0 00000000 00000000 00000c97 2**0 + 8 .debug_loc 000001e1 00000000 00000000 00000d35 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_ranges 00000070 00000000 00000000 00000e37 2**0 + 9 .debug_ranges 00000068 00000000 00000000 00000f16 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: 00003e00
    : -#ifdef VIRTUAL_BOOT_PARTITION -#define rstVect (*(uint16_t*)(0x204)) -#define wdtVect (*(uint16_t*)(0x206)) +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif + /* main program starts here */ int main(void) { - 3e00: 85 e0 ldi r24, 0x05 ; 5 - 3e02: 80 93 81 00 sts 0x0081, r24 - UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); - UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); + 3e00: 11 24 eor r1, r1 +#ifdef __AVR_ATmega8__ + SP=RAMEND; // This is done by hardware reset #endif // Adaboot no-wait mod ch = MCUSR; - 3e06: 84 b7 in r24, 0x34 ; 52 + 3e02: 84 b7 in r24, 0x34 ; 52 MCUSR = 0; - 3e08: 14 be out 0x34, r1 ; 52 + 3e04: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); - 3e0a: 81 ff sbrs r24, 1 - 3e0c: e4 d0 rcall .+456 ; 0x3fd6 + 3e06: 81 ff sbrs r24, 1 + 3e08: e6 d0 rcall .+460 ; 0x3fd6 + +#if LED_START_FLASHES > 0 + // Set up Timer 1 for timeout counter + TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 + 3e0a: 85 e0 ldi r24, 0x05 ; 5 + 3e0c: 80 93 81 00 sts 0x0081, r24 + UCSRA = _BV(U2X); //Double speed mode USART + UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx + UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 + UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); +#else + UCSR0A = _BV(U2X0); //Double speed mode USART0 + 3e10: 82 e0 ldi r24, 0x02 ; 2 + 3e12: 80 93 c0 00 sts 0x00C0, r24 + UCSR0B = _BV(RXEN0) | _BV(TXEN0); + 3e16: 88 e1 ldi r24, 0x18 ; 24 + 3e18: 80 93 c1 00 sts 0x00C1, r24 + UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); + 3e1c: 86 e0 ldi r24, 0x06 ; 6 + 3e1e: 80 93 c2 00 sts 0x00C2, r24 + UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); + 3e22: 88 e0 ldi r24, 0x08 ; 8 + 3e24: 80 93 c4 00 sts 0x00C4, r24 +#endif +#endif // Set up watchdog to trigger after 500ms - watchdogConfig(WATCHDOG_500MS); - 3e0e: 8d e0 ldi r24, 0x0D ; 13 - 3e10: dc d0 rcall .+440 ; 0x3fca + watchdogConfig(WATCHDOG_1S); + 3e28: 8e e0 ldi r24, 0x0E ; 14 + 3e2a: cf d0 rcall .+414 ; 0x3fca /* Set LED pin as output */ LED_DDR |= _BV(LED); - 3e12: 25 9a sbi 0x04, 5 ; 4 - -#ifdef SOFT_UART - /* Set TX pin as output */ - UART_DDR |= _BV(UART_TX_BIT); - 3e14: 51 9a sbi 0x0a, 1 ; 10 - 3e16: 86 e0 ldi r24, 0x06 ; 6 + 3e2c: 25 9a sbi 0x04, 5 ; 4 + 3e2e: 86 e0 ldi r24, 0x06 ; 6 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - 3e18: 28 e1 ldi r18, 0x18 ; 24 - 3e1a: 3e ef ldi r19, 0xFE ; 254 + 3e30: 28 e1 ldi r18, 0x18 ; 24 + 3e32: 3e ef ldi r19, 0xFE ; 254 TIFR1 = _BV(TOV1); - 3e1c: 91 e0 ldi r25, 0x01 ; 1 + 3e34: 91 e0 ldi r25, 0x01 ; 1 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - 3e1e: 30 93 85 00 sts 0x0085, r19 - 3e22: 20 93 84 00 sts 0x0084, r18 + 3e36: 30 93 85 00 sts 0x0085, r19 + 3e3a: 20 93 84 00 sts 0x0084, r18 TIFR1 = _BV(TOV1); - 3e26: 96 bb out 0x16, r25 ; 22 + 3e3e: 96 bb out 0x16, r25 ; 22 while(!(TIFR1 & _BV(TOV1))); - 3e28: b0 9b sbis 0x16, 0 ; 22 - 3e2a: fe cf rjmp .-4 ; 0x3e28 + 3e40: b0 9b sbis 0x16, 0 ; 22 + 3e42: fe cf rjmp .-4 ; 0x3e40 +#ifdef __AVR_ATmega8__ + LED_PORT ^= _BV(LED); +#else LED_PIN |= _BV(LED); - 3e2c: 1d 9a sbi 0x03, 5 ; 3 + 3e44: 1d 9a sbi 0x03, 5 ; 3 return getch(); } // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 3e2e: a8 95 wdr - TCNT1 = -(F_CPU/(1024*16)); - TIFR1 = _BV(TOV1); - while(!(TIFR1 & _BV(TOV1))); + 3e46: a8 95 wdr + LED_PORT ^= _BV(LED); +#else LED_PIN |= _BV(LED); +#endif watchdogReset(); } while (--count); - 3e30: 81 50 subi r24, 0x01 ; 1 - 3e32: a9 f7 brne .-22 ; 0x3e1e + 3e48: 81 50 subi r24, 0x01 ; 1 + 3e4a: a9 f7 brne .-22 ; 0x3e36 /* get character from UART */ ch = getch(); if(ch == STK_GET_PARAMETER) { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 3e34: dd 24 eor r13, r13 - 3e36: d3 94 inc r13 - boot_page_fill((uint16_t)(void*)addrPtr,a); + 3e4c: dd 24 eor r13, r13 + 3e4e: d3 94 inc r13 + __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); // Write from programming buffer - boot_page_write((uint16_t)(void*)address); - 3e38: a5 e0 ldi r26, 0x05 ; 5 - 3e3a: ea 2e mov r14, r26 + __boot_page_write_short((uint16_t)(void*)address); + 3e50: a5 e0 ldi r26, 0x05 ; 5 + 3e52: ea 2e mov r14, r26 boot_spm_busy_wait(); #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 3e3c: f1 e1 ldi r31, 0x11 ; 17 - 3e3e: ff 2e mov r15, r31 + 3e54: f1 e1 ldi r31, 0x11 ; 17 + 3e56: ff 2e mov r15, r31 #endif /* Forever loop */ for (;;) { /* get character from UART */ ch = getch(); - 3e40: ab d0 rcall .+342 ; 0x3f98 + 3e58: ab d0 rcall .+342 ; 0x3fb0 if(ch == STK_GET_PARAMETER) { - 3e42: 81 34 cpi r24, 0x41 ; 65 - 3e44: 21 f4 brne .+8 ; 0x3e4e + 3e5a: 81 34 cpi r24, 0x41 ; 65 + 3e5c: 21 f4 brne .+8 ; 0x3e66 // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 3e46: 81 e0 ldi r24, 0x01 ; 1 - 3e48: d1 d0 rcall .+418 ; 0x3fec + 3e5e: 81 e0 ldi r24, 0x01 ; 1 + 3e60: c5 d0 rcall .+394 ; 0x3fec putch(0x03); - 3e4a: 83 e0 ldi r24, 0x03 ; 3 - 3e4c: 24 c0 rjmp .+72 ; 0x3e96 + 3e62: 83 e0 ldi r24, 0x03 ; 3 + 3e64: 20 c0 rjmp .+64 ; 0x3ea6 } else if(ch == STK_SET_DEVICE) { - 3e4e: 82 34 cpi r24, 0x42 ; 66 - 3e50: 11 f4 brne .+4 ; 0x3e56 + 3e66: 82 34 cpi r24, 0x42 ; 66 + 3e68: 11 f4 brne .+4 ; 0x3e6e // SET DEVICE is ignored getNch(20); - 3e52: 84 e1 ldi r24, 0x14 ; 20 - 3e54: 03 c0 rjmp .+6 ; 0x3e5c + 3e6a: 84 e1 ldi r24, 0x14 ; 20 + 3e6c: 03 c0 rjmp .+6 ; 0x3e74 } else if(ch == STK_SET_DEVICE_EXT) { - 3e56: 85 34 cpi r24, 0x45 ; 69 - 3e58: 19 f4 brne .+6 ; 0x3e60 + 3e6e: 85 34 cpi r24, 0x45 ; 69 + 3e70: 19 f4 brne .+6 ; 0x3e78 // SET DEVICE EXT is ignored getNch(5); - 3e5a: 85 e0 ldi r24, 0x05 ; 5 - 3e5c: c7 d0 rcall .+398 ; 0x3fec - 3e5e: 8a c0 rjmp .+276 ; 0x3f74 + 3e72: 85 e0 ldi r24, 0x05 ; 5 + 3e74: bb d0 rcall .+374 ; 0x3fec + 3e76: 91 c0 rjmp .+290 ; 0x3f9a } else if(ch == STK_LOAD_ADDRESS) { - 3e60: 85 35 cpi r24, 0x55 ; 85 - 3e62: a1 f4 brne .+40 ; 0x3e8c + 3e78: 85 35 cpi r24, 0x55 ; 85 + 3e7a: 81 f4 brne .+32 ; 0x3e9c // LOAD ADDRESS - address = getch(); - 3e64: 99 d0 rcall .+306 ; 0x3f98 - 3e66: 08 2f mov r16, r24 - 3e68: 10 e0 ldi r17, 0x00 ; 0 - 3e6a: 10 93 01 02 sts 0x0201, r17 - 3e6e: 00 93 00 02 sts 0x0200, r16 - address = (address & 0xff) | (getch() << 8); - 3e72: 92 d0 rcall .+292 ; 0x3f98 - 3e74: 90 e0 ldi r25, 0x00 ; 0 - 3e76: 98 2f mov r25, r24 - 3e78: 88 27 eor r24, r24 - 3e7a: 80 2b or r24, r16 - 3e7c: 91 2b or r25, r17 - address += address; // Convert from word address to byte address - 3e7e: 88 0f add r24, r24 - 3e80: 99 1f adc r25, r25 - 3e82: 90 93 01 02 sts 0x0201, r25 - 3e86: 80 93 00 02 sts 0x0200, r24 - 3e8a: 73 c0 rjmp .+230 ; 0x3f72 + uint16_t newAddress; + newAddress = getch(); + 3e7c: 99 d0 rcall .+306 ; 0x3fb0 + newAddress = (newAddress & 0xff) | (getch() << 8); + 3e7e: 08 2f mov r16, r24 + 3e80: 10 e0 ldi r17, 0x00 ; 0 + 3e82: 96 d0 rcall .+300 ; 0x3fb0 + 3e84: 90 e0 ldi r25, 0x00 ; 0 + 3e86: 98 2f mov r25, r24 + 3e88: 88 27 eor r24, r24 + 3e8a: 80 2b or r24, r16 + 3e8c: 91 2b or r25, r17 +#ifdef RAMPZ + // Transfer top bit to RAMPZ + RAMPZ = (newAddress & 0x8000) ? 1 : 0; +#endif + newAddress += newAddress; // Convert from word address to byte address + 3e8e: 88 0f add r24, r24 + 3e90: 99 1f adc r25, r25 + address = newAddress; + 3e92: 90 93 01 02 sts 0x0201, r25 + 3e96: 80 93 00 02 sts 0x0200, r24 + 3e9a: 7e c0 rjmp .+252 ; 0x3f98 verifySpace(); } else if(ch == STK_UNIVERSAL) { - 3e8c: 86 35 cpi r24, 0x56 ; 86 - 3e8e: 29 f4 brne .+10 ; 0x3e9a + 3e9c: 86 35 cpi r24, 0x56 ; 86 + 3e9e: 29 f4 brne .+10 ; 0x3eaa // UNIVERSAL command is ignored getNch(4); - 3e90: 84 e0 ldi r24, 0x04 ; 4 - 3e92: ac d0 rcall .+344 ; 0x3fec + 3ea0: 84 e0 ldi r24, 0x04 ; 4 + 3ea2: a4 d0 rcall .+328 ; 0x3fec putch(0x00); - 3e94: 80 e0 ldi r24, 0x00 ; 0 - 3e96: 71 d0 rcall .+226 ; 0x3f7a - 3e98: 6d c0 rjmp .+218 ; 0x3f74 + 3ea4: 80 e0 ldi r24, 0x00 ; 0 + 3ea6: 7c d0 rcall .+248 ; 0x3fa0 + 3ea8: 78 c0 rjmp .+240 ; 0x3f9a } - /* Write memory, length is big endian and is in bytes */ + /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { - 3e9a: 84 36 cpi r24, 0x64 ; 100 - 3e9c: 09 f0 breq .+2 ; 0x3ea0 - 3e9e: 43 c0 rjmp .+134 ; 0x3f26 + 3eaa: 84 36 cpi r24, 0x64 ; 100 + 3eac: 09 f0 breq .+2 ; 0x3eb0 + 3eae: 4e c0 rjmp .+156 ; 0x3f4c // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t *bufPtr; uint16_t addrPtr; getLen(); - 3ea0: 8f d0 rcall .+286 ; 0x3fc0 - - // Immediately start page erase - this will 4.5ms - boot_page_erase((uint16_t)(void*)address); - 3ea2: e0 91 00 02 lds r30, 0x0200 - 3ea6: f0 91 01 02 lds r31, 0x0201 - 3eaa: 83 e0 ldi r24, 0x03 ; 3 - 3eac: 80 93 57 00 sts 0x0057, r24 - 3eb0: e8 95 spm - 3eb2: c0 e0 ldi r28, 0x00 ; 0 - 3eb4: d1 e0 ldi r29, 0x01 ; 1 + 3eb0: 87 d0 rcall .+270 ; 0x3fc0 + // If we are in RWW section, immediately start page erase + if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + 3eb2: e0 91 00 02 lds r30, 0x0200 + 3eb6: f0 91 01 02 lds r31, 0x0201 + 3eba: 88 e3 ldi r24, 0x38 ; 56 + 3ebc: e0 30 cpi r30, 0x00 ; 0 + 3ebe: f8 07 cpc r31, r24 + 3ec0: 18 f4 brcc .+6 ; 0x3ec8 + 3ec2: 83 e0 ldi r24, 0x03 ; 3 + 3ec4: 87 bf out 0x37, r24 ; 55 + 3ec6: e8 95 spm + 3ec8: c0 e0 ldi r28, 0x00 ; 0 + 3eca: d1 e0 ldi r29, 0x01 ; 1 + // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); - 3eb6: 70 d0 rcall .+224 ; 0x3f98 - 3eb8: 89 93 st Y+, r24 + 3ecc: 71 d0 rcall .+226 ; 0x3fb0 + 3ece: 89 93 st Y+, r24 while (--length); - 3eba: 80 91 02 02 lds r24, 0x0202 - 3ebe: 81 50 subi r24, 0x01 ; 1 - 3ec0: 80 93 02 02 sts 0x0202, r24 - 3ec4: 88 23 and r24, r24 - 3ec6: b9 f7 brne .-18 ; 0x3eb6 + 3ed0: 80 91 02 02 lds r24, 0x0202 + 3ed4: 81 50 subi r24, 0x01 ; 1 + 3ed6: 80 93 02 02 sts 0x0202, r24 + 3eda: 88 23 and r24, r24 + 3edc: b9 f7 brne .-18 ; 0x3ecc + + // If we are in NRWW section, page erase has to be delayed until now. + // Todo: Take RAMPZ into account + if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + 3ede: e0 91 00 02 lds r30, 0x0200 + 3ee2: f0 91 01 02 lds r31, 0x0201 + 3ee6: 88 e3 ldi r24, 0x38 ; 56 + 3ee8: e0 30 cpi r30, 0x00 ; 0 + 3eea: f8 07 cpc r31, r24 + 3eec: 18 f0 brcs .+6 ; 0x3ef4 + 3eee: 83 e0 ldi r24, 0x03 ; 3 + 3ef0: 87 bf out 0x37, r24 ; 55 + 3ef2: e8 95 spm // Read command terminator, start reply verifySpace(); - 3ec8: 8b d0 rcall .+278 ; 0x3fe0 + 3ef4: 75 d0 rcall .+234 ; 0x3fe0 // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); - 3eca: 07 b6 in r0, 0x37 ; 55 - 3ecc: 00 fc sbrc r0, 0 - 3ece: fd cf rjmp .-6 ; 0x3eca + 3ef6: 07 b6 in r0, 0x37 ; 55 + 3ef8: 00 fc sbrc r0, 0 + 3efa: fd cf rjmp .-6 ; 0x3ef6 } #endif // Copy buffer into programming buffer bufPtr = buff; addrPtr = (uint16_t)(void*)address; - 3ed0: 40 91 00 02 lds r20, 0x0200 - 3ed4: 50 91 01 02 lds r21, 0x0201 - 3ed8: a0 e0 ldi r26, 0x00 ; 0 - 3eda: b1 e0 ldi r27, 0x01 ; 1 + 3efc: 40 91 00 02 lds r20, 0x0200 + 3f00: 50 91 01 02 lds r21, 0x0201 + 3f04: a0 e0 ldi r26, 0x00 ; 0 + 3f06: b1 e0 ldi r27, 0x01 ; 1 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; - 3edc: 2c 91 ld r18, X - 3ede: 30 e0 ldi r19, 0x00 ; 0 + 3f08: 2c 91 ld r18, X + 3f0a: 30 e0 ldi r19, 0x00 ; 0 a |= (*bufPtr++) << 8; - 3ee0: 11 96 adiw r26, 0x01 ; 1 - 3ee2: 8c 91 ld r24, X - 3ee4: 11 97 sbiw r26, 0x01 ; 1 - 3ee6: 90 e0 ldi r25, 0x00 ; 0 - 3ee8: 98 2f mov r25, r24 - 3eea: 88 27 eor r24, r24 - 3eec: 82 2b or r24, r18 - 3eee: 93 2b or r25, r19 -#ifdef VIRTUAL_BOOT_PARTITION -#define rstVect (*(uint16_t*)(0x204)) -#define wdtVect (*(uint16_t*)(0x206)) + 3f0c: 11 96 adiw r26, 0x01 ; 1 + 3f0e: 8c 91 ld r24, X + 3f10: 11 97 sbiw r26, 0x01 ; 1 + 3f12: 90 e0 ldi r25, 0x00 ; 0 + 3f14: 98 2f mov r25, r24 + 3f16: 88 27 eor r24, r24 + 3f18: 82 2b or r24, r18 + 3f1a: 93 2b or r25, r19 +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif + /* main program starts here */ int main(void) { - 3ef0: 12 96 adiw r26, 0x02 ; 2 + 3f1c: 12 96 adiw r26, 0x02 ; 2 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; a |= (*bufPtr++) << 8; - boot_page_fill((uint16_t)(void*)addrPtr,a); - 3ef2: fa 01 movw r30, r20 - 3ef4: 0c 01 movw r0, r24 - 3ef6: d0 92 57 00 sts 0x0057, r13 - 3efa: e8 95 spm - 3efc: 11 24 eor r1, r1 + __boot_page_fill_short((uint16_t)(void*)addrPtr,a); + 3f1e: fa 01 movw r30, r20 + 3f20: 0c 01 movw r0, r24 + 3f22: d7 be out 0x37, r13 ; 55 + 3f24: e8 95 spm + 3f26: 11 24 eor r1, r1 addrPtr += 2; - 3efe: 4e 5f subi r20, 0xFE ; 254 - 3f00: 5f 4f sbci r21, 0xFF ; 255 + 3f28: 4e 5f subi r20, 0xFE ; 254 + 3f2a: 5f 4f sbci r21, 0xFF ; 255 } while (--ch); - 3f02: f1 e0 ldi r31, 0x01 ; 1 - 3f04: a0 38 cpi r26, 0x80 ; 128 - 3f06: bf 07 cpc r27, r31 - 3f08: 49 f7 brne .-46 ; 0x3edc + 3f2c: f1 e0 ldi r31, 0x01 ; 1 + 3f2e: a0 38 cpi r26, 0x80 ; 128 + 3f30: bf 07 cpc r27, r31 + 3f32: 51 f7 brne .-44 ; 0x3f08 // Write from programming buffer - boot_page_write((uint16_t)(void*)address); - 3f0a: e0 91 00 02 lds r30, 0x0200 - 3f0e: f0 91 01 02 lds r31, 0x0201 - 3f12: e0 92 57 00 sts 0x0057, r14 - 3f16: e8 95 spm + __boot_page_write_short((uint16_t)(void*)address); + 3f34: e0 91 00 02 lds r30, 0x0200 + 3f38: f0 91 01 02 lds r31, 0x0201 + 3f3c: e7 be out 0x37, r14 ; 55 + 3f3e: e8 95 spm boot_spm_busy_wait(); - 3f18: 07 b6 in r0, 0x37 ; 55 - 3f1a: 00 fc sbrc r0, 0 - 3f1c: fd cf rjmp .-6 ; 0x3f18 + 3f40: 07 b6 in r0, 0x37 ; 55 + 3f42: 00 fc sbrc r0, 0 + 3f44: fd cf rjmp .-6 ; 0x3f40 #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 3f1e: f0 92 57 00 sts 0x0057, r15 - 3f22: e8 95 spm - 3f24: 27 c0 rjmp .+78 ; 0x3f74 + 3f46: f7 be out 0x37, r15 ; 55 + 3f48: e8 95 spm + 3f4a: 27 c0 rjmp .+78 ; 0x3f9a #endif } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { - 3f26: 84 37 cpi r24, 0x74 ; 116 - 3f28: b9 f4 brne .+46 ; 0x3f58 + 3f4c: 84 37 cpi r24, 0x74 ; 116 + 3f4e: b9 f4 brne .+46 ; 0x3f7e // READ PAGE - we only read flash getLen(); - 3f2a: 4a d0 rcall .+148 ; 0x3fc0 + 3f50: 37 d0 rcall .+110 ; 0x3fc0 verifySpace(); - 3f2c: 59 d0 rcall .+178 ; 0x3fe0 - else ch = pgm_read_byte_near(address); + 3f52: 46 d0 rcall .+140 ; 0x3fe0 + putch(result); address++; - putch(ch); - } while (--length); + } + while (--length); #else do putch(pgm_read_byte_near(address++)); - 3f2e: e0 91 00 02 lds r30, 0x0200 - 3f32: f0 91 01 02 lds r31, 0x0201 - 3f36: 31 96 adiw r30, 0x01 ; 1 - 3f38: f0 93 01 02 sts 0x0201, r31 - 3f3c: e0 93 00 02 sts 0x0200, r30 - 3f40: 31 97 sbiw r30, 0x01 ; 1 - 3f42: e4 91 lpm r30, Z+ - 3f44: 8e 2f mov r24, r30 - 3f46: 19 d0 rcall .+50 ; 0x3f7a + 3f54: e0 91 00 02 lds r30, 0x0200 + 3f58: f0 91 01 02 lds r31, 0x0201 + 3f5c: 31 96 adiw r30, 0x01 ; 1 + 3f5e: f0 93 01 02 sts 0x0201, r31 + 3f62: e0 93 00 02 sts 0x0200, r30 + 3f66: 31 97 sbiw r30, 0x01 ; 1 + 3f68: e4 91 lpm r30, Z+ + 3f6a: 8e 2f mov r24, r30 + 3f6c: 19 d0 rcall .+50 ; 0x3fa0 while (--length); - 3f48: 80 91 02 02 lds r24, 0x0202 - 3f4c: 81 50 subi r24, 0x01 ; 1 - 3f4e: 80 93 02 02 sts 0x0202, r24 - 3f52: 88 23 and r24, r24 - 3f54: 61 f7 brne .-40 ; 0x3f2e - 3f56: 0e c0 rjmp .+28 ; 0x3f74 + 3f6e: 80 91 02 02 lds r24, 0x0202 + 3f72: 81 50 subi r24, 0x01 ; 1 + 3f74: 80 93 02 02 sts 0x0202, r24 + 3f78: 88 23 and r24, r24 + 3f7a: 61 f7 brne .-40 ; 0x3f54 + 3f7c: 0e c0 rjmp .+28 ; 0x3f9a +#endif #endif } /* Get device signature bytes */ else if(ch == STK_READ_SIGN) { - 3f58: 85 37 cpi r24, 0x75 ; 117 - 3f5a: 39 f4 brne .+14 ; 0x3f6a + 3f7e: 85 37 cpi r24, 0x75 ; 117 + 3f80: 39 f4 brne .+14 ; 0x3f90 // READ SIGN - return what Avrdude wants to hear verifySpace(); - 3f5c: 41 d0 rcall .+130 ; 0x3fe0 + 3f82: 2e d0 rcall .+92 ; 0x3fe0 putch(SIGNATURE_0); - 3f5e: 8e e1 ldi r24, 0x1E ; 30 - 3f60: 0c d0 rcall .+24 ; 0x3f7a + 3f84: 8e e1 ldi r24, 0x1E ; 30 + 3f86: 0c d0 rcall .+24 ; 0x3fa0 putch(SIGNATURE_1); - 3f62: 84 e9 ldi r24, 0x94 ; 148 - 3f64: 0a d0 rcall .+20 ; 0x3f7a + 3f88: 84 e9 ldi r24, 0x94 ; 148 + 3f8a: 0a d0 rcall .+20 ; 0x3fa0 putch(SIGNATURE_2); - 3f66: 86 e0 ldi r24, 0x06 ; 6 - 3f68: 96 cf rjmp .-212 ; 0x3e96 + 3f8c: 86 e0 ldi r24, 0x06 ; 6 + 3f8e: 8b cf rjmp .-234 ; 0x3ea6 } else if (ch == 'Q') { - 3f6a: 81 35 cpi r24, 0x51 ; 81 - 3f6c: 11 f4 brne .+4 ; 0x3f72 + 3f90: 81 35 cpi r24, 0x51 ; 81 + 3f92: 11 f4 brne .+4 ; 0x3f98 // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); - 3f6e: 88 e0 ldi r24, 0x08 ; 8 - 3f70: 2c d0 rcall .+88 ; 0x3fca + 3f94: 88 e0 ldi r24, 0x08 ; 8 + 3f96: 19 d0 rcall .+50 ; 0x3fca verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 3f72: 36 d0 rcall .+108 ; 0x3fe0 + 3f98: 23 d0 rcall .+70 ; 0x3fe0 } putch(STK_OK); - 3f74: 80 e1 ldi r24, 0x10 ; 16 - 3f76: 01 d0 rcall .+2 ; 0x3f7a - 3f78: 63 cf rjmp .-314 ; 0x3e40 + 3f9a: 80 e1 ldi r24, 0x10 ; 16 + 3f9c: 01 d0 rcall .+2 ; 0x3fa0 + 3f9e: 5c cf rjmp .-328 ; 0x3e58 + +00003fa0 : + } +} -00003f7a : void putch(char ch) { + 3fa0: 98 2f mov r25, r24 #ifndef SOFT_UART while (!(UCSR0A & _BV(UDRE0))); + 3fa2: 80 91 c0 00 lds r24, 0x00C0 + 3fa6: 85 ff sbrs r24, 5 + 3fa8: fc cf rjmp .-8 ; 0x3fa2 UDR0 = ch; -#else - __asm__ __volatile__ ( - 3f7a: 2a e0 ldi r18, 0x0A ; 10 - 3f7c: 30 e0 ldi r19, 0x00 ; 0 - 3f7e: 80 95 com r24 - 3f80: 08 94 sec - 3f82: 10 f4 brcc .+4 ; 0x3f88 - 3f84: 59 98 cbi 0x0b, 1 ; 11 - 3f86: 02 c0 rjmp .+4 ; 0x3f8c - 3f88: 59 9a sbi 0x0b, 1 ; 11 - 3f8a: 00 00 nop - 3f8c: 15 d0 rcall .+42 ; 0x3fb8 - 3f8e: 14 d0 rcall .+40 ; 0x3fb8 - 3f90: 86 95 lsr r24 - 3f92: 2a 95 dec r18 - 3f94: b1 f7 brne .-20 ; 0x3f82 + 3faa: 90 93 c6 00 sts 0x00C6, r25 [uartBit] "I" (UART_TX_BIT) : "r25" ); #endif } - 3f96: 08 95 ret + 3fae: 08 95 ret -00003f98 : +00003fb0 : return getch(); } // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 3f98: a8 95 wdr -#ifdef LED_DATA_FLASH + 3fb0: a8 95 wdr + [uartBit] "I" (UART_RX_BIT) + : + "r25" +); +#else + while(!(UCSR0A & _BV(RXC0))); + 3fb2: 80 91 c0 00 lds r24, 0x00C0 + 3fb6: 87 ff sbrs r24, 7 + 3fb8: fc cf rjmp .-8 ; 0x3fb2 + ch = UDR0; + 3fba: 80 91 c6 00 lds r24, 0x00C6 LED_PIN |= _BV(LED); +#endif #endif return ch; } - 3f9a: 29 e0 ldi r18, 0x09 ; 9 - 3f9c: 30 e0 ldi r19, 0x00 ; 0 - 3f9e: 48 99 sbic 0x09, 0 ; 9 - 3fa0: fe cf rjmp .-4 ; 0x3f9e - 3fa2: 0a d0 rcall .+20 ; 0x3fb8 - 3fa4: 09 d0 rcall .+18 ; 0x3fb8 - 3fa6: 08 d0 rcall .+16 ; 0x3fb8 - 3fa8: 88 94 clc - 3faa: 48 99 sbic 0x09, 0 ; 9 - 3fac: 08 94 sec - 3fae: 2a 95 dec r18 - 3fb0: 11 f0 breq .+4 ; 0x3fb6 - 3fb2: 87 95 ror r24 - 3fb4: f7 cf rjmp .-18 ; 0x3fa4 - 3fb6: 08 95 ret - -00003fb8 : -#if UART_B_VALUE > 255 -#error Baud rate too slow for soft UART -#endif - -void uartDelay() { - __asm__ __volatile__ ( - 3fb8: 98 e0 ldi r25, 0x08 ; 8 - 3fba: 9a 95 dec r25 - 3fbc: f1 f7 brne .-4 ; 0x3fba 3fbe: 08 95 ret 00003fc0 : @@ -462,13 +483,13 @@ void uartDelay() { uint8_t getLen() { getch(); - 3fc0: eb df rcall .-42 ; 0x3f98 + 3fc0: f7 df rcall .-18 ; 0x3fb0 length = getch(); - 3fc2: ea df rcall .-44 ; 0x3f98 + 3fc2: f6 df rcall .-20 ; 0x3fb0 3fc4: 80 93 02 02 sts 0x0202, r24 return getch(); } - 3fc8: e7 cf rjmp .-50 ; 0x3f98 + 3fc8: f3 cf rjmp .-26 ; 0x3fb0 00003fca : "wdr\n" @@ -504,14 +525,16 @@ void appStart() { void verifySpace() { if (getch() != CRC_EOP) appStart(); - 3fe0: db df rcall .-74 ; 0x3f98 + 3fe0: e7 df rcall .-50 ; 0x3fb0 3fe2: 80 32 cpi r24, 0x20 ; 32 3fe4: 09 f0 breq .+2 ; 0x3fe8 3fe6: f7 df rcall .-18 ; 0x3fd6 putch(STK_INSYNC); 3fe8: 84 e1 ldi r24, 0x14 ; 20 } - 3fea: c7 cf rjmp .-114 ; 0x3f7a + 3fea: da cf rjmp .-76 ; 0x3fa0 + +00003fec : ::[count] "M" (UART_B_VALUE) ); } @@ -520,12 +543,10 @@ void verifySpace() { void getNch(uint8_t count) { 3fec: 1f 93 push r17 3fee: 18 2f mov r17, r24 - -00003ff0 : do getch(); while (--count); - 3ff0: d3 df rcall .-90 ; 0x3f98 + 3ff0: df df rcall .-66 ; 0x3fb0 3ff2: 11 50 subi r17, 0x01 ; 1 - 3ff4: e9 f7 brne .-6 ; 0x3ff0 + 3ff4: e9 f7 brne .-6 ; 0x3ff0 verifySpace(); 3ff6: f4 df rcall .-24 ; 0x3fe0 } diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.hex b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.hex index 9d31a7a18..757928697 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.hex @@ -1,34 +1,34 @@ -:103E000085E08093810084B714BE81FFE4D08DE00B -:103E1000DCD0259A519A86E028E13EEF91E030937C -:103E200085002093840096BBB09BFECF1D9AA89579 -:103E30008150A9F7DD24D394A5E0EA2EF1E1FF2E0D -:103E4000ABD0813421F481E0D1D083E024C082342E -:103E500011F484E103C0853419F485E0C7D08AC029 -:103E60008535A1F499D0082F10E01093010200933A -:103E7000000292D090E0982F8827802B912B880FFA -:103E8000991F909301028093000273C0863529F434 -:103E900084E0ACD080E071D06DC0843609F043C0BE -:103EA0008FD0E0910002F091010283E080935700EF -:103EB000E895C0E0D1E070D08993809102028150F2 -:103EC000809302028823B9F78BD007B600FCFDCFA0 -:103ED0004091000250910102A0E0B1E02C9130E04D -:103EE00011968C91119790E0982F8827822B932B15 -:103EF0001296FA010C01D0925700E89511244E5FFA -:103F00005F4FF1E0A038BF0749F7E0910002F09160 -:103F10000102E0925700E89507B600FCFDCFF09251 -:103F20005700E89527C08437B9F44AD059D0E091BA -:103F30000002F09101023196F0930102E093000239 -:103F40003197E4918E2F19D0809102028150809395 -:103F50000202882361F70EC0853739F441D08EE123 -:103F60000CD084E90AD086E096CF813511F488E040 -:103F70002CD036D080E101D063CF2AE030E08095AC -:103F8000089410F4599802C0599A000015D014D022 -:103F900086952A95B1F70895A89529E030E04899CB -:103FA000FECF0AD009D008D08894489908942A9561 -:103FB00011F08795F7CF089598E09A95F1F7089555 -:103FC000EBDFEADF80930202E7CFE0E6F0E098E182 +:103E0000112484B714BE81FFE6D085E08093810041 +:103E100082E08093C00088E18093C10086E08093B7 +:103E2000C20088E08093C4008EE0CFD0259A86E05F +:103E300028E13EEF91E0309385002093840096BB0B +:103E4000B09BFECF1D9AA8958150A9F7DD24D3948D +:103E5000A5E0EA2EF1E1FF2EABD0813421F481E020 +:103E6000C5D083E020C0823411F484E103C08534DE +:103E700019F485E0BBD091C0853581F499D0082F25 +:103E800010E096D090E0982F8827802B912B880FF8 +:103E9000991F90930102809300027EC0863529F419 +:103EA00084E0A4D080E07CD078C0843609F04EC095 +:103EB00087D0E0910002F091010288E3E030F8073A +:103EC00018F483E087BFE895C0E0D1E071D0899312 +:103ED000809102028150809302028823B9F7E09119 +:103EE0000002F091010288E3E030F80718F083E067 +:103EF00087BFE89575D007B600FCFDCF4091000262 +:103F000050910102A0E0B1E02C9130E011968C912B +:103F1000119790E0982F8827822B932B1296FA0105 +:103F20000C01D7BEE89511244E5F5F4FF1E0A03839 +:103F3000BF0751F7E0910002F0910102E7BEE8955A +:103F400007B600FCFDCFF7BEE89527C08437B9F46B +:103F500037D046D0E0910002F09101023196F09303 +:103F60000102E09300023197E4918E2F19D08091E5 +:103F70000202815080930202882361F70EC08537C8 +:103F800039F42ED08EE10CD084E90AD086E08BCFB4 +:103F9000813511F488E019D023D080E101D05CCFC5 +:103FA000982F8091C00085FFFCCF9093C6000895A4 +:103FB000A8958091C00087FFFCCF8091C60008952E +:103FC000F7DFF6DF80930202F3CFE0E6F0E098E15E :103FD00090838083089580E0F8DFEE27FF2709941F -:103FE000DBDF803209F0F7DF84E1C7CF1F93182FA2 -:0C3FF000D3DF1150E9F7F4DF1F910895B2 +:103FE000E7DF803209F0F7DF84E1DACF1F93182F83 +:0C3FF000DFDF1150E9F7F4DF1F910895A6 :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.lst b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.lst index 80ecb8396..c5d771009 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.lst @@ -7,452 +7,473 @@ Idx Name Size VMA LMA File off Algn CONTENTS, ALLOC, LOAD, READONLY, CODE 1 .debug_aranges 00000028 00000000 00000000 00000250 2**0 CONTENTS, READONLY, DEBUGGING - 2 .debug_pubnames 00000078 00000000 00000000 00000278 2**0 + 2 .debug_pubnames 0000006a 00000000 00000000 00000278 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_info 00000277 00000000 00000000 000002f0 2**0 + 3 .debug_info 00000284 00000000 00000000 000002e2 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_abbrev 00000194 00000000 00000000 00000567 2**0 + 4 .debug_abbrev 000001ae 00000000 00000000 00000566 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_line 000003bb 00000000 00000000 000006fb 2**0 + 5 .debug_line 00000450 00000000 00000000 00000714 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_frame 000000a0 00000000 00000000 00000ab8 2**2 + 6 .debug_frame 00000090 00000000 00000000 00000b64 2**2 CONTENTS, READONLY, DEBUGGING - 7 .debug_str 0000013f 00000000 00000000 00000b58 2**0 + 7 .debug_str 00000141 00000000 00000000 00000bf4 2**0 CONTENTS, READONLY, DEBUGGING - 8 .debug_loc 000001a0 00000000 00000000 00000c97 2**0 + 8 .debug_loc 000001e1 00000000 00000000 00000d35 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_ranges 00000070 00000000 00000000 00000e37 2**0 + 9 .debug_ranges 00000068 00000000 00000000 00000f16 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: 00003e00
    : -#ifdef VIRTUAL_BOOT_PARTITION -#define rstVect (*(uint16_t*)(0x204)) -#define wdtVect (*(uint16_t*)(0x206)) +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif + /* main program starts here */ int main(void) { - 3e00: 85 e0 ldi r24, 0x05 ; 5 - 3e02: 80 93 81 00 sts 0x0081, r24 - UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); - UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); + 3e00: 11 24 eor r1, r1 +#ifdef __AVR_ATmega8__ + SP=RAMEND; // This is done by hardware reset #endif // Adaboot no-wait mod ch = MCUSR; - 3e06: 84 b7 in r24, 0x34 ; 52 + 3e02: 84 b7 in r24, 0x34 ; 52 MCUSR = 0; - 3e08: 14 be out 0x34, r1 ; 52 + 3e04: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); - 3e0a: 81 ff sbrs r24, 1 - 3e0c: e4 d0 rcall .+456 ; 0x3fd6 + 3e06: 81 ff sbrs r24, 1 + 3e08: e6 d0 rcall .+460 ; 0x3fd6 + +#if LED_START_FLASHES > 0 + // Set up Timer 1 for timeout counter + TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 + 3e0a: 85 e0 ldi r24, 0x05 ; 5 + 3e0c: 80 93 81 00 sts 0x0081, r24 + UCSRA = _BV(U2X); //Double speed mode USART + UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx + UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 + UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); +#else + UCSR0A = _BV(U2X0); //Double speed mode USART0 + 3e10: 82 e0 ldi r24, 0x02 ; 2 + 3e12: 80 93 c0 00 sts 0x00C0, r24 + UCSR0B = _BV(RXEN0) | _BV(TXEN0); + 3e16: 88 e1 ldi r24, 0x18 ; 24 + 3e18: 80 93 c1 00 sts 0x00C1, r24 + UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); + 3e1c: 86 e0 ldi r24, 0x06 ; 6 + 3e1e: 80 93 c2 00 sts 0x00C2, r24 + UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); + 3e22: 88 e0 ldi r24, 0x08 ; 8 + 3e24: 80 93 c4 00 sts 0x00C4, r24 +#endif +#endif // Set up watchdog to trigger after 500ms - watchdogConfig(WATCHDOG_500MS); - 3e0e: 8d e0 ldi r24, 0x0D ; 13 - 3e10: dc d0 rcall .+440 ; 0x3fca + watchdogConfig(WATCHDOG_1S); + 3e28: 8e e0 ldi r24, 0x0E ; 14 + 3e2a: cf d0 rcall .+414 ; 0x3fca /* Set LED pin as output */ LED_DDR |= _BV(LED); - 3e12: 25 9a sbi 0x04, 5 ; 4 - -#ifdef SOFT_UART - /* Set TX pin as output */ - UART_DDR |= _BV(UART_TX_BIT); - 3e14: 51 9a sbi 0x0a, 1 ; 10 - 3e16: 86 e0 ldi r24, 0x06 ; 6 + 3e2c: 25 9a sbi 0x04, 5 ; 4 + 3e2e: 86 e0 ldi r24, 0x06 ; 6 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - 3e18: 28 e1 ldi r18, 0x18 ; 24 - 3e1a: 3e ef ldi r19, 0xFE ; 254 + 3e30: 28 e1 ldi r18, 0x18 ; 24 + 3e32: 3e ef ldi r19, 0xFE ; 254 TIFR1 = _BV(TOV1); - 3e1c: 91 e0 ldi r25, 0x01 ; 1 + 3e34: 91 e0 ldi r25, 0x01 ; 1 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - 3e1e: 30 93 85 00 sts 0x0085, r19 - 3e22: 20 93 84 00 sts 0x0084, r18 + 3e36: 30 93 85 00 sts 0x0085, r19 + 3e3a: 20 93 84 00 sts 0x0084, r18 TIFR1 = _BV(TOV1); - 3e26: 96 bb out 0x16, r25 ; 22 + 3e3e: 96 bb out 0x16, r25 ; 22 while(!(TIFR1 & _BV(TOV1))); - 3e28: b0 9b sbis 0x16, 0 ; 22 - 3e2a: fe cf rjmp .-4 ; 0x3e28 + 3e40: b0 9b sbis 0x16, 0 ; 22 + 3e42: fe cf rjmp .-4 ; 0x3e40 +#ifdef __AVR_ATmega8__ + LED_PORT ^= _BV(LED); +#else LED_PIN |= _BV(LED); - 3e2c: 1d 9a sbi 0x03, 5 ; 3 + 3e44: 1d 9a sbi 0x03, 5 ; 3 return getch(); } // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 3e2e: a8 95 wdr - TCNT1 = -(F_CPU/(1024*16)); - TIFR1 = _BV(TOV1); - while(!(TIFR1 & _BV(TOV1))); + 3e46: a8 95 wdr + LED_PORT ^= _BV(LED); +#else LED_PIN |= _BV(LED); +#endif watchdogReset(); } while (--count); - 3e30: 81 50 subi r24, 0x01 ; 1 - 3e32: a9 f7 brne .-22 ; 0x3e1e + 3e48: 81 50 subi r24, 0x01 ; 1 + 3e4a: a9 f7 brne .-22 ; 0x3e36 /* get character from UART */ ch = getch(); if(ch == STK_GET_PARAMETER) { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 3e34: dd 24 eor r13, r13 - 3e36: d3 94 inc r13 - boot_page_fill((uint16_t)(void*)addrPtr,a); + 3e4c: dd 24 eor r13, r13 + 3e4e: d3 94 inc r13 + __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); // Write from programming buffer - boot_page_write((uint16_t)(void*)address); - 3e38: a5 e0 ldi r26, 0x05 ; 5 - 3e3a: ea 2e mov r14, r26 + __boot_page_write_short((uint16_t)(void*)address); + 3e50: a5 e0 ldi r26, 0x05 ; 5 + 3e52: ea 2e mov r14, r26 boot_spm_busy_wait(); #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 3e3c: f1 e1 ldi r31, 0x11 ; 17 - 3e3e: ff 2e mov r15, r31 + 3e54: f1 e1 ldi r31, 0x11 ; 17 + 3e56: ff 2e mov r15, r31 #endif /* Forever loop */ for (;;) { /* get character from UART */ ch = getch(); - 3e40: ab d0 rcall .+342 ; 0x3f98 + 3e58: ab d0 rcall .+342 ; 0x3fb0 if(ch == STK_GET_PARAMETER) { - 3e42: 81 34 cpi r24, 0x41 ; 65 - 3e44: 21 f4 brne .+8 ; 0x3e4e + 3e5a: 81 34 cpi r24, 0x41 ; 65 + 3e5c: 21 f4 brne .+8 ; 0x3e66 // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 3e46: 81 e0 ldi r24, 0x01 ; 1 - 3e48: d1 d0 rcall .+418 ; 0x3fec + 3e5e: 81 e0 ldi r24, 0x01 ; 1 + 3e60: c5 d0 rcall .+394 ; 0x3fec putch(0x03); - 3e4a: 83 e0 ldi r24, 0x03 ; 3 - 3e4c: 24 c0 rjmp .+72 ; 0x3e96 + 3e62: 83 e0 ldi r24, 0x03 ; 3 + 3e64: 20 c0 rjmp .+64 ; 0x3ea6 } else if(ch == STK_SET_DEVICE) { - 3e4e: 82 34 cpi r24, 0x42 ; 66 - 3e50: 11 f4 brne .+4 ; 0x3e56 + 3e66: 82 34 cpi r24, 0x42 ; 66 + 3e68: 11 f4 brne .+4 ; 0x3e6e // SET DEVICE is ignored getNch(20); - 3e52: 84 e1 ldi r24, 0x14 ; 20 - 3e54: 03 c0 rjmp .+6 ; 0x3e5c + 3e6a: 84 e1 ldi r24, 0x14 ; 20 + 3e6c: 03 c0 rjmp .+6 ; 0x3e74 } else if(ch == STK_SET_DEVICE_EXT) { - 3e56: 85 34 cpi r24, 0x45 ; 69 - 3e58: 19 f4 brne .+6 ; 0x3e60 + 3e6e: 85 34 cpi r24, 0x45 ; 69 + 3e70: 19 f4 brne .+6 ; 0x3e78 // SET DEVICE EXT is ignored getNch(5); - 3e5a: 85 e0 ldi r24, 0x05 ; 5 - 3e5c: c7 d0 rcall .+398 ; 0x3fec - 3e5e: 8a c0 rjmp .+276 ; 0x3f74 + 3e72: 85 e0 ldi r24, 0x05 ; 5 + 3e74: bb d0 rcall .+374 ; 0x3fec + 3e76: 91 c0 rjmp .+290 ; 0x3f9a } else if(ch == STK_LOAD_ADDRESS) { - 3e60: 85 35 cpi r24, 0x55 ; 85 - 3e62: a1 f4 brne .+40 ; 0x3e8c + 3e78: 85 35 cpi r24, 0x55 ; 85 + 3e7a: 81 f4 brne .+32 ; 0x3e9c // LOAD ADDRESS - address = getch(); - 3e64: 99 d0 rcall .+306 ; 0x3f98 - 3e66: 08 2f mov r16, r24 - 3e68: 10 e0 ldi r17, 0x00 ; 0 - 3e6a: 10 93 01 02 sts 0x0201, r17 - 3e6e: 00 93 00 02 sts 0x0200, r16 - address = (address & 0xff) | (getch() << 8); - 3e72: 92 d0 rcall .+292 ; 0x3f98 - 3e74: 90 e0 ldi r25, 0x00 ; 0 - 3e76: 98 2f mov r25, r24 - 3e78: 88 27 eor r24, r24 - 3e7a: 80 2b or r24, r16 - 3e7c: 91 2b or r25, r17 - address += address; // Convert from word address to byte address - 3e7e: 88 0f add r24, r24 - 3e80: 99 1f adc r25, r25 - 3e82: 90 93 01 02 sts 0x0201, r25 - 3e86: 80 93 00 02 sts 0x0200, r24 - 3e8a: 73 c0 rjmp .+230 ; 0x3f72 + uint16_t newAddress; + newAddress = getch(); + 3e7c: 99 d0 rcall .+306 ; 0x3fb0 + newAddress = (newAddress & 0xff) | (getch() << 8); + 3e7e: 08 2f mov r16, r24 + 3e80: 10 e0 ldi r17, 0x00 ; 0 + 3e82: 96 d0 rcall .+300 ; 0x3fb0 + 3e84: 90 e0 ldi r25, 0x00 ; 0 + 3e86: 98 2f mov r25, r24 + 3e88: 88 27 eor r24, r24 + 3e8a: 80 2b or r24, r16 + 3e8c: 91 2b or r25, r17 +#ifdef RAMPZ + // Transfer top bit to RAMPZ + RAMPZ = (newAddress & 0x8000) ? 1 : 0; +#endif + newAddress += newAddress; // Convert from word address to byte address + 3e8e: 88 0f add r24, r24 + 3e90: 99 1f adc r25, r25 + address = newAddress; + 3e92: 90 93 01 02 sts 0x0201, r25 + 3e96: 80 93 00 02 sts 0x0200, r24 + 3e9a: 7e c0 rjmp .+252 ; 0x3f98 verifySpace(); } else if(ch == STK_UNIVERSAL) { - 3e8c: 86 35 cpi r24, 0x56 ; 86 - 3e8e: 29 f4 brne .+10 ; 0x3e9a + 3e9c: 86 35 cpi r24, 0x56 ; 86 + 3e9e: 29 f4 brne .+10 ; 0x3eaa // UNIVERSAL command is ignored getNch(4); - 3e90: 84 e0 ldi r24, 0x04 ; 4 - 3e92: ac d0 rcall .+344 ; 0x3fec + 3ea0: 84 e0 ldi r24, 0x04 ; 4 + 3ea2: a4 d0 rcall .+328 ; 0x3fec putch(0x00); - 3e94: 80 e0 ldi r24, 0x00 ; 0 - 3e96: 71 d0 rcall .+226 ; 0x3f7a - 3e98: 6d c0 rjmp .+218 ; 0x3f74 + 3ea4: 80 e0 ldi r24, 0x00 ; 0 + 3ea6: 7c d0 rcall .+248 ; 0x3fa0 + 3ea8: 78 c0 rjmp .+240 ; 0x3f9a } - /* Write memory, length is big endian and is in bytes */ + /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { - 3e9a: 84 36 cpi r24, 0x64 ; 100 - 3e9c: 09 f0 breq .+2 ; 0x3ea0 - 3e9e: 43 c0 rjmp .+134 ; 0x3f26 + 3eaa: 84 36 cpi r24, 0x64 ; 100 + 3eac: 09 f0 breq .+2 ; 0x3eb0 + 3eae: 4e c0 rjmp .+156 ; 0x3f4c // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t *bufPtr; uint16_t addrPtr; getLen(); - 3ea0: 8f d0 rcall .+286 ; 0x3fc0 - - // Immediately start page erase - this will 4.5ms - boot_page_erase((uint16_t)(void*)address); - 3ea2: e0 91 00 02 lds r30, 0x0200 - 3ea6: f0 91 01 02 lds r31, 0x0201 - 3eaa: 83 e0 ldi r24, 0x03 ; 3 - 3eac: 80 93 57 00 sts 0x0057, r24 - 3eb0: e8 95 spm - 3eb2: c0 e0 ldi r28, 0x00 ; 0 - 3eb4: d1 e0 ldi r29, 0x01 ; 1 + 3eb0: 87 d0 rcall .+270 ; 0x3fc0 + // If we are in RWW section, immediately start page erase + if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + 3eb2: e0 91 00 02 lds r30, 0x0200 + 3eb6: f0 91 01 02 lds r31, 0x0201 + 3eba: 88 e3 ldi r24, 0x38 ; 56 + 3ebc: e0 30 cpi r30, 0x00 ; 0 + 3ebe: f8 07 cpc r31, r24 + 3ec0: 18 f4 brcc .+6 ; 0x3ec8 + 3ec2: 83 e0 ldi r24, 0x03 ; 3 + 3ec4: 87 bf out 0x37, r24 ; 55 + 3ec6: e8 95 spm + 3ec8: c0 e0 ldi r28, 0x00 ; 0 + 3eca: d1 e0 ldi r29, 0x01 ; 1 + // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); - 3eb6: 70 d0 rcall .+224 ; 0x3f98 - 3eb8: 89 93 st Y+, r24 + 3ecc: 71 d0 rcall .+226 ; 0x3fb0 + 3ece: 89 93 st Y+, r24 while (--length); - 3eba: 80 91 02 02 lds r24, 0x0202 - 3ebe: 81 50 subi r24, 0x01 ; 1 - 3ec0: 80 93 02 02 sts 0x0202, r24 - 3ec4: 88 23 and r24, r24 - 3ec6: b9 f7 brne .-18 ; 0x3eb6 + 3ed0: 80 91 02 02 lds r24, 0x0202 + 3ed4: 81 50 subi r24, 0x01 ; 1 + 3ed6: 80 93 02 02 sts 0x0202, r24 + 3eda: 88 23 and r24, r24 + 3edc: b9 f7 brne .-18 ; 0x3ecc + + // If we are in NRWW section, page erase has to be delayed until now. + // Todo: Take RAMPZ into account + if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + 3ede: e0 91 00 02 lds r30, 0x0200 + 3ee2: f0 91 01 02 lds r31, 0x0201 + 3ee6: 88 e3 ldi r24, 0x38 ; 56 + 3ee8: e0 30 cpi r30, 0x00 ; 0 + 3eea: f8 07 cpc r31, r24 + 3eec: 18 f0 brcs .+6 ; 0x3ef4 + 3eee: 83 e0 ldi r24, 0x03 ; 3 + 3ef0: 87 bf out 0x37, r24 ; 55 + 3ef2: e8 95 spm // Read command terminator, start reply verifySpace(); - 3ec8: 8b d0 rcall .+278 ; 0x3fe0 + 3ef4: 75 d0 rcall .+234 ; 0x3fe0 // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); - 3eca: 07 b6 in r0, 0x37 ; 55 - 3ecc: 00 fc sbrc r0, 0 - 3ece: fd cf rjmp .-6 ; 0x3eca + 3ef6: 07 b6 in r0, 0x37 ; 55 + 3ef8: 00 fc sbrc r0, 0 + 3efa: fd cf rjmp .-6 ; 0x3ef6 } #endif // Copy buffer into programming buffer bufPtr = buff; addrPtr = (uint16_t)(void*)address; - 3ed0: 40 91 00 02 lds r20, 0x0200 - 3ed4: 50 91 01 02 lds r21, 0x0201 - 3ed8: a0 e0 ldi r26, 0x00 ; 0 - 3eda: b1 e0 ldi r27, 0x01 ; 1 + 3efc: 40 91 00 02 lds r20, 0x0200 + 3f00: 50 91 01 02 lds r21, 0x0201 + 3f04: a0 e0 ldi r26, 0x00 ; 0 + 3f06: b1 e0 ldi r27, 0x01 ; 1 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; - 3edc: 2c 91 ld r18, X - 3ede: 30 e0 ldi r19, 0x00 ; 0 + 3f08: 2c 91 ld r18, X + 3f0a: 30 e0 ldi r19, 0x00 ; 0 a |= (*bufPtr++) << 8; - 3ee0: 11 96 adiw r26, 0x01 ; 1 - 3ee2: 8c 91 ld r24, X - 3ee4: 11 97 sbiw r26, 0x01 ; 1 - 3ee6: 90 e0 ldi r25, 0x00 ; 0 - 3ee8: 98 2f mov r25, r24 - 3eea: 88 27 eor r24, r24 - 3eec: 82 2b or r24, r18 - 3eee: 93 2b or r25, r19 -#ifdef VIRTUAL_BOOT_PARTITION -#define rstVect (*(uint16_t*)(0x204)) -#define wdtVect (*(uint16_t*)(0x206)) + 3f0c: 11 96 adiw r26, 0x01 ; 1 + 3f0e: 8c 91 ld r24, X + 3f10: 11 97 sbiw r26, 0x01 ; 1 + 3f12: 90 e0 ldi r25, 0x00 ; 0 + 3f14: 98 2f mov r25, r24 + 3f16: 88 27 eor r24, r24 + 3f18: 82 2b or r24, r18 + 3f1a: 93 2b or r25, r19 +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif + /* main program starts here */ int main(void) { - 3ef0: 12 96 adiw r26, 0x02 ; 2 + 3f1c: 12 96 adiw r26, 0x02 ; 2 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; a |= (*bufPtr++) << 8; - boot_page_fill((uint16_t)(void*)addrPtr,a); - 3ef2: fa 01 movw r30, r20 - 3ef4: 0c 01 movw r0, r24 - 3ef6: d0 92 57 00 sts 0x0057, r13 - 3efa: e8 95 spm - 3efc: 11 24 eor r1, r1 + __boot_page_fill_short((uint16_t)(void*)addrPtr,a); + 3f1e: fa 01 movw r30, r20 + 3f20: 0c 01 movw r0, r24 + 3f22: d7 be out 0x37, r13 ; 55 + 3f24: e8 95 spm + 3f26: 11 24 eor r1, r1 addrPtr += 2; - 3efe: 4e 5f subi r20, 0xFE ; 254 - 3f00: 5f 4f sbci r21, 0xFF ; 255 + 3f28: 4e 5f subi r20, 0xFE ; 254 + 3f2a: 5f 4f sbci r21, 0xFF ; 255 } while (--ch); - 3f02: f1 e0 ldi r31, 0x01 ; 1 - 3f04: a0 38 cpi r26, 0x80 ; 128 - 3f06: bf 07 cpc r27, r31 - 3f08: 49 f7 brne .-46 ; 0x3edc + 3f2c: f1 e0 ldi r31, 0x01 ; 1 + 3f2e: a0 38 cpi r26, 0x80 ; 128 + 3f30: bf 07 cpc r27, r31 + 3f32: 51 f7 brne .-44 ; 0x3f08 // Write from programming buffer - boot_page_write((uint16_t)(void*)address); - 3f0a: e0 91 00 02 lds r30, 0x0200 - 3f0e: f0 91 01 02 lds r31, 0x0201 - 3f12: e0 92 57 00 sts 0x0057, r14 - 3f16: e8 95 spm + __boot_page_write_short((uint16_t)(void*)address); + 3f34: e0 91 00 02 lds r30, 0x0200 + 3f38: f0 91 01 02 lds r31, 0x0201 + 3f3c: e7 be out 0x37, r14 ; 55 + 3f3e: e8 95 spm boot_spm_busy_wait(); - 3f18: 07 b6 in r0, 0x37 ; 55 - 3f1a: 00 fc sbrc r0, 0 - 3f1c: fd cf rjmp .-6 ; 0x3f18 + 3f40: 07 b6 in r0, 0x37 ; 55 + 3f42: 00 fc sbrc r0, 0 + 3f44: fd cf rjmp .-6 ; 0x3f40 #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 3f1e: f0 92 57 00 sts 0x0057, r15 - 3f22: e8 95 spm - 3f24: 27 c0 rjmp .+78 ; 0x3f74 + 3f46: f7 be out 0x37, r15 ; 55 + 3f48: e8 95 spm + 3f4a: 27 c0 rjmp .+78 ; 0x3f9a #endif } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { - 3f26: 84 37 cpi r24, 0x74 ; 116 - 3f28: b9 f4 brne .+46 ; 0x3f58 + 3f4c: 84 37 cpi r24, 0x74 ; 116 + 3f4e: b9 f4 brne .+46 ; 0x3f7e // READ PAGE - we only read flash getLen(); - 3f2a: 4a d0 rcall .+148 ; 0x3fc0 + 3f50: 37 d0 rcall .+110 ; 0x3fc0 verifySpace(); - 3f2c: 59 d0 rcall .+178 ; 0x3fe0 - else ch = pgm_read_byte_near(address); + 3f52: 46 d0 rcall .+140 ; 0x3fe0 + putch(result); address++; - putch(ch); - } while (--length); + } + while (--length); #else do putch(pgm_read_byte_near(address++)); - 3f2e: e0 91 00 02 lds r30, 0x0200 - 3f32: f0 91 01 02 lds r31, 0x0201 - 3f36: 31 96 adiw r30, 0x01 ; 1 - 3f38: f0 93 01 02 sts 0x0201, r31 - 3f3c: e0 93 00 02 sts 0x0200, r30 - 3f40: 31 97 sbiw r30, 0x01 ; 1 - 3f42: e4 91 lpm r30, Z+ - 3f44: 8e 2f mov r24, r30 - 3f46: 19 d0 rcall .+50 ; 0x3f7a + 3f54: e0 91 00 02 lds r30, 0x0200 + 3f58: f0 91 01 02 lds r31, 0x0201 + 3f5c: 31 96 adiw r30, 0x01 ; 1 + 3f5e: f0 93 01 02 sts 0x0201, r31 + 3f62: e0 93 00 02 sts 0x0200, r30 + 3f66: 31 97 sbiw r30, 0x01 ; 1 + 3f68: e4 91 lpm r30, Z+ + 3f6a: 8e 2f mov r24, r30 + 3f6c: 19 d0 rcall .+50 ; 0x3fa0 while (--length); - 3f48: 80 91 02 02 lds r24, 0x0202 - 3f4c: 81 50 subi r24, 0x01 ; 1 - 3f4e: 80 93 02 02 sts 0x0202, r24 - 3f52: 88 23 and r24, r24 - 3f54: 61 f7 brne .-40 ; 0x3f2e - 3f56: 0e c0 rjmp .+28 ; 0x3f74 + 3f6e: 80 91 02 02 lds r24, 0x0202 + 3f72: 81 50 subi r24, 0x01 ; 1 + 3f74: 80 93 02 02 sts 0x0202, r24 + 3f78: 88 23 and r24, r24 + 3f7a: 61 f7 brne .-40 ; 0x3f54 + 3f7c: 0e c0 rjmp .+28 ; 0x3f9a +#endif #endif } /* Get device signature bytes */ else if(ch == STK_READ_SIGN) { - 3f58: 85 37 cpi r24, 0x75 ; 117 - 3f5a: 39 f4 brne .+14 ; 0x3f6a + 3f7e: 85 37 cpi r24, 0x75 ; 117 + 3f80: 39 f4 brne .+14 ; 0x3f90 // READ SIGN - return what Avrdude wants to hear verifySpace(); - 3f5c: 41 d0 rcall .+130 ; 0x3fe0 + 3f82: 2e d0 rcall .+92 ; 0x3fe0 putch(SIGNATURE_0); - 3f5e: 8e e1 ldi r24, 0x1E ; 30 - 3f60: 0c d0 rcall .+24 ; 0x3f7a + 3f84: 8e e1 ldi r24, 0x1E ; 30 + 3f86: 0c d0 rcall .+24 ; 0x3fa0 putch(SIGNATURE_1); - 3f62: 84 e9 ldi r24, 0x94 ; 148 - 3f64: 0a d0 rcall .+20 ; 0x3f7a + 3f88: 84 e9 ldi r24, 0x94 ; 148 + 3f8a: 0a d0 rcall .+20 ; 0x3fa0 putch(SIGNATURE_2); - 3f66: 86 e0 ldi r24, 0x06 ; 6 - 3f68: 96 cf rjmp .-212 ; 0x3e96 + 3f8c: 86 e0 ldi r24, 0x06 ; 6 + 3f8e: 8b cf rjmp .-234 ; 0x3ea6 } else if (ch == 'Q') { - 3f6a: 81 35 cpi r24, 0x51 ; 81 - 3f6c: 11 f4 brne .+4 ; 0x3f72 + 3f90: 81 35 cpi r24, 0x51 ; 81 + 3f92: 11 f4 brne .+4 ; 0x3f98 // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); - 3f6e: 88 e0 ldi r24, 0x08 ; 8 - 3f70: 2c d0 rcall .+88 ; 0x3fca + 3f94: 88 e0 ldi r24, 0x08 ; 8 + 3f96: 19 d0 rcall .+50 ; 0x3fca verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 3f72: 36 d0 rcall .+108 ; 0x3fe0 + 3f98: 23 d0 rcall .+70 ; 0x3fe0 } putch(STK_OK); - 3f74: 80 e1 ldi r24, 0x10 ; 16 - 3f76: 01 d0 rcall .+2 ; 0x3f7a - 3f78: 63 cf rjmp .-314 ; 0x3e40 + 3f9a: 80 e1 ldi r24, 0x10 ; 16 + 3f9c: 01 d0 rcall .+2 ; 0x3fa0 + 3f9e: 5c cf rjmp .-328 ; 0x3e58 + +00003fa0 : + } +} -00003f7a : void putch(char ch) { + 3fa0: 98 2f mov r25, r24 #ifndef SOFT_UART while (!(UCSR0A & _BV(UDRE0))); + 3fa2: 80 91 c0 00 lds r24, 0x00C0 + 3fa6: 85 ff sbrs r24, 5 + 3fa8: fc cf rjmp .-8 ; 0x3fa2 UDR0 = ch; -#else - __asm__ __volatile__ ( - 3f7a: 2a e0 ldi r18, 0x0A ; 10 - 3f7c: 30 e0 ldi r19, 0x00 ; 0 - 3f7e: 80 95 com r24 - 3f80: 08 94 sec - 3f82: 10 f4 brcc .+4 ; 0x3f88 - 3f84: 59 98 cbi 0x0b, 1 ; 11 - 3f86: 02 c0 rjmp .+4 ; 0x3f8c - 3f88: 59 9a sbi 0x0b, 1 ; 11 - 3f8a: 00 00 nop - 3f8c: 15 d0 rcall .+42 ; 0x3fb8 - 3f8e: 14 d0 rcall .+40 ; 0x3fb8 - 3f90: 86 95 lsr r24 - 3f92: 2a 95 dec r18 - 3f94: b1 f7 brne .-20 ; 0x3f82 + 3faa: 90 93 c6 00 sts 0x00C6, r25 [uartBit] "I" (UART_TX_BIT) : "r25" ); #endif } - 3f96: 08 95 ret + 3fae: 08 95 ret -00003f98 : +00003fb0 : return getch(); } // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 3f98: a8 95 wdr -#ifdef LED_DATA_FLASH + 3fb0: a8 95 wdr + [uartBit] "I" (UART_RX_BIT) + : + "r25" +); +#else + while(!(UCSR0A & _BV(RXC0))); + 3fb2: 80 91 c0 00 lds r24, 0x00C0 + 3fb6: 87 ff sbrs r24, 7 + 3fb8: fc cf rjmp .-8 ; 0x3fb2 + ch = UDR0; + 3fba: 80 91 c6 00 lds r24, 0x00C6 LED_PIN |= _BV(LED); +#endif #endif return ch; } - 3f9a: 29 e0 ldi r18, 0x09 ; 9 - 3f9c: 30 e0 ldi r19, 0x00 ; 0 - 3f9e: 48 99 sbic 0x09, 0 ; 9 - 3fa0: fe cf rjmp .-4 ; 0x3f9e - 3fa2: 0a d0 rcall .+20 ; 0x3fb8 - 3fa4: 09 d0 rcall .+18 ; 0x3fb8 - 3fa6: 08 d0 rcall .+16 ; 0x3fb8 - 3fa8: 88 94 clc - 3faa: 48 99 sbic 0x09, 0 ; 9 - 3fac: 08 94 sec - 3fae: 2a 95 dec r18 - 3fb0: 11 f0 breq .+4 ; 0x3fb6 - 3fb2: 87 95 ror r24 - 3fb4: f7 cf rjmp .-18 ; 0x3fa4 - 3fb6: 08 95 ret - -00003fb8 : -#if UART_B_VALUE > 255 -#error Baud rate too slow for soft UART -#endif - -void uartDelay() { - __asm__ __volatile__ ( - 3fb8: 98 e0 ldi r25, 0x08 ; 8 - 3fba: 9a 95 dec r25 - 3fbc: f1 f7 brne .-4 ; 0x3fba 3fbe: 08 95 ret 00003fc0 : @@ -462,13 +483,13 @@ void uartDelay() { uint8_t getLen() { getch(); - 3fc0: eb df rcall .-42 ; 0x3f98 + 3fc0: f7 df rcall .-18 ; 0x3fb0 length = getch(); - 3fc2: ea df rcall .-44 ; 0x3f98 + 3fc2: f6 df rcall .-20 ; 0x3fb0 3fc4: 80 93 02 02 sts 0x0202, r24 return getch(); } - 3fc8: e7 cf rjmp .-50 ; 0x3f98 + 3fc8: f3 cf rjmp .-26 ; 0x3fb0 00003fca : "wdr\n" @@ -504,14 +525,16 @@ void appStart() { void verifySpace() { if (getch() != CRC_EOP) appStart(); - 3fe0: db df rcall .-74 ; 0x3f98 + 3fe0: e7 df rcall .-50 ; 0x3fb0 3fe2: 80 32 cpi r24, 0x20 ; 32 3fe4: 09 f0 breq .+2 ; 0x3fe8 3fe6: f7 df rcall .-18 ; 0x3fd6 putch(STK_INSYNC); 3fe8: 84 e1 ldi r24, 0x14 ; 20 } - 3fea: c7 cf rjmp .-114 ; 0x3f7a + 3fea: da cf rjmp .-76 ; 0x3fa0 + +00003fec : ::[count] "M" (UART_B_VALUE) ); } @@ -520,12 +543,10 @@ void verifySpace() { void getNch(uint8_t count) { 3fec: 1f 93 push r17 3fee: 18 2f mov r17, r24 - -00003ff0 : do getch(); while (--count); - 3ff0: d3 df rcall .-90 ; 0x3f98 + 3ff0: df df rcall .-66 ; 0x3fb0 3ff2: 11 50 subi r17, 0x01 ; 1 - 3ff4: e9 f7 brne .-6 ; 0x3ff0 + 3ff4: e9 f7 brne .-6 ; 0x3ff0 verifySpace(); 3ff6: f4 df rcall .-24 ; 0x3fe0 } diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_luminet.hex b/hardware/arduino/bootloaders/optiboot/optiboot_luminet.hex index 0e5112466..3ad3c0a7a 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_luminet.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_luminet.hex @@ -1,42 +1,42 @@ -:101D000085E08EBD84B714BE81FF27D18DE021D13F -:101D1000D49AD29A86E023EC3FEF91E03DBD2CBDF2 -:101D20009BB9589BFECFCC9AA8958150B9F7CC248B -:101D3000C39485E0E82E0FE7D02E1EECF12EF0D0F4 -:101D4000813421F481E014D183E024C0823411F481 -:101D500084E103C0853419F485E00AD1CFC085350C -:101D6000A1F4DED0082F10E01093010200930002CE -:101D7000D7D090E0982F8827802B912B880F991F20 -:101D80009093010280930002B8C0863529F484E064 -:101D9000EFD080E0B6D0B2C0843609F06EC0D4D0A7 -:101DA000E0910002F091010283E080935700E895F2 -:101DB000C0E0D1E0B5D08993809102028150809338 -:101DC00002028823B9F7CED007B600FCFDCF809180 -:101DD000000290910102892B41F580910001209130 -:101DE000010130E0322F222790E0282B392B30934D -:101DF00005022093040240910A0180910B0190E0BA -:101E0000982F882750E0842B952B9093070280937E -:101E100006022450304020930A01232F33272093B9 -:101E20000B01D0920001F09201014091000250910B -:101E30000102A0E0B1E02C9130E011968C91119755 -:101E400090E0982F8827822B932B1296FA010C0191 -:101E5000C0925700E89511244E5F5F4FF1E0A03427 -:101E6000BF0749F7E0910002F0910102E0925700AC -:101E7000E89507B600FCFDCF41C0843789F564D0F2 -:101E800071D0E0910002F0910102309719F4209195 -:101E9000040213C0E130F10519F4209105020DC0D0 -:101EA000EA30F10519F42091060207C0EB30F10584 -:101EB00019F42091070201C02491809100029091B1 -:101EC000010201969093010280930002822F19D0A3 -:101ED00080910202815080930202882391F60EC005 -:101EE000853739F43FD08EE10CD083E90AD08CE0FD -:101EF00051CF813511F488E02CD034D080E101D06D -:101F00001ECF2AE030E08095089410F4DA9802C0E1 -:101F1000DA9A000015D014D086952A95B1F7089565 -:101F2000A89529E030E0CB99FECF0AD009D008D09F -:101F30008894CB9908942A9511F08795F7CF089546 -:101F40009EE09A95F1F70895EBDFEADF80930202B5 -:101F5000E7CF98E191BD81BD089580E0FADFE5E02B -:101F6000FF270994DDDF803209F0F7DF84E1C9CF74 -:101F70001F93182FD5DF1150E9F7F4DF1F91089553 +:101D0000112484B714BE81FF22D185E08EBD8EE000 +:101D10001AD1D49AD29A86E023EC3FEF91E03DBDF0 +:101D20002CBD9BB9589BFECFCC9AA8958150B9F792 +:101D3000DD24D39485E0C82E0FE7F02E1EECE12EB3 +:101D4000E9D0813421F481E00DD183E020C08234D8 +:101D500011F484E103C0853419F485E003D1C8C0CF +:101D6000853581F4D7D0082F10E0D4D090E0982F9B +:101D70008827802B912B880F991F90938101809346 +:101D80008001B5C0863529F484E0ECD080E0B3D082 +:101D9000AFC0843609F06BC0D1D0C0E0D1E0BAD07A +:101DA0008993809182018150809382018823B9F7C1 +:101DB000E0918001F091810183E087BFE895CCD06C +:101DC00007B600FCFDCF8091800190918101892BA5 +:101DD00041F5809100012091010130E0322F22274E +:101DE00090E0282B392B309385012093840140917A +:101DF00008018091090190E0982F882750E0842BFA +:101E0000952B909387018093860124503040209336 +:101E10000801232F332720930901F0920001E0925B +:101E200001014091800150918101A0E0B1E02C912D +:101E300030E011968C91119790E0982F8827822B93 +:101E4000932B1296FA010C01D7BEE89511244E5F30 +:101E50005F4FF1E0A034BF0751F7E0918001F091AE +:101E60008101C7BEE89507B600FCFDCF41C08437AD +:101E700089F564D071D0E0918001F09181013097B3 +:101E800019F42091840113C0E130F10519F4209177 +:101E900085010DC0E830F10519F42091860107C0D5 +:101EA000E930F10519F42091870101C02491809156 +:101EB000800190918101019690938101809380012E +:101EC000822F19D0809182018150809382018823D2 +:101ED00091F60EC0853739F43FD08EE10CD083E9FE +:101EE0000AD08CE054CF813511F488E02CD034D066 +:101EF00080E101D025CF2AE030E08095089410F4ED +:101F0000DA9802C0DA9A000015D014D086952A9586 +:101F1000B1F70895A89529E030E0CB99FECF0AD01B +:101F200009D008D08894CB9908942A9511F0879508 +:101F3000F7CF08959EE09A95F1F70895EBDFEADF79 +:101F400080938201E7CF98E191BD81BD089580E043 +:101F5000FADFE4E0FF270994DDDF803209F0F7DFE4 +:101F600084E1C9CF1F93182FD5DF1150E9F7F4DFB3 +:041F70001F91089520 :0400000300001D00DC :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_luminet.lst b/hardware/arduino/bootloaders/optiboot/optiboot_luminet.lst index 59468cb1f..737d2c549 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_luminet.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_luminet.lst @@ -3,602 +3,620 @@ optiboot_luminet.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .text 00000280 00001d00 00001d00 00000054 2**1 + 0 .text 00000274 00001d00 00001d00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .debug_aranges 00000028 00000000 00000000 000002d4 2**0 + 1 .debug_aranges 00000028 00000000 00000000 000002c8 2**0 CONTENTS, READONLY, DEBUGGING - 2 .debug_pubnames 00000078 00000000 00000000 000002fc 2**0 + 2 .debug_pubnames 00000078 00000000 00000000 000002f0 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_info 00000289 00000000 00000000 00000374 2**0 + 3 .debug_info 000002a4 00000000 00000000 00000368 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_abbrev 000001a1 00000000 00000000 000005fd 2**0 + 4 .debug_abbrev 000001ac 00000000 00000000 0000060c 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_line 00000435 00000000 00000000 0000079e 2**0 + 5 .debug_line 000004a9 00000000 00000000 000007b8 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_frame 000000a0 00000000 00000000 00000bd4 2**2 + 6 .debug_frame 000000a0 00000000 00000000 00000c64 2**2 CONTENTS, READONLY, DEBUGGING - 7 .debug_str 00000144 00000000 00000000 00000c74 2**0 + 7 .debug_str 00000150 00000000 00000000 00000d04 2**0 CONTENTS, READONLY, DEBUGGING - 8 .debug_loc 00000194 00000000 00000000 00000db8 2**0 + 8 .debug_loc 00000194 00000000 00000000 00000e54 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_ranges 00000088 00000000 00000000 00000f4c 2**0 + 9 .debug_ranges 00000088 00000000 00000000 00000fe8 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: 00001d00
    : -#ifdef VIRTUAL_BOOT_PARTITION -#define rstVect (*(uint16_t*)(0x204)) -#define wdtVect (*(uint16_t*)(0x206)) +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif + /* main program starts here */ int main(void) { - 1d00: 85 e0 ldi r24, 0x05 ; 5 - 1d02: 8e bd out 0x2e, r24 ; 46 - UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); - UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); + 1d00: 11 24 eor r1, r1 +#ifdef __AVR_ATmega8__ + SP=RAMEND; // This is done by hardware reset #endif // Adaboot no-wait mod ch = MCUSR; - 1d04: 84 b7 in r24, 0x34 ; 52 + 1d02: 84 b7 in r24, 0x34 ; 52 MCUSR = 0; - 1d06: 14 be out 0x34, r1 ; 52 + 1d04: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); - 1d08: 81 ff sbrs r24, 1 - 1d0a: 27 d1 rcall .+590 ; 0x1f5a + 1d06: 81 ff sbrs r24, 1 + 1d08: 22 d1 rcall .+580 ; 0x1f4e + +#if LED_START_FLASHES > 0 + // Set up Timer 1 for timeout counter + TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 + 1d0a: 85 e0 ldi r24, 0x05 ; 5 + 1d0c: 8e bd out 0x2e, r24 ; 46 + UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); +#endif +#endif // Set up watchdog to trigger after 500ms - watchdogConfig(WATCHDOG_500MS); - 1d0c: 8d e0 ldi r24, 0x0D ; 13 - 1d0e: 21 d1 rcall .+578 ; 0x1f52 + watchdogConfig(WATCHDOG_1S); + 1d0e: 8e e0 ldi r24, 0x0E ; 14 + 1d10: 1a d1 rcall .+564 ; 0x1f46 /* Set LED pin as output */ LED_DDR |= _BV(LED); - 1d10: d4 9a sbi 0x1a, 4 ; 26 + 1d12: d4 9a sbi 0x1a, 4 ; 26 #ifdef SOFT_UART /* Set TX pin as output */ UART_DDR |= _BV(UART_TX_BIT); - 1d12: d2 9a sbi 0x1a, 2 ; 26 - 1d14: 86 e0 ldi r24, 0x06 ; 6 + 1d14: d2 9a sbi 0x1a, 2 ; 26 + 1d16: 86 e0 ldi r24, 0x06 ; 6 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - 1d16: 23 ec ldi r18, 0xC3 ; 195 - 1d18: 3f ef ldi r19, 0xFF ; 255 + 1d18: 23 ec ldi r18, 0xC3 ; 195 + 1d1a: 3f ef ldi r19, 0xFF ; 255 TIFR1 = _BV(TOV1); - 1d1a: 91 e0 ldi r25, 0x01 ; 1 + 1d1c: 91 e0 ldi r25, 0x01 ; 1 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - 1d1c: 3d bd out 0x2d, r19 ; 45 - 1d1e: 2c bd out 0x2c, r18 ; 44 + 1d1e: 3d bd out 0x2d, r19 ; 45 + 1d20: 2c bd out 0x2c, r18 ; 44 TIFR1 = _BV(TOV1); - 1d20: 9b b9 out 0x0b, r25 ; 11 + 1d22: 9b b9 out 0x0b, r25 ; 11 while(!(TIFR1 & _BV(TOV1))); - 1d22: 58 9b sbis 0x0b, 0 ; 11 - 1d24: fe cf rjmp .-4 ; 0x1d22 + 1d24: 58 9b sbis 0x0b, 0 ; 11 + 1d26: fe cf rjmp .-4 ; 0x1d24 +#ifdef __AVR_ATmega8__ + LED_PORT ^= _BV(LED); +#else LED_PIN |= _BV(LED); - 1d26: cc 9a sbi 0x19, 4 ; 25 + 1d28: cc 9a sbi 0x19, 4 ; 25 return getch(); } // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 1d28: a8 95 wdr - TCNT1 = -(F_CPU/(1024*16)); - TIFR1 = _BV(TOV1); - while(!(TIFR1 & _BV(TOV1))); + 1d2a: a8 95 wdr + LED_PORT ^= _BV(LED); +#else LED_PIN |= _BV(LED); +#endif watchdogReset(); } while (--count); - 1d2a: 81 50 subi r24, 0x01 ; 1 - 1d2c: b9 f7 brne .-18 ; 0x1d1c + 1d2c: 81 50 subi r24, 0x01 ; 1 + 1d2e: b9 f7 brne .-18 ; 0x1d1e /* get character from UART */ ch = getch(); if(ch == STK_GET_PARAMETER) { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 1d2e: cc 24 eor r12, r12 - 1d30: c3 94 inc r12 - boot_page_fill((uint16_t)(void*)addrPtr,a); + 1d30: dd 24 eor r13, r13 + 1d32: d3 94 inc r13 + __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); // Write from programming buffer - boot_page_write((uint16_t)(void*)address); - 1d32: 85 e0 ldi r24, 0x05 ; 5 - 1d34: e8 2e mov r14, r24 + __boot_page_write_short((uint16_t)(void*)address); + 1d34: 85 e0 ldi r24, 0x05 ; 5 + 1d36: c8 2e mov r12, r24 vect -= 4; // Instruction is a relative jump (rjmp), so recalculate. - buff[10] = vect & 0xff; - buff[11] = vect >> 8; + buff[8] = vect & 0xff; + buff[9] = vect >> 8; // Add jump to bootloader at RESET vector buff[0] = 0x7f; - 1d36: 0f e7 ldi r16, 0x7F ; 127 - 1d38: d0 2e mov r13, r16 + 1d38: 0f e7 ldi r16, 0x7F ; 127 + 1d3a: f0 2e mov r15, r16 buff[1] = 0xce; // rjmp 0x1d00 instruction - 1d3a: 1e ec ldi r17, 0xCE ; 206 - 1d3c: f1 2e mov r15, r17 + 1d3c: 1e ec ldi r17, 0xCE ; 206 + 1d3e: e1 2e mov r14, r17 #endif /* Forever loop */ for (;;) { /* get character from UART */ ch = getch(); - 1d3e: f0 d0 rcall .+480 ; 0x1f20 + 1d40: e9 d0 rcall .+466 ; 0x1f14 if(ch == STK_GET_PARAMETER) { - 1d40: 81 34 cpi r24, 0x41 ; 65 - 1d42: 21 f4 brne .+8 ; 0x1d4c + 1d42: 81 34 cpi r24, 0x41 ; 65 + 1d44: 21 f4 brne .+8 ; 0x1d4e // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 1d44: 81 e0 ldi r24, 0x01 ; 1 - 1d46: 14 d1 rcall .+552 ; 0x1f70 + 1d46: 81 e0 ldi r24, 0x01 ; 1 + 1d48: 0d d1 rcall .+538 ; 0x1f64 putch(0x03); - 1d48: 83 e0 ldi r24, 0x03 ; 3 - 1d4a: 24 c0 rjmp .+72 ; 0x1d94 + 1d4a: 83 e0 ldi r24, 0x03 ; 3 + 1d4c: 20 c0 rjmp .+64 ; 0x1d8e } else if(ch == STK_SET_DEVICE) { - 1d4c: 82 34 cpi r24, 0x42 ; 66 - 1d4e: 11 f4 brne .+4 ; 0x1d54 + 1d4e: 82 34 cpi r24, 0x42 ; 66 + 1d50: 11 f4 brne .+4 ; 0x1d56 // SET DEVICE is ignored getNch(20); - 1d50: 84 e1 ldi r24, 0x14 ; 20 - 1d52: 03 c0 rjmp .+6 ; 0x1d5a + 1d52: 84 e1 ldi r24, 0x14 ; 20 + 1d54: 03 c0 rjmp .+6 ; 0x1d5c } else if(ch == STK_SET_DEVICE_EXT) { - 1d54: 85 34 cpi r24, 0x45 ; 69 - 1d56: 19 f4 brne .+6 ; 0x1d5e + 1d56: 85 34 cpi r24, 0x45 ; 69 + 1d58: 19 f4 brne .+6 ; 0x1d60 // SET DEVICE EXT is ignored getNch(5); - 1d58: 85 e0 ldi r24, 0x05 ; 5 - 1d5a: 0a d1 rcall .+532 ; 0x1f70 - 1d5c: cf c0 rjmp .+414 ; 0x1efc + 1d5a: 85 e0 ldi r24, 0x05 ; 5 + 1d5c: 03 d1 rcall .+518 ; 0x1f64 + 1d5e: c8 c0 rjmp .+400 ; 0x1ef0 } else if(ch == STK_LOAD_ADDRESS) { - 1d5e: 85 35 cpi r24, 0x55 ; 85 - 1d60: a1 f4 brne .+40 ; 0x1d8a + 1d60: 85 35 cpi r24, 0x55 ; 85 + 1d62: 81 f4 brne .+32 ; 0x1d84 // LOAD ADDRESS - address = getch(); - 1d62: de d0 rcall .+444 ; 0x1f20 - 1d64: 08 2f mov r16, r24 - 1d66: 10 e0 ldi r17, 0x00 ; 0 - 1d68: 10 93 01 02 sts 0x0201, r17 - 1d6c: 00 93 00 02 sts 0x0200, r16 - address = (address & 0xff) | (getch() << 8); - 1d70: d7 d0 rcall .+430 ; 0x1f20 - 1d72: 90 e0 ldi r25, 0x00 ; 0 - 1d74: 98 2f mov r25, r24 - 1d76: 88 27 eor r24, r24 - 1d78: 80 2b or r24, r16 - 1d7a: 91 2b or r25, r17 - address += address; // Convert from word address to byte address - 1d7c: 88 0f add r24, r24 - 1d7e: 99 1f adc r25, r25 - 1d80: 90 93 01 02 sts 0x0201, r25 - 1d84: 80 93 00 02 sts 0x0200, r24 - 1d88: b8 c0 rjmp .+368 ; 0x1efa + uint16_t newAddress; + newAddress = getch(); + 1d64: d7 d0 rcall .+430 ; 0x1f14 + newAddress = (newAddress & 0xff) | (getch() << 8); + 1d66: 08 2f mov r16, r24 + 1d68: 10 e0 ldi r17, 0x00 ; 0 + 1d6a: d4 d0 rcall .+424 ; 0x1f14 + 1d6c: 90 e0 ldi r25, 0x00 ; 0 + 1d6e: 98 2f mov r25, r24 + 1d70: 88 27 eor r24, r24 + 1d72: 80 2b or r24, r16 + 1d74: 91 2b or r25, r17 +#ifdef RAMPZ + // Transfer top bit to RAMPZ + RAMPZ = (newAddress & 0x8000) ? 1 : 0; +#endif + newAddress += newAddress; // Convert from word address to byte address + 1d76: 88 0f add r24, r24 + 1d78: 99 1f adc r25, r25 + address = newAddress; + 1d7a: 90 93 81 01 sts 0x0181, r25 + 1d7e: 80 93 80 01 sts 0x0180, r24 + 1d82: b5 c0 rjmp .+362 ; 0x1eee verifySpace(); } else if(ch == STK_UNIVERSAL) { - 1d8a: 86 35 cpi r24, 0x56 ; 86 - 1d8c: 29 f4 brne .+10 ; 0x1d98 + 1d84: 86 35 cpi r24, 0x56 ; 86 + 1d86: 29 f4 brne .+10 ; 0x1d92 // UNIVERSAL command is ignored getNch(4); - 1d8e: 84 e0 ldi r24, 0x04 ; 4 - 1d90: ef d0 rcall .+478 ; 0x1f70 + 1d88: 84 e0 ldi r24, 0x04 ; 4 + 1d8a: ec d0 rcall .+472 ; 0x1f64 putch(0x00); - 1d92: 80 e0 ldi r24, 0x00 ; 0 - 1d94: b6 d0 rcall .+364 ; 0x1f02 - 1d96: b2 c0 rjmp .+356 ; 0x1efc + 1d8c: 80 e0 ldi r24, 0x00 ; 0 + 1d8e: b3 d0 rcall .+358 ; 0x1ef6 + 1d90: af c0 rjmp .+350 ; 0x1ef0 } - /* Write memory, length is big endian and is in bytes */ + /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { - 1d98: 84 36 cpi r24, 0x64 ; 100 - 1d9a: 09 f0 breq .+2 ; 0x1d9e - 1d9c: 6e c0 rjmp .+220 ; 0x1e7a + 1d92: 84 36 cpi r24, 0x64 ; 100 + 1d94: 09 f0 breq .+2 ; 0x1d98 + 1d96: 6b c0 rjmp .+214 ; 0x1e6e // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t *bufPtr; uint16_t addrPtr; getLen(); - 1d9e: d4 d0 rcall .+424 ; 0x1f48 - - // Immediately start page erase - this will 4.5ms - boot_page_erase((uint16_t)(void*)address); - 1da0: e0 91 00 02 lds r30, 0x0200 - 1da4: f0 91 01 02 lds r31, 0x0201 - 1da8: 83 e0 ldi r24, 0x03 ; 3 - 1daa: 80 93 57 00 sts 0x0057, r24 - 1dae: e8 95 spm - 1db0: c0 e0 ldi r28, 0x00 ; 0 - 1db2: d1 e0 ldi r29, 0x01 ; 1 - + 1d98: d1 d0 rcall .+418 ; 0x1f3c + 1d9a: c0 e0 ldi r28, 0x00 ; 0 + 1d9c: d1 e0 ldi r29, 0x01 ; 1 + // If we are in RWW section, immediately start page erase + if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); - 1db4: b5 d0 rcall .+362 ; 0x1f20 - 1db6: 89 93 st Y+, r24 + 1d9e: ba d0 rcall .+372 ; 0x1f14 + 1da0: 89 93 st Y+, r24 while (--length); - 1db8: 80 91 02 02 lds r24, 0x0202 - 1dbc: 81 50 subi r24, 0x01 ; 1 - 1dbe: 80 93 02 02 sts 0x0202, r24 - 1dc2: 88 23 and r24, r24 - 1dc4: b9 f7 brne .-18 ; 0x1db4 + 1da2: 80 91 82 01 lds r24, 0x0182 + 1da6: 81 50 subi r24, 0x01 ; 1 + 1da8: 80 93 82 01 sts 0x0182, r24 + 1dac: 88 23 and r24, r24 + 1dae: b9 f7 brne .-18 ; 0x1d9e + + // If we are in NRWW section, page erase has to be delayed until now. + // Todo: Take RAMPZ into account + if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + 1db0: e0 91 80 01 lds r30, 0x0180 + 1db4: f0 91 81 01 lds r31, 0x0181 + 1db8: 83 e0 ldi r24, 0x03 ; 3 + 1dba: 87 bf out 0x37, r24 ; 55 + 1dbc: e8 95 spm // Read command terminator, start reply verifySpace(); - 1dc6: ce d0 rcall .+412 ; 0x1f64 + 1dbe: cc d0 rcall .+408 ; 0x1f58 // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); - 1dc8: 07 b6 in r0, 0x37 ; 55 - 1dca: 00 fc sbrc r0, 0 - 1dcc: fd cf rjmp .-6 ; 0x1dc8 + 1dc0: 07 b6 in r0, 0x37 ; 55 + 1dc2: 00 fc sbrc r0, 0 + 1dc4: fd cf rjmp .-6 ; 0x1dc0 #ifdef VIRTUAL_BOOT_PARTITION if ((uint16_t)(void*)address == 0) { - 1dce: 80 91 00 02 lds r24, 0x0200 - 1dd2: 90 91 01 02 lds r25, 0x0201 - 1dd6: 89 2b or r24, r25 - 1dd8: 41 f5 brne .+80 ; 0x1e2a + 1dc6: 80 91 80 01 lds r24, 0x0180 + 1dca: 90 91 81 01 lds r25, 0x0181 + 1dce: 89 2b or r24, r25 + 1dd0: 41 f5 brne .+80 ; 0x1e22 // This is the reset vector page. We need to live-patch the code so the // bootloader runs. // // Move RESET vector to WDT vector uint16_t vect = buff[0] | (buff[1]<<8); - 1dda: 80 91 00 01 lds r24, 0x0100 - 1dde: 20 91 01 01 lds r18, 0x0101 - 1de2: 30 e0 ldi r19, 0x00 ; 0 - 1de4: 32 2f mov r19, r18 - 1de6: 22 27 eor r18, r18 - 1de8: 90 e0 ldi r25, 0x00 ; 0 - 1dea: 28 2b or r18, r24 - 1dec: 39 2b or r19, r25 + 1dd2: 80 91 00 01 lds r24, 0x0100 + 1dd6: 20 91 01 01 lds r18, 0x0101 + 1dda: 30 e0 ldi r19, 0x00 ; 0 + 1ddc: 32 2f mov r19, r18 + 1dde: 22 27 eor r18, r18 + 1de0: 90 e0 ldi r25, 0x00 ; 0 + 1de2: 28 2b or r18, r24 + 1de4: 39 2b or r19, r25 rstVect = vect; - 1dee: 30 93 05 02 sts 0x0205, r19 - 1df2: 20 93 04 02 sts 0x0204, r18 - wdtVect = buff[10] | (buff[11]<<8); - 1df6: 40 91 0a 01 lds r20, 0x010A - 1dfa: 80 91 0b 01 lds r24, 0x010B - 1dfe: 90 e0 ldi r25, 0x00 ; 0 - 1e00: 98 2f mov r25, r24 - 1e02: 88 27 eor r24, r24 - 1e04: 50 e0 ldi r21, 0x00 ; 0 - 1e06: 84 2b or r24, r20 - 1e08: 95 2b or r25, r21 - 1e0a: 90 93 07 02 sts 0x0207, r25 - 1e0e: 80 93 06 02 sts 0x0206, r24 + 1de6: 30 93 85 01 sts 0x0185, r19 + 1dea: 20 93 84 01 sts 0x0184, r18 + wdtVect = buff[8] | (buff[9]<<8); + 1dee: 40 91 08 01 lds r20, 0x0108 + 1df2: 80 91 09 01 lds r24, 0x0109 + 1df6: 90 e0 ldi r25, 0x00 ; 0 + 1df8: 98 2f mov r25, r24 + 1dfa: 88 27 eor r24, r24 + 1dfc: 50 e0 ldi r21, 0x00 ; 0 + 1dfe: 84 2b or r24, r20 + 1e00: 95 2b or r25, r21 + 1e02: 90 93 87 01 sts 0x0187, r25 + 1e06: 80 93 86 01 sts 0x0186, r24 vect -= 4; // Instruction is a relative jump (rjmp), so recalculate. - 1e12: 24 50 subi r18, 0x04 ; 4 - 1e14: 30 40 sbci r19, 0x00 ; 0 - buff[10] = vect & 0xff; - 1e16: 20 93 0a 01 sts 0x010A, r18 - buff[11] = vect >> 8; - 1e1a: 23 2f mov r18, r19 - 1e1c: 33 27 eor r19, r19 - 1e1e: 20 93 0b 01 sts 0x010B, r18 + 1e0a: 24 50 subi r18, 0x04 ; 4 + 1e0c: 30 40 sbci r19, 0x00 ; 0 + buff[8] = vect & 0xff; + 1e0e: 20 93 08 01 sts 0x0108, r18 + buff[9] = vect >> 8; + 1e12: 23 2f mov r18, r19 + 1e14: 33 27 eor r19, r19 + 1e16: 20 93 09 01 sts 0x0109, r18 // Add jump to bootloader at RESET vector buff[0] = 0x7f; - 1e22: d0 92 00 01 sts 0x0100, r13 + 1e1a: f0 92 00 01 sts 0x0100, r15 buff[1] = 0xce; // rjmp 0x1d00 instruction - 1e26: f0 92 01 01 sts 0x0101, r15 + 1e1e: e0 92 01 01 sts 0x0101, r14 } #endif // Copy buffer into programming buffer bufPtr = buff; addrPtr = (uint16_t)(void*)address; - 1e2a: 40 91 00 02 lds r20, 0x0200 - 1e2e: 50 91 01 02 lds r21, 0x0201 - 1e32: a0 e0 ldi r26, 0x00 ; 0 - 1e34: b1 e0 ldi r27, 0x01 ; 1 + 1e22: 40 91 80 01 lds r20, 0x0180 + 1e26: 50 91 81 01 lds r21, 0x0181 + 1e2a: a0 e0 ldi r26, 0x00 ; 0 + 1e2c: b1 e0 ldi r27, 0x01 ; 1 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; - 1e36: 2c 91 ld r18, X - 1e38: 30 e0 ldi r19, 0x00 ; 0 + 1e2e: 2c 91 ld r18, X + 1e30: 30 e0 ldi r19, 0x00 ; 0 a |= (*bufPtr++) << 8; - 1e3a: 11 96 adiw r26, 0x01 ; 1 - 1e3c: 8c 91 ld r24, X - 1e3e: 11 97 sbiw r26, 0x01 ; 1 - 1e40: 90 e0 ldi r25, 0x00 ; 0 - 1e42: 98 2f mov r25, r24 - 1e44: 88 27 eor r24, r24 - 1e46: 82 2b or r24, r18 - 1e48: 93 2b or r25, r19 -#ifdef VIRTUAL_BOOT_PARTITION -#define rstVect (*(uint16_t*)(0x204)) -#define wdtVect (*(uint16_t*)(0x206)) + 1e32: 11 96 adiw r26, 0x01 ; 1 + 1e34: 8c 91 ld r24, X + 1e36: 11 97 sbiw r26, 0x01 ; 1 + 1e38: 90 e0 ldi r25, 0x00 ; 0 + 1e3a: 98 2f mov r25, r24 + 1e3c: 88 27 eor r24, r24 + 1e3e: 82 2b or r24, r18 + 1e40: 93 2b or r25, r19 +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif + /* main program starts here */ int main(void) { - 1e4a: 12 96 adiw r26, 0x02 ; 2 + 1e42: 12 96 adiw r26, 0x02 ; 2 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; a |= (*bufPtr++) << 8; - boot_page_fill((uint16_t)(void*)addrPtr,a); - 1e4c: fa 01 movw r30, r20 - 1e4e: 0c 01 movw r0, r24 - 1e50: c0 92 57 00 sts 0x0057, r12 - 1e54: e8 95 spm - 1e56: 11 24 eor r1, r1 + __boot_page_fill_short((uint16_t)(void*)addrPtr,a); + 1e44: fa 01 movw r30, r20 + 1e46: 0c 01 movw r0, r24 + 1e48: d7 be out 0x37, r13 ; 55 + 1e4a: e8 95 spm + 1e4c: 11 24 eor r1, r1 addrPtr += 2; - 1e58: 4e 5f subi r20, 0xFE ; 254 - 1e5a: 5f 4f sbci r21, 0xFF ; 255 + 1e4e: 4e 5f subi r20, 0xFE ; 254 + 1e50: 5f 4f sbci r21, 0xFF ; 255 } while (--ch); - 1e5c: f1 e0 ldi r31, 0x01 ; 1 - 1e5e: a0 34 cpi r26, 0x40 ; 64 - 1e60: bf 07 cpc r27, r31 - 1e62: 49 f7 brne .-46 ; 0x1e36 + 1e52: f1 e0 ldi r31, 0x01 ; 1 + 1e54: a0 34 cpi r26, 0x40 ; 64 + 1e56: bf 07 cpc r27, r31 + 1e58: 51 f7 brne .-44 ; 0x1e2e // Write from programming buffer - boot_page_write((uint16_t)(void*)address); - 1e64: e0 91 00 02 lds r30, 0x0200 - 1e68: f0 91 01 02 lds r31, 0x0201 - 1e6c: e0 92 57 00 sts 0x0057, r14 - 1e70: e8 95 spm + __boot_page_write_short((uint16_t)(void*)address); + 1e5a: e0 91 80 01 lds r30, 0x0180 + 1e5e: f0 91 81 01 lds r31, 0x0181 + 1e62: c7 be out 0x37, r12 ; 55 + 1e64: e8 95 spm boot_spm_busy_wait(); - 1e72: 07 b6 in r0, 0x37 ; 55 - 1e74: 00 fc sbrc r0, 0 - 1e76: fd cf rjmp .-6 ; 0x1e72 - 1e78: 41 c0 rjmp .+130 ; 0x1efc + 1e66: 07 b6 in r0, 0x37 ; 55 + 1e68: 00 fc sbrc r0, 0 + 1e6a: fd cf rjmp .-6 ; 0x1e66 + 1e6c: 41 c0 rjmp .+130 ; 0x1ef0 boot_rww_enable(); #endif } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { - 1e7a: 84 37 cpi r24, 0x74 ; 116 - 1e7c: 89 f5 brne .+98 ; 0x1ee0 + 1e6e: 84 37 cpi r24, 0x74 ; 116 + 1e70: 89 f5 brne .+98 ; 0x1ed4 // READ PAGE - we only read flash getLen(); - 1e7e: 64 d0 rcall .+200 ; 0x1f48 + 1e72: 64 d0 rcall .+200 ; 0x1f3c verifySpace(); - 1e80: 71 d0 rcall .+226 ; 0x1f64 + 1e74: 71 d0 rcall .+226 ; 0x1f58 #ifdef VIRTUAL_BOOT_PARTITION do { // Undo vector patch in bottom page so verify passes if (address == 0) ch=rstVect & 0xff; - 1e82: e0 91 00 02 lds r30, 0x0200 - 1e86: f0 91 01 02 lds r31, 0x0201 - 1e8a: 30 97 sbiw r30, 0x00 ; 0 - 1e8c: 19 f4 brne .+6 ; 0x1e94 - 1e8e: 20 91 04 02 lds r18, 0x0204 - 1e92: 13 c0 rjmp .+38 ; 0x1eba + 1e76: e0 91 80 01 lds r30, 0x0180 + 1e7a: f0 91 81 01 lds r31, 0x0181 + 1e7e: 30 97 sbiw r30, 0x00 ; 0 + 1e80: 19 f4 brne .+6 ; 0x1e88 + 1e82: 20 91 84 01 lds r18, 0x0184 + 1e86: 13 c0 rjmp .+38 ; 0x1eae else if (address == 1) ch=rstVect >> 8; - 1e94: e1 30 cpi r30, 0x01 ; 1 + 1e88: e1 30 cpi r30, 0x01 ; 1 + 1e8a: f1 05 cpc r31, r1 + 1e8c: 19 f4 brne .+6 ; 0x1e94 + 1e8e: 20 91 85 01 lds r18, 0x0185 + 1e92: 0d c0 rjmp .+26 ; 0x1eae + else if (address == 8) ch=wdtVect & 0xff; + 1e94: e8 30 cpi r30, 0x08 ; 8 1e96: f1 05 cpc r31, r1 1e98: 19 f4 brne .+6 ; 0x1ea0 - 1e9a: 20 91 05 02 lds r18, 0x0205 - 1e9e: 0d c0 rjmp .+26 ; 0x1eba - else if (address == 10) ch=wdtVect & 0xff; - 1ea0: ea 30 cpi r30, 0x0A ; 10 + 1e9a: 20 91 86 01 lds r18, 0x0186 + 1e9e: 07 c0 rjmp .+14 ; 0x1eae + else if (address == 9) ch=wdtVect >> 8; + 1ea0: e9 30 cpi r30, 0x09 ; 9 1ea2: f1 05 cpc r31, r1 1ea4: 19 f4 brne .+6 ; 0x1eac - 1ea6: 20 91 06 02 lds r18, 0x0206 - 1eaa: 07 c0 rjmp .+14 ; 0x1eba - else if (address == 11) ch=wdtVect >> 8; - 1eac: eb 30 cpi r30, 0x0B ; 11 - 1eae: f1 05 cpc r31, r1 - 1eb0: 19 f4 brne .+6 ; 0x1eb8 - 1eb2: 20 91 07 02 lds r18, 0x0207 - 1eb6: 01 c0 rjmp .+2 ; 0x1eba + 1ea6: 20 91 87 01 lds r18, 0x0187 + 1eaa: 01 c0 rjmp .+2 ; 0x1eae else ch = pgm_read_byte_near(address); - 1eb8: 24 91 lpm r18, Z+ + 1eac: 24 91 lpm r18, Z+ address++; - 1eba: 80 91 00 02 lds r24, 0x0200 - 1ebe: 90 91 01 02 lds r25, 0x0201 - 1ec2: 01 96 adiw r24, 0x01 ; 1 - 1ec4: 90 93 01 02 sts 0x0201, r25 - 1ec8: 80 93 00 02 sts 0x0200, r24 + 1eae: 80 91 80 01 lds r24, 0x0180 + 1eb2: 90 91 81 01 lds r25, 0x0181 + 1eb6: 01 96 adiw r24, 0x01 ; 1 + 1eb8: 90 93 81 01 sts 0x0181, r25 + 1ebc: 80 93 80 01 sts 0x0180, r24 putch(ch); - 1ecc: 82 2f mov r24, r18 - 1ece: 19 d0 rcall .+50 ; 0x1f02 + 1ec0: 82 2f mov r24, r18 + 1ec2: 19 d0 rcall .+50 ; 0x1ef6 } while (--length); - 1ed0: 80 91 02 02 lds r24, 0x0202 - 1ed4: 81 50 subi r24, 0x01 ; 1 - 1ed6: 80 93 02 02 sts 0x0202, r24 - 1eda: 88 23 and r24, r24 - 1edc: 91 f6 brne .-92 ; 0x1e82 - 1ede: 0e c0 rjmp .+28 ; 0x1efc - while (--length); + 1ec4: 80 91 82 01 lds r24, 0x0182 + 1ec8: 81 50 subi r24, 0x01 ; 1 + 1eca: 80 93 82 01 sts 0x0182, r24 + 1ece: 88 23 and r24, r24 + 1ed0: 91 f6 brne .-92 ; 0x1e76 + 1ed2: 0e c0 rjmp .+28 ; 0x1ef0 +#endif #endif } /* Get device signature bytes */ else if(ch == STK_READ_SIGN) { - 1ee0: 85 37 cpi r24, 0x75 ; 117 - 1ee2: 39 f4 brne .+14 ; 0x1ef2 + 1ed4: 85 37 cpi r24, 0x75 ; 117 + 1ed6: 39 f4 brne .+14 ; 0x1ee6 // READ SIGN - return what Avrdude wants to hear verifySpace(); - 1ee4: 3f d0 rcall .+126 ; 0x1f64 + 1ed8: 3f d0 rcall .+126 ; 0x1f58 putch(SIGNATURE_0); - 1ee6: 8e e1 ldi r24, 0x1E ; 30 - 1ee8: 0c d0 rcall .+24 ; 0x1f02 + 1eda: 8e e1 ldi r24, 0x1E ; 30 + 1edc: 0c d0 rcall .+24 ; 0x1ef6 putch(SIGNATURE_1); - 1eea: 83 e9 ldi r24, 0x93 ; 147 - 1eec: 0a d0 rcall .+20 ; 0x1f02 + 1ede: 83 e9 ldi r24, 0x93 ; 147 + 1ee0: 0a d0 rcall .+20 ; 0x1ef6 putch(SIGNATURE_2); - 1eee: 8c e0 ldi r24, 0x0C ; 12 - 1ef0: 51 cf rjmp .-350 ; 0x1d94 + 1ee2: 8c e0 ldi r24, 0x0C ; 12 + 1ee4: 54 cf rjmp .-344 ; 0x1d8e } else if (ch == 'Q') { - 1ef2: 81 35 cpi r24, 0x51 ; 81 - 1ef4: 11 f4 brne .+4 ; 0x1efa + 1ee6: 81 35 cpi r24, 0x51 ; 81 + 1ee8: 11 f4 brne .+4 ; 0x1eee // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); - 1ef6: 88 e0 ldi r24, 0x08 ; 8 - 1ef8: 2c d0 rcall .+88 ; 0x1f52 + 1eea: 88 e0 ldi r24, 0x08 ; 8 + 1eec: 2c d0 rcall .+88 ; 0x1f46 verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 1efa: 34 d0 rcall .+104 ; 0x1f64 + 1eee: 34 d0 rcall .+104 ; 0x1f58 } putch(STK_OK); - 1efc: 80 e1 ldi r24, 0x10 ; 16 - 1efe: 01 d0 rcall .+2 ; 0x1f02 - 1f00: 1e cf rjmp .-452 ; 0x1d3e + 1ef0: 80 e1 ldi r24, 0x10 ; 16 + 1ef2: 01 d0 rcall .+2 ; 0x1ef6 + 1ef4: 25 cf rjmp .-438 ; 0x1d40 -00001f02 : +00001ef6 : void putch(char ch) { #ifndef SOFT_UART while (!(UCSR0A & _BV(UDRE0))); UDR0 = ch; #else __asm__ __volatile__ ( - 1f02: 2a e0 ldi r18, 0x0A ; 10 - 1f04: 30 e0 ldi r19, 0x00 ; 0 - 1f06: 80 95 com r24 - 1f08: 08 94 sec - 1f0a: 10 f4 brcc .+4 ; 0x1f10 - 1f0c: da 98 cbi 0x1b, 2 ; 27 - 1f0e: 02 c0 rjmp .+4 ; 0x1f14 - 1f10: da 9a sbi 0x1b, 2 ; 27 - 1f12: 00 00 nop - 1f14: 15 d0 rcall .+42 ; 0x1f40 - 1f16: 14 d0 rcall .+40 ; 0x1f40 - 1f18: 86 95 lsr r24 - 1f1a: 2a 95 dec r18 - 1f1c: b1 f7 brne .-20 ; 0x1f0a + 1ef6: 2a e0 ldi r18, 0x0A ; 10 + 1ef8: 30 e0 ldi r19, 0x00 ; 0 + 1efa: 80 95 com r24 + 1efc: 08 94 sec + 1efe: 10 f4 brcc .+4 ; 0x1f04 + 1f00: da 98 cbi 0x1b, 2 ; 27 + 1f02: 02 c0 rjmp .+4 ; 0x1f08 + 1f04: da 9a sbi 0x1b, 2 ; 27 + 1f06: 00 00 nop + 1f08: 15 d0 rcall .+42 ; 0x1f34 + 1f0a: 14 d0 rcall .+40 ; 0x1f34 + 1f0c: 86 95 lsr r24 + 1f0e: 2a 95 dec r18 + 1f10: b1 f7 brne .-20 ; 0x1efe [uartBit] "I" (UART_TX_BIT) : "r25" ); #endif } - 1f1e: 08 95 ret + 1f12: 08 95 ret -00001f20 : +00001f14 : return getch(); } // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 1f20: a8 95 wdr -#ifdef LED_DATA_FLASH + 1f14: a8 95 wdr LED_PIN |= _BV(LED); +#endif #endif return ch; } - 1f22: 29 e0 ldi r18, 0x09 ; 9 - 1f24: 30 e0 ldi r19, 0x00 ; 0 + 1f16: 29 e0 ldi r18, 0x09 ; 9 + 1f18: 30 e0 ldi r19, 0x00 ; 0 + 1f1a: cb 99 sbic 0x19, 3 ; 25 + 1f1c: fe cf rjmp .-4 ; 0x1f1a + 1f1e: 0a d0 rcall .+20 ; 0x1f34 + 1f20: 09 d0 rcall .+18 ; 0x1f34 + 1f22: 08 d0 rcall .+16 ; 0x1f34 + 1f24: 88 94 clc 1f26: cb 99 sbic 0x19, 3 ; 25 - 1f28: fe cf rjmp .-4 ; 0x1f26 - 1f2a: 0a d0 rcall .+20 ; 0x1f40 - 1f2c: 09 d0 rcall .+18 ; 0x1f40 - 1f2e: 08 d0 rcall .+16 ; 0x1f40 - 1f30: 88 94 clc - 1f32: cb 99 sbic 0x19, 3 ; 25 - 1f34: 08 94 sec - 1f36: 2a 95 dec r18 - 1f38: 11 f0 breq .+4 ; 0x1f3e - 1f3a: 87 95 ror r24 - 1f3c: f7 cf rjmp .-18 ; 0x1f2c - 1f3e: 08 95 ret + 1f28: 08 94 sec + 1f2a: 2a 95 dec r18 + 1f2c: 11 f0 breq .+4 ; 0x1f32 + 1f2e: 87 95 ror r24 + 1f30: f7 cf rjmp .-18 ; 0x1f20 + 1f32: 08 95 ret -00001f40 : +00001f34 : #if UART_B_VALUE > 255 #error Baud rate too slow for soft UART #endif void uartDelay() { __asm__ __volatile__ ( - 1f40: 9e e0 ldi r25, 0x0E ; 14 - 1f42: 9a 95 dec r25 - 1f44: f1 f7 brne .-4 ; 0x1f42 - 1f46: 08 95 ret + 1f34: 9e e0 ldi r25, 0x0E ; 14 + 1f36: 9a 95 dec r25 + 1f38: f1 f7 brne .-4 ; 0x1f36 + 1f3a: 08 95 ret -00001f48 : +00001f3c : } while (--count); } #endif uint8_t getLen() { getch(); - 1f48: eb df rcall .-42 ; 0x1f20 + 1f3c: eb df rcall .-42 ; 0x1f14 length = getch(); - 1f4a: ea df rcall .-44 ; 0x1f20 - 1f4c: 80 93 02 02 sts 0x0202, r24 + 1f3e: ea df rcall .-44 ; 0x1f14 + 1f40: 80 93 82 01 sts 0x0182, r24 return getch(); } - 1f50: e7 cf rjmp .-50 ; 0x1f20 + 1f44: e7 cf rjmp .-50 ; 0x1f14 -00001f52 : +00001f46 : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 1f52: 98 e1 ldi r25, 0x18 ; 24 - 1f54: 91 bd out 0x21, r25 ; 33 + 1f46: 98 e1 ldi r25, 0x18 ; 24 + 1f48: 91 bd out 0x21, r25 ; 33 WDTCSR = x; - 1f56: 81 bd out 0x21, r24 ; 33 + 1f4a: 81 bd out 0x21, r24 ; 33 } - 1f58: 08 95 ret + 1f4c: 08 95 ret -00001f5a : +00001f4e : void appStart() { watchdogConfig(WATCHDOG_OFF); - 1f5a: 80 e0 ldi r24, 0x00 ; 0 - 1f5c: fa df rcall .-12 ; 0x1f52 + 1f4e: 80 e0 ldi r24, 0x00 ; 0 + 1f50: fa df rcall .-12 ; 0x1f46 __asm__ __volatile__ ( - 1f5e: e5 e0 ldi r30, 0x05 ; 5 - 1f60: ff 27 eor r31, r31 - 1f62: 09 94 ijmp + 1f52: e4 e0 ldi r30, 0x04 ; 4 + 1f54: ff 27 eor r31, r31 + 1f56: 09 94 ijmp -00001f64 : +00001f58 : do getch(); while (--count); verifySpace(); } void verifySpace() { if (getch() != CRC_EOP) appStart(); - 1f64: dd df rcall .-70 ; 0x1f20 - 1f66: 80 32 cpi r24, 0x20 ; 32 - 1f68: 09 f0 breq .+2 ; 0x1f6c - 1f6a: f7 df rcall .-18 ; 0x1f5a + 1f58: dd df rcall .-70 ; 0x1f14 + 1f5a: 80 32 cpi r24, 0x20 ; 32 + 1f5c: 09 f0 breq .+2 ; 0x1f60 + 1f5e: f7 df rcall .-18 ; 0x1f4e putch(STK_INSYNC); - 1f6c: 84 e1 ldi r24, 0x14 ; 20 + 1f60: 84 e1 ldi r24, 0x14 ; 20 } - 1f6e: c9 cf rjmp .-110 ; 0x1f02 + 1f62: c9 cf rjmp .-110 ; 0x1ef6 + +00001f64 : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 1f70: 1f 93 push r17 - 1f72: 18 2f mov r17, r24 - -00001f74 : + 1f64: 1f 93 push r17 + 1f66: 18 2f mov r17, r24 do getch(); while (--count); - 1f74: d5 df rcall .-86 ; 0x1f20 - 1f76: 11 50 subi r17, 0x01 ; 1 - 1f78: e9 f7 brne .-6 ; 0x1f74 + 1f68: d5 df rcall .-86 ; 0x1f14 + 1f6a: 11 50 subi r17, 0x01 ; 1 + 1f6c: e9 f7 brne .-6 ; 0x1f68 verifySpace(); - 1f7a: f4 df rcall .-24 ; 0x1f64 + 1f6e: f4 df rcall .-24 ; 0x1f58 } - 1f7c: 1f 91 pop r17 - 1f7e: 08 95 ret + 1f70: 1f 91 pop r17 + 1f72: 08 95 ret diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.hex b/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.hex index 1e9341468..2b4a582a4 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.hex @@ -1,33 +1,34 @@ -:103E000085E08093810082E08093C00088E1809308 -:103E1000C10086E08093C20080E18093C40084B733 -:103E200014BE81FFD0D08DE0C8D0259A86E020E373 -:103E30003CEF91E0309385002093840096BBB09BCB -:103E4000FECF1D9AA8958150A9F7DD24D394A5E053 -:103E5000EA2EF1E1FF2EA4D0813421F481E0BED01E -:103E600083E024C0823411F484E103C0853419F462 -:103E700085E0B4D08AC08535A1F492D0082F10E037 -:103E800010930102009300028BD090E0982F8827B6 -:103E9000802B912B880F991F909301028093000231 -:103EA00073C0863529F484E099D080E071D06DC06C -:103EB000843609F043C07CD0E0910002F091010209 -:103EC00083E080935700E895C0E0D1E069D0899302 -:103ED000809102028150809302028823B9F778D042 -:103EE00007B600FCFDCF4091000250910102A0E016 -:103EF000B1E02C9130E011968C91119790E0982FC1 -:103F00008827822B932B1296FA010C01D09257002E -:103F1000E89511244E5F5F4FF1E0A038BF0749F7E5 -:103F2000E0910002F0910102E0925700E89507B697 -:103F300000FCFDCFF0925700E89527C08437B9F414 -:103F400037D046D0E0910002F09101023196F09313 -:103F50000102E09300023197E4918E2F19D08091F5 -:103F60000202815080930202882361F70EC08537D8 -:103F700039F42ED08EE10CD084E90AD086E096CFB9 -:103F8000813511F488E019D023D080E101D063CFCE -:103F9000982F8091C00085FFFCCF9093C6000895B4 -:103FA000A8958091C00087FFFCCF8091C60008953E -:103FB000F7DFF6DF80930202F3CFE0E6F0E098E16E -:103FC00090838083089580E0F8DFEE27FF2709942F -:103FD000E7DF803209F0F7DF84E1DACF1F93182F93 -:0C3FE000DFDF1150E9F7F4DF1F910895B6 +:103E0000112484B714BE81FFE6D085E08093810041 +:103E100082E08093C00088E18093C10086E08093B7 +:103E2000C20080E18093C4008EE0CFD0259A86E066 +:103E300020E33CEF91E0309385002093840096BB13 +:103E4000B09BFECF1D9AA8958150A9F7DD24D3948D +:103E5000A5E0EA2EF1E1FF2EABD0813421F481E020 +:103E6000C5D083E020C0823411F484E103C08534DE +:103E700019F485E0BBD091C0853581F499D0082F25 +:103E800010E096D090E0982F8827802B912B880FF8 +:103E9000991F90930102809300027EC0863529F419 +:103EA00084E0A4D080E07CD078C0843609F04EC095 +:103EB00087D0E0910002F091010288E3E030F8073A +:103EC00018F483E087BFE895C0E0D1E071D0899312 +:103ED000809102028150809302028823B9F7E09119 +:103EE0000002F091010288E3E030F80718F083E067 +:103EF00087BFE89575D007B600FCFDCF4091000262 +:103F000050910102A0E0B1E02C9130E011968C912B +:103F1000119790E0982F8827822B932B1296FA0105 +:103F20000C01D7BEE89511244E5F5F4FF1E0A03839 +:103F3000BF0751F7E0910002F0910102E7BEE8955A +:103F400007B600FCFDCFF7BEE89527C08437B9F46B +:103F500037D046D0E0910002F09101023196F09303 +:103F60000102E09300023197E4918E2F19D08091E5 +:103F70000202815080930202882361F70EC08537C8 +:103F800039F42ED08EE10CD084E90AD086E08BCFB4 +:103F9000813511F488E019D023D080E101D05CCFC5 +:103FA000982F8091C00085FFFCCF9093C6000895A4 +:103FB000A8958091C00087FFFCCF8091C60008952E +:103FC000F7DFF6DF80930202F3CFE0E6F0E098E15E +:103FD00090838083089580E0F8DFEE27FF2709941F +:103FE000E7DF803209F0F7DF84E1DACF1F93182F83 +:0C3FF000DFDF1150E9F7F4DF1F910895A6 :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.lst b/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.lst index 9920a769c..25dc46bc0 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.lst @@ -3,237 +3,257 @@ optiboot_pro_16MHz.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .text 000001ec 00003e00 00003e00 00000054 2**1 + 0 .text 000001fc 00003e00 00003e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .debug_aranges 00000028 00000000 00000000 00000240 2**0 + 1 .debug_aranges 00000028 00000000 00000000 00000250 2**0 CONTENTS, READONLY, DEBUGGING - 2 .debug_pubnames 0000006a 00000000 00000000 00000268 2**0 + 2 .debug_pubnames 0000006a 00000000 00000000 00000278 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_info 00000269 00000000 00000000 000002d2 2**0 + 3 .debug_info 00000284 00000000 00000000 000002e2 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_abbrev 00000196 00000000 00000000 0000053b 2**0 + 4 .debug_abbrev 000001ae 00000000 00000000 00000566 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_line 000003d3 00000000 00000000 000006d1 2**0 + 5 .debug_line 00000450 00000000 00000000 00000714 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_frame 00000090 00000000 00000000 00000aa4 2**2 + 6 .debug_frame 00000090 00000000 00000000 00000b64 2**2 CONTENTS, READONLY, DEBUGGING - 7 .debug_str 00000135 00000000 00000000 00000b34 2**0 + 7 .debug_str 00000141 00000000 00000000 00000bf4 2**0 CONTENTS, READONLY, DEBUGGING - 8 .debug_loc 000001d1 00000000 00000000 00000c69 2**0 + 8 .debug_loc 000001e1 00000000 00000000 00000d35 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_ranges 00000068 00000000 00000000 00000e3a 2**0 + 9 .debug_ranges 00000068 00000000 00000000 00000f16 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: 00003e00
    : -#ifdef VIRTUAL_BOOT_PARTITION -#define rstVect (*(uint16_t*)(0x204)) -#define wdtVect (*(uint16_t*)(0x206)) +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif + /* main program starts here */ int main(void) { - 3e00: 85 e0 ldi r24, 0x05 ; 5 - 3e02: 80 93 81 00 sts 0x0081, r24 -#if LED_START_FLASHES > 0 - // Set up Timer 1 for timeout counter - TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 -#endif -#ifndef SOFT_UART - UCSR0A = _BV(U2X0); //Double speed mode USART0 - 3e06: 82 e0 ldi r24, 0x02 ; 2 - 3e08: 80 93 c0 00 sts 0x00C0, r24 - UCSR0B = _BV(RXEN0) | _BV(TXEN0); - 3e0c: 88 e1 ldi r24, 0x18 ; 24 - 3e0e: 80 93 c1 00 sts 0x00C1, r24 - UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); - 3e12: 86 e0 ldi r24, 0x06 ; 6 - 3e14: 80 93 c2 00 sts 0x00C2, r24 - UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); - 3e18: 80 e1 ldi r24, 0x10 ; 16 - 3e1a: 80 93 c4 00 sts 0x00C4, r24 + 3e00: 11 24 eor r1, r1 +#ifdef __AVR_ATmega8__ + SP=RAMEND; // This is done by hardware reset #endif // Adaboot no-wait mod ch = MCUSR; - 3e1e: 84 b7 in r24, 0x34 ; 52 + 3e02: 84 b7 in r24, 0x34 ; 52 MCUSR = 0; - 3e20: 14 be out 0x34, r1 ; 52 + 3e04: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); - 3e22: 81 ff sbrs r24, 1 - 3e24: d0 d0 rcall .+416 ; 0x3fc6 + 3e06: 81 ff sbrs r24, 1 + 3e08: e6 d0 rcall .+460 ; 0x3fd6 + +#if LED_START_FLASHES > 0 + // Set up Timer 1 for timeout counter + TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 + 3e0a: 85 e0 ldi r24, 0x05 ; 5 + 3e0c: 80 93 81 00 sts 0x0081, r24 + UCSRA = _BV(U2X); //Double speed mode USART + UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx + UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 + UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); +#else + UCSR0A = _BV(U2X0); //Double speed mode USART0 + 3e10: 82 e0 ldi r24, 0x02 ; 2 + 3e12: 80 93 c0 00 sts 0x00C0, r24 + UCSR0B = _BV(RXEN0) | _BV(TXEN0); + 3e16: 88 e1 ldi r24, 0x18 ; 24 + 3e18: 80 93 c1 00 sts 0x00C1, r24 + UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); + 3e1c: 86 e0 ldi r24, 0x06 ; 6 + 3e1e: 80 93 c2 00 sts 0x00C2, r24 + UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); + 3e22: 80 e1 ldi r24, 0x10 ; 16 + 3e24: 80 93 c4 00 sts 0x00C4, r24 +#endif +#endif // Set up watchdog to trigger after 500ms - watchdogConfig(WATCHDOG_500MS); - 3e26: 8d e0 ldi r24, 0x0D ; 13 - 3e28: c8 d0 rcall .+400 ; 0x3fba + watchdogConfig(WATCHDOG_1S); + 3e28: 8e e0 ldi r24, 0x0E ; 14 + 3e2a: cf d0 rcall .+414 ; 0x3fca /* Set LED pin as output */ LED_DDR |= _BV(LED); - 3e2a: 25 9a sbi 0x04, 5 ; 4 - 3e2c: 86 e0 ldi r24, 0x06 ; 6 + 3e2c: 25 9a sbi 0x04, 5 ; 4 + 3e2e: 86 e0 ldi r24, 0x06 ; 6 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - 3e2e: 20 e3 ldi r18, 0x30 ; 48 - 3e30: 3c ef ldi r19, 0xFC ; 252 + 3e30: 20 e3 ldi r18, 0x30 ; 48 + 3e32: 3c ef ldi r19, 0xFC ; 252 TIFR1 = _BV(TOV1); - 3e32: 91 e0 ldi r25, 0x01 ; 1 + 3e34: 91 e0 ldi r25, 0x01 ; 1 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - 3e34: 30 93 85 00 sts 0x0085, r19 - 3e38: 20 93 84 00 sts 0x0084, r18 + 3e36: 30 93 85 00 sts 0x0085, r19 + 3e3a: 20 93 84 00 sts 0x0084, r18 TIFR1 = _BV(TOV1); - 3e3c: 96 bb out 0x16, r25 ; 22 + 3e3e: 96 bb out 0x16, r25 ; 22 while(!(TIFR1 & _BV(TOV1))); - 3e3e: b0 9b sbis 0x16, 0 ; 22 - 3e40: fe cf rjmp .-4 ; 0x3e3e + 3e40: b0 9b sbis 0x16, 0 ; 22 + 3e42: fe cf rjmp .-4 ; 0x3e40 +#ifdef __AVR_ATmega8__ + LED_PORT ^= _BV(LED); +#else LED_PIN |= _BV(LED); - 3e42: 1d 9a sbi 0x03, 5 ; 3 + 3e44: 1d 9a sbi 0x03, 5 ; 3 return getch(); } // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 3e44: a8 95 wdr - TCNT1 = -(F_CPU/(1024*16)); - TIFR1 = _BV(TOV1); - while(!(TIFR1 & _BV(TOV1))); + 3e46: a8 95 wdr + LED_PORT ^= _BV(LED); +#else LED_PIN |= _BV(LED); +#endif watchdogReset(); } while (--count); - 3e46: 81 50 subi r24, 0x01 ; 1 - 3e48: a9 f7 brne .-22 ; 0x3e34 + 3e48: 81 50 subi r24, 0x01 ; 1 + 3e4a: a9 f7 brne .-22 ; 0x3e36 /* get character from UART */ ch = getch(); if(ch == STK_GET_PARAMETER) { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 3e4a: dd 24 eor r13, r13 - 3e4c: d3 94 inc r13 - boot_page_fill((uint16_t)(void*)addrPtr,a); + 3e4c: dd 24 eor r13, r13 + 3e4e: d3 94 inc r13 + __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); // Write from programming buffer - boot_page_write((uint16_t)(void*)address); - 3e4e: a5 e0 ldi r26, 0x05 ; 5 - 3e50: ea 2e mov r14, r26 + __boot_page_write_short((uint16_t)(void*)address); + 3e50: a5 e0 ldi r26, 0x05 ; 5 + 3e52: ea 2e mov r14, r26 boot_spm_busy_wait(); #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 3e52: f1 e1 ldi r31, 0x11 ; 17 - 3e54: ff 2e mov r15, r31 + 3e54: f1 e1 ldi r31, 0x11 ; 17 + 3e56: ff 2e mov r15, r31 #endif /* Forever loop */ for (;;) { /* get character from UART */ ch = getch(); - 3e56: a4 d0 rcall .+328 ; 0x3fa0 + 3e58: ab d0 rcall .+342 ; 0x3fb0 if(ch == STK_GET_PARAMETER) { - 3e58: 81 34 cpi r24, 0x41 ; 65 - 3e5a: 21 f4 brne .+8 ; 0x3e64 + 3e5a: 81 34 cpi r24, 0x41 ; 65 + 3e5c: 21 f4 brne .+8 ; 0x3e66 // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 3e5c: 81 e0 ldi r24, 0x01 ; 1 - 3e5e: be d0 rcall .+380 ; 0x3fdc + 3e5e: 81 e0 ldi r24, 0x01 ; 1 + 3e60: c5 d0 rcall .+394 ; 0x3fec putch(0x03); - 3e60: 83 e0 ldi r24, 0x03 ; 3 - 3e62: 24 c0 rjmp .+72 ; 0x3eac + 3e62: 83 e0 ldi r24, 0x03 ; 3 + 3e64: 20 c0 rjmp .+64 ; 0x3ea6 } else if(ch == STK_SET_DEVICE) { - 3e64: 82 34 cpi r24, 0x42 ; 66 - 3e66: 11 f4 brne .+4 ; 0x3e6c + 3e66: 82 34 cpi r24, 0x42 ; 66 + 3e68: 11 f4 brne .+4 ; 0x3e6e // SET DEVICE is ignored getNch(20); - 3e68: 84 e1 ldi r24, 0x14 ; 20 - 3e6a: 03 c0 rjmp .+6 ; 0x3e72 + 3e6a: 84 e1 ldi r24, 0x14 ; 20 + 3e6c: 03 c0 rjmp .+6 ; 0x3e74 } else if(ch == STK_SET_DEVICE_EXT) { - 3e6c: 85 34 cpi r24, 0x45 ; 69 - 3e6e: 19 f4 brne .+6 ; 0x3e76 + 3e6e: 85 34 cpi r24, 0x45 ; 69 + 3e70: 19 f4 brne .+6 ; 0x3e78 // SET DEVICE EXT is ignored getNch(5); - 3e70: 85 e0 ldi r24, 0x05 ; 5 - 3e72: b4 d0 rcall .+360 ; 0x3fdc - 3e74: 8a c0 rjmp .+276 ; 0x3f8a + 3e72: 85 e0 ldi r24, 0x05 ; 5 + 3e74: bb d0 rcall .+374 ; 0x3fec + 3e76: 91 c0 rjmp .+290 ; 0x3f9a } else if(ch == STK_LOAD_ADDRESS) { - 3e76: 85 35 cpi r24, 0x55 ; 85 - 3e78: a1 f4 brne .+40 ; 0x3ea2 + 3e78: 85 35 cpi r24, 0x55 ; 85 + 3e7a: 81 f4 brne .+32 ; 0x3e9c // LOAD ADDRESS - address = getch(); - 3e7a: 92 d0 rcall .+292 ; 0x3fa0 - 3e7c: 08 2f mov r16, r24 - 3e7e: 10 e0 ldi r17, 0x00 ; 0 - 3e80: 10 93 01 02 sts 0x0201, r17 - 3e84: 00 93 00 02 sts 0x0200, r16 - address = (address & 0xff) | (getch() << 8); - 3e88: 8b d0 rcall .+278 ; 0x3fa0 - 3e8a: 90 e0 ldi r25, 0x00 ; 0 - 3e8c: 98 2f mov r25, r24 - 3e8e: 88 27 eor r24, r24 - 3e90: 80 2b or r24, r16 - 3e92: 91 2b or r25, r17 - address += address; // Convert from word address to byte address - 3e94: 88 0f add r24, r24 - 3e96: 99 1f adc r25, r25 - 3e98: 90 93 01 02 sts 0x0201, r25 - 3e9c: 80 93 00 02 sts 0x0200, r24 - 3ea0: 73 c0 rjmp .+230 ; 0x3f88 + uint16_t newAddress; + newAddress = getch(); + 3e7c: 99 d0 rcall .+306 ; 0x3fb0 + newAddress = (newAddress & 0xff) | (getch() << 8); + 3e7e: 08 2f mov r16, r24 + 3e80: 10 e0 ldi r17, 0x00 ; 0 + 3e82: 96 d0 rcall .+300 ; 0x3fb0 + 3e84: 90 e0 ldi r25, 0x00 ; 0 + 3e86: 98 2f mov r25, r24 + 3e88: 88 27 eor r24, r24 + 3e8a: 80 2b or r24, r16 + 3e8c: 91 2b or r25, r17 +#ifdef RAMPZ + // Transfer top bit to RAMPZ + RAMPZ = (newAddress & 0x8000) ? 1 : 0; +#endif + newAddress += newAddress; // Convert from word address to byte address + 3e8e: 88 0f add r24, r24 + 3e90: 99 1f adc r25, r25 + address = newAddress; + 3e92: 90 93 01 02 sts 0x0201, r25 + 3e96: 80 93 00 02 sts 0x0200, r24 + 3e9a: 7e c0 rjmp .+252 ; 0x3f98 verifySpace(); } else if(ch == STK_UNIVERSAL) { - 3ea2: 86 35 cpi r24, 0x56 ; 86 - 3ea4: 29 f4 brne .+10 ; 0x3eb0 + 3e9c: 86 35 cpi r24, 0x56 ; 86 + 3e9e: 29 f4 brne .+10 ; 0x3eaa // UNIVERSAL command is ignored getNch(4); - 3ea6: 84 e0 ldi r24, 0x04 ; 4 - 3ea8: 99 d0 rcall .+306 ; 0x3fdc + 3ea0: 84 e0 ldi r24, 0x04 ; 4 + 3ea2: a4 d0 rcall .+328 ; 0x3fec putch(0x00); - 3eaa: 80 e0 ldi r24, 0x00 ; 0 - 3eac: 71 d0 rcall .+226 ; 0x3f90 - 3eae: 6d c0 rjmp .+218 ; 0x3f8a + 3ea4: 80 e0 ldi r24, 0x00 ; 0 + 3ea6: 7c d0 rcall .+248 ; 0x3fa0 + 3ea8: 78 c0 rjmp .+240 ; 0x3f9a } - /* Write memory, length is big endian and is in bytes */ + /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { - 3eb0: 84 36 cpi r24, 0x64 ; 100 - 3eb2: 09 f0 breq .+2 ; 0x3eb6 - 3eb4: 43 c0 rjmp .+134 ; 0x3f3c + 3eaa: 84 36 cpi r24, 0x64 ; 100 + 3eac: 09 f0 breq .+2 ; 0x3eb0 + 3eae: 4e c0 rjmp .+156 ; 0x3f4c // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t *bufPtr; uint16_t addrPtr; getLen(); - 3eb6: 7c d0 rcall .+248 ; 0x3fb0 + 3eb0: 87 d0 rcall .+270 ; 0x3fc0 - // Immediately start page erase - this will 4.5ms - boot_page_erase((uint16_t)(void*)address); - 3eb8: e0 91 00 02 lds r30, 0x0200 - 3ebc: f0 91 01 02 lds r31, 0x0201 - 3ec0: 83 e0 ldi r24, 0x03 ; 3 - 3ec2: 80 93 57 00 sts 0x0057, r24 + // If we are in RWW section, immediately start page erase + if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + 3eb2: e0 91 00 02 lds r30, 0x0200 + 3eb6: f0 91 01 02 lds r31, 0x0201 + 3eba: 88 e3 ldi r24, 0x38 ; 56 + 3ebc: e0 30 cpi r30, 0x00 ; 0 + 3ebe: f8 07 cpc r31, r24 + 3ec0: 18 f4 brcc .+6 ; 0x3ec8 + 3ec2: 83 e0 ldi r24, 0x03 ; 3 + 3ec4: 87 bf out 0x37, r24 ; 55 3ec6: e8 95 spm 3ec8: c0 e0 ldi r28, 0x00 ; 0 3eca: d1 e0 ldi r29, 0x01 ; 1 - + // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); - 3ecc: 69 d0 rcall .+210 ; 0x3fa0 + 3ecc: 71 d0 rcall .+226 ; 0x3fb0 3ece: 89 93 st Y+, r24 while (--length); 3ed0: 80 91 02 02 lds r24, 0x0202 @@ -242,279 +262,293 @@ void watchdogReset() { 3eda: 88 23 and r24, r24 3edc: b9 f7 brne .-18 ; 0x3ecc + // If we are in NRWW section, page erase has to be delayed until now. + // Todo: Take RAMPZ into account + if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + 3ede: e0 91 00 02 lds r30, 0x0200 + 3ee2: f0 91 01 02 lds r31, 0x0201 + 3ee6: 88 e3 ldi r24, 0x38 ; 56 + 3ee8: e0 30 cpi r30, 0x00 ; 0 + 3eea: f8 07 cpc r31, r24 + 3eec: 18 f0 brcs .+6 ; 0x3ef4 + 3eee: 83 e0 ldi r24, 0x03 ; 3 + 3ef0: 87 bf out 0x37, r24 ; 55 + 3ef2: e8 95 spm + // Read command terminator, start reply verifySpace(); - 3ede: 78 d0 rcall .+240 ; 0x3fd0 + 3ef4: 75 d0 rcall .+234 ; 0x3fe0 // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); - 3ee0: 07 b6 in r0, 0x37 ; 55 - 3ee2: 00 fc sbrc r0, 0 - 3ee4: fd cf rjmp .-6 ; 0x3ee0 + 3ef6: 07 b6 in r0, 0x37 ; 55 + 3ef8: 00 fc sbrc r0, 0 + 3efa: fd cf rjmp .-6 ; 0x3ef6 } #endif // Copy buffer into programming buffer bufPtr = buff; addrPtr = (uint16_t)(void*)address; - 3ee6: 40 91 00 02 lds r20, 0x0200 - 3eea: 50 91 01 02 lds r21, 0x0201 - 3eee: a0 e0 ldi r26, 0x00 ; 0 - 3ef0: b1 e0 ldi r27, 0x01 ; 1 + 3efc: 40 91 00 02 lds r20, 0x0200 + 3f00: 50 91 01 02 lds r21, 0x0201 + 3f04: a0 e0 ldi r26, 0x00 ; 0 + 3f06: b1 e0 ldi r27, 0x01 ; 1 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; - 3ef2: 2c 91 ld r18, X - 3ef4: 30 e0 ldi r19, 0x00 ; 0 + 3f08: 2c 91 ld r18, X + 3f0a: 30 e0 ldi r19, 0x00 ; 0 a |= (*bufPtr++) << 8; - 3ef6: 11 96 adiw r26, 0x01 ; 1 - 3ef8: 8c 91 ld r24, X - 3efa: 11 97 sbiw r26, 0x01 ; 1 - 3efc: 90 e0 ldi r25, 0x00 ; 0 - 3efe: 98 2f mov r25, r24 - 3f00: 88 27 eor r24, r24 - 3f02: 82 2b or r24, r18 - 3f04: 93 2b or r25, r19 -#ifdef VIRTUAL_BOOT_PARTITION -#define rstVect (*(uint16_t*)(0x204)) -#define wdtVect (*(uint16_t*)(0x206)) + 3f0c: 11 96 adiw r26, 0x01 ; 1 + 3f0e: 8c 91 ld r24, X + 3f10: 11 97 sbiw r26, 0x01 ; 1 + 3f12: 90 e0 ldi r25, 0x00 ; 0 + 3f14: 98 2f mov r25, r24 + 3f16: 88 27 eor r24, r24 + 3f18: 82 2b or r24, r18 + 3f1a: 93 2b or r25, r19 +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif + /* main program starts here */ int main(void) { - 3f06: 12 96 adiw r26, 0x02 ; 2 + 3f1c: 12 96 adiw r26, 0x02 ; 2 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; a |= (*bufPtr++) << 8; - boot_page_fill((uint16_t)(void*)addrPtr,a); - 3f08: fa 01 movw r30, r20 - 3f0a: 0c 01 movw r0, r24 - 3f0c: d0 92 57 00 sts 0x0057, r13 - 3f10: e8 95 spm - 3f12: 11 24 eor r1, r1 + __boot_page_fill_short((uint16_t)(void*)addrPtr,a); + 3f1e: fa 01 movw r30, r20 + 3f20: 0c 01 movw r0, r24 + 3f22: d7 be out 0x37, r13 ; 55 + 3f24: e8 95 spm + 3f26: 11 24 eor r1, r1 addrPtr += 2; - 3f14: 4e 5f subi r20, 0xFE ; 254 - 3f16: 5f 4f sbci r21, 0xFF ; 255 + 3f28: 4e 5f subi r20, 0xFE ; 254 + 3f2a: 5f 4f sbci r21, 0xFF ; 255 } while (--ch); - 3f18: f1 e0 ldi r31, 0x01 ; 1 - 3f1a: a0 38 cpi r26, 0x80 ; 128 - 3f1c: bf 07 cpc r27, r31 - 3f1e: 49 f7 brne .-46 ; 0x3ef2 + 3f2c: f1 e0 ldi r31, 0x01 ; 1 + 3f2e: a0 38 cpi r26, 0x80 ; 128 + 3f30: bf 07 cpc r27, r31 + 3f32: 51 f7 brne .-44 ; 0x3f08 // Write from programming buffer - boot_page_write((uint16_t)(void*)address); - 3f20: e0 91 00 02 lds r30, 0x0200 - 3f24: f0 91 01 02 lds r31, 0x0201 - 3f28: e0 92 57 00 sts 0x0057, r14 - 3f2c: e8 95 spm + __boot_page_write_short((uint16_t)(void*)address); + 3f34: e0 91 00 02 lds r30, 0x0200 + 3f38: f0 91 01 02 lds r31, 0x0201 + 3f3c: e7 be out 0x37, r14 ; 55 + 3f3e: e8 95 spm boot_spm_busy_wait(); - 3f2e: 07 b6 in r0, 0x37 ; 55 - 3f30: 00 fc sbrc r0, 0 - 3f32: fd cf rjmp .-6 ; 0x3f2e + 3f40: 07 b6 in r0, 0x37 ; 55 + 3f42: 00 fc sbrc r0, 0 + 3f44: fd cf rjmp .-6 ; 0x3f40 #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 3f34: f0 92 57 00 sts 0x0057, r15 - 3f38: e8 95 spm - 3f3a: 27 c0 rjmp .+78 ; 0x3f8a + 3f46: f7 be out 0x37, r15 ; 55 + 3f48: e8 95 spm + 3f4a: 27 c0 rjmp .+78 ; 0x3f9a #endif } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { - 3f3c: 84 37 cpi r24, 0x74 ; 116 - 3f3e: b9 f4 brne .+46 ; 0x3f6e + 3f4c: 84 37 cpi r24, 0x74 ; 116 + 3f4e: b9 f4 brne .+46 ; 0x3f7e // READ PAGE - we only read flash getLen(); - 3f40: 37 d0 rcall .+110 ; 0x3fb0 + 3f50: 37 d0 rcall .+110 ; 0x3fc0 verifySpace(); - 3f42: 46 d0 rcall .+140 ; 0x3fd0 - else ch = pgm_read_byte_near(address); + 3f52: 46 d0 rcall .+140 ; 0x3fe0 + putch(result); address++; - putch(ch); - } while (--length); + } + while (--length); #else do putch(pgm_read_byte_near(address++)); - 3f44: e0 91 00 02 lds r30, 0x0200 - 3f48: f0 91 01 02 lds r31, 0x0201 - 3f4c: 31 96 adiw r30, 0x01 ; 1 - 3f4e: f0 93 01 02 sts 0x0201, r31 - 3f52: e0 93 00 02 sts 0x0200, r30 - 3f56: 31 97 sbiw r30, 0x01 ; 1 - 3f58: e4 91 lpm r30, Z+ - 3f5a: 8e 2f mov r24, r30 - 3f5c: 19 d0 rcall .+50 ; 0x3f90 + 3f54: e0 91 00 02 lds r30, 0x0200 + 3f58: f0 91 01 02 lds r31, 0x0201 + 3f5c: 31 96 adiw r30, 0x01 ; 1 + 3f5e: f0 93 01 02 sts 0x0201, r31 + 3f62: e0 93 00 02 sts 0x0200, r30 + 3f66: 31 97 sbiw r30, 0x01 ; 1 + 3f68: e4 91 lpm r30, Z+ + 3f6a: 8e 2f mov r24, r30 + 3f6c: 19 d0 rcall .+50 ; 0x3fa0 while (--length); - 3f5e: 80 91 02 02 lds r24, 0x0202 - 3f62: 81 50 subi r24, 0x01 ; 1 - 3f64: 80 93 02 02 sts 0x0202, r24 - 3f68: 88 23 and r24, r24 - 3f6a: 61 f7 brne .-40 ; 0x3f44 - 3f6c: 0e c0 rjmp .+28 ; 0x3f8a + 3f6e: 80 91 02 02 lds r24, 0x0202 + 3f72: 81 50 subi r24, 0x01 ; 1 + 3f74: 80 93 02 02 sts 0x0202, r24 + 3f78: 88 23 and r24, r24 + 3f7a: 61 f7 brne .-40 ; 0x3f54 + 3f7c: 0e c0 rjmp .+28 ; 0x3f9a +#endif #endif } /* Get device signature bytes */ else if(ch == STK_READ_SIGN) { - 3f6e: 85 37 cpi r24, 0x75 ; 117 - 3f70: 39 f4 brne .+14 ; 0x3f80 + 3f7e: 85 37 cpi r24, 0x75 ; 117 + 3f80: 39 f4 brne .+14 ; 0x3f90 // READ SIGN - return what Avrdude wants to hear verifySpace(); - 3f72: 2e d0 rcall .+92 ; 0x3fd0 + 3f82: 2e d0 rcall .+92 ; 0x3fe0 putch(SIGNATURE_0); - 3f74: 8e e1 ldi r24, 0x1E ; 30 - 3f76: 0c d0 rcall .+24 ; 0x3f90 + 3f84: 8e e1 ldi r24, 0x1E ; 30 + 3f86: 0c d0 rcall .+24 ; 0x3fa0 putch(SIGNATURE_1); - 3f78: 84 e9 ldi r24, 0x94 ; 148 - 3f7a: 0a d0 rcall .+20 ; 0x3f90 + 3f88: 84 e9 ldi r24, 0x94 ; 148 + 3f8a: 0a d0 rcall .+20 ; 0x3fa0 putch(SIGNATURE_2); - 3f7c: 86 e0 ldi r24, 0x06 ; 6 - 3f7e: 96 cf rjmp .-212 ; 0x3eac + 3f8c: 86 e0 ldi r24, 0x06 ; 6 + 3f8e: 8b cf rjmp .-234 ; 0x3ea6 } else if (ch == 'Q') { - 3f80: 81 35 cpi r24, 0x51 ; 81 - 3f82: 11 f4 brne .+4 ; 0x3f88 + 3f90: 81 35 cpi r24, 0x51 ; 81 + 3f92: 11 f4 brne .+4 ; 0x3f98 // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); - 3f84: 88 e0 ldi r24, 0x08 ; 8 - 3f86: 19 d0 rcall .+50 ; 0x3fba + 3f94: 88 e0 ldi r24, 0x08 ; 8 + 3f96: 19 d0 rcall .+50 ; 0x3fca verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 3f88: 23 d0 rcall .+70 ; 0x3fd0 + 3f98: 23 d0 rcall .+70 ; 0x3fe0 } putch(STK_OK); - 3f8a: 80 e1 ldi r24, 0x10 ; 16 - 3f8c: 01 d0 rcall .+2 ; 0x3f90 - 3f8e: 63 cf rjmp .-314 ; 0x3e56 + 3f9a: 80 e1 ldi r24, 0x10 ; 16 + 3f9c: 01 d0 rcall .+2 ; 0x3fa0 + 3f9e: 5c cf rjmp .-328 ; 0x3e58 -00003f90 : +00003fa0 : } } void putch(char ch) { - 3f90: 98 2f mov r25, r24 + 3fa0: 98 2f mov r25, r24 #ifndef SOFT_UART while (!(UCSR0A & _BV(UDRE0))); - 3f92: 80 91 c0 00 lds r24, 0x00C0 - 3f96: 85 ff sbrs r24, 5 - 3f98: fc cf rjmp .-8 ; 0x3f92 + 3fa2: 80 91 c0 00 lds r24, 0x00C0 + 3fa6: 85 ff sbrs r24, 5 + 3fa8: fc cf rjmp .-8 ; 0x3fa2 UDR0 = ch; - 3f9a: 90 93 c6 00 sts 0x00C6, r25 + 3faa: 90 93 c6 00 sts 0x00C6, r25 [uartBit] "I" (UART_TX_BIT) : "r25" ); #endif } - 3f9e: 08 95 ret + 3fae: 08 95 ret -00003fa0 : +00003fb0 : return getch(); } // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 3fa0: a8 95 wdr + 3fb0: a8 95 wdr [uartBit] "I" (UART_RX_BIT) : "r25" ); #else while(!(UCSR0A & _BV(RXC0))); - 3fa2: 80 91 c0 00 lds r24, 0x00C0 - 3fa6: 87 ff sbrs r24, 7 - 3fa8: fc cf rjmp .-8 ; 0x3fa2 + 3fb2: 80 91 c0 00 lds r24, 0x00C0 + 3fb6: 87 ff sbrs r24, 7 + 3fb8: fc cf rjmp .-8 ; 0x3fb2 ch = UDR0; - 3faa: 80 91 c6 00 lds r24, 0x00C6 -#ifdef LED_DATA_FLASH + 3fba: 80 91 c6 00 lds r24, 0x00C6 LED_PIN |= _BV(LED); +#endif #endif return ch; } - 3fae: 08 95 ret + 3fbe: 08 95 ret -00003fb0 : +00003fc0 : } while (--count); } #endif uint8_t getLen() { getch(); - 3fb0: f7 df rcall .-18 ; 0x3fa0 + 3fc0: f7 df rcall .-18 ; 0x3fb0 length = getch(); - 3fb2: f6 df rcall .-20 ; 0x3fa0 - 3fb4: 80 93 02 02 sts 0x0202, r24 + 3fc2: f6 df rcall .-20 ; 0x3fb0 + 3fc4: 80 93 02 02 sts 0x0202, r24 return getch(); } - 3fb8: f3 cf rjmp .-26 ; 0x3fa0 + 3fc8: f3 cf rjmp .-26 ; 0x3fb0 -00003fba : +00003fca : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 3fba: e0 e6 ldi r30, 0x60 ; 96 - 3fbc: f0 e0 ldi r31, 0x00 ; 0 - 3fbe: 98 e1 ldi r25, 0x18 ; 24 - 3fc0: 90 83 st Z, r25 + 3fca: e0 e6 ldi r30, 0x60 ; 96 + 3fcc: f0 e0 ldi r31, 0x00 ; 0 + 3fce: 98 e1 ldi r25, 0x18 ; 24 + 3fd0: 90 83 st Z, r25 WDTCSR = x; - 3fc2: 80 83 st Z, r24 + 3fd2: 80 83 st Z, r24 } - 3fc4: 08 95 ret + 3fd4: 08 95 ret -00003fc6 : +00003fd6 : void appStart() { watchdogConfig(WATCHDOG_OFF); - 3fc6: 80 e0 ldi r24, 0x00 ; 0 - 3fc8: f8 df rcall .-16 ; 0x3fba + 3fd6: 80 e0 ldi r24, 0x00 ; 0 + 3fd8: f8 df rcall .-16 ; 0x3fca __asm__ __volatile__ ( - 3fca: ee 27 eor r30, r30 - 3fcc: ff 27 eor r31, r31 - 3fce: 09 94 ijmp + 3fda: ee 27 eor r30, r30 + 3fdc: ff 27 eor r31, r31 + 3fde: 09 94 ijmp -00003fd0 : +00003fe0 : do getch(); while (--count); verifySpace(); } void verifySpace() { if (getch() != CRC_EOP) appStart(); - 3fd0: e7 df rcall .-50 ; 0x3fa0 - 3fd2: 80 32 cpi r24, 0x20 ; 32 - 3fd4: 09 f0 breq .+2 ; 0x3fd8 - 3fd6: f7 df rcall .-18 ; 0x3fc6 + 3fe0: e7 df rcall .-50 ; 0x3fb0 + 3fe2: 80 32 cpi r24, 0x20 ; 32 + 3fe4: 09 f0 breq .+2 ; 0x3fe8 + 3fe6: f7 df rcall .-18 ; 0x3fd6 putch(STK_INSYNC); - 3fd8: 84 e1 ldi r24, 0x14 ; 20 + 3fe8: 84 e1 ldi r24, 0x14 ; 20 } - 3fda: da cf rjmp .-76 ; 0x3f90 + 3fea: da cf rjmp .-76 ; 0x3fa0 + +00003fec : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 3fdc: 1f 93 push r17 - 3fde: 18 2f mov r17, r24 - -00003fe0 : + 3fec: 1f 93 push r17 + 3fee: 18 2f mov r17, r24 do getch(); while (--count); - 3fe0: df df rcall .-66 ; 0x3fa0 - 3fe2: 11 50 subi r17, 0x01 ; 1 - 3fe4: e9 f7 brne .-6 ; 0x3fe0 + 3ff0: df df rcall .-66 ; 0x3fb0 + 3ff2: 11 50 subi r17, 0x01 ; 1 + 3ff4: e9 f7 brne .-6 ; 0x3ff0 verifySpace(); - 3fe6: f4 df rcall .-24 ; 0x3fd0 + 3ff6: f4 df rcall .-24 ; 0x3fe0 } - 3fe8: 1f 91 pop r17 - 3fea: 08 95 ret + 3ff8: 1f 91 pop r17 + 3ffa: 08 95 ret diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.hex b/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.hex index 19c9ae4e1..d147f8f7d 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.hex @@ -1,33 +1,34 @@ -:103E000085E08093810082E08093C00088E1809308 -:103E1000C10086E08093C20085E18093C40084B72E -:103E200014BE81FFD0D08DE0C8D0259A86E02CE367 -:103E30003BEF91E0309385002093840096BBB09BCC -:103E4000FECF1D9AA8958150A9F7DD24D394A5E053 -:103E5000EA2EF1E1FF2EA4D0813421F481E0BED01E -:103E600083E024C0823411F484E103C0853419F462 -:103E700085E0B4D08AC08535A1F492D0082F10E037 -:103E800010930102009300028BD090E0982F8827B6 -:103E9000802B912B880F991F909301028093000231 -:103EA00073C0863529F484E099D080E071D06DC06C -:103EB000843609F043C07CD0E0910002F091010209 -:103EC00083E080935700E895C0E0D1E069D0899302 -:103ED000809102028150809302028823B9F778D042 -:103EE00007B600FCFDCF4091000250910102A0E016 -:103EF000B1E02C9130E011968C91119790E0982FC1 -:103F00008827822B932B1296FA010C01D09257002E -:103F1000E89511244E5F5F4FF1E0A038BF0749F7E5 -:103F2000E0910002F0910102E0925700E89507B697 -:103F300000FCFDCFF0925700E89527C08437B9F414 -:103F400037D046D0E0910002F09101023196F09313 -:103F50000102E09300023197E4918E2F19D08091F5 -:103F60000202815080930202882361F70EC08537D8 -:103F700039F42ED08EE10CD084E90AD086E096CFB9 -:103F8000813511F488E019D023D080E101D063CFCE -:103F9000982F8091C00085FFFCCF9093C6000895B4 -:103FA000A8958091C00087FFFCCF8091C60008953E -:103FB000F7DFF6DF80930202F3CFE0E6F0E098E16E -:103FC00090838083089580E0F8DFEE27FF2709942F -:103FD000E7DF803209F0F7DF84E1DACF1F93182F93 -:0C3FE000DFDF1150E9F7F4DF1F910895B6 +:103E0000112484B714BE81FFE6D085E08093810041 +:103E100082E08093C00088E18093C10086E08093B7 +:103E2000C20085E18093C4008EE0CFD0259A86E061 +:103E30002CE33BEF91E0309385002093840096BB08 +:103E4000B09BFECF1D9AA8958150A9F7DD24D3948D +:103E5000A5E0EA2EF1E1FF2EABD0813421F481E020 +:103E6000C5D083E020C0823411F484E103C08534DE +:103E700019F485E0BBD091C0853581F499D0082F25 +:103E800010E096D090E0982F8827802B912B880FF8 +:103E9000991F90930102809300027EC0863529F419 +:103EA00084E0A4D080E07CD078C0843609F04EC095 +:103EB00087D0E0910002F091010288E3E030F8073A +:103EC00018F483E087BFE895C0E0D1E071D0899312 +:103ED000809102028150809302028823B9F7E09119 +:103EE0000002F091010288E3E030F80718F083E067 +:103EF00087BFE89575D007B600FCFDCF4091000262 +:103F000050910102A0E0B1E02C9130E011968C912B +:103F1000119790E0982F8827822B932B1296FA0105 +:103F20000C01D7BEE89511244E5F5F4FF1E0A03839 +:103F3000BF0751F7E0910002F0910102E7BEE8955A +:103F400007B600FCFDCFF7BEE89527C08437B9F46B +:103F500037D046D0E0910002F09101023196F09303 +:103F60000102E09300023197E4918E2F19D08091E5 +:103F70000202815080930202882361F70EC08537C8 +:103F800039F42ED08EE10CD084E90AD086E08BCFB4 +:103F9000813511F488E019D023D080E101D05CCFC5 +:103FA000982F8091C00085FFFCCF9093C6000895A4 +:103FB000A8958091C00087FFFCCF8091C60008952E +:103FC000F7DFF6DF80930202F3CFE0E6F0E098E15E +:103FD00090838083089580E0F8DFEE27FF2709941F +:103FE000E7DF803209F0F7DF84E1DACF1F93182F83 +:0C3FF000DFDF1150E9F7F4DF1F910895A6 :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.lst b/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.lst index 62178d375..1868d16d0 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.lst @@ -3,237 +3,257 @@ optiboot_pro_20mhz.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .text 000001ec 00003e00 00003e00 00000054 2**1 + 0 .text 000001fc 00003e00 00003e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .debug_aranges 00000028 00000000 00000000 00000240 2**0 + 1 .debug_aranges 00000028 00000000 00000000 00000250 2**0 CONTENTS, READONLY, DEBUGGING - 2 .debug_pubnames 0000006a 00000000 00000000 00000268 2**0 + 2 .debug_pubnames 0000006a 00000000 00000000 00000278 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_info 00000269 00000000 00000000 000002d2 2**0 + 3 .debug_info 00000284 00000000 00000000 000002e2 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_abbrev 00000196 00000000 00000000 0000053b 2**0 + 4 .debug_abbrev 000001ae 00000000 00000000 00000566 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_line 000003d3 00000000 00000000 000006d1 2**0 + 5 .debug_line 00000450 00000000 00000000 00000714 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_frame 00000090 00000000 00000000 00000aa4 2**2 + 6 .debug_frame 00000090 00000000 00000000 00000b64 2**2 CONTENTS, READONLY, DEBUGGING - 7 .debug_str 00000135 00000000 00000000 00000b34 2**0 + 7 .debug_str 00000141 00000000 00000000 00000bf4 2**0 CONTENTS, READONLY, DEBUGGING - 8 .debug_loc 000001d1 00000000 00000000 00000c69 2**0 + 8 .debug_loc 000001e1 00000000 00000000 00000d35 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_ranges 00000068 00000000 00000000 00000e3a 2**0 + 9 .debug_ranges 00000068 00000000 00000000 00000f16 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: 00003e00
    : -#ifdef VIRTUAL_BOOT_PARTITION -#define rstVect (*(uint16_t*)(0x204)) -#define wdtVect (*(uint16_t*)(0x206)) +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif + /* main program starts here */ int main(void) { - 3e00: 85 e0 ldi r24, 0x05 ; 5 - 3e02: 80 93 81 00 sts 0x0081, r24 -#if LED_START_FLASHES > 0 - // Set up Timer 1 for timeout counter - TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 -#endif -#ifndef SOFT_UART - UCSR0A = _BV(U2X0); //Double speed mode USART0 - 3e06: 82 e0 ldi r24, 0x02 ; 2 - 3e08: 80 93 c0 00 sts 0x00C0, r24 - UCSR0B = _BV(RXEN0) | _BV(TXEN0); - 3e0c: 88 e1 ldi r24, 0x18 ; 24 - 3e0e: 80 93 c1 00 sts 0x00C1, r24 - UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); - 3e12: 86 e0 ldi r24, 0x06 ; 6 - 3e14: 80 93 c2 00 sts 0x00C2, r24 - UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); - 3e18: 85 e1 ldi r24, 0x15 ; 21 - 3e1a: 80 93 c4 00 sts 0x00C4, r24 + 3e00: 11 24 eor r1, r1 +#ifdef __AVR_ATmega8__ + SP=RAMEND; // This is done by hardware reset #endif // Adaboot no-wait mod ch = MCUSR; - 3e1e: 84 b7 in r24, 0x34 ; 52 + 3e02: 84 b7 in r24, 0x34 ; 52 MCUSR = 0; - 3e20: 14 be out 0x34, r1 ; 52 + 3e04: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); - 3e22: 81 ff sbrs r24, 1 - 3e24: d0 d0 rcall .+416 ; 0x3fc6 + 3e06: 81 ff sbrs r24, 1 + 3e08: e6 d0 rcall .+460 ; 0x3fd6 + +#if LED_START_FLASHES > 0 + // Set up Timer 1 for timeout counter + TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 + 3e0a: 85 e0 ldi r24, 0x05 ; 5 + 3e0c: 80 93 81 00 sts 0x0081, r24 + UCSRA = _BV(U2X); //Double speed mode USART + UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx + UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 + UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); +#else + UCSR0A = _BV(U2X0); //Double speed mode USART0 + 3e10: 82 e0 ldi r24, 0x02 ; 2 + 3e12: 80 93 c0 00 sts 0x00C0, r24 + UCSR0B = _BV(RXEN0) | _BV(TXEN0); + 3e16: 88 e1 ldi r24, 0x18 ; 24 + 3e18: 80 93 c1 00 sts 0x00C1, r24 + UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); + 3e1c: 86 e0 ldi r24, 0x06 ; 6 + 3e1e: 80 93 c2 00 sts 0x00C2, r24 + UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); + 3e22: 85 e1 ldi r24, 0x15 ; 21 + 3e24: 80 93 c4 00 sts 0x00C4, r24 +#endif +#endif // Set up watchdog to trigger after 500ms - watchdogConfig(WATCHDOG_500MS); - 3e26: 8d e0 ldi r24, 0x0D ; 13 - 3e28: c8 d0 rcall .+400 ; 0x3fba + watchdogConfig(WATCHDOG_1S); + 3e28: 8e e0 ldi r24, 0x0E ; 14 + 3e2a: cf d0 rcall .+414 ; 0x3fca /* Set LED pin as output */ LED_DDR |= _BV(LED); - 3e2a: 25 9a sbi 0x04, 5 ; 4 - 3e2c: 86 e0 ldi r24, 0x06 ; 6 + 3e2c: 25 9a sbi 0x04, 5 ; 4 + 3e2e: 86 e0 ldi r24, 0x06 ; 6 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - 3e2e: 2c e3 ldi r18, 0x3C ; 60 - 3e30: 3b ef ldi r19, 0xFB ; 251 + 3e30: 2c e3 ldi r18, 0x3C ; 60 + 3e32: 3b ef ldi r19, 0xFB ; 251 TIFR1 = _BV(TOV1); - 3e32: 91 e0 ldi r25, 0x01 ; 1 + 3e34: 91 e0 ldi r25, 0x01 ; 1 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - 3e34: 30 93 85 00 sts 0x0085, r19 - 3e38: 20 93 84 00 sts 0x0084, r18 + 3e36: 30 93 85 00 sts 0x0085, r19 + 3e3a: 20 93 84 00 sts 0x0084, r18 TIFR1 = _BV(TOV1); - 3e3c: 96 bb out 0x16, r25 ; 22 + 3e3e: 96 bb out 0x16, r25 ; 22 while(!(TIFR1 & _BV(TOV1))); - 3e3e: b0 9b sbis 0x16, 0 ; 22 - 3e40: fe cf rjmp .-4 ; 0x3e3e + 3e40: b0 9b sbis 0x16, 0 ; 22 + 3e42: fe cf rjmp .-4 ; 0x3e40 +#ifdef __AVR_ATmega8__ + LED_PORT ^= _BV(LED); +#else LED_PIN |= _BV(LED); - 3e42: 1d 9a sbi 0x03, 5 ; 3 + 3e44: 1d 9a sbi 0x03, 5 ; 3 return getch(); } // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 3e44: a8 95 wdr - TCNT1 = -(F_CPU/(1024*16)); - TIFR1 = _BV(TOV1); - while(!(TIFR1 & _BV(TOV1))); + 3e46: a8 95 wdr + LED_PORT ^= _BV(LED); +#else LED_PIN |= _BV(LED); +#endif watchdogReset(); } while (--count); - 3e46: 81 50 subi r24, 0x01 ; 1 - 3e48: a9 f7 brne .-22 ; 0x3e34 + 3e48: 81 50 subi r24, 0x01 ; 1 + 3e4a: a9 f7 brne .-22 ; 0x3e36 /* get character from UART */ ch = getch(); if(ch == STK_GET_PARAMETER) { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 3e4a: dd 24 eor r13, r13 - 3e4c: d3 94 inc r13 - boot_page_fill((uint16_t)(void*)addrPtr,a); + 3e4c: dd 24 eor r13, r13 + 3e4e: d3 94 inc r13 + __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); // Write from programming buffer - boot_page_write((uint16_t)(void*)address); - 3e4e: a5 e0 ldi r26, 0x05 ; 5 - 3e50: ea 2e mov r14, r26 + __boot_page_write_short((uint16_t)(void*)address); + 3e50: a5 e0 ldi r26, 0x05 ; 5 + 3e52: ea 2e mov r14, r26 boot_spm_busy_wait(); #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 3e52: f1 e1 ldi r31, 0x11 ; 17 - 3e54: ff 2e mov r15, r31 + 3e54: f1 e1 ldi r31, 0x11 ; 17 + 3e56: ff 2e mov r15, r31 #endif /* Forever loop */ for (;;) { /* get character from UART */ ch = getch(); - 3e56: a4 d0 rcall .+328 ; 0x3fa0 + 3e58: ab d0 rcall .+342 ; 0x3fb0 if(ch == STK_GET_PARAMETER) { - 3e58: 81 34 cpi r24, 0x41 ; 65 - 3e5a: 21 f4 brne .+8 ; 0x3e64 + 3e5a: 81 34 cpi r24, 0x41 ; 65 + 3e5c: 21 f4 brne .+8 ; 0x3e66 // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 3e5c: 81 e0 ldi r24, 0x01 ; 1 - 3e5e: be d0 rcall .+380 ; 0x3fdc + 3e5e: 81 e0 ldi r24, 0x01 ; 1 + 3e60: c5 d0 rcall .+394 ; 0x3fec putch(0x03); - 3e60: 83 e0 ldi r24, 0x03 ; 3 - 3e62: 24 c0 rjmp .+72 ; 0x3eac + 3e62: 83 e0 ldi r24, 0x03 ; 3 + 3e64: 20 c0 rjmp .+64 ; 0x3ea6 } else if(ch == STK_SET_DEVICE) { - 3e64: 82 34 cpi r24, 0x42 ; 66 - 3e66: 11 f4 brne .+4 ; 0x3e6c + 3e66: 82 34 cpi r24, 0x42 ; 66 + 3e68: 11 f4 brne .+4 ; 0x3e6e // SET DEVICE is ignored getNch(20); - 3e68: 84 e1 ldi r24, 0x14 ; 20 - 3e6a: 03 c0 rjmp .+6 ; 0x3e72 + 3e6a: 84 e1 ldi r24, 0x14 ; 20 + 3e6c: 03 c0 rjmp .+6 ; 0x3e74 } else if(ch == STK_SET_DEVICE_EXT) { - 3e6c: 85 34 cpi r24, 0x45 ; 69 - 3e6e: 19 f4 brne .+6 ; 0x3e76 + 3e6e: 85 34 cpi r24, 0x45 ; 69 + 3e70: 19 f4 brne .+6 ; 0x3e78 // SET DEVICE EXT is ignored getNch(5); - 3e70: 85 e0 ldi r24, 0x05 ; 5 - 3e72: b4 d0 rcall .+360 ; 0x3fdc - 3e74: 8a c0 rjmp .+276 ; 0x3f8a + 3e72: 85 e0 ldi r24, 0x05 ; 5 + 3e74: bb d0 rcall .+374 ; 0x3fec + 3e76: 91 c0 rjmp .+290 ; 0x3f9a } else if(ch == STK_LOAD_ADDRESS) { - 3e76: 85 35 cpi r24, 0x55 ; 85 - 3e78: a1 f4 brne .+40 ; 0x3ea2 + 3e78: 85 35 cpi r24, 0x55 ; 85 + 3e7a: 81 f4 brne .+32 ; 0x3e9c // LOAD ADDRESS - address = getch(); - 3e7a: 92 d0 rcall .+292 ; 0x3fa0 - 3e7c: 08 2f mov r16, r24 - 3e7e: 10 e0 ldi r17, 0x00 ; 0 - 3e80: 10 93 01 02 sts 0x0201, r17 - 3e84: 00 93 00 02 sts 0x0200, r16 - address = (address & 0xff) | (getch() << 8); - 3e88: 8b d0 rcall .+278 ; 0x3fa0 - 3e8a: 90 e0 ldi r25, 0x00 ; 0 - 3e8c: 98 2f mov r25, r24 - 3e8e: 88 27 eor r24, r24 - 3e90: 80 2b or r24, r16 - 3e92: 91 2b or r25, r17 - address += address; // Convert from word address to byte address - 3e94: 88 0f add r24, r24 - 3e96: 99 1f adc r25, r25 - 3e98: 90 93 01 02 sts 0x0201, r25 - 3e9c: 80 93 00 02 sts 0x0200, r24 - 3ea0: 73 c0 rjmp .+230 ; 0x3f88 + uint16_t newAddress; + newAddress = getch(); + 3e7c: 99 d0 rcall .+306 ; 0x3fb0 + newAddress = (newAddress & 0xff) | (getch() << 8); + 3e7e: 08 2f mov r16, r24 + 3e80: 10 e0 ldi r17, 0x00 ; 0 + 3e82: 96 d0 rcall .+300 ; 0x3fb0 + 3e84: 90 e0 ldi r25, 0x00 ; 0 + 3e86: 98 2f mov r25, r24 + 3e88: 88 27 eor r24, r24 + 3e8a: 80 2b or r24, r16 + 3e8c: 91 2b or r25, r17 +#ifdef RAMPZ + // Transfer top bit to RAMPZ + RAMPZ = (newAddress & 0x8000) ? 1 : 0; +#endif + newAddress += newAddress; // Convert from word address to byte address + 3e8e: 88 0f add r24, r24 + 3e90: 99 1f adc r25, r25 + address = newAddress; + 3e92: 90 93 01 02 sts 0x0201, r25 + 3e96: 80 93 00 02 sts 0x0200, r24 + 3e9a: 7e c0 rjmp .+252 ; 0x3f98 verifySpace(); } else if(ch == STK_UNIVERSAL) { - 3ea2: 86 35 cpi r24, 0x56 ; 86 - 3ea4: 29 f4 brne .+10 ; 0x3eb0 + 3e9c: 86 35 cpi r24, 0x56 ; 86 + 3e9e: 29 f4 brne .+10 ; 0x3eaa // UNIVERSAL command is ignored getNch(4); - 3ea6: 84 e0 ldi r24, 0x04 ; 4 - 3ea8: 99 d0 rcall .+306 ; 0x3fdc + 3ea0: 84 e0 ldi r24, 0x04 ; 4 + 3ea2: a4 d0 rcall .+328 ; 0x3fec putch(0x00); - 3eaa: 80 e0 ldi r24, 0x00 ; 0 - 3eac: 71 d0 rcall .+226 ; 0x3f90 - 3eae: 6d c0 rjmp .+218 ; 0x3f8a + 3ea4: 80 e0 ldi r24, 0x00 ; 0 + 3ea6: 7c d0 rcall .+248 ; 0x3fa0 + 3ea8: 78 c0 rjmp .+240 ; 0x3f9a } - /* Write memory, length is big endian and is in bytes */ + /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { - 3eb0: 84 36 cpi r24, 0x64 ; 100 - 3eb2: 09 f0 breq .+2 ; 0x3eb6 - 3eb4: 43 c0 rjmp .+134 ; 0x3f3c + 3eaa: 84 36 cpi r24, 0x64 ; 100 + 3eac: 09 f0 breq .+2 ; 0x3eb0 + 3eae: 4e c0 rjmp .+156 ; 0x3f4c // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t *bufPtr; uint16_t addrPtr; getLen(); - 3eb6: 7c d0 rcall .+248 ; 0x3fb0 + 3eb0: 87 d0 rcall .+270 ; 0x3fc0 - // Immediately start page erase - this will 4.5ms - boot_page_erase((uint16_t)(void*)address); - 3eb8: e0 91 00 02 lds r30, 0x0200 - 3ebc: f0 91 01 02 lds r31, 0x0201 - 3ec0: 83 e0 ldi r24, 0x03 ; 3 - 3ec2: 80 93 57 00 sts 0x0057, r24 + // If we are in RWW section, immediately start page erase + if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + 3eb2: e0 91 00 02 lds r30, 0x0200 + 3eb6: f0 91 01 02 lds r31, 0x0201 + 3eba: 88 e3 ldi r24, 0x38 ; 56 + 3ebc: e0 30 cpi r30, 0x00 ; 0 + 3ebe: f8 07 cpc r31, r24 + 3ec0: 18 f4 brcc .+6 ; 0x3ec8 + 3ec2: 83 e0 ldi r24, 0x03 ; 3 + 3ec4: 87 bf out 0x37, r24 ; 55 3ec6: e8 95 spm 3ec8: c0 e0 ldi r28, 0x00 ; 0 3eca: d1 e0 ldi r29, 0x01 ; 1 - + // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); - 3ecc: 69 d0 rcall .+210 ; 0x3fa0 + 3ecc: 71 d0 rcall .+226 ; 0x3fb0 3ece: 89 93 st Y+, r24 while (--length); 3ed0: 80 91 02 02 lds r24, 0x0202 @@ -242,279 +262,293 @@ void watchdogReset() { 3eda: 88 23 and r24, r24 3edc: b9 f7 brne .-18 ; 0x3ecc + // If we are in NRWW section, page erase has to be delayed until now. + // Todo: Take RAMPZ into account + if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + 3ede: e0 91 00 02 lds r30, 0x0200 + 3ee2: f0 91 01 02 lds r31, 0x0201 + 3ee6: 88 e3 ldi r24, 0x38 ; 56 + 3ee8: e0 30 cpi r30, 0x00 ; 0 + 3eea: f8 07 cpc r31, r24 + 3eec: 18 f0 brcs .+6 ; 0x3ef4 + 3eee: 83 e0 ldi r24, 0x03 ; 3 + 3ef0: 87 bf out 0x37, r24 ; 55 + 3ef2: e8 95 spm + // Read command terminator, start reply verifySpace(); - 3ede: 78 d0 rcall .+240 ; 0x3fd0 + 3ef4: 75 d0 rcall .+234 ; 0x3fe0 // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); - 3ee0: 07 b6 in r0, 0x37 ; 55 - 3ee2: 00 fc sbrc r0, 0 - 3ee4: fd cf rjmp .-6 ; 0x3ee0 + 3ef6: 07 b6 in r0, 0x37 ; 55 + 3ef8: 00 fc sbrc r0, 0 + 3efa: fd cf rjmp .-6 ; 0x3ef6 } #endif // Copy buffer into programming buffer bufPtr = buff; addrPtr = (uint16_t)(void*)address; - 3ee6: 40 91 00 02 lds r20, 0x0200 - 3eea: 50 91 01 02 lds r21, 0x0201 - 3eee: a0 e0 ldi r26, 0x00 ; 0 - 3ef0: b1 e0 ldi r27, 0x01 ; 1 + 3efc: 40 91 00 02 lds r20, 0x0200 + 3f00: 50 91 01 02 lds r21, 0x0201 + 3f04: a0 e0 ldi r26, 0x00 ; 0 + 3f06: b1 e0 ldi r27, 0x01 ; 1 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; - 3ef2: 2c 91 ld r18, X - 3ef4: 30 e0 ldi r19, 0x00 ; 0 + 3f08: 2c 91 ld r18, X + 3f0a: 30 e0 ldi r19, 0x00 ; 0 a |= (*bufPtr++) << 8; - 3ef6: 11 96 adiw r26, 0x01 ; 1 - 3ef8: 8c 91 ld r24, X - 3efa: 11 97 sbiw r26, 0x01 ; 1 - 3efc: 90 e0 ldi r25, 0x00 ; 0 - 3efe: 98 2f mov r25, r24 - 3f00: 88 27 eor r24, r24 - 3f02: 82 2b or r24, r18 - 3f04: 93 2b or r25, r19 -#ifdef VIRTUAL_BOOT_PARTITION -#define rstVect (*(uint16_t*)(0x204)) -#define wdtVect (*(uint16_t*)(0x206)) + 3f0c: 11 96 adiw r26, 0x01 ; 1 + 3f0e: 8c 91 ld r24, X + 3f10: 11 97 sbiw r26, 0x01 ; 1 + 3f12: 90 e0 ldi r25, 0x00 ; 0 + 3f14: 98 2f mov r25, r24 + 3f16: 88 27 eor r24, r24 + 3f18: 82 2b or r24, r18 + 3f1a: 93 2b or r25, r19 +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif + /* main program starts here */ int main(void) { - 3f06: 12 96 adiw r26, 0x02 ; 2 + 3f1c: 12 96 adiw r26, 0x02 ; 2 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; a |= (*bufPtr++) << 8; - boot_page_fill((uint16_t)(void*)addrPtr,a); - 3f08: fa 01 movw r30, r20 - 3f0a: 0c 01 movw r0, r24 - 3f0c: d0 92 57 00 sts 0x0057, r13 - 3f10: e8 95 spm - 3f12: 11 24 eor r1, r1 + __boot_page_fill_short((uint16_t)(void*)addrPtr,a); + 3f1e: fa 01 movw r30, r20 + 3f20: 0c 01 movw r0, r24 + 3f22: d7 be out 0x37, r13 ; 55 + 3f24: e8 95 spm + 3f26: 11 24 eor r1, r1 addrPtr += 2; - 3f14: 4e 5f subi r20, 0xFE ; 254 - 3f16: 5f 4f sbci r21, 0xFF ; 255 + 3f28: 4e 5f subi r20, 0xFE ; 254 + 3f2a: 5f 4f sbci r21, 0xFF ; 255 } while (--ch); - 3f18: f1 e0 ldi r31, 0x01 ; 1 - 3f1a: a0 38 cpi r26, 0x80 ; 128 - 3f1c: bf 07 cpc r27, r31 - 3f1e: 49 f7 brne .-46 ; 0x3ef2 + 3f2c: f1 e0 ldi r31, 0x01 ; 1 + 3f2e: a0 38 cpi r26, 0x80 ; 128 + 3f30: bf 07 cpc r27, r31 + 3f32: 51 f7 brne .-44 ; 0x3f08 // Write from programming buffer - boot_page_write((uint16_t)(void*)address); - 3f20: e0 91 00 02 lds r30, 0x0200 - 3f24: f0 91 01 02 lds r31, 0x0201 - 3f28: e0 92 57 00 sts 0x0057, r14 - 3f2c: e8 95 spm + __boot_page_write_short((uint16_t)(void*)address); + 3f34: e0 91 00 02 lds r30, 0x0200 + 3f38: f0 91 01 02 lds r31, 0x0201 + 3f3c: e7 be out 0x37, r14 ; 55 + 3f3e: e8 95 spm boot_spm_busy_wait(); - 3f2e: 07 b6 in r0, 0x37 ; 55 - 3f30: 00 fc sbrc r0, 0 - 3f32: fd cf rjmp .-6 ; 0x3f2e + 3f40: 07 b6 in r0, 0x37 ; 55 + 3f42: 00 fc sbrc r0, 0 + 3f44: fd cf rjmp .-6 ; 0x3f40 #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 3f34: f0 92 57 00 sts 0x0057, r15 - 3f38: e8 95 spm - 3f3a: 27 c0 rjmp .+78 ; 0x3f8a + 3f46: f7 be out 0x37, r15 ; 55 + 3f48: e8 95 spm + 3f4a: 27 c0 rjmp .+78 ; 0x3f9a #endif } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { - 3f3c: 84 37 cpi r24, 0x74 ; 116 - 3f3e: b9 f4 brne .+46 ; 0x3f6e + 3f4c: 84 37 cpi r24, 0x74 ; 116 + 3f4e: b9 f4 brne .+46 ; 0x3f7e // READ PAGE - we only read flash getLen(); - 3f40: 37 d0 rcall .+110 ; 0x3fb0 + 3f50: 37 d0 rcall .+110 ; 0x3fc0 verifySpace(); - 3f42: 46 d0 rcall .+140 ; 0x3fd0 - else ch = pgm_read_byte_near(address); + 3f52: 46 d0 rcall .+140 ; 0x3fe0 + putch(result); address++; - putch(ch); - } while (--length); + } + while (--length); #else do putch(pgm_read_byte_near(address++)); - 3f44: e0 91 00 02 lds r30, 0x0200 - 3f48: f0 91 01 02 lds r31, 0x0201 - 3f4c: 31 96 adiw r30, 0x01 ; 1 - 3f4e: f0 93 01 02 sts 0x0201, r31 - 3f52: e0 93 00 02 sts 0x0200, r30 - 3f56: 31 97 sbiw r30, 0x01 ; 1 - 3f58: e4 91 lpm r30, Z+ - 3f5a: 8e 2f mov r24, r30 - 3f5c: 19 d0 rcall .+50 ; 0x3f90 + 3f54: e0 91 00 02 lds r30, 0x0200 + 3f58: f0 91 01 02 lds r31, 0x0201 + 3f5c: 31 96 adiw r30, 0x01 ; 1 + 3f5e: f0 93 01 02 sts 0x0201, r31 + 3f62: e0 93 00 02 sts 0x0200, r30 + 3f66: 31 97 sbiw r30, 0x01 ; 1 + 3f68: e4 91 lpm r30, Z+ + 3f6a: 8e 2f mov r24, r30 + 3f6c: 19 d0 rcall .+50 ; 0x3fa0 while (--length); - 3f5e: 80 91 02 02 lds r24, 0x0202 - 3f62: 81 50 subi r24, 0x01 ; 1 - 3f64: 80 93 02 02 sts 0x0202, r24 - 3f68: 88 23 and r24, r24 - 3f6a: 61 f7 brne .-40 ; 0x3f44 - 3f6c: 0e c0 rjmp .+28 ; 0x3f8a + 3f6e: 80 91 02 02 lds r24, 0x0202 + 3f72: 81 50 subi r24, 0x01 ; 1 + 3f74: 80 93 02 02 sts 0x0202, r24 + 3f78: 88 23 and r24, r24 + 3f7a: 61 f7 brne .-40 ; 0x3f54 + 3f7c: 0e c0 rjmp .+28 ; 0x3f9a +#endif #endif } /* Get device signature bytes */ else if(ch == STK_READ_SIGN) { - 3f6e: 85 37 cpi r24, 0x75 ; 117 - 3f70: 39 f4 brne .+14 ; 0x3f80 + 3f7e: 85 37 cpi r24, 0x75 ; 117 + 3f80: 39 f4 brne .+14 ; 0x3f90 // READ SIGN - return what Avrdude wants to hear verifySpace(); - 3f72: 2e d0 rcall .+92 ; 0x3fd0 + 3f82: 2e d0 rcall .+92 ; 0x3fe0 putch(SIGNATURE_0); - 3f74: 8e e1 ldi r24, 0x1E ; 30 - 3f76: 0c d0 rcall .+24 ; 0x3f90 + 3f84: 8e e1 ldi r24, 0x1E ; 30 + 3f86: 0c d0 rcall .+24 ; 0x3fa0 putch(SIGNATURE_1); - 3f78: 84 e9 ldi r24, 0x94 ; 148 - 3f7a: 0a d0 rcall .+20 ; 0x3f90 + 3f88: 84 e9 ldi r24, 0x94 ; 148 + 3f8a: 0a d0 rcall .+20 ; 0x3fa0 putch(SIGNATURE_2); - 3f7c: 86 e0 ldi r24, 0x06 ; 6 - 3f7e: 96 cf rjmp .-212 ; 0x3eac + 3f8c: 86 e0 ldi r24, 0x06 ; 6 + 3f8e: 8b cf rjmp .-234 ; 0x3ea6 } else if (ch == 'Q') { - 3f80: 81 35 cpi r24, 0x51 ; 81 - 3f82: 11 f4 brne .+4 ; 0x3f88 + 3f90: 81 35 cpi r24, 0x51 ; 81 + 3f92: 11 f4 brne .+4 ; 0x3f98 // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); - 3f84: 88 e0 ldi r24, 0x08 ; 8 - 3f86: 19 d0 rcall .+50 ; 0x3fba + 3f94: 88 e0 ldi r24, 0x08 ; 8 + 3f96: 19 d0 rcall .+50 ; 0x3fca verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 3f88: 23 d0 rcall .+70 ; 0x3fd0 + 3f98: 23 d0 rcall .+70 ; 0x3fe0 } putch(STK_OK); - 3f8a: 80 e1 ldi r24, 0x10 ; 16 - 3f8c: 01 d0 rcall .+2 ; 0x3f90 - 3f8e: 63 cf rjmp .-314 ; 0x3e56 + 3f9a: 80 e1 ldi r24, 0x10 ; 16 + 3f9c: 01 d0 rcall .+2 ; 0x3fa0 + 3f9e: 5c cf rjmp .-328 ; 0x3e58 -00003f90 : +00003fa0 : } } void putch(char ch) { - 3f90: 98 2f mov r25, r24 + 3fa0: 98 2f mov r25, r24 #ifndef SOFT_UART while (!(UCSR0A & _BV(UDRE0))); - 3f92: 80 91 c0 00 lds r24, 0x00C0 - 3f96: 85 ff sbrs r24, 5 - 3f98: fc cf rjmp .-8 ; 0x3f92 + 3fa2: 80 91 c0 00 lds r24, 0x00C0 + 3fa6: 85 ff sbrs r24, 5 + 3fa8: fc cf rjmp .-8 ; 0x3fa2 UDR0 = ch; - 3f9a: 90 93 c6 00 sts 0x00C6, r25 + 3faa: 90 93 c6 00 sts 0x00C6, r25 [uartBit] "I" (UART_TX_BIT) : "r25" ); #endif } - 3f9e: 08 95 ret + 3fae: 08 95 ret -00003fa0 : +00003fb0 : return getch(); } // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 3fa0: a8 95 wdr + 3fb0: a8 95 wdr [uartBit] "I" (UART_RX_BIT) : "r25" ); #else while(!(UCSR0A & _BV(RXC0))); - 3fa2: 80 91 c0 00 lds r24, 0x00C0 - 3fa6: 87 ff sbrs r24, 7 - 3fa8: fc cf rjmp .-8 ; 0x3fa2 + 3fb2: 80 91 c0 00 lds r24, 0x00C0 + 3fb6: 87 ff sbrs r24, 7 + 3fb8: fc cf rjmp .-8 ; 0x3fb2 ch = UDR0; - 3faa: 80 91 c6 00 lds r24, 0x00C6 -#ifdef LED_DATA_FLASH + 3fba: 80 91 c6 00 lds r24, 0x00C6 LED_PIN |= _BV(LED); +#endif #endif return ch; } - 3fae: 08 95 ret + 3fbe: 08 95 ret -00003fb0 : +00003fc0 : } while (--count); } #endif uint8_t getLen() { getch(); - 3fb0: f7 df rcall .-18 ; 0x3fa0 + 3fc0: f7 df rcall .-18 ; 0x3fb0 length = getch(); - 3fb2: f6 df rcall .-20 ; 0x3fa0 - 3fb4: 80 93 02 02 sts 0x0202, r24 + 3fc2: f6 df rcall .-20 ; 0x3fb0 + 3fc4: 80 93 02 02 sts 0x0202, r24 return getch(); } - 3fb8: f3 cf rjmp .-26 ; 0x3fa0 + 3fc8: f3 cf rjmp .-26 ; 0x3fb0 -00003fba : +00003fca : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 3fba: e0 e6 ldi r30, 0x60 ; 96 - 3fbc: f0 e0 ldi r31, 0x00 ; 0 - 3fbe: 98 e1 ldi r25, 0x18 ; 24 - 3fc0: 90 83 st Z, r25 + 3fca: e0 e6 ldi r30, 0x60 ; 96 + 3fcc: f0 e0 ldi r31, 0x00 ; 0 + 3fce: 98 e1 ldi r25, 0x18 ; 24 + 3fd0: 90 83 st Z, r25 WDTCSR = x; - 3fc2: 80 83 st Z, r24 + 3fd2: 80 83 st Z, r24 } - 3fc4: 08 95 ret + 3fd4: 08 95 ret -00003fc6 : +00003fd6 : void appStart() { watchdogConfig(WATCHDOG_OFF); - 3fc6: 80 e0 ldi r24, 0x00 ; 0 - 3fc8: f8 df rcall .-16 ; 0x3fba + 3fd6: 80 e0 ldi r24, 0x00 ; 0 + 3fd8: f8 df rcall .-16 ; 0x3fca __asm__ __volatile__ ( - 3fca: ee 27 eor r30, r30 - 3fcc: ff 27 eor r31, r31 - 3fce: 09 94 ijmp + 3fda: ee 27 eor r30, r30 + 3fdc: ff 27 eor r31, r31 + 3fde: 09 94 ijmp -00003fd0 : +00003fe0 : do getch(); while (--count); verifySpace(); } void verifySpace() { if (getch() != CRC_EOP) appStart(); - 3fd0: e7 df rcall .-50 ; 0x3fa0 - 3fd2: 80 32 cpi r24, 0x20 ; 32 - 3fd4: 09 f0 breq .+2 ; 0x3fd8 - 3fd6: f7 df rcall .-18 ; 0x3fc6 + 3fe0: e7 df rcall .-50 ; 0x3fb0 + 3fe2: 80 32 cpi r24, 0x20 ; 32 + 3fe4: 09 f0 breq .+2 ; 0x3fe8 + 3fe6: f7 df rcall .-18 ; 0x3fd6 putch(STK_INSYNC); - 3fd8: 84 e1 ldi r24, 0x14 ; 20 + 3fe8: 84 e1 ldi r24, 0x14 ; 20 } - 3fda: da cf rjmp .-76 ; 0x3f90 + 3fea: da cf rjmp .-76 ; 0x3fa0 + +00003fec : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 3fdc: 1f 93 push r17 - 3fde: 18 2f mov r17, r24 - -00003fe0 : + 3fec: 1f 93 push r17 + 3fee: 18 2f mov r17, r24 do getch(); while (--count); - 3fe0: df df rcall .-66 ; 0x3fa0 - 3fe2: 11 50 subi r17, 0x01 ; 1 - 3fe4: e9 f7 brne .-6 ; 0x3fe0 + 3ff0: df df rcall .-66 ; 0x3fb0 + 3ff2: 11 50 subi r17, 0x01 ; 1 + 3ff4: e9 f7 brne .-6 ; 0x3ff0 verifySpace(); - 3fe6: f4 df rcall .-24 ; 0x3fd0 + 3ff6: f4 df rcall .-24 ; 0x3fe0 } - 3fe8: 1f 91 pop r17 - 3fea: 08 95 ret + 3ff8: 1f 91 pop r17 + 3ffa: 08 95 ret diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.hex b/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.hex index 9d31a7a18..757928697 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.hex @@ -1,34 +1,34 @@ -:103E000085E08093810084B714BE81FFE4D08DE00B -:103E1000DCD0259A519A86E028E13EEF91E030937C -:103E200085002093840096BBB09BFECF1D9AA89579 -:103E30008150A9F7DD24D394A5E0EA2EF1E1FF2E0D -:103E4000ABD0813421F481E0D1D083E024C082342E -:103E500011F484E103C0853419F485E0C7D08AC029 -:103E60008535A1F499D0082F10E01093010200933A -:103E7000000292D090E0982F8827802B912B880FFA -:103E8000991F909301028093000273C0863529F434 -:103E900084E0ACD080E071D06DC0843609F043C0BE -:103EA0008FD0E0910002F091010283E080935700EF -:103EB000E895C0E0D1E070D08993809102028150F2 -:103EC000809302028823B9F78BD007B600FCFDCFA0 -:103ED0004091000250910102A0E0B1E02C9130E04D -:103EE00011968C91119790E0982F8827822B932B15 -:103EF0001296FA010C01D0925700E89511244E5FFA -:103F00005F4FF1E0A038BF0749F7E0910002F09160 -:103F10000102E0925700E89507B600FCFDCFF09251 -:103F20005700E89527C08437B9F44AD059D0E091BA -:103F30000002F09101023196F0930102E093000239 -:103F40003197E4918E2F19D0809102028150809395 -:103F50000202882361F70EC0853739F441D08EE123 -:103F60000CD084E90AD086E096CF813511F488E040 -:103F70002CD036D080E101D063CF2AE030E08095AC -:103F8000089410F4599802C0599A000015D014D022 -:103F900086952A95B1F70895A89529E030E04899CB -:103FA000FECF0AD009D008D08894489908942A9561 -:103FB00011F08795F7CF089598E09A95F1F7089555 -:103FC000EBDFEADF80930202E7CFE0E6F0E098E182 +:103E0000112484B714BE81FFE6D085E08093810041 +:103E100082E08093C00088E18093C10086E08093B7 +:103E2000C20088E08093C4008EE0CFD0259A86E05F +:103E300028E13EEF91E0309385002093840096BB0B +:103E4000B09BFECF1D9AA8958150A9F7DD24D3948D +:103E5000A5E0EA2EF1E1FF2EABD0813421F481E020 +:103E6000C5D083E020C0823411F484E103C08534DE +:103E700019F485E0BBD091C0853581F499D0082F25 +:103E800010E096D090E0982F8827802B912B880FF8 +:103E9000991F90930102809300027EC0863529F419 +:103EA00084E0A4D080E07CD078C0843609F04EC095 +:103EB00087D0E0910002F091010288E3E030F8073A +:103EC00018F483E087BFE895C0E0D1E071D0899312 +:103ED000809102028150809302028823B9F7E09119 +:103EE0000002F091010288E3E030F80718F083E067 +:103EF00087BFE89575D007B600FCFDCF4091000262 +:103F000050910102A0E0B1E02C9130E011968C912B +:103F1000119790E0982F8827822B932B1296FA0105 +:103F20000C01D7BEE89511244E5F5F4FF1E0A03839 +:103F3000BF0751F7E0910002F0910102E7BEE8955A +:103F400007B600FCFDCFF7BEE89527C08437B9F46B +:103F500037D046D0E0910002F09101023196F09303 +:103F60000102E09300023197E4918E2F19D08091E5 +:103F70000202815080930202882361F70EC08537C8 +:103F800039F42ED08EE10CD084E90AD086E08BCFB4 +:103F9000813511F488E019D023D080E101D05CCFC5 +:103FA000982F8091C00085FFFCCF9093C6000895A4 +:103FB000A8958091C00087FFFCCF8091C60008952E +:103FC000F7DFF6DF80930202F3CFE0E6F0E098E15E :103FD00090838083089580E0F8DFEE27FF2709941F -:103FE000DBDF803209F0F7DF84E1C7CF1F93182FA2 -:0C3FF000D3DF1150E9F7F4DF1F910895B2 +:103FE000E7DF803209F0F7DF84E1DACF1F93182F83 +:0C3FF000DFDF1150E9F7F4DF1F910895A6 :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.lst b/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.lst index 94603e28e..25a4bd24c 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.lst @@ -7,452 +7,473 @@ Idx Name Size VMA LMA File off Algn CONTENTS, ALLOC, LOAD, READONLY, CODE 1 .debug_aranges 00000028 00000000 00000000 00000250 2**0 CONTENTS, READONLY, DEBUGGING - 2 .debug_pubnames 00000078 00000000 00000000 00000278 2**0 + 2 .debug_pubnames 0000006a 00000000 00000000 00000278 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_info 00000277 00000000 00000000 000002f0 2**0 + 3 .debug_info 00000284 00000000 00000000 000002e2 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_abbrev 00000194 00000000 00000000 00000567 2**0 + 4 .debug_abbrev 000001ae 00000000 00000000 00000566 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_line 000003bb 00000000 00000000 000006fb 2**0 + 5 .debug_line 00000450 00000000 00000000 00000714 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_frame 000000a0 00000000 00000000 00000ab8 2**2 + 6 .debug_frame 00000090 00000000 00000000 00000b64 2**2 CONTENTS, READONLY, DEBUGGING - 7 .debug_str 0000013f 00000000 00000000 00000b58 2**0 + 7 .debug_str 00000141 00000000 00000000 00000bf4 2**0 CONTENTS, READONLY, DEBUGGING - 8 .debug_loc 000001a0 00000000 00000000 00000c97 2**0 + 8 .debug_loc 000001e1 00000000 00000000 00000d35 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_ranges 00000070 00000000 00000000 00000e37 2**0 + 9 .debug_ranges 00000068 00000000 00000000 00000f16 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: 00003e00
    : -#ifdef VIRTUAL_BOOT_PARTITION -#define rstVect (*(uint16_t*)(0x204)) -#define wdtVect (*(uint16_t*)(0x206)) +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif + /* main program starts here */ int main(void) { - 3e00: 85 e0 ldi r24, 0x05 ; 5 - 3e02: 80 93 81 00 sts 0x0081, r24 - UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); - UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); + 3e00: 11 24 eor r1, r1 +#ifdef __AVR_ATmega8__ + SP=RAMEND; // This is done by hardware reset #endif // Adaboot no-wait mod ch = MCUSR; - 3e06: 84 b7 in r24, 0x34 ; 52 + 3e02: 84 b7 in r24, 0x34 ; 52 MCUSR = 0; - 3e08: 14 be out 0x34, r1 ; 52 + 3e04: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); - 3e0a: 81 ff sbrs r24, 1 - 3e0c: e4 d0 rcall .+456 ; 0x3fd6 + 3e06: 81 ff sbrs r24, 1 + 3e08: e6 d0 rcall .+460 ; 0x3fd6 + +#if LED_START_FLASHES > 0 + // Set up Timer 1 for timeout counter + TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 + 3e0a: 85 e0 ldi r24, 0x05 ; 5 + 3e0c: 80 93 81 00 sts 0x0081, r24 + UCSRA = _BV(U2X); //Double speed mode USART + UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx + UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 + UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); +#else + UCSR0A = _BV(U2X0); //Double speed mode USART0 + 3e10: 82 e0 ldi r24, 0x02 ; 2 + 3e12: 80 93 c0 00 sts 0x00C0, r24 + UCSR0B = _BV(RXEN0) | _BV(TXEN0); + 3e16: 88 e1 ldi r24, 0x18 ; 24 + 3e18: 80 93 c1 00 sts 0x00C1, r24 + UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); + 3e1c: 86 e0 ldi r24, 0x06 ; 6 + 3e1e: 80 93 c2 00 sts 0x00C2, r24 + UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); + 3e22: 88 e0 ldi r24, 0x08 ; 8 + 3e24: 80 93 c4 00 sts 0x00C4, r24 +#endif +#endif // Set up watchdog to trigger after 500ms - watchdogConfig(WATCHDOG_500MS); - 3e0e: 8d e0 ldi r24, 0x0D ; 13 - 3e10: dc d0 rcall .+440 ; 0x3fca + watchdogConfig(WATCHDOG_1S); + 3e28: 8e e0 ldi r24, 0x0E ; 14 + 3e2a: cf d0 rcall .+414 ; 0x3fca /* Set LED pin as output */ LED_DDR |= _BV(LED); - 3e12: 25 9a sbi 0x04, 5 ; 4 - -#ifdef SOFT_UART - /* Set TX pin as output */ - UART_DDR |= _BV(UART_TX_BIT); - 3e14: 51 9a sbi 0x0a, 1 ; 10 - 3e16: 86 e0 ldi r24, 0x06 ; 6 + 3e2c: 25 9a sbi 0x04, 5 ; 4 + 3e2e: 86 e0 ldi r24, 0x06 ; 6 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - 3e18: 28 e1 ldi r18, 0x18 ; 24 - 3e1a: 3e ef ldi r19, 0xFE ; 254 + 3e30: 28 e1 ldi r18, 0x18 ; 24 + 3e32: 3e ef ldi r19, 0xFE ; 254 TIFR1 = _BV(TOV1); - 3e1c: 91 e0 ldi r25, 0x01 ; 1 + 3e34: 91 e0 ldi r25, 0x01 ; 1 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - 3e1e: 30 93 85 00 sts 0x0085, r19 - 3e22: 20 93 84 00 sts 0x0084, r18 + 3e36: 30 93 85 00 sts 0x0085, r19 + 3e3a: 20 93 84 00 sts 0x0084, r18 TIFR1 = _BV(TOV1); - 3e26: 96 bb out 0x16, r25 ; 22 + 3e3e: 96 bb out 0x16, r25 ; 22 while(!(TIFR1 & _BV(TOV1))); - 3e28: b0 9b sbis 0x16, 0 ; 22 - 3e2a: fe cf rjmp .-4 ; 0x3e28 + 3e40: b0 9b sbis 0x16, 0 ; 22 + 3e42: fe cf rjmp .-4 ; 0x3e40 +#ifdef __AVR_ATmega8__ + LED_PORT ^= _BV(LED); +#else LED_PIN |= _BV(LED); - 3e2c: 1d 9a sbi 0x03, 5 ; 3 + 3e44: 1d 9a sbi 0x03, 5 ; 3 return getch(); } // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 3e2e: a8 95 wdr - TCNT1 = -(F_CPU/(1024*16)); - TIFR1 = _BV(TOV1); - while(!(TIFR1 & _BV(TOV1))); + 3e46: a8 95 wdr + LED_PORT ^= _BV(LED); +#else LED_PIN |= _BV(LED); +#endif watchdogReset(); } while (--count); - 3e30: 81 50 subi r24, 0x01 ; 1 - 3e32: a9 f7 brne .-22 ; 0x3e1e + 3e48: 81 50 subi r24, 0x01 ; 1 + 3e4a: a9 f7 brne .-22 ; 0x3e36 /* get character from UART */ ch = getch(); if(ch == STK_GET_PARAMETER) { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 3e34: dd 24 eor r13, r13 - 3e36: d3 94 inc r13 - boot_page_fill((uint16_t)(void*)addrPtr,a); + 3e4c: dd 24 eor r13, r13 + 3e4e: d3 94 inc r13 + __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); // Write from programming buffer - boot_page_write((uint16_t)(void*)address); - 3e38: a5 e0 ldi r26, 0x05 ; 5 - 3e3a: ea 2e mov r14, r26 + __boot_page_write_short((uint16_t)(void*)address); + 3e50: a5 e0 ldi r26, 0x05 ; 5 + 3e52: ea 2e mov r14, r26 boot_spm_busy_wait(); #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 3e3c: f1 e1 ldi r31, 0x11 ; 17 - 3e3e: ff 2e mov r15, r31 + 3e54: f1 e1 ldi r31, 0x11 ; 17 + 3e56: ff 2e mov r15, r31 #endif /* Forever loop */ for (;;) { /* get character from UART */ ch = getch(); - 3e40: ab d0 rcall .+342 ; 0x3f98 + 3e58: ab d0 rcall .+342 ; 0x3fb0 if(ch == STK_GET_PARAMETER) { - 3e42: 81 34 cpi r24, 0x41 ; 65 - 3e44: 21 f4 brne .+8 ; 0x3e4e + 3e5a: 81 34 cpi r24, 0x41 ; 65 + 3e5c: 21 f4 brne .+8 ; 0x3e66 // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 3e46: 81 e0 ldi r24, 0x01 ; 1 - 3e48: d1 d0 rcall .+418 ; 0x3fec + 3e5e: 81 e0 ldi r24, 0x01 ; 1 + 3e60: c5 d0 rcall .+394 ; 0x3fec putch(0x03); - 3e4a: 83 e0 ldi r24, 0x03 ; 3 - 3e4c: 24 c0 rjmp .+72 ; 0x3e96 + 3e62: 83 e0 ldi r24, 0x03 ; 3 + 3e64: 20 c0 rjmp .+64 ; 0x3ea6 } else if(ch == STK_SET_DEVICE) { - 3e4e: 82 34 cpi r24, 0x42 ; 66 - 3e50: 11 f4 brne .+4 ; 0x3e56 + 3e66: 82 34 cpi r24, 0x42 ; 66 + 3e68: 11 f4 brne .+4 ; 0x3e6e // SET DEVICE is ignored getNch(20); - 3e52: 84 e1 ldi r24, 0x14 ; 20 - 3e54: 03 c0 rjmp .+6 ; 0x3e5c + 3e6a: 84 e1 ldi r24, 0x14 ; 20 + 3e6c: 03 c0 rjmp .+6 ; 0x3e74 } else if(ch == STK_SET_DEVICE_EXT) { - 3e56: 85 34 cpi r24, 0x45 ; 69 - 3e58: 19 f4 brne .+6 ; 0x3e60 + 3e6e: 85 34 cpi r24, 0x45 ; 69 + 3e70: 19 f4 brne .+6 ; 0x3e78 // SET DEVICE EXT is ignored getNch(5); - 3e5a: 85 e0 ldi r24, 0x05 ; 5 - 3e5c: c7 d0 rcall .+398 ; 0x3fec - 3e5e: 8a c0 rjmp .+276 ; 0x3f74 + 3e72: 85 e0 ldi r24, 0x05 ; 5 + 3e74: bb d0 rcall .+374 ; 0x3fec + 3e76: 91 c0 rjmp .+290 ; 0x3f9a } else if(ch == STK_LOAD_ADDRESS) { - 3e60: 85 35 cpi r24, 0x55 ; 85 - 3e62: a1 f4 brne .+40 ; 0x3e8c + 3e78: 85 35 cpi r24, 0x55 ; 85 + 3e7a: 81 f4 brne .+32 ; 0x3e9c // LOAD ADDRESS - address = getch(); - 3e64: 99 d0 rcall .+306 ; 0x3f98 - 3e66: 08 2f mov r16, r24 - 3e68: 10 e0 ldi r17, 0x00 ; 0 - 3e6a: 10 93 01 02 sts 0x0201, r17 - 3e6e: 00 93 00 02 sts 0x0200, r16 - address = (address & 0xff) | (getch() << 8); - 3e72: 92 d0 rcall .+292 ; 0x3f98 - 3e74: 90 e0 ldi r25, 0x00 ; 0 - 3e76: 98 2f mov r25, r24 - 3e78: 88 27 eor r24, r24 - 3e7a: 80 2b or r24, r16 - 3e7c: 91 2b or r25, r17 - address += address; // Convert from word address to byte address - 3e7e: 88 0f add r24, r24 - 3e80: 99 1f adc r25, r25 - 3e82: 90 93 01 02 sts 0x0201, r25 - 3e86: 80 93 00 02 sts 0x0200, r24 - 3e8a: 73 c0 rjmp .+230 ; 0x3f72 + uint16_t newAddress; + newAddress = getch(); + 3e7c: 99 d0 rcall .+306 ; 0x3fb0 + newAddress = (newAddress & 0xff) | (getch() << 8); + 3e7e: 08 2f mov r16, r24 + 3e80: 10 e0 ldi r17, 0x00 ; 0 + 3e82: 96 d0 rcall .+300 ; 0x3fb0 + 3e84: 90 e0 ldi r25, 0x00 ; 0 + 3e86: 98 2f mov r25, r24 + 3e88: 88 27 eor r24, r24 + 3e8a: 80 2b or r24, r16 + 3e8c: 91 2b or r25, r17 +#ifdef RAMPZ + // Transfer top bit to RAMPZ + RAMPZ = (newAddress & 0x8000) ? 1 : 0; +#endif + newAddress += newAddress; // Convert from word address to byte address + 3e8e: 88 0f add r24, r24 + 3e90: 99 1f adc r25, r25 + address = newAddress; + 3e92: 90 93 01 02 sts 0x0201, r25 + 3e96: 80 93 00 02 sts 0x0200, r24 + 3e9a: 7e c0 rjmp .+252 ; 0x3f98 verifySpace(); } else if(ch == STK_UNIVERSAL) { - 3e8c: 86 35 cpi r24, 0x56 ; 86 - 3e8e: 29 f4 brne .+10 ; 0x3e9a + 3e9c: 86 35 cpi r24, 0x56 ; 86 + 3e9e: 29 f4 brne .+10 ; 0x3eaa // UNIVERSAL command is ignored getNch(4); - 3e90: 84 e0 ldi r24, 0x04 ; 4 - 3e92: ac d0 rcall .+344 ; 0x3fec + 3ea0: 84 e0 ldi r24, 0x04 ; 4 + 3ea2: a4 d0 rcall .+328 ; 0x3fec putch(0x00); - 3e94: 80 e0 ldi r24, 0x00 ; 0 - 3e96: 71 d0 rcall .+226 ; 0x3f7a - 3e98: 6d c0 rjmp .+218 ; 0x3f74 + 3ea4: 80 e0 ldi r24, 0x00 ; 0 + 3ea6: 7c d0 rcall .+248 ; 0x3fa0 + 3ea8: 78 c0 rjmp .+240 ; 0x3f9a } - /* Write memory, length is big endian and is in bytes */ + /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { - 3e9a: 84 36 cpi r24, 0x64 ; 100 - 3e9c: 09 f0 breq .+2 ; 0x3ea0 - 3e9e: 43 c0 rjmp .+134 ; 0x3f26 + 3eaa: 84 36 cpi r24, 0x64 ; 100 + 3eac: 09 f0 breq .+2 ; 0x3eb0 + 3eae: 4e c0 rjmp .+156 ; 0x3f4c // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t *bufPtr; uint16_t addrPtr; getLen(); - 3ea0: 8f d0 rcall .+286 ; 0x3fc0 - - // Immediately start page erase - this will 4.5ms - boot_page_erase((uint16_t)(void*)address); - 3ea2: e0 91 00 02 lds r30, 0x0200 - 3ea6: f0 91 01 02 lds r31, 0x0201 - 3eaa: 83 e0 ldi r24, 0x03 ; 3 - 3eac: 80 93 57 00 sts 0x0057, r24 - 3eb0: e8 95 spm - 3eb2: c0 e0 ldi r28, 0x00 ; 0 - 3eb4: d1 e0 ldi r29, 0x01 ; 1 + 3eb0: 87 d0 rcall .+270 ; 0x3fc0 + // If we are in RWW section, immediately start page erase + if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + 3eb2: e0 91 00 02 lds r30, 0x0200 + 3eb6: f0 91 01 02 lds r31, 0x0201 + 3eba: 88 e3 ldi r24, 0x38 ; 56 + 3ebc: e0 30 cpi r30, 0x00 ; 0 + 3ebe: f8 07 cpc r31, r24 + 3ec0: 18 f4 brcc .+6 ; 0x3ec8 + 3ec2: 83 e0 ldi r24, 0x03 ; 3 + 3ec4: 87 bf out 0x37, r24 ; 55 + 3ec6: e8 95 spm + 3ec8: c0 e0 ldi r28, 0x00 ; 0 + 3eca: d1 e0 ldi r29, 0x01 ; 1 + // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); - 3eb6: 70 d0 rcall .+224 ; 0x3f98 - 3eb8: 89 93 st Y+, r24 + 3ecc: 71 d0 rcall .+226 ; 0x3fb0 + 3ece: 89 93 st Y+, r24 while (--length); - 3eba: 80 91 02 02 lds r24, 0x0202 - 3ebe: 81 50 subi r24, 0x01 ; 1 - 3ec0: 80 93 02 02 sts 0x0202, r24 - 3ec4: 88 23 and r24, r24 - 3ec6: b9 f7 brne .-18 ; 0x3eb6 + 3ed0: 80 91 02 02 lds r24, 0x0202 + 3ed4: 81 50 subi r24, 0x01 ; 1 + 3ed6: 80 93 02 02 sts 0x0202, r24 + 3eda: 88 23 and r24, r24 + 3edc: b9 f7 brne .-18 ; 0x3ecc + + // If we are in NRWW section, page erase has to be delayed until now. + // Todo: Take RAMPZ into account + if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + 3ede: e0 91 00 02 lds r30, 0x0200 + 3ee2: f0 91 01 02 lds r31, 0x0201 + 3ee6: 88 e3 ldi r24, 0x38 ; 56 + 3ee8: e0 30 cpi r30, 0x00 ; 0 + 3eea: f8 07 cpc r31, r24 + 3eec: 18 f0 brcs .+6 ; 0x3ef4 + 3eee: 83 e0 ldi r24, 0x03 ; 3 + 3ef0: 87 bf out 0x37, r24 ; 55 + 3ef2: e8 95 spm // Read command terminator, start reply verifySpace(); - 3ec8: 8b d0 rcall .+278 ; 0x3fe0 + 3ef4: 75 d0 rcall .+234 ; 0x3fe0 // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); - 3eca: 07 b6 in r0, 0x37 ; 55 - 3ecc: 00 fc sbrc r0, 0 - 3ece: fd cf rjmp .-6 ; 0x3eca + 3ef6: 07 b6 in r0, 0x37 ; 55 + 3ef8: 00 fc sbrc r0, 0 + 3efa: fd cf rjmp .-6 ; 0x3ef6 } #endif // Copy buffer into programming buffer bufPtr = buff; addrPtr = (uint16_t)(void*)address; - 3ed0: 40 91 00 02 lds r20, 0x0200 - 3ed4: 50 91 01 02 lds r21, 0x0201 - 3ed8: a0 e0 ldi r26, 0x00 ; 0 - 3eda: b1 e0 ldi r27, 0x01 ; 1 + 3efc: 40 91 00 02 lds r20, 0x0200 + 3f00: 50 91 01 02 lds r21, 0x0201 + 3f04: a0 e0 ldi r26, 0x00 ; 0 + 3f06: b1 e0 ldi r27, 0x01 ; 1 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; - 3edc: 2c 91 ld r18, X - 3ede: 30 e0 ldi r19, 0x00 ; 0 + 3f08: 2c 91 ld r18, X + 3f0a: 30 e0 ldi r19, 0x00 ; 0 a |= (*bufPtr++) << 8; - 3ee0: 11 96 adiw r26, 0x01 ; 1 - 3ee2: 8c 91 ld r24, X - 3ee4: 11 97 sbiw r26, 0x01 ; 1 - 3ee6: 90 e0 ldi r25, 0x00 ; 0 - 3ee8: 98 2f mov r25, r24 - 3eea: 88 27 eor r24, r24 - 3eec: 82 2b or r24, r18 - 3eee: 93 2b or r25, r19 -#ifdef VIRTUAL_BOOT_PARTITION -#define rstVect (*(uint16_t*)(0x204)) -#define wdtVect (*(uint16_t*)(0x206)) + 3f0c: 11 96 adiw r26, 0x01 ; 1 + 3f0e: 8c 91 ld r24, X + 3f10: 11 97 sbiw r26, 0x01 ; 1 + 3f12: 90 e0 ldi r25, 0x00 ; 0 + 3f14: 98 2f mov r25, r24 + 3f16: 88 27 eor r24, r24 + 3f18: 82 2b or r24, r18 + 3f1a: 93 2b or r25, r19 +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif + /* main program starts here */ int main(void) { - 3ef0: 12 96 adiw r26, 0x02 ; 2 + 3f1c: 12 96 adiw r26, 0x02 ; 2 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; a |= (*bufPtr++) << 8; - boot_page_fill((uint16_t)(void*)addrPtr,a); - 3ef2: fa 01 movw r30, r20 - 3ef4: 0c 01 movw r0, r24 - 3ef6: d0 92 57 00 sts 0x0057, r13 - 3efa: e8 95 spm - 3efc: 11 24 eor r1, r1 + __boot_page_fill_short((uint16_t)(void*)addrPtr,a); + 3f1e: fa 01 movw r30, r20 + 3f20: 0c 01 movw r0, r24 + 3f22: d7 be out 0x37, r13 ; 55 + 3f24: e8 95 spm + 3f26: 11 24 eor r1, r1 addrPtr += 2; - 3efe: 4e 5f subi r20, 0xFE ; 254 - 3f00: 5f 4f sbci r21, 0xFF ; 255 + 3f28: 4e 5f subi r20, 0xFE ; 254 + 3f2a: 5f 4f sbci r21, 0xFF ; 255 } while (--ch); - 3f02: f1 e0 ldi r31, 0x01 ; 1 - 3f04: a0 38 cpi r26, 0x80 ; 128 - 3f06: bf 07 cpc r27, r31 - 3f08: 49 f7 brne .-46 ; 0x3edc + 3f2c: f1 e0 ldi r31, 0x01 ; 1 + 3f2e: a0 38 cpi r26, 0x80 ; 128 + 3f30: bf 07 cpc r27, r31 + 3f32: 51 f7 brne .-44 ; 0x3f08 // Write from programming buffer - boot_page_write((uint16_t)(void*)address); - 3f0a: e0 91 00 02 lds r30, 0x0200 - 3f0e: f0 91 01 02 lds r31, 0x0201 - 3f12: e0 92 57 00 sts 0x0057, r14 - 3f16: e8 95 spm + __boot_page_write_short((uint16_t)(void*)address); + 3f34: e0 91 00 02 lds r30, 0x0200 + 3f38: f0 91 01 02 lds r31, 0x0201 + 3f3c: e7 be out 0x37, r14 ; 55 + 3f3e: e8 95 spm boot_spm_busy_wait(); - 3f18: 07 b6 in r0, 0x37 ; 55 - 3f1a: 00 fc sbrc r0, 0 - 3f1c: fd cf rjmp .-6 ; 0x3f18 + 3f40: 07 b6 in r0, 0x37 ; 55 + 3f42: 00 fc sbrc r0, 0 + 3f44: fd cf rjmp .-6 ; 0x3f40 #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 3f1e: f0 92 57 00 sts 0x0057, r15 - 3f22: e8 95 spm - 3f24: 27 c0 rjmp .+78 ; 0x3f74 + 3f46: f7 be out 0x37, r15 ; 55 + 3f48: e8 95 spm + 3f4a: 27 c0 rjmp .+78 ; 0x3f9a #endif } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { - 3f26: 84 37 cpi r24, 0x74 ; 116 - 3f28: b9 f4 brne .+46 ; 0x3f58 + 3f4c: 84 37 cpi r24, 0x74 ; 116 + 3f4e: b9 f4 brne .+46 ; 0x3f7e // READ PAGE - we only read flash getLen(); - 3f2a: 4a d0 rcall .+148 ; 0x3fc0 + 3f50: 37 d0 rcall .+110 ; 0x3fc0 verifySpace(); - 3f2c: 59 d0 rcall .+178 ; 0x3fe0 - else ch = pgm_read_byte_near(address); + 3f52: 46 d0 rcall .+140 ; 0x3fe0 + putch(result); address++; - putch(ch); - } while (--length); + } + while (--length); #else do putch(pgm_read_byte_near(address++)); - 3f2e: e0 91 00 02 lds r30, 0x0200 - 3f32: f0 91 01 02 lds r31, 0x0201 - 3f36: 31 96 adiw r30, 0x01 ; 1 - 3f38: f0 93 01 02 sts 0x0201, r31 - 3f3c: e0 93 00 02 sts 0x0200, r30 - 3f40: 31 97 sbiw r30, 0x01 ; 1 - 3f42: e4 91 lpm r30, Z+ - 3f44: 8e 2f mov r24, r30 - 3f46: 19 d0 rcall .+50 ; 0x3f7a + 3f54: e0 91 00 02 lds r30, 0x0200 + 3f58: f0 91 01 02 lds r31, 0x0201 + 3f5c: 31 96 adiw r30, 0x01 ; 1 + 3f5e: f0 93 01 02 sts 0x0201, r31 + 3f62: e0 93 00 02 sts 0x0200, r30 + 3f66: 31 97 sbiw r30, 0x01 ; 1 + 3f68: e4 91 lpm r30, Z+ + 3f6a: 8e 2f mov r24, r30 + 3f6c: 19 d0 rcall .+50 ; 0x3fa0 while (--length); - 3f48: 80 91 02 02 lds r24, 0x0202 - 3f4c: 81 50 subi r24, 0x01 ; 1 - 3f4e: 80 93 02 02 sts 0x0202, r24 - 3f52: 88 23 and r24, r24 - 3f54: 61 f7 brne .-40 ; 0x3f2e - 3f56: 0e c0 rjmp .+28 ; 0x3f74 + 3f6e: 80 91 02 02 lds r24, 0x0202 + 3f72: 81 50 subi r24, 0x01 ; 1 + 3f74: 80 93 02 02 sts 0x0202, r24 + 3f78: 88 23 and r24, r24 + 3f7a: 61 f7 brne .-40 ; 0x3f54 + 3f7c: 0e c0 rjmp .+28 ; 0x3f9a +#endif #endif } /* Get device signature bytes */ else if(ch == STK_READ_SIGN) { - 3f58: 85 37 cpi r24, 0x75 ; 117 - 3f5a: 39 f4 brne .+14 ; 0x3f6a + 3f7e: 85 37 cpi r24, 0x75 ; 117 + 3f80: 39 f4 brne .+14 ; 0x3f90 // READ SIGN - return what Avrdude wants to hear verifySpace(); - 3f5c: 41 d0 rcall .+130 ; 0x3fe0 + 3f82: 2e d0 rcall .+92 ; 0x3fe0 putch(SIGNATURE_0); - 3f5e: 8e e1 ldi r24, 0x1E ; 30 - 3f60: 0c d0 rcall .+24 ; 0x3f7a + 3f84: 8e e1 ldi r24, 0x1E ; 30 + 3f86: 0c d0 rcall .+24 ; 0x3fa0 putch(SIGNATURE_1); - 3f62: 84 e9 ldi r24, 0x94 ; 148 - 3f64: 0a d0 rcall .+20 ; 0x3f7a + 3f88: 84 e9 ldi r24, 0x94 ; 148 + 3f8a: 0a d0 rcall .+20 ; 0x3fa0 putch(SIGNATURE_2); - 3f66: 86 e0 ldi r24, 0x06 ; 6 - 3f68: 96 cf rjmp .-212 ; 0x3e96 + 3f8c: 86 e0 ldi r24, 0x06 ; 6 + 3f8e: 8b cf rjmp .-234 ; 0x3ea6 } else if (ch == 'Q') { - 3f6a: 81 35 cpi r24, 0x51 ; 81 - 3f6c: 11 f4 brne .+4 ; 0x3f72 + 3f90: 81 35 cpi r24, 0x51 ; 81 + 3f92: 11 f4 brne .+4 ; 0x3f98 // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); - 3f6e: 88 e0 ldi r24, 0x08 ; 8 - 3f70: 2c d0 rcall .+88 ; 0x3fca + 3f94: 88 e0 ldi r24, 0x08 ; 8 + 3f96: 19 d0 rcall .+50 ; 0x3fca verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 3f72: 36 d0 rcall .+108 ; 0x3fe0 + 3f98: 23 d0 rcall .+70 ; 0x3fe0 } putch(STK_OK); - 3f74: 80 e1 ldi r24, 0x10 ; 16 - 3f76: 01 d0 rcall .+2 ; 0x3f7a - 3f78: 63 cf rjmp .-314 ; 0x3e40 + 3f9a: 80 e1 ldi r24, 0x10 ; 16 + 3f9c: 01 d0 rcall .+2 ; 0x3fa0 + 3f9e: 5c cf rjmp .-328 ; 0x3e58 + +00003fa0 : + } +} -00003f7a : void putch(char ch) { + 3fa0: 98 2f mov r25, r24 #ifndef SOFT_UART while (!(UCSR0A & _BV(UDRE0))); + 3fa2: 80 91 c0 00 lds r24, 0x00C0 + 3fa6: 85 ff sbrs r24, 5 + 3fa8: fc cf rjmp .-8 ; 0x3fa2 UDR0 = ch; -#else - __asm__ __volatile__ ( - 3f7a: 2a e0 ldi r18, 0x0A ; 10 - 3f7c: 30 e0 ldi r19, 0x00 ; 0 - 3f7e: 80 95 com r24 - 3f80: 08 94 sec - 3f82: 10 f4 brcc .+4 ; 0x3f88 - 3f84: 59 98 cbi 0x0b, 1 ; 11 - 3f86: 02 c0 rjmp .+4 ; 0x3f8c - 3f88: 59 9a sbi 0x0b, 1 ; 11 - 3f8a: 00 00 nop - 3f8c: 15 d0 rcall .+42 ; 0x3fb8 - 3f8e: 14 d0 rcall .+40 ; 0x3fb8 - 3f90: 86 95 lsr r24 - 3f92: 2a 95 dec r18 - 3f94: b1 f7 brne .-20 ; 0x3f82 + 3faa: 90 93 c6 00 sts 0x00C6, r25 [uartBit] "I" (UART_TX_BIT) : "r25" ); #endif } - 3f96: 08 95 ret + 3fae: 08 95 ret -00003f98 : +00003fb0 : return getch(); } // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 3f98: a8 95 wdr -#ifdef LED_DATA_FLASH + 3fb0: a8 95 wdr + [uartBit] "I" (UART_RX_BIT) + : + "r25" +); +#else + while(!(UCSR0A & _BV(RXC0))); + 3fb2: 80 91 c0 00 lds r24, 0x00C0 + 3fb6: 87 ff sbrs r24, 7 + 3fb8: fc cf rjmp .-8 ; 0x3fb2 + ch = UDR0; + 3fba: 80 91 c6 00 lds r24, 0x00C6 LED_PIN |= _BV(LED); +#endif #endif return ch; } - 3f9a: 29 e0 ldi r18, 0x09 ; 9 - 3f9c: 30 e0 ldi r19, 0x00 ; 0 - 3f9e: 48 99 sbic 0x09, 0 ; 9 - 3fa0: fe cf rjmp .-4 ; 0x3f9e - 3fa2: 0a d0 rcall .+20 ; 0x3fb8 - 3fa4: 09 d0 rcall .+18 ; 0x3fb8 - 3fa6: 08 d0 rcall .+16 ; 0x3fb8 - 3fa8: 88 94 clc - 3faa: 48 99 sbic 0x09, 0 ; 9 - 3fac: 08 94 sec - 3fae: 2a 95 dec r18 - 3fb0: 11 f0 breq .+4 ; 0x3fb6 - 3fb2: 87 95 ror r24 - 3fb4: f7 cf rjmp .-18 ; 0x3fa4 - 3fb6: 08 95 ret - -00003fb8 : -#if UART_B_VALUE > 255 -#error Baud rate too slow for soft UART -#endif - -void uartDelay() { - __asm__ __volatile__ ( - 3fb8: 98 e0 ldi r25, 0x08 ; 8 - 3fba: 9a 95 dec r25 - 3fbc: f1 f7 brne .-4 ; 0x3fba 3fbe: 08 95 ret 00003fc0 : @@ -462,13 +483,13 @@ void uartDelay() { uint8_t getLen() { getch(); - 3fc0: eb df rcall .-42 ; 0x3f98 + 3fc0: f7 df rcall .-18 ; 0x3fb0 length = getch(); - 3fc2: ea df rcall .-44 ; 0x3f98 + 3fc2: f6 df rcall .-20 ; 0x3fb0 3fc4: 80 93 02 02 sts 0x0202, r24 return getch(); } - 3fc8: e7 cf rjmp .-50 ; 0x3f98 + 3fc8: f3 cf rjmp .-26 ; 0x3fb0 00003fca : "wdr\n" @@ -504,14 +525,16 @@ void appStart() { void verifySpace() { if (getch() != CRC_EOP) appStart(); - 3fe0: db df rcall .-74 ; 0x3f98 + 3fe0: e7 df rcall .-50 ; 0x3fb0 3fe2: 80 32 cpi r24, 0x20 ; 32 3fe4: 09 f0 breq .+2 ; 0x3fe8 3fe6: f7 df rcall .-18 ; 0x3fd6 putch(STK_INSYNC); 3fe8: 84 e1 ldi r24, 0x14 ; 20 } - 3fea: c7 cf rjmp .-114 ; 0x3f7a + 3fea: da cf rjmp .-76 ; 0x3fa0 + +00003fec : ::[count] "M" (UART_B_VALUE) ); } @@ -520,12 +543,10 @@ void verifySpace() { void getNch(uint8_t count) { 3fec: 1f 93 push r17 3fee: 18 2f mov r17, r24 - -00003ff0 : do getch(); while (--count); - 3ff0: d3 df rcall .-90 ; 0x3f98 + 3ff0: df df rcall .-66 ; 0x3fb0 3ff2: 11 50 subi r17, 0x01 ; 1 - 3ff4: e9 f7 brne .-6 ; 0x3ff0 + 3ff4: e9 f7 brne .-6 ; 0x3ff0 verifySpace(); 3ff6: f4 df rcall .-24 ; 0x3fe0 } diff --git a/hardware/arduino/bootloaders/optiboot/pin_defs.h b/hardware/arduino/bootloaders/optiboot/pin_defs.h new file mode 100644 index 000000000..313e45385 --- /dev/null +++ b/hardware/arduino/bootloaders/optiboot/pin_defs.h @@ -0,0 +1,79 @@ +#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__) +/* Onboard LED is connected to pin PB5 in Arduino NG, Diecimila, and Duemilanove */ +#define LED_DDR DDRB +#define LED_PORT PORTB +#define LED_PIN PINB +#define LED PINB5 + +/* Ports for soft UART */ +#ifdef SOFT_UART +#define UART_PORT PORTD +#define UART_PIN PIND +#define UART_DDR DDRD +#define UART_TX_BIT 1 +#define UART_RX_BIT 0 +#endif +#endif + +#if defined(__AVR_ATmega8__) + //Name conversion R.Wiersma + #define UCSR0A UCSRA + #define UDR0 UDR + #define UDRE0 UDRE + #define RXC0 RXC + #define TIFR1 TIFR + #define WDTCSR WDTCR +#endif + +/* Luminet support */ +#if defined(__AVR_ATtiny84__) +/* Red LED is connected to pin PA4 */ +#define LED_DDR DDRA +#define LED_PORT PORTA +#define LED_PIN PINA +#define LED PINA4 +/* Ports for soft UART - left port only for now. TX/RX on PA2/PA3 */ +#ifdef SOFT_UART +#define UART_PORT PORTA +#define UART_PIN PINA +#define UART_DDR DDRA +#define UART_TX_BIT 2 +#define UART_RX_BIT 3 +#endif +#endif + +/* Sanguino support */ +#if defined(__AVR_ATmega644P__) +/* Onboard LED is connected to pin PB0 on Sanguino */ +#define LED_DDR DDRB +#define LED_PORT PORTB +#define LED_PIN PINB +#define LED PINB0 + +/* Ports for soft UART */ +#ifdef SOFT_UART +#define UART_PORT PORTD +#define UART_PIN PIND +#define UART_DDR DDRD +#define UART_TX_BIT 1 +#define UART_RX_BIT 0 +#endif +#endif + +/* Mega support */ +#if defined(__AVR_ATmega1280__) +/* Onboard LED is connected to pin PB7 on Arduino Mega */ +#define LED_DDR DDRB +#define LED_PORT PORTB +#define LED_PIN PINB +#define LED PINB7 + +/* Ports for soft UART */ +#ifdef SOFT_UART +#define UART_PORT PORTE +#define UART_PIN PINE +#define UART_DDR DDRE +#define UART_TX_BIT 1 +#define UART_RX_BIT 0 +#endif +#endif diff --git a/hardware/arduino/bootloaders/optiboot/stk500.h b/hardware/arduino/bootloaders/optiboot/stk500.h new file mode 100644 index 000000000..ca0dd91df --- /dev/null +++ b/hardware/arduino/bootloaders/optiboot/stk500.h @@ -0,0 +1,39 @@ +/* STK500 constants list, from AVRDUDE */ +#define STK_OK 0x10 +#define STK_FAILED 0x11 // Not used +#define STK_UNKNOWN 0x12 // Not used +#define STK_NODEVICE 0x13 // Not used +#define STK_INSYNC 0x14 // ' ' +#define STK_NOSYNC 0x15 // Not used +#define ADC_CHANNEL_ERROR 0x16 // Not used +#define ADC_MEASURE_OK 0x17 // Not used +#define PWM_CHANNEL_ERROR 0x18 // Not used +#define PWM_ADJUST_OK 0x19 // Not used +#define CRC_EOP 0x20 // 'SPACE' +#define STK_GET_SYNC 0x30 // '0' +#define STK_GET_SIGN_ON 0x31 // '1' +#define STK_SET_PARAMETER 0x40 // '@' +#define STK_GET_PARAMETER 0x41 // 'A' +#define STK_SET_DEVICE 0x42 // 'B' +#define STK_SET_DEVICE_EXT 0x45 // 'E' +#define STK_ENTER_PROGMODE 0x50 // 'P' +#define STK_LEAVE_PROGMODE 0x51 // 'Q' +#define STK_CHIP_ERASE 0x52 // 'R' +#define STK_CHECK_AUTOINC 0x53 // 'S' +#define STK_LOAD_ADDRESS 0x55 // 'U' +#define STK_UNIVERSAL 0x56 // 'V' +#define STK_PROG_FLASH 0x60 // '`' +#define STK_PROG_DATA 0x61 // 'a' +#define STK_PROG_FUSE 0x62 // 'b' +#define STK_PROG_LOCK 0x63 // 'c' +#define STK_PROG_PAGE 0x64 // 'd' +#define STK_PROG_FUSE_EXT 0x65 // 'e' +#define STK_READ_FLASH 0x70 // 'p' +#define STK_READ_DATA 0x71 // 'q' +#define STK_READ_FUSE 0x72 // 'r' +#define STK_READ_LOCK 0x73 // 's' +#define STK_READ_PAGE 0x74 // 't' +#define STK_READ_SIGN 0x75 // 'u' +#define STK_READ_OSCCAL 0x76 // 'v' +#define STK_READ_FUSE_EXT 0x77 // 'w' +#define STK_READ_OSCCAL_EXT 0x78 // 'x' From d4632cb09593e44bc8624c6b9a432c672fe4ad45 Mon Sep 17 00:00:00 2001 From: WestfW Date: Fri, 10 Jun 2011 16:29:34 -0700 Subject: [PATCH 22/33] Update shell script makeall --- hardware/arduino/bootloaders/optiboot/makeall | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hardware/arduino/bootloaders/optiboot/makeall b/hardware/arduino/bootloaders/optiboot/makeall index 7a0b82d0b..b92c56e35 100755 --- a/hardware/arduino/bootloaders/optiboot/makeall +++ b/hardware/arduino/bootloaders/optiboot/makeall @@ -6,8 +6,10 @@ make pro8 make pro16 make pro20 make diecimila -make ng make atmega328 make atmega328_pro8 +make sanguino +make mega +make atmega8 +make atmega88 make luminet - From 00706284dec3171646419839bd4a9e3f1c2d7088 Mon Sep 17 00:00:00 2001 From: WestfW Date: Fri, 10 Jun 2011 17:47:47 -0700 Subject: [PATCH 23/33] Add a version number to the optiboot source and binary. http://code.google.com/p/arduino/issues/detail?id=554 end of flash memory where they can be read (at least in theory) by device programmers, hex-file examination, or application programs. This is done by putting the version number in a separate section (".version"), and using linker/objcopy magic to locate that section as appropriate for the target chip. (See http://lists.gnu.org/archive/html/avr-gcc-list/2011-02/msg00016.html for some discussion on the details.) Start the version at 4.1 (the last "packaged" version of optiboot was called version 3, so the "top of source" would be 4.0, and adding the version number makes 4.1) Refactor LDSECTION in the Makefile to LDSECTIONS so that multiple section start addresses can be defined. Change the _isp makefile definitions to make the bootloader section readable (but not writable) by the application section. (This would need to be done elsewhere as well to handle all bootloader programming techniques. Notably Arduino's boards.txt Note that this change does not change the "code" portion of optiboot at all. The only diffs in the .hex files are the added version word at the end of flash memory. --- .../arduino/bootloaders/optiboot/Makefile | 26 +- .../arduino/bootloaders/optiboot/optiboot.c | 38 +- .../optiboot/optiboot_atmega328.hex | 1 + .../optiboot/optiboot_atmega328.lst | 28 +- .../optiboot/optiboot_atmega328_pro_8MHz.hex | 66 +- .../optiboot/optiboot_atmega328_pro_8MHz.lst | 494 +++++++------- .../optiboot/optiboot_diecimila.hex | 1 + .../optiboot/optiboot_diecimila.lst | 28 +- .../bootloaders/optiboot/optiboot_lilypad.hex | 1 + .../bootloaders/optiboot/optiboot_lilypad.lst | 28 +- .../optiboot/optiboot_lilypad_resonator.hex | 1 + .../optiboot/optiboot_lilypad_resonator.lst | 28 +- .../bootloaders/optiboot/optiboot_luminet.hex | 82 +-- .../bootloaders/optiboot/optiboot_luminet.lst | 602 +++++++++--------- .../optiboot/optiboot_pro_16MHz.hex | 1 + .../optiboot/optiboot_pro_16MHz.lst | 28 +- .../optiboot/optiboot_pro_20mhz.hex | 1 + .../optiboot/optiboot_pro_20mhz.lst | 28 +- .../optiboot/optiboot_pro_8MHz.hex | 1 + .../optiboot/optiboot_pro_8MHz.lst | 28 +- 20 files changed, 783 insertions(+), 728 deletions(-) diff --git a/hardware/arduino/bootloaders/optiboot/Makefile b/hardware/arduino/bootloaders/optiboot/Makefile index 88cb9a20d..ce25ac397 100644 --- a/hardware/arduino/bootloaders/optiboot/Makefile +++ b/hardware/arduino/bootloaders/optiboot/Makefile @@ -36,7 +36,7 @@ ISPPORT = usb ISPSPEED = -b 115200 MCU_TARGET = atmega168 -LDSECTION = --section-start=.text=0x3e00 +LDSECTIONS = -Wl,--section-start=.text=0x3e00 -Wl,--section-start=.version=0x3ffe # Build environments # Start of some ugly makefile-isms to allow optiboot to be built @@ -88,7 +88,7 @@ endif # http://tinker.it/now/2007/02/24/the-tale-of-avrdude-atmega168-and-extended-bits-fuses/ # # similarly, the lock bits should be 0xff instead of 0x3f (to -# unlock the bootloader section) and 0xcf instead of 0x0f (to +# unlock the bootloader section) and 0xcf instead of 0x2f (to # lock it), but since the high two bits of the lock byte are # unused, avrdude would get confused. @@ -98,7 +98,7 @@ ISPFUSES = $(GCCROOT)avrdude $(AVRDUDE_CONF) -c $(ISPTOOL) \ -U hfuse:w:0x$(HFUSE):m -U lfuse:w:0x$(LFUSE):m ISPFLASH = $(GCCROOT)avrdude $(AVRDUDE_CONF) -c $(ISPTOOL) \ -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \ - -U flash:w:$(PROGRAM)_$(TARGET).hex -U lock:w:0x0f:m + -U flash:w:$(PROGRAM)_$(TARGET).hex -U lock:w:0x2f:m STK500 = "C:\Program Files\Atmel\AVR Tools\STK500\Stk500.exe" STK500-1 = $(STK500) -e -d$(MCU_TARGET) -pf -vf -if$(PROGRAM)_$(TARGET).hex \ @@ -116,7 +116,7 @@ CC = $(GCCROOT)avr-gcc # Override is only needed by avr-lib build system. override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) -DF_CPU=$(AVR_FREQ) $(DEFS) -override LDFLAGS = -Wl,$(LDSECTION) -Wl,--relax -Wl,--gc-sections -nostartfiles -nostdlib +override LDFLAGS = $(LDSECTIONS) -Wl,--relax -Wl,--gc-sections -nostartfiles -nostdlib OBJCOPY = $(GCCROOT)avr-objcopy OBJDUMP = $(call fixpath,$(GCCROOT)avr-objdump) @@ -129,7 +129,7 @@ virboot328: TARGET = atmega328 virboot328: MCU_TARGET = atmega328p virboot328: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' '-DVIRTUAL_BOOT' virboot328: AVR_FREQ = 16000000L -virboot328: LDSECTION = --section-start=.text=0x7e00 +virboot328: LDSECTIONS = --section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe virboot328: $(PROGRAM)_atmega328.hex virboot328: $(PROGRAM)_atmega328.lst @@ -200,7 +200,7 @@ atmega328: TARGET = atmega328 atmega328: MCU_TARGET = atmega328p atmega328: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' atmega328: AVR_FREQ = 16000000L -atmega328: LDSECTION = --section-start=.text=0x7e00 +atmega328: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe atmega328: $(PROGRAM)_atmega328.hex atmega328: $(PROGRAM)_atmega328.lst @@ -262,7 +262,7 @@ atmega8: TARGET = atmega8 atmega8: MCU_TARGET = atmega8 atmega8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' atmega8: AVR_FREQ = 16000000L -atmega8: LDSECTION = --section-start=.text=0x1e00 +atmega8: LDSECTIONS = --section-start=.text=0x1e00 -Wl,--section-start=.version=0x1ffe atmega8: $(PROGRAM)_atmega8.hex atmega8: $(PROGRAM)_atmega8.lst @@ -281,7 +281,7 @@ atmega88: TARGET = atmega88 atmega88: MCU_TARGET = atmega88 atmega88: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' atmega88: AVR_FREQ = 16000000L -atmega88: LDSECTION = --section-start=.text=0x1e00 +atmega88: LDSECTIONS = --section-start=.text=0x1e00 -Wl,--section-start=.version=0x1ffe atmega88: $(PROGRAM)_atmega88.hex atmega88: $(PROGRAM)_atmega88.lst @@ -357,7 +357,7 @@ atmega328_pro8: TARGET = atmega328_pro_8MHz atmega328_pro8: MCU_TARGET = atmega328p atmega328_pro8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' atmega328_pro8: AVR_FREQ = 8000000L -atmega328_pro8: LDSECTION = --section-start=.text=0x7e00 +atmega328_pro8: LDSECTIONS = --section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.hex atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.lst @@ -382,7 +382,7 @@ luminet: MCU_TARGET = attiny84 luminet: CFLAGS += '-DLED_START_FLASHES=3' '-DSOFT_UART' '-DBAUD_RATE=9600' luminet: CFLAGS += '-DVIRTUAL_BOOT_PARTITION' luminet: AVR_FREQ = 1000000L -luminet: LDSECTION = --section-start=.text=0x1d00 +luminet: LDSECTIONS = --section-start=.text=0x1d00 -Wl,--section-start=.version=0x1efe luminet: $(PROGRAM)_luminet.hex luminet: $(PROGRAM)_luminet.lst @@ -421,10 +421,10 @@ clean: $(OBJDUMP) -h -S $< > $@ %.hex: %.elf - $(OBJCOPY) -j .text -j .data -O ihex $< $@ + $(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O ihex $< $@ %.srec: %.elf - $(OBJCOPY) -j .text -j .data -O srec $< $@ + $(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O srec $< $@ %.bin: %.elf - $(OBJCOPY) -j .text -j .data -O binary $< $@ + $(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O binary $< $@ diff --git a/hardware/arduino/bootloaders/optiboot/optiboot.c b/hardware/arduino/bootloaders/optiboot/optiboot.c index 4b4a10a80..ece8b43a7 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot.c +++ b/hardware/arduino/bootloaders/optiboot/optiboot.c @@ -114,7 +114,37 @@ /* 500,1000,2000,4000,8000 supported. */ /* */ /**********************************************************/ + +/**********************************************************/ +/* Version Numbers! */ +/* */ +/* Arduino Optiboot now includes this Version number in */ +/* the source and object code. */ +/* */ +/* Version 3 was released as zip from the optiboot */ +/* repository and was distributed with Arduino 0022. */ +/* Version 4 starts with the arduino repository commit */ +/* that brought the arduino repository up-to-date with */ +/* the optiboot source tree changes since v3. */ +/* */ +/**********************************************************/ +/**********************************************************/ +/* Edit History: */ +/* */ +/* 4.1 WestfW: put version number in binary. */ +/**********************************************************/ + +#define OPTIBOOT_MAJVER 4 +#define OPTIBOOT_MINVER 1 + +#define MAKESTR(a) #a +#define MAKEVER(a, b) MAKESTR(a*256+b) + +asm(" .section .version\n" + "optiboot_version: .word " MAKEVER(OPTIBOOT_MAJVER, OPTIBOOT_MINVER) "\n" + " .section .text\n"); + #include #include #include @@ -324,7 +354,7 @@ int main(void) { // If we are in RWW section, immediately start page erase if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - + // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); @@ -336,7 +366,7 @@ int main(void) { // Read command terminator, start reply verifySpace(); - + // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); @@ -371,7 +401,7 @@ int main(void) { __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); - + // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); boot_spm_busy_wait(); @@ -489,7 +519,7 @@ uint8_t getch(void) { " rcall uartDelay\n" // Wait 1 bit period " clc\n" " sbic %[uartPin],%[uartBit]\n" - " sec\n" + " sec\n" " dec %[bitCnt]\n" " breq 3f\n" " ror %[ch]\n" diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.hex b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.hex index 72108ee10..7286e0d6a 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.hex @@ -30,5 +30,6 @@ :107FD00090838083089580E0F8DFEE27FF270994DF :107FE000E7DF803209F0F7DF84E1DACF1F93182F43 :0C7FF000DFDF1150E9F7F4DF1F91089566 +:027FFE0001047C :0400000300007E007B :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.lst b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.lst index 1af4a3c62..0da8aafe0 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.lst @@ -5,23 +5,25 @@ Sections: Idx Name Size VMA LMA File off Algn 0 .text 000001fc 00007e00 00007e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .debug_aranges 00000028 00000000 00000000 00000250 2**0 + 1 .version 00000002 00007ffe 00007ffe 00000250 2**0 + CONTENTS, READONLY + 2 .debug_aranges 00000028 00000000 00000000 00000252 2**0 CONTENTS, READONLY, DEBUGGING - 2 .debug_pubnames 0000006a 00000000 00000000 00000278 2**0 + 3 .debug_pubnames 0000006a 00000000 00000000 0000027a 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_info 00000284 00000000 00000000 000002e2 2**0 + 4 .debug_info 00000285 00000000 00000000 000002e4 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_abbrev 000001ae 00000000 00000000 00000566 2**0 + 5 .debug_abbrev 0000019f 00000000 00000000 00000569 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_line 00000450 00000000 00000000 00000714 2**0 + 6 .debug_line 00000453 00000000 00000000 00000708 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_frame 00000090 00000000 00000000 00000b64 2**2 + 7 .debug_frame 00000090 00000000 00000000 00000b5c 2**2 CONTENTS, READONLY, DEBUGGING - 7 .debug_str 00000141 00000000 00000000 00000bf4 2**0 + 8 .debug_str 00000141 00000000 00000000 00000bec 2**0 CONTENTS, READONLY, DEBUGGING - 8 .debug_loc 000001e1 00000000 00000000 00000d35 2**0 + 9 .debug_loc 000001e1 00000000 00000000 00000d2d 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_ranges 00000068 00000000 00000000 00000f16 2**0 + 10 .debug_ranges 00000068 00000000 00000000 00000f0e 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: @@ -135,7 +137,7 @@ void watchdogReset() { __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); - + // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); 7e50: a5 e0 ldi r26, 0x05 ; 5 @@ -249,7 +251,7 @@ void watchdogReset() { 7ec6: e8 95 spm 7ec8: c0 e0 ldi r28, 0x00 ; 0 7eca: d1 e0 ldi r29, 0x01 ; 1 - + // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); @@ -278,7 +280,7 @@ void watchdogReset() { // Read command terminator, start reply verifySpace(); 7ef4: 75 d0 rcall .+234 ; 0x7fe0 - + // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); @@ -336,7 +338,7 @@ int main(void) { 7f2e: a0 38 cpi r26, 0x80 ; 128 7f30: bf 07 cpc r27, r31 7f32: 51 f7 brne .-44 ; 0x7f08 - + // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); 7f34: e0 91 00 02 lds r30, 0x0200 diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.hex b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.hex index f4a151437..1e5683914 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.hex @@ -1,34 +1,34 @@ -:107E0000112484B714BE81FFE6D085E08093810001 -:107E100082E08093C00088E18093C10086E0809377 -:107E2000C20088E08093C4008EE0CFD0259A86E01F -:107E300028E13EEF91E0309385002093840096BBCB -:107E4000B09BFECF1D9AA8958150A9F7DD24D3944D -:107E5000A5E0EA2EF1E1FF2EABD0813421F481E0E0 -:107E6000C5D083E020C0823411F484E103C085349E -:107E700019F485E0BBD091C0853581F499D0082FE5 -:107E800010E096D090E0982F8827802B912B880FB8 -:107E9000991F90930102809300027EC0863529F4D9 -:107EA00084E0A4D080E07CD078C0843609F04EC055 -:107EB00087D0E0910002F091010280E7E030F807FE -:107EC00018F483E087BFE895C0E0D1E071D08993D2 -:107ED000809102028150809302028823B9F7E091D9 -:107EE0000002F091010280E7E030F80718F083E02B -:107EF00087BFE89575D007B600FCFDCF4091000222 -:107F000050910102A0E0B1E02C9130E011968C91EB -:107F1000119790E0982F8827822B932B1296FA01C5 -:107F20000C01D7BEE89511244E5F5F4FF1E0A038F9 -:107F3000BF0751F7E0910002F0910102E7BEE8951A -:107F400007B600FCFDCFF7BEE89527C08437B9F42B -:107F500037D046D0E0910002F09101023196F093C3 -:107F60000102E09300023197E4918E2F19D08091A5 -:107F70000202815080930202882361F70EC0853788 -:107F800039F42ED08EE10CD085E90AD08FE08BCF6A -:107F9000813511F488E019D023D080E101D05CCF85 -:107FA000982F8091C00085FFFCCF9093C600089564 -:107FB000A8958091C00087FFFCCF8091C6000895EE -:107FC000F7DFF6DF80930202F3CFE0E6F0E098E11E -:107FD00090838083089580E0F8DFEE27FF270994DF -:107FE000E7DF803209F0F7DF84E1DACF1F93182F43 -:0C7FF000DFDF1150E9F7F4DF1F91089566 -:0400000300007E007B +:10000000112484B714BE81FFE6D085E0809381007F +:1000100082E08093C00088E18093C10086E08093F5 +:10002000C20088E08093C4008EE0CFD0259A86E09D +:1000300028E13EEF91E0309385002093840096BB49 +:10004000B09BFECF1D9AA8958150A9F7DD24D394CB +:10005000A5E0EA2EF1E1FF2EABD0813421F481E05E +:10006000C5D083E020C0823411F484E103C085341C +:1000700019F485E0BBD091C0853581F499D0082F63 +:1000800010E096D090E0982F8827802B912B880F36 +:10009000991F90930102809300027EC0863529F457 +:1000A00084E0A4D080E07CD078C0843609F04EC0D3 +:1000B00087D0E0910002F091010280E7E030F8077C +:1000C00018F483E087BFE895C0E0D1E071D0899350 +:1000D000809102028150809302028823B9F7E09157 +:1000E0000002F091010280E7E030F80718F083E0A9 +:1000F00087BFE89575D007B600FCFDCF40910002A0 +:1001000050910102A0E0B1E02C9130E011968C9169 +:10011000119790E0982F8827822B932B1296FA0143 +:100120000C01D7BEE89511244E5F5F4FF1E0A03877 +:10013000BF0751F7E0910002F0910102E7BEE89598 +:1001400007B600FCFDCFF7BEE89527C08437B9F4A9 +:1001500037D046D0E0910002F09101023196F09341 +:100160000102E09300023197E4918E2F19D0809123 +:100170000202815080930202882361F70EC0853706 +:1001800039F42ED08EE10CD085E90AD08FE08BCFE8 +:10019000813511F488E019D023D080E101D05CCF03 +:1001A000982F8091C00085FFFCCF9093C6000895E2 +:1001B000A8958091C00087FFFCCF8091C60008956C +:1001C000F7DFF6DF80930202F3CFE0E6F0E098E19C +:1001D00090838083089580E0F8DFEE27FF2709945D +:1001E000E7DF803209F0F7DF84E1DACF1F93182FC1 +:0C01F000DFDF1150E9F7F4DF1F910895E4 +:027FFE0001047C :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.lst b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.lst index 4cbcf626e..d7ce99102 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.lst @@ -3,552 +3,554 @@ optiboot_atmega328_pro_8MHz.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .text 000001fc 00007e00 00007e00 00000054 2**1 + 0 .text 000001fc 00000000 00000000 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .debug_aranges 00000028 00000000 00000000 00000250 2**0 + 1 .version 00000002 00007ffe 00007ffe 00000250 2**0 + CONTENTS, READONLY + 2 .debug_aranges 00000028 00000000 00000000 00000252 2**0 CONTENTS, READONLY, DEBUGGING - 2 .debug_pubnames 0000006a 00000000 00000000 00000278 2**0 + 3 .debug_pubnames 0000006a 00000000 00000000 0000027a 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_info 00000284 00000000 00000000 000002e2 2**0 + 4 .debug_info 00000285 00000000 00000000 000002e4 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_abbrev 000001ae 00000000 00000000 00000566 2**0 + 5 .debug_abbrev 0000019f 00000000 00000000 00000569 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_line 00000450 00000000 00000000 00000714 2**0 + 6 .debug_line 00000453 00000000 00000000 00000708 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_frame 00000090 00000000 00000000 00000b64 2**2 + 7 .debug_frame 00000090 00000000 00000000 00000b5c 2**2 CONTENTS, READONLY, DEBUGGING - 7 .debug_str 00000141 00000000 00000000 00000bf4 2**0 + 8 .debug_str 00000141 00000000 00000000 00000bec 2**0 CONTENTS, READONLY, DEBUGGING - 8 .debug_loc 000001e1 00000000 00000000 00000d35 2**0 + 9 .debug_loc 000001e1 00000000 00000000 00000d2d 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_ranges 00000068 00000000 00000000 00000f16 2**0 + 10 .debug_ranges 00000068 00000000 00000000 00000f0e 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: -00007e00
    : +00000000
    : #define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) #define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif /* main program starts here */ int main(void) { - 7e00: 11 24 eor r1, r1 + 0: 11 24 eor r1, r1 #ifdef __AVR_ATmega8__ SP=RAMEND; // This is done by hardware reset #endif // Adaboot no-wait mod ch = MCUSR; - 7e02: 84 b7 in r24, 0x34 ; 52 + 2: 84 b7 in r24, 0x34 ; 52 MCUSR = 0; - 7e04: 14 be out 0x34, r1 ; 52 + 4: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); - 7e06: 81 ff sbrs r24, 1 - 7e08: e6 d0 rcall .+460 ; 0x7fd6 + 6: 81 ff sbrs r24, 1 + 8: e6 d0 rcall .+460 ; 0x1d6 #if LED_START_FLASHES > 0 // Set up Timer 1 for timeout counter TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 - 7e0a: 85 e0 ldi r24, 0x05 ; 5 - 7e0c: 80 93 81 00 sts 0x0081, r24 + a: 85 e0 ldi r24, 0x05 ; 5 + c: 80 93 81 00 sts 0x0081, r24 UCSRA = _BV(U2X); //Double speed mode USART UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); #else UCSR0A = _BV(U2X0); //Double speed mode USART0 - 7e10: 82 e0 ldi r24, 0x02 ; 2 - 7e12: 80 93 c0 00 sts 0x00C0, r24 + 10: 82 e0 ldi r24, 0x02 ; 2 + 12: 80 93 c0 00 sts 0x00C0, r24 UCSR0B = _BV(RXEN0) | _BV(TXEN0); - 7e16: 88 e1 ldi r24, 0x18 ; 24 - 7e18: 80 93 c1 00 sts 0x00C1, r24 + 16: 88 e1 ldi r24, 0x18 ; 24 + 18: 80 93 c1 00 sts 0x00C1, r24 UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); - 7e1c: 86 e0 ldi r24, 0x06 ; 6 - 7e1e: 80 93 c2 00 sts 0x00C2, r24 + 1c: 86 e0 ldi r24, 0x06 ; 6 + 1e: 80 93 c2 00 sts 0x00C2, r24 UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); - 7e22: 88 e0 ldi r24, 0x08 ; 8 - 7e24: 80 93 c4 00 sts 0x00C4, r24 + 22: 88 e0 ldi r24, 0x08 ; 8 + 24: 80 93 c4 00 sts 0x00C4, r24 #endif #endif // Set up watchdog to trigger after 500ms watchdogConfig(WATCHDOG_1S); - 7e28: 8e e0 ldi r24, 0x0E ; 14 - 7e2a: cf d0 rcall .+414 ; 0x7fca + 28: 8e e0 ldi r24, 0x0E ; 14 + 2a: cf d0 rcall .+414 ; 0x1ca /* Set LED pin as output */ LED_DDR |= _BV(LED); - 7e2c: 25 9a sbi 0x04, 5 ; 4 - 7e2e: 86 e0 ldi r24, 0x06 ; 6 + 2c: 25 9a sbi 0x04, 5 ; 4 + 2e: 86 e0 ldi r24, 0x06 ; 6 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - 7e30: 28 e1 ldi r18, 0x18 ; 24 - 7e32: 3e ef ldi r19, 0xFE ; 254 + 30: 28 e1 ldi r18, 0x18 ; 24 + 32: 3e ef ldi r19, 0xFE ; 254 TIFR1 = _BV(TOV1); - 7e34: 91 e0 ldi r25, 0x01 ; 1 + 34: 91 e0 ldi r25, 0x01 ; 1 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - 7e36: 30 93 85 00 sts 0x0085, r19 - 7e3a: 20 93 84 00 sts 0x0084, r18 + 36: 30 93 85 00 sts 0x0085, r19 + 3a: 20 93 84 00 sts 0x0084, r18 TIFR1 = _BV(TOV1); - 7e3e: 96 bb out 0x16, r25 ; 22 + 3e: 96 bb out 0x16, r25 ; 22 while(!(TIFR1 & _BV(TOV1))); - 7e40: b0 9b sbis 0x16, 0 ; 22 - 7e42: fe cf rjmp .-4 ; 0x7e40 + 40: b0 9b sbis 0x16, 0 ; 22 + 42: fe cf rjmp .-4 ; 0x40 <__SREG__+0x1> #ifdef __AVR_ATmega8__ LED_PORT ^= _BV(LED); #else LED_PIN |= _BV(LED); - 7e44: 1d 9a sbi 0x03, 5 ; 3 + 44: 1d 9a sbi 0x03, 5 ; 3 return getch(); } // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 7e46: a8 95 wdr + 46: a8 95 wdr LED_PORT ^= _BV(LED); #else LED_PIN |= _BV(LED); #endif watchdogReset(); } while (--count); - 7e48: 81 50 subi r24, 0x01 ; 1 - 7e4a: a9 f7 brne .-22 ; 0x7e36 + 48: 81 50 subi r24, 0x01 ; 1 + 4a: a9 f7 brne .-22 ; 0x36 <__CCP__+0x2> /* get character from UART */ ch = getch(); if(ch == STK_GET_PARAMETER) { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 7e4c: dd 24 eor r13, r13 - 7e4e: d3 94 inc r13 + 4c: dd 24 eor r13, r13 + 4e: d3 94 inc r13 __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); - + // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); - 7e50: a5 e0 ldi r26, 0x05 ; 5 - 7e52: ea 2e mov r14, r26 + 50: a5 e0 ldi r26, 0x05 ; 5 + 52: ea 2e mov r14, r26 boot_spm_busy_wait(); #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 7e54: f1 e1 ldi r31, 0x11 ; 17 - 7e56: ff 2e mov r15, r31 + 54: f1 e1 ldi r31, 0x11 ; 17 + 56: ff 2e mov r15, r31 #endif /* Forever loop */ for (;;) { /* get character from UART */ ch = getch(); - 7e58: ab d0 rcall .+342 ; 0x7fb0 + 58: ab d0 rcall .+342 ; 0x1b0 if(ch == STK_GET_PARAMETER) { - 7e5a: 81 34 cpi r24, 0x41 ; 65 - 7e5c: 21 f4 brne .+8 ; 0x7e66 + 5a: 81 34 cpi r24, 0x41 ; 65 + 5c: 21 f4 brne .+8 ; 0x66 <__SREG__+0x27> // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 7e5e: 81 e0 ldi r24, 0x01 ; 1 - 7e60: c5 d0 rcall .+394 ; 0x7fec + 5e: 81 e0 ldi r24, 0x01 ; 1 + 60: c5 d0 rcall .+394 ; 0x1ec putch(0x03); - 7e62: 83 e0 ldi r24, 0x03 ; 3 - 7e64: 20 c0 rjmp .+64 ; 0x7ea6 + 62: 83 e0 ldi r24, 0x03 ; 3 + 64: 20 c0 rjmp .+64 ; 0xa6 <__SREG__+0x67> } else if(ch == STK_SET_DEVICE) { - 7e66: 82 34 cpi r24, 0x42 ; 66 - 7e68: 11 f4 brne .+4 ; 0x7e6e + 66: 82 34 cpi r24, 0x42 ; 66 + 68: 11 f4 brne .+4 ; 0x6e <__SREG__+0x2f> // SET DEVICE is ignored getNch(20); - 7e6a: 84 e1 ldi r24, 0x14 ; 20 - 7e6c: 03 c0 rjmp .+6 ; 0x7e74 + 6a: 84 e1 ldi r24, 0x14 ; 20 + 6c: 03 c0 rjmp .+6 ; 0x74 <__SREG__+0x35> } else if(ch == STK_SET_DEVICE_EXT) { - 7e6e: 85 34 cpi r24, 0x45 ; 69 - 7e70: 19 f4 brne .+6 ; 0x7e78 + 6e: 85 34 cpi r24, 0x45 ; 69 + 70: 19 f4 brne .+6 ; 0x78 <__SREG__+0x39> // SET DEVICE EXT is ignored getNch(5); - 7e72: 85 e0 ldi r24, 0x05 ; 5 - 7e74: bb d0 rcall .+374 ; 0x7fec - 7e76: 91 c0 rjmp .+290 ; 0x7f9a + 72: 85 e0 ldi r24, 0x05 ; 5 + 74: bb d0 rcall .+374 ; 0x1ec + 76: 91 c0 rjmp .+290 ; 0x19a <__SREG__+0x15b> } else if(ch == STK_LOAD_ADDRESS) { - 7e78: 85 35 cpi r24, 0x55 ; 85 - 7e7a: 81 f4 brne .+32 ; 0x7e9c + 78: 85 35 cpi r24, 0x55 ; 85 + 7a: 81 f4 brne .+32 ; 0x9c <__SREG__+0x5d> // LOAD ADDRESS uint16_t newAddress; newAddress = getch(); - 7e7c: 99 d0 rcall .+306 ; 0x7fb0 + 7c: 99 d0 rcall .+306 ; 0x1b0 newAddress = (newAddress & 0xff) | (getch() << 8); - 7e7e: 08 2f mov r16, r24 - 7e80: 10 e0 ldi r17, 0x00 ; 0 - 7e82: 96 d0 rcall .+300 ; 0x7fb0 - 7e84: 90 e0 ldi r25, 0x00 ; 0 - 7e86: 98 2f mov r25, r24 - 7e88: 88 27 eor r24, r24 - 7e8a: 80 2b or r24, r16 - 7e8c: 91 2b or r25, r17 + 7e: 08 2f mov r16, r24 + 80: 10 e0 ldi r17, 0x00 ; 0 + 82: 96 d0 rcall .+300 ; 0x1b0 + 84: 90 e0 ldi r25, 0x00 ; 0 + 86: 98 2f mov r25, r24 + 88: 88 27 eor r24, r24 + 8a: 80 2b or r24, r16 + 8c: 91 2b or r25, r17 #ifdef RAMPZ // Transfer top bit to RAMPZ RAMPZ = (newAddress & 0x8000) ? 1 : 0; #endif newAddress += newAddress; // Convert from word address to byte address - 7e8e: 88 0f add r24, r24 - 7e90: 99 1f adc r25, r25 + 8e: 88 0f add r24, r24 + 90: 99 1f adc r25, r25 address = newAddress; - 7e92: 90 93 01 02 sts 0x0201, r25 - 7e96: 80 93 00 02 sts 0x0200, r24 - 7e9a: 7e c0 rjmp .+252 ; 0x7f98 + 92: 90 93 01 02 sts 0x0201, r25 + 96: 80 93 00 02 sts 0x0200, r24 + 9a: 7e c0 rjmp .+252 ; 0x198 <__SREG__+0x159> verifySpace(); } else if(ch == STK_UNIVERSAL) { - 7e9c: 86 35 cpi r24, 0x56 ; 86 - 7e9e: 29 f4 brne .+10 ; 0x7eaa + 9c: 86 35 cpi r24, 0x56 ; 86 + 9e: 29 f4 brne .+10 ; 0xaa <__SREG__+0x6b> // UNIVERSAL command is ignored getNch(4); - 7ea0: 84 e0 ldi r24, 0x04 ; 4 - 7ea2: a4 d0 rcall .+328 ; 0x7fec + a0: 84 e0 ldi r24, 0x04 ; 4 + a2: a4 d0 rcall .+328 ; 0x1ec putch(0x00); - 7ea4: 80 e0 ldi r24, 0x00 ; 0 - 7ea6: 7c d0 rcall .+248 ; 0x7fa0 - 7ea8: 78 c0 rjmp .+240 ; 0x7f9a + a4: 80 e0 ldi r24, 0x00 ; 0 + a6: 7c d0 rcall .+248 ; 0x1a0 + a8: 78 c0 rjmp .+240 ; 0x19a <__SREG__+0x15b> } /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { - 7eaa: 84 36 cpi r24, 0x64 ; 100 - 7eac: 09 f0 breq .+2 ; 0x7eb0 - 7eae: 4e c0 rjmp .+156 ; 0x7f4c + aa: 84 36 cpi r24, 0x64 ; 100 + ac: 09 f0 breq .+2 ; 0xb0 <__SREG__+0x71> + ae: 4e c0 rjmp .+156 ; 0x14c <__SREG__+0x10d> // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t *bufPtr; uint16_t addrPtr; getLen(); - 7eb0: 87 d0 rcall .+270 ; 0x7fc0 + b0: 87 d0 rcall .+270 ; 0x1c0 // If we are in RWW section, immediately start page erase if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 7eb2: e0 91 00 02 lds r30, 0x0200 - 7eb6: f0 91 01 02 lds r31, 0x0201 - 7eba: 80 e7 ldi r24, 0x70 ; 112 - 7ebc: e0 30 cpi r30, 0x00 ; 0 - 7ebe: f8 07 cpc r31, r24 - 7ec0: 18 f4 brcc .+6 ; 0x7ec8 - 7ec2: 83 e0 ldi r24, 0x03 ; 3 - 7ec4: 87 bf out 0x37, r24 ; 55 - 7ec6: e8 95 spm - 7ec8: c0 e0 ldi r28, 0x00 ; 0 - 7eca: d1 e0 ldi r29, 0x01 ; 1 - + b2: e0 91 00 02 lds r30, 0x0200 + b6: f0 91 01 02 lds r31, 0x0201 + ba: 80 e7 ldi r24, 0x70 ; 112 + bc: e0 30 cpi r30, 0x00 ; 0 + be: f8 07 cpc r31, r24 + c0: 18 f4 brcc .+6 ; 0xc8 <__SREG__+0x89> + c2: 83 e0 ldi r24, 0x03 ; 3 + c4: 87 bf out 0x37, r24 ; 55 + c6: e8 95 spm + c8: c0 e0 ldi r28, 0x00 ; 0 + ca: d1 e0 ldi r29, 0x01 ; 1 + // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); - 7ecc: 71 d0 rcall .+226 ; 0x7fb0 - 7ece: 89 93 st Y+, r24 + cc: 71 d0 rcall .+226 ; 0x1b0 + ce: 89 93 st Y+, r24 while (--length); - 7ed0: 80 91 02 02 lds r24, 0x0202 - 7ed4: 81 50 subi r24, 0x01 ; 1 - 7ed6: 80 93 02 02 sts 0x0202, r24 - 7eda: 88 23 and r24, r24 - 7edc: b9 f7 brne .-18 ; 0x7ecc + d0: 80 91 02 02 lds r24, 0x0202 + d4: 81 50 subi r24, 0x01 ; 1 + d6: 80 93 02 02 sts 0x0202, r24 + da: 88 23 and r24, r24 + dc: b9 f7 brne .-18 ; 0xcc <__SREG__+0x8d> // If we are in NRWW section, page erase has to be delayed until now. // Todo: Take RAMPZ into account if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 7ede: e0 91 00 02 lds r30, 0x0200 - 7ee2: f0 91 01 02 lds r31, 0x0201 - 7ee6: 80 e7 ldi r24, 0x70 ; 112 - 7ee8: e0 30 cpi r30, 0x00 ; 0 - 7eea: f8 07 cpc r31, r24 - 7eec: 18 f0 brcs .+6 ; 0x7ef4 - 7eee: 83 e0 ldi r24, 0x03 ; 3 - 7ef0: 87 bf out 0x37, r24 ; 55 - 7ef2: e8 95 spm + de: e0 91 00 02 lds r30, 0x0200 + e2: f0 91 01 02 lds r31, 0x0201 + e6: 80 e7 ldi r24, 0x70 ; 112 + e8: e0 30 cpi r30, 0x00 ; 0 + ea: f8 07 cpc r31, r24 + ec: 18 f0 brcs .+6 ; 0xf4 <__SREG__+0xb5> + ee: 83 e0 ldi r24, 0x03 ; 3 + f0: 87 bf out 0x37, r24 ; 55 + f2: e8 95 spm // Read command terminator, start reply verifySpace(); - 7ef4: 75 d0 rcall .+234 ; 0x7fe0 - + f4: 75 d0 rcall .+234 ; 0x1e0 + // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); - 7ef6: 07 b6 in r0, 0x37 ; 55 - 7ef8: 00 fc sbrc r0, 0 - 7efa: fd cf rjmp .-6 ; 0x7ef6 + f6: 07 b6 in r0, 0x37 ; 55 + f8: 00 fc sbrc r0, 0 + fa: fd cf rjmp .-6 ; 0xf6 <__SREG__+0xb7> } #endif // Copy buffer into programming buffer bufPtr = buff; addrPtr = (uint16_t)(void*)address; - 7efc: 40 91 00 02 lds r20, 0x0200 - 7f00: 50 91 01 02 lds r21, 0x0201 - 7f04: a0 e0 ldi r26, 0x00 ; 0 - 7f06: b1 e0 ldi r27, 0x01 ; 1 + fc: 40 91 00 02 lds r20, 0x0200 + 100: 50 91 01 02 lds r21, 0x0201 + 104: a0 e0 ldi r26, 0x00 ; 0 + 106: b1 e0 ldi r27, 0x01 ; 1 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; - 7f08: 2c 91 ld r18, X - 7f0a: 30 e0 ldi r19, 0x00 ; 0 + 108: 2c 91 ld r18, X + 10a: 30 e0 ldi r19, 0x00 ; 0 a |= (*bufPtr++) << 8; - 7f0c: 11 96 adiw r26, 0x01 ; 1 - 7f0e: 8c 91 ld r24, X - 7f10: 11 97 sbiw r26, 0x01 ; 1 - 7f12: 90 e0 ldi r25, 0x00 ; 0 - 7f14: 98 2f mov r25, r24 - 7f16: 88 27 eor r24, r24 - 7f18: 82 2b or r24, r18 - 7f1a: 93 2b or r25, r19 + 10c: 11 96 adiw r26, 0x01 ; 1 + 10e: 8c 91 ld r24, X + 110: 11 97 sbiw r26, 0x01 ; 1 + 112: 90 e0 ldi r25, 0x00 ; 0 + 114: 98 2f mov r25, r24 + 116: 88 27 eor r24, r24 + 118: 82 2b or r24, r18 + 11a: 93 2b or r25, r19 #define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) #define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif /* main program starts here */ int main(void) { - 7f1c: 12 96 adiw r26, 0x02 ; 2 + 11c: 12 96 adiw r26, 0x02 ; 2 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; a |= (*bufPtr++) << 8; __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - 7f1e: fa 01 movw r30, r20 - 7f20: 0c 01 movw r0, r24 - 7f22: d7 be out 0x37, r13 ; 55 - 7f24: e8 95 spm - 7f26: 11 24 eor r1, r1 + 11e: fa 01 movw r30, r20 + 120: 0c 01 movw r0, r24 + 122: d7 be out 0x37, r13 ; 55 + 124: e8 95 spm + 126: 11 24 eor r1, r1 addrPtr += 2; - 7f28: 4e 5f subi r20, 0xFE ; 254 - 7f2a: 5f 4f sbci r21, 0xFF ; 255 + 128: 4e 5f subi r20, 0xFE ; 254 + 12a: 5f 4f sbci r21, 0xFF ; 255 } while (--ch); - 7f2c: f1 e0 ldi r31, 0x01 ; 1 - 7f2e: a0 38 cpi r26, 0x80 ; 128 - 7f30: bf 07 cpc r27, r31 - 7f32: 51 f7 brne .-44 ; 0x7f08 - + 12c: f1 e0 ldi r31, 0x01 ; 1 + 12e: a0 38 cpi r26, 0x80 ; 128 + 130: bf 07 cpc r27, r31 + 132: 51 f7 brne .-44 ; 0x108 <__SREG__+0xc9> + // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); - 7f34: e0 91 00 02 lds r30, 0x0200 - 7f38: f0 91 01 02 lds r31, 0x0201 - 7f3c: e7 be out 0x37, r14 ; 55 - 7f3e: e8 95 spm + 134: e0 91 00 02 lds r30, 0x0200 + 138: f0 91 01 02 lds r31, 0x0201 + 13c: e7 be out 0x37, r14 ; 55 + 13e: e8 95 spm boot_spm_busy_wait(); - 7f40: 07 b6 in r0, 0x37 ; 55 - 7f42: 00 fc sbrc r0, 0 - 7f44: fd cf rjmp .-6 ; 0x7f40 + 140: 07 b6 in r0, 0x37 ; 55 + 142: 00 fc sbrc r0, 0 + 144: fd cf rjmp .-6 ; 0x140 <__SREG__+0x101> #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 7f46: f7 be out 0x37, r15 ; 55 - 7f48: e8 95 spm - 7f4a: 27 c0 rjmp .+78 ; 0x7f9a + 146: f7 be out 0x37, r15 ; 55 + 148: e8 95 spm + 14a: 27 c0 rjmp .+78 ; 0x19a <__SREG__+0x15b> #endif } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { - 7f4c: 84 37 cpi r24, 0x74 ; 116 - 7f4e: b9 f4 brne .+46 ; 0x7f7e + 14c: 84 37 cpi r24, 0x74 ; 116 + 14e: b9 f4 brne .+46 ; 0x17e <__SREG__+0x13f> // READ PAGE - we only read flash getLen(); - 7f50: 37 d0 rcall .+110 ; 0x7fc0 + 150: 37 d0 rcall .+110 ; 0x1c0 verifySpace(); - 7f52: 46 d0 rcall .+140 ; 0x7fe0 + 152: 46 d0 rcall .+140 ; 0x1e0 putch(result); address++; } while (--length); #else do putch(pgm_read_byte_near(address++)); - 7f54: e0 91 00 02 lds r30, 0x0200 - 7f58: f0 91 01 02 lds r31, 0x0201 - 7f5c: 31 96 adiw r30, 0x01 ; 1 - 7f5e: f0 93 01 02 sts 0x0201, r31 - 7f62: e0 93 00 02 sts 0x0200, r30 - 7f66: 31 97 sbiw r30, 0x01 ; 1 - 7f68: e4 91 lpm r30, Z+ - 7f6a: 8e 2f mov r24, r30 - 7f6c: 19 d0 rcall .+50 ; 0x7fa0 + 154: e0 91 00 02 lds r30, 0x0200 + 158: f0 91 01 02 lds r31, 0x0201 + 15c: 31 96 adiw r30, 0x01 ; 1 + 15e: f0 93 01 02 sts 0x0201, r31 + 162: e0 93 00 02 sts 0x0200, r30 + 166: 31 97 sbiw r30, 0x01 ; 1 + 168: e4 91 lpm r30, Z+ + 16a: 8e 2f mov r24, r30 + 16c: 19 d0 rcall .+50 ; 0x1a0 while (--length); - 7f6e: 80 91 02 02 lds r24, 0x0202 - 7f72: 81 50 subi r24, 0x01 ; 1 - 7f74: 80 93 02 02 sts 0x0202, r24 - 7f78: 88 23 and r24, r24 - 7f7a: 61 f7 brne .-40 ; 0x7f54 - 7f7c: 0e c0 rjmp .+28 ; 0x7f9a + 16e: 80 91 02 02 lds r24, 0x0202 + 172: 81 50 subi r24, 0x01 ; 1 + 174: 80 93 02 02 sts 0x0202, r24 + 178: 88 23 and r24, r24 + 17a: 61 f7 brne .-40 ; 0x154 <__SREG__+0x115> + 17c: 0e c0 rjmp .+28 ; 0x19a <__SREG__+0x15b> #endif #endif } /* Get device signature bytes */ else if(ch == STK_READ_SIGN) { - 7f7e: 85 37 cpi r24, 0x75 ; 117 - 7f80: 39 f4 brne .+14 ; 0x7f90 + 17e: 85 37 cpi r24, 0x75 ; 117 + 180: 39 f4 brne .+14 ; 0x190 <__SREG__+0x151> // READ SIGN - return what Avrdude wants to hear verifySpace(); - 7f82: 2e d0 rcall .+92 ; 0x7fe0 + 182: 2e d0 rcall .+92 ; 0x1e0 putch(SIGNATURE_0); - 7f84: 8e e1 ldi r24, 0x1E ; 30 - 7f86: 0c d0 rcall .+24 ; 0x7fa0 + 184: 8e e1 ldi r24, 0x1E ; 30 + 186: 0c d0 rcall .+24 ; 0x1a0 putch(SIGNATURE_1); - 7f88: 85 e9 ldi r24, 0x95 ; 149 - 7f8a: 0a d0 rcall .+20 ; 0x7fa0 + 188: 85 e9 ldi r24, 0x95 ; 149 + 18a: 0a d0 rcall .+20 ; 0x1a0 putch(SIGNATURE_2); - 7f8c: 8f e0 ldi r24, 0x0F ; 15 - 7f8e: 8b cf rjmp .-234 ; 0x7ea6 + 18c: 8f e0 ldi r24, 0x0F ; 15 + 18e: 8b cf rjmp .-234 ; 0xa6 <__SREG__+0x67> } else if (ch == 'Q') { - 7f90: 81 35 cpi r24, 0x51 ; 81 - 7f92: 11 f4 brne .+4 ; 0x7f98 + 190: 81 35 cpi r24, 0x51 ; 81 + 192: 11 f4 brne .+4 ; 0x198 <__SREG__+0x159> // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); - 7f94: 88 e0 ldi r24, 0x08 ; 8 - 7f96: 19 d0 rcall .+50 ; 0x7fca + 194: 88 e0 ldi r24, 0x08 ; 8 + 196: 19 d0 rcall .+50 ; 0x1ca verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 7f98: 23 d0 rcall .+70 ; 0x7fe0 + 198: 23 d0 rcall .+70 ; 0x1e0 } putch(STK_OK); - 7f9a: 80 e1 ldi r24, 0x10 ; 16 - 7f9c: 01 d0 rcall .+2 ; 0x7fa0 - 7f9e: 5c cf rjmp .-328 ; 0x7e58 + 19a: 80 e1 ldi r24, 0x10 ; 16 + 19c: 01 d0 rcall .+2 ; 0x1a0 + 19e: 5c cf rjmp .-328 ; 0x58 <__SREG__+0x19> -00007fa0 : +000001a0 : } } void putch(char ch) { - 7fa0: 98 2f mov r25, r24 + 1a0: 98 2f mov r25, r24 #ifndef SOFT_UART while (!(UCSR0A & _BV(UDRE0))); - 7fa2: 80 91 c0 00 lds r24, 0x00C0 - 7fa6: 85 ff sbrs r24, 5 - 7fa8: fc cf rjmp .-8 ; 0x7fa2 + 1a2: 80 91 c0 00 lds r24, 0x00C0 + 1a6: 85 ff sbrs r24, 5 + 1a8: fc cf rjmp .-8 ; 0x1a2 UDR0 = ch; - 7faa: 90 93 c6 00 sts 0x00C6, r25 + 1aa: 90 93 c6 00 sts 0x00C6, r25 [uartBit] "I" (UART_TX_BIT) : "r25" ); #endif } - 7fae: 08 95 ret + 1ae: 08 95 ret -00007fb0 : +000001b0 : return getch(); } // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 7fb0: a8 95 wdr + 1b0: a8 95 wdr [uartBit] "I" (UART_RX_BIT) : "r25" ); #else while(!(UCSR0A & _BV(RXC0))); - 7fb2: 80 91 c0 00 lds r24, 0x00C0 - 7fb6: 87 ff sbrs r24, 7 - 7fb8: fc cf rjmp .-8 ; 0x7fb2 + 1b2: 80 91 c0 00 lds r24, 0x00C0 + 1b6: 87 ff sbrs r24, 7 + 1b8: fc cf rjmp .-8 ; 0x1b2 ch = UDR0; - 7fba: 80 91 c6 00 lds r24, 0x00C6 + 1ba: 80 91 c6 00 lds r24, 0x00C6 LED_PIN |= _BV(LED); #endif #endif return ch; } - 7fbe: 08 95 ret + 1be: 08 95 ret -00007fc0 : +000001c0 : } while (--count); } #endif uint8_t getLen() { getch(); - 7fc0: f7 df rcall .-18 ; 0x7fb0 + 1c0: f7 df rcall .-18 ; 0x1b0 length = getch(); - 7fc2: f6 df rcall .-20 ; 0x7fb0 - 7fc4: 80 93 02 02 sts 0x0202, r24 + 1c2: f6 df rcall .-20 ; 0x1b0 + 1c4: 80 93 02 02 sts 0x0202, r24 return getch(); } - 7fc8: f3 cf rjmp .-26 ; 0x7fb0 + 1c8: f3 cf rjmp .-26 ; 0x1b0 -00007fca : +000001ca : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 7fca: e0 e6 ldi r30, 0x60 ; 96 - 7fcc: f0 e0 ldi r31, 0x00 ; 0 - 7fce: 98 e1 ldi r25, 0x18 ; 24 - 7fd0: 90 83 st Z, r25 + 1ca: e0 e6 ldi r30, 0x60 ; 96 + 1cc: f0 e0 ldi r31, 0x00 ; 0 + 1ce: 98 e1 ldi r25, 0x18 ; 24 + 1d0: 90 83 st Z, r25 WDTCSR = x; - 7fd2: 80 83 st Z, r24 + 1d2: 80 83 st Z, r24 } - 7fd4: 08 95 ret + 1d4: 08 95 ret -00007fd6 : +000001d6 : void appStart() { watchdogConfig(WATCHDOG_OFF); - 7fd6: 80 e0 ldi r24, 0x00 ; 0 - 7fd8: f8 df rcall .-16 ; 0x7fca + 1d6: 80 e0 ldi r24, 0x00 ; 0 + 1d8: f8 df rcall .-16 ; 0x1ca __asm__ __volatile__ ( - 7fda: ee 27 eor r30, r30 - 7fdc: ff 27 eor r31, r31 - 7fde: 09 94 ijmp + 1da: ee 27 eor r30, r30 + 1dc: ff 27 eor r31, r31 + 1de: 09 94 ijmp -00007fe0 : +000001e0 : do getch(); while (--count); verifySpace(); } void verifySpace() { if (getch() != CRC_EOP) appStart(); - 7fe0: e7 df rcall .-50 ; 0x7fb0 - 7fe2: 80 32 cpi r24, 0x20 ; 32 - 7fe4: 09 f0 breq .+2 ; 0x7fe8 - 7fe6: f7 df rcall .-18 ; 0x7fd6 + 1e0: e7 df rcall .-50 ; 0x1b0 + 1e2: 80 32 cpi r24, 0x20 ; 32 + 1e4: 09 f0 breq .+2 ; 0x1e8 + 1e6: f7 df rcall .-18 ; 0x1d6 putch(STK_INSYNC); - 7fe8: 84 e1 ldi r24, 0x14 ; 20 + 1e8: 84 e1 ldi r24, 0x14 ; 20 } - 7fea: da cf rjmp .-76 ; 0x7fa0 + 1ea: da cf rjmp .-76 ; 0x1a0 -00007fec : +000001ec : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 7fec: 1f 93 push r17 - 7fee: 18 2f mov r17, r24 + 1ec: 1f 93 push r17 + 1ee: 18 2f mov r17, r24 do getch(); while (--count); - 7ff0: df df rcall .-66 ; 0x7fb0 - 7ff2: 11 50 subi r17, 0x01 ; 1 - 7ff4: e9 f7 brne .-6 ; 0x7ff0 + 1f0: df df rcall .-66 ; 0x1b0 + 1f2: 11 50 subi r17, 0x01 ; 1 + 1f4: e9 f7 brne .-6 ; 0x1f0 verifySpace(); - 7ff6: f4 df rcall .-24 ; 0x7fe0 + 1f6: f4 df rcall .-24 ; 0x1e0 } - 7ff8: 1f 91 pop r17 - 7ffa: 08 95 ret + 1f8: 1f 91 pop r17 + 1fa: 08 95 ret diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.hex b/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.hex index 2b4a582a4..3ac0de204 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.hex @@ -30,5 +30,6 @@ :103FD00090838083089580E0F8DFEE27FF2709941F :103FE000E7DF803209F0F7DF84E1DACF1F93182F83 :0C3FF000DFDF1150E9F7F4DF1F910895A6 +:023FFE000104BC :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.lst b/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.lst index e0a1ecf51..8b1736859 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.lst @@ -5,23 +5,25 @@ Sections: Idx Name Size VMA LMA File off Algn 0 .text 000001fc 00003e00 00003e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .debug_aranges 00000028 00000000 00000000 00000250 2**0 + 1 .version 00000002 00003ffe 00003ffe 00000250 2**0 + CONTENTS, READONLY + 2 .debug_aranges 00000028 00000000 00000000 00000252 2**0 CONTENTS, READONLY, DEBUGGING - 2 .debug_pubnames 0000006a 00000000 00000000 00000278 2**0 + 3 .debug_pubnames 0000006a 00000000 00000000 0000027a 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_info 00000284 00000000 00000000 000002e2 2**0 + 4 .debug_info 00000285 00000000 00000000 000002e4 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_abbrev 000001ae 00000000 00000000 00000566 2**0 + 5 .debug_abbrev 0000019f 00000000 00000000 00000569 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_line 00000450 00000000 00000000 00000714 2**0 + 6 .debug_line 00000453 00000000 00000000 00000708 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_frame 00000090 00000000 00000000 00000b64 2**2 + 7 .debug_frame 00000090 00000000 00000000 00000b5c 2**2 CONTENTS, READONLY, DEBUGGING - 7 .debug_str 00000141 00000000 00000000 00000bf4 2**0 + 8 .debug_str 00000141 00000000 00000000 00000bec 2**0 CONTENTS, READONLY, DEBUGGING - 8 .debug_loc 000001e1 00000000 00000000 00000d35 2**0 + 9 .debug_loc 000001e1 00000000 00000000 00000d2d 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_ranges 00000068 00000000 00000000 00000f16 2**0 + 10 .debug_ranges 00000068 00000000 00000000 00000f0e 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: @@ -135,7 +137,7 @@ void watchdogReset() { __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); - + // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); 3e50: a5 e0 ldi r26, 0x05 ; 5 @@ -249,7 +251,7 @@ void watchdogReset() { 3ec6: e8 95 spm 3ec8: c0 e0 ldi r28, 0x00 ; 0 3eca: d1 e0 ldi r29, 0x01 ; 1 - + // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); @@ -278,7 +280,7 @@ void watchdogReset() { // Read command terminator, start reply verifySpace(); 3ef4: 75 d0 rcall .+234 ; 0x3fe0 - + // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); @@ -336,7 +338,7 @@ int main(void) { 3f2e: a0 38 cpi r26, 0x80 ; 128 3f30: bf 07 cpc r27, r31 3f32: 51 f7 brne .-44 ; 0x3f08 - + // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); 3f34: e0 91 00 02 lds r30, 0x0200 diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.hex b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.hex index 757928697..77897e798 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.hex @@ -30,5 +30,6 @@ :103FD00090838083089580E0F8DFEE27FF2709941F :103FE000E7DF803209F0F7DF84E1DACF1F93182F83 :0C3FF000DFDF1150E9F7F4DF1F910895A6 +:023FFE000104BC :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.lst b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.lst index cbae2687c..75180bc30 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.lst @@ -5,23 +5,25 @@ Sections: Idx Name Size VMA LMA File off Algn 0 .text 000001fc 00003e00 00003e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .debug_aranges 00000028 00000000 00000000 00000250 2**0 + 1 .version 00000002 00003ffe 00003ffe 00000250 2**0 + CONTENTS, READONLY + 2 .debug_aranges 00000028 00000000 00000000 00000252 2**0 CONTENTS, READONLY, DEBUGGING - 2 .debug_pubnames 0000006a 00000000 00000000 00000278 2**0 + 3 .debug_pubnames 0000006a 00000000 00000000 0000027a 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_info 00000284 00000000 00000000 000002e2 2**0 + 4 .debug_info 00000285 00000000 00000000 000002e4 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_abbrev 000001ae 00000000 00000000 00000566 2**0 + 5 .debug_abbrev 0000019f 00000000 00000000 00000569 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_line 00000450 00000000 00000000 00000714 2**0 + 6 .debug_line 00000453 00000000 00000000 00000708 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_frame 00000090 00000000 00000000 00000b64 2**2 + 7 .debug_frame 00000090 00000000 00000000 00000b5c 2**2 CONTENTS, READONLY, DEBUGGING - 7 .debug_str 00000141 00000000 00000000 00000bf4 2**0 + 8 .debug_str 00000141 00000000 00000000 00000bec 2**0 CONTENTS, READONLY, DEBUGGING - 8 .debug_loc 000001e1 00000000 00000000 00000d35 2**0 + 9 .debug_loc 000001e1 00000000 00000000 00000d2d 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_ranges 00000068 00000000 00000000 00000f16 2**0 + 10 .debug_ranges 00000068 00000000 00000000 00000f0e 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: @@ -135,7 +137,7 @@ void watchdogReset() { __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); - + // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); 3e50: a5 e0 ldi r26, 0x05 ; 5 @@ -249,7 +251,7 @@ void watchdogReset() { 3ec6: e8 95 spm 3ec8: c0 e0 ldi r28, 0x00 ; 0 3eca: d1 e0 ldi r29, 0x01 ; 1 - + // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); @@ -278,7 +280,7 @@ void watchdogReset() { // Read command terminator, start reply verifySpace(); 3ef4: 75 d0 rcall .+234 ; 0x3fe0 - + // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); @@ -336,7 +338,7 @@ int main(void) { 3f2e: a0 38 cpi r26, 0x80 ; 128 3f30: bf 07 cpc r27, r31 3f32: 51 f7 brne .-44 ; 0x3f08 - + // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); 3f34: e0 91 00 02 lds r30, 0x0200 diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.hex b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.hex index 757928697..77897e798 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.hex @@ -30,5 +30,6 @@ :103FD00090838083089580E0F8DFEE27FF2709941F :103FE000E7DF803209F0F7DF84E1DACF1F93182F83 :0C3FF000DFDF1150E9F7F4DF1F910895A6 +:023FFE000104BC :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.lst b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.lst index c5d771009..48c2778ac 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.lst @@ -5,23 +5,25 @@ Sections: Idx Name Size VMA LMA File off Algn 0 .text 000001fc 00003e00 00003e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .debug_aranges 00000028 00000000 00000000 00000250 2**0 + 1 .version 00000002 00003ffe 00003ffe 00000250 2**0 + CONTENTS, READONLY + 2 .debug_aranges 00000028 00000000 00000000 00000252 2**0 CONTENTS, READONLY, DEBUGGING - 2 .debug_pubnames 0000006a 00000000 00000000 00000278 2**0 + 3 .debug_pubnames 0000006a 00000000 00000000 0000027a 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_info 00000284 00000000 00000000 000002e2 2**0 + 4 .debug_info 00000285 00000000 00000000 000002e4 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_abbrev 000001ae 00000000 00000000 00000566 2**0 + 5 .debug_abbrev 0000019f 00000000 00000000 00000569 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_line 00000450 00000000 00000000 00000714 2**0 + 6 .debug_line 00000453 00000000 00000000 00000708 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_frame 00000090 00000000 00000000 00000b64 2**2 + 7 .debug_frame 00000090 00000000 00000000 00000b5c 2**2 CONTENTS, READONLY, DEBUGGING - 7 .debug_str 00000141 00000000 00000000 00000bf4 2**0 + 8 .debug_str 00000141 00000000 00000000 00000bec 2**0 CONTENTS, READONLY, DEBUGGING - 8 .debug_loc 000001e1 00000000 00000000 00000d35 2**0 + 9 .debug_loc 000001e1 00000000 00000000 00000d2d 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_ranges 00000068 00000000 00000000 00000f16 2**0 + 10 .debug_ranges 00000068 00000000 00000000 00000f0e 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: @@ -135,7 +137,7 @@ void watchdogReset() { __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); - + // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); 3e50: a5 e0 ldi r26, 0x05 ; 5 @@ -249,7 +251,7 @@ void watchdogReset() { 3ec6: e8 95 spm 3ec8: c0 e0 ldi r28, 0x00 ; 0 3eca: d1 e0 ldi r29, 0x01 ; 1 - + // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); @@ -278,7 +280,7 @@ void watchdogReset() { // Read command terminator, start reply verifySpace(); 3ef4: 75 d0 rcall .+234 ; 0x3fe0 - + // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); @@ -336,7 +338,7 @@ int main(void) { 3f2e: a0 38 cpi r26, 0x80 ; 128 3f30: bf 07 cpc r27, r31 3f32: 51 f7 brne .-44 ; 0x3f08 - + // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); 3f34: e0 91 00 02 lds r30, 0x0200 diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_luminet.hex b/hardware/arduino/bootloaders/optiboot/optiboot_luminet.hex index 3ad3c0a7a..0f901f4ee 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_luminet.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_luminet.hex @@ -1,42 +1,42 @@ -:101D0000112484B714BE81FF22D185E08EBD8EE000 -:101D10001AD1D49AD29A86E023EC3FEF91E03DBDF0 -:101D20002CBD9BB9589BFECFCC9AA8958150B9F792 -:101D3000DD24D39485E0C82E0FE7F02E1EECE12EB3 -:101D4000E9D0813421F481E00DD183E020C08234D8 -:101D500011F484E103C0853419F485E003D1C8C0CF -:101D6000853581F4D7D0082F10E0D4D090E0982F9B -:101D70008827802B912B880F991F90938101809346 -:101D80008001B5C0863529F484E0ECD080E0B3D082 -:101D9000AFC0843609F06BC0D1D0C0E0D1E0BAD07A -:101DA0008993809182018150809382018823B9F7C1 -:101DB000E0918001F091810183E087BFE895CCD06C -:101DC00007B600FCFDCF8091800190918101892BA5 -:101DD00041F5809100012091010130E0322F22274E -:101DE00090E0282B392B309385012093840140917A -:101DF00008018091090190E0982F882750E0842BFA -:101E0000952B909387018093860124503040209336 -:101E10000801232F332720930901F0920001E0925B -:101E200001014091800150918101A0E0B1E02C912D -:101E300030E011968C91119790E0982F8827822B93 -:101E4000932B1296FA010C01D7BEE89511244E5F30 -:101E50005F4FF1E0A034BF0751F7E0918001F091AE -:101E60008101C7BEE89507B600FCFDCF41C08437AD -:101E700089F564D071D0E0918001F09181013097B3 -:101E800019F42091840113C0E130F10519F4209177 -:101E900085010DC0E830F10519F42091860107C0D5 -:101EA000E930F10519F42091870101C02491809156 -:101EB000800190918101019690938101809380012E -:101EC000822F19D0809182018150809382018823D2 -:101ED00091F60EC0853739F43FD08EE10CD083E9FE -:101EE0000AD08CE054CF813511F488E02CD034D066 -:101EF00080E101D025CF2AE030E08095089410F4ED -:101F0000DA9802C0DA9A000015D014D086952A9586 -:101F1000B1F70895A89529E030E0CB99FECF0AD01B -:101F200009D008D08894CB9908942A9511F0879508 -:101F3000F7CF08959EE09A95F1F70895EBDFEADF79 -:101F400080938201E7CF98E191BD81BD089580E043 -:101F5000FADFE4E0FF270994DDDF803209F0F7DFE4 -:101F600084E1C9CF1F93182FD5DF1150E9F7F4DFB3 -:041F70001F91089520 -:0400000300001D00DC +:10000000112484B714BE81FF22D185E08EBD8EE01D +:100010001AD1D49AD29A86E023EC3FEF91E03DBD0D +:100020002CBD9BB9589BFECFCC9AA8958150B9F7AF +:10003000DD24D39485E0C82E0FE7F02E1EECE12ED0 +:10004000E9D0813421F481E00DD183E020C08234F5 +:1000500011F484E103C0853419F485E003D1C8C0EC +:10006000853581F4D7D0082F10E0D4D090E0982FB8 +:100070008827802B912B880F991F90938101809363 +:100080008001B5C0863529F484E0ECD080E0B3D09F +:10009000AFC0843609F06BC0D1D0C0E0D1E0BAD097 +:1000A0008993809182018150809382018823B9F7DE +:1000B000E0918001F091810183E087BFE895CCD089 +:1000C00007B600FCFDCF8091800190918101892BC2 +:1000D00041F5809100012091010130E0322F22276B +:1000E00090E0282B392B3093850120938401409197 +:1000F00008018091090190E0982F882750E0842B17 +:10010000952B909387018093860124503040209353 +:100110000801232F332720930901F0920001E09278 +:1001200001014091800150918101A0E0B1E02C914A +:1001300030E011968C91119790E0982F8827822BB0 +:10014000932B1296FA010C01D7BEE89511244E5F4D +:100150005F4FF1E0A034BF0751F7E0918001F091CB +:100160008101C7BEE89507B600FCFDCF41C08437CA +:1001700089F564D071D0E0918001F09181013097D0 +:1001800019F42091840113C0E130F10519F4209194 +:1001900085010DC0E830F10519F42091860107C0F2 +:1001A000E930F10519F42091870101C02491809173 +:1001B000800190918101019690938101809380014B +:1001C000822F19D0809182018150809382018823EF +:1001D00091F60EC0853739F43FD08EE10CD083E91B +:1001E0000AD08CE054CF813511F488E02CD034D083 +:1001F00080E101D025CF2AE030E08095089410F40A +:10020000DA9802C0DA9A000015D014D086952A95A3 +:10021000B1F70895A89529E030E0CB99FECF0AD038 +:1002200009D008D08894CB9908942A9511F0879525 +:10023000F7CF08959EE09A95F1F70895EBDFEADF96 +:1002400080938201E7CF98E191BD81BD089580E060 +:10025000FADFE4E0FF270994DDDF803209F0F7DF01 +:1002600084E1C9CF1F93182FD5DF1150E9F7F4DFD0 +:040270001F9108953D +:021EFE000104DD :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_luminet.lst b/hardware/arduino/bootloaders/optiboot/optiboot_luminet.lst index 737d2c549..1be7e4fab 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_luminet.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_luminet.lst @@ -3,620 +3,622 @@ optiboot_luminet.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .text 00000274 00001d00 00001d00 00000054 2**1 + 0 .version 00000002 00001efe 00001efe 000002c8 2**0 + CONTENTS, READONLY + 1 .text 00000274 00000000 00000000 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .debug_aranges 00000028 00000000 00000000 000002c8 2**0 + 2 .debug_aranges 00000028 00000000 00000000 000002ca 2**0 CONTENTS, READONLY, DEBUGGING - 2 .debug_pubnames 00000078 00000000 00000000 000002f0 2**0 + 3 .debug_pubnames 00000078 00000000 00000000 000002f2 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_info 000002a4 00000000 00000000 00000368 2**0 + 4 .debug_info 000002a5 00000000 00000000 0000036a 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_abbrev 000001ac 00000000 00000000 0000060c 2**0 + 5 .debug_abbrev 0000019d 00000000 00000000 0000060f 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_line 000004a9 00000000 00000000 000007b8 2**0 + 6 .debug_line 000004ac 00000000 00000000 000007ac 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_frame 000000a0 00000000 00000000 00000c64 2**2 + 7 .debug_frame 000000a0 00000000 00000000 00000c58 2**2 CONTENTS, READONLY, DEBUGGING - 7 .debug_str 00000150 00000000 00000000 00000d04 2**0 + 8 .debug_str 00000150 00000000 00000000 00000cf8 2**0 CONTENTS, READONLY, DEBUGGING - 8 .debug_loc 00000194 00000000 00000000 00000e54 2**0 + 9 .debug_loc 00000194 00000000 00000000 00000e48 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_ranges 00000088 00000000 00000000 00000fe8 2**0 + 10 .debug_ranges 00000088 00000000 00000000 00000fdc 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: -00001d00
    : +00000000
    : #define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) #define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif /* main program starts here */ int main(void) { - 1d00: 11 24 eor r1, r1 + 0: 11 24 eor r1, r1 #ifdef __AVR_ATmega8__ SP=RAMEND; // This is done by hardware reset #endif // Adaboot no-wait mod ch = MCUSR; - 1d02: 84 b7 in r24, 0x34 ; 52 + 2: 84 b7 in r24, 0x34 ; 52 MCUSR = 0; - 1d04: 14 be out 0x34, r1 ; 52 + 4: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); - 1d06: 81 ff sbrs r24, 1 - 1d08: 22 d1 rcall .+580 ; 0x1f4e + 6: 81 ff sbrs r24, 1 + 8: 22 d1 rcall .+580 ; 0x24e #if LED_START_FLASHES > 0 // Set up Timer 1 for timeout counter TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 - 1d0a: 85 e0 ldi r24, 0x05 ; 5 - 1d0c: 8e bd out 0x2e, r24 ; 46 + a: 85 e0 ldi r24, 0x05 ; 5 + c: 8e bd out 0x2e, r24 ; 46 UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); #endif #endif // Set up watchdog to trigger after 500ms watchdogConfig(WATCHDOG_1S); - 1d0e: 8e e0 ldi r24, 0x0E ; 14 - 1d10: 1a d1 rcall .+564 ; 0x1f46 + e: 8e e0 ldi r24, 0x0E ; 14 + 10: 1a d1 rcall .+564 ; 0x246 /* Set LED pin as output */ LED_DDR |= _BV(LED); - 1d12: d4 9a sbi 0x1a, 4 ; 26 + 12: d4 9a sbi 0x1a, 4 ; 26 #ifdef SOFT_UART /* Set TX pin as output */ UART_DDR |= _BV(UART_TX_BIT); - 1d14: d2 9a sbi 0x1a, 2 ; 26 - 1d16: 86 e0 ldi r24, 0x06 ; 6 + 14: d2 9a sbi 0x1a, 2 ; 26 + 16: 86 e0 ldi r24, 0x06 ; 6 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - 1d18: 23 ec ldi r18, 0xC3 ; 195 - 1d1a: 3f ef ldi r19, 0xFF ; 255 + 18: 23 ec ldi r18, 0xC3 ; 195 + 1a: 3f ef ldi r19, 0xFF ; 255 TIFR1 = _BV(TOV1); - 1d1c: 91 e0 ldi r25, 0x01 ; 1 + 1c: 91 e0 ldi r25, 0x01 ; 1 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - 1d1e: 3d bd out 0x2d, r19 ; 45 - 1d20: 2c bd out 0x2c, r18 ; 44 + 1e: 3d bd out 0x2d, r19 ; 45 + 20: 2c bd out 0x2c, r18 ; 44 TIFR1 = _BV(TOV1); - 1d22: 9b b9 out 0x0b, r25 ; 11 + 22: 9b b9 out 0x0b, r25 ; 11 while(!(TIFR1 & _BV(TOV1))); - 1d24: 58 9b sbis 0x0b, 0 ; 11 - 1d26: fe cf rjmp .-4 ; 0x1d24 + 24: 58 9b sbis 0x0b, 0 ; 11 + 26: fe cf rjmp .-4 ; 0x24 <__zero_reg__+0x23> #ifdef __AVR_ATmega8__ LED_PORT ^= _BV(LED); #else LED_PIN |= _BV(LED); - 1d28: cc 9a sbi 0x19, 4 ; 25 + 28: cc 9a sbi 0x19, 4 ; 25 return getch(); } // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 1d2a: a8 95 wdr + 2a: a8 95 wdr LED_PORT ^= _BV(LED); #else LED_PIN |= _BV(LED); #endif watchdogReset(); } while (--count); - 1d2c: 81 50 subi r24, 0x01 ; 1 - 1d2e: b9 f7 brne .-18 ; 0x1d1e + 2c: 81 50 subi r24, 0x01 ; 1 + 2e: b9 f7 brne .-18 ; 0x1e <__zero_reg__+0x1d> /* get character from UART */ ch = getch(); if(ch == STK_GET_PARAMETER) { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 1d30: dd 24 eor r13, r13 - 1d32: d3 94 inc r13 + 30: dd 24 eor r13, r13 + 32: d3 94 inc r13 __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); - + // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); - 1d34: 85 e0 ldi r24, 0x05 ; 5 - 1d36: c8 2e mov r12, r24 + 34: 85 e0 ldi r24, 0x05 ; 5 + 36: c8 2e mov r12, r24 vect -= 4; // Instruction is a relative jump (rjmp), so recalculate. buff[8] = vect & 0xff; buff[9] = vect >> 8; // Add jump to bootloader at RESET vector buff[0] = 0x7f; - 1d38: 0f e7 ldi r16, 0x7F ; 127 - 1d3a: f0 2e mov r15, r16 + 38: 0f e7 ldi r16, 0x7F ; 127 + 3a: f0 2e mov r15, r16 buff[1] = 0xce; // rjmp 0x1d00 instruction - 1d3c: 1e ec ldi r17, 0xCE ; 206 - 1d3e: e1 2e mov r14, r17 + 3c: 1e ec ldi r17, 0xCE ; 206 + 3e: e1 2e mov r14, r17 #endif /* Forever loop */ for (;;) { /* get character from UART */ ch = getch(); - 1d40: e9 d0 rcall .+466 ; 0x1f14 + 40: e9 d0 rcall .+466 ; 0x214 if(ch == STK_GET_PARAMETER) { - 1d42: 81 34 cpi r24, 0x41 ; 65 - 1d44: 21 f4 brne .+8 ; 0x1d4e + 42: 81 34 cpi r24, 0x41 ; 65 + 44: 21 f4 brne .+8 ; 0x4e <__SREG__+0xf> // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 1d46: 81 e0 ldi r24, 0x01 ; 1 - 1d48: 0d d1 rcall .+538 ; 0x1f64 + 46: 81 e0 ldi r24, 0x01 ; 1 + 48: 0d d1 rcall .+538 ; 0x264 putch(0x03); - 1d4a: 83 e0 ldi r24, 0x03 ; 3 - 1d4c: 20 c0 rjmp .+64 ; 0x1d8e + 4a: 83 e0 ldi r24, 0x03 ; 3 + 4c: 20 c0 rjmp .+64 ; 0x8e <__SREG__+0x4f> } else if(ch == STK_SET_DEVICE) { - 1d4e: 82 34 cpi r24, 0x42 ; 66 - 1d50: 11 f4 brne .+4 ; 0x1d56 + 4e: 82 34 cpi r24, 0x42 ; 66 + 50: 11 f4 brne .+4 ; 0x56 <__SREG__+0x17> // SET DEVICE is ignored getNch(20); - 1d52: 84 e1 ldi r24, 0x14 ; 20 - 1d54: 03 c0 rjmp .+6 ; 0x1d5c + 52: 84 e1 ldi r24, 0x14 ; 20 + 54: 03 c0 rjmp .+6 ; 0x5c <__SREG__+0x1d> } else if(ch == STK_SET_DEVICE_EXT) { - 1d56: 85 34 cpi r24, 0x45 ; 69 - 1d58: 19 f4 brne .+6 ; 0x1d60 + 56: 85 34 cpi r24, 0x45 ; 69 + 58: 19 f4 brne .+6 ; 0x60 <__SREG__+0x21> // SET DEVICE EXT is ignored getNch(5); - 1d5a: 85 e0 ldi r24, 0x05 ; 5 - 1d5c: 03 d1 rcall .+518 ; 0x1f64 - 1d5e: c8 c0 rjmp .+400 ; 0x1ef0 + 5a: 85 e0 ldi r24, 0x05 ; 5 + 5c: 03 d1 rcall .+518 ; 0x264 + 5e: c8 c0 rjmp .+400 ; 0x1f0 <__SREG__+0x1b1> } else if(ch == STK_LOAD_ADDRESS) { - 1d60: 85 35 cpi r24, 0x55 ; 85 - 1d62: 81 f4 brne .+32 ; 0x1d84 + 60: 85 35 cpi r24, 0x55 ; 85 + 62: 81 f4 brne .+32 ; 0x84 <__SREG__+0x45> // LOAD ADDRESS uint16_t newAddress; newAddress = getch(); - 1d64: d7 d0 rcall .+430 ; 0x1f14 + 64: d7 d0 rcall .+430 ; 0x214 newAddress = (newAddress & 0xff) | (getch() << 8); - 1d66: 08 2f mov r16, r24 - 1d68: 10 e0 ldi r17, 0x00 ; 0 - 1d6a: d4 d0 rcall .+424 ; 0x1f14 - 1d6c: 90 e0 ldi r25, 0x00 ; 0 - 1d6e: 98 2f mov r25, r24 - 1d70: 88 27 eor r24, r24 - 1d72: 80 2b or r24, r16 - 1d74: 91 2b or r25, r17 + 66: 08 2f mov r16, r24 + 68: 10 e0 ldi r17, 0x00 ; 0 + 6a: d4 d0 rcall .+424 ; 0x214 + 6c: 90 e0 ldi r25, 0x00 ; 0 + 6e: 98 2f mov r25, r24 + 70: 88 27 eor r24, r24 + 72: 80 2b or r24, r16 + 74: 91 2b or r25, r17 #ifdef RAMPZ // Transfer top bit to RAMPZ RAMPZ = (newAddress & 0x8000) ? 1 : 0; #endif newAddress += newAddress; // Convert from word address to byte address - 1d76: 88 0f add r24, r24 - 1d78: 99 1f adc r25, r25 + 76: 88 0f add r24, r24 + 78: 99 1f adc r25, r25 address = newAddress; - 1d7a: 90 93 81 01 sts 0x0181, r25 - 1d7e: 80 93 80 01 sts 0x0180, r24 - 1d82: b5 c0 rjmp .+362 ; 0x1eee + 7a: 90 93 81 01 sts 0x0181, r25 + 7e: 80 93 80 01 sts 0x0180, r24 + 82: b5 c0 rjmp .+362 ; 0x1ee <__SREG__+0x1af> verifySpace(); } else if(ch == STK_UNIVERSAL) { - 1d84: 86 35 cpi r24, 0x56 ; 86 - 1d86: 29 f4 brne .+10 ; 0x1d92 + 84: 86 35 cpi r24, 0x56 ; 86 + 86: 29 f4 brne .+10 ; 0x92 <__SREG__+0x53> // UNIVERSAL command is ignored getNch(4); - 1d88: 84 e0 ldi r24, 0x04 ; 4 - 1d8a: ec d0 rcall .+472 ; 0x1f64 + 88: 84 e0 ldi r24, 0x04 ; 4 + 8a: ec d0 rcall .+472 ; 0x264 putch(0x00); - 1d8c: 80 e0 ldi r24, 0x00 ; 0 - 1d8e: b3 d0 rcall .+358 ; 0x1ef6 - 1d90: af c0 rjmp .+350 ; 0x1ef0 + 8c: 80 e0 ldi r24, 0x00 ; 0 + 8e: b3 d0 rcall .+358 ; 0x1f6 + 90: af c0 rjmp .+350 ; 0x1f0 <__SREG__+0x1b1> } /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { - 1d92: 84 36 cpi r24, 0x64 ; 100 - 1d94: 09 f0 breq .+2 ; 0x1d98 - 1d96: 6b c0 rjmp .+214 ; 0x1e6e + 92: 84 36 cpi r24, 0x64 ; 100 + 94: 09 f0 breq .+2 ; 0x98 <__SREG__+0x59> + 96: 6b c0 rjmp .+214 ; 0x16e <__SREG__+0x12f> // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t *bufPtr; uint16_t addrPtr; getLen(); - 1d98: d1 d0 rcall .+418 ; 0x1f3c - 1d9a: c0 e0 ldi r28, 0x00 ; 0 - 1d9c: d1 e0 ldi r29, 0x01 ; 1 + 98: d1 d0 rcall .+418 ; 0x23c + 9a: c0 e0 ldi r28, 0x00 ; 0 + 9c: d1 e0 ldi r29, 0x01 ; 1 // If we are in RWW section, immediately start page erase if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - + // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); - 1d9e: ba d0 rcall .+372 ; 0x1f14 - 1da0: 89 93 st Y+, r24 + 9e: ba d0 rcall .+372 ; 0x214 + a0: 89 93 st Y+, r24 while (--length); - 1da2: 80 91 82 01 lds r24, 0x0182 - 1da6: 81 50 subi r24, 0x01 ; 1 - 1da8: 80 93 82 01 sts 0x0182, r24 - 1dac: 88 23 and r24, r24 - 1dae: b9 f7 brne .-18 ; 0x1d9e + a2: 80 91 82 01 lds r24, 0x0182 + a6: 81 50 subi r24, 0x01 ; 1 + a8: 80 93 82 01 sts 0x0182, r24 + ac: 88 23 and r24, r24 + ae: b9 f7 brne .-18 ; 0x9e <__SREG__+0x5f> // If we are in NRWW section, page erase has to be delayed until now. // Todo: Take RAMPZ into account if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 1db0: e0 91 80 01 lds r30, 0x0180 - 1db4: f0 91 81 01 lds r31, 0x0181 - 1db8: 83 e0 ldi r24, 0x03 ; 3 - 1dba: 87 bf out 0x37, r24 ; 55 - 1dbc: e8 95 spm + b0: e0 91 80 01 lds r30, 0x0180 + b4: f0 91 81 01 lds r31, 0x0181 + b8: 83 e0 ldi r24, 0x03 ; 3 + ba: 87 bf out 0x37, r24 ; 55 + bc: e8 95 spm // Read command terminator, start reply verifySpace(); - 1dbe: cc d0 rcall .+408 ; 0x1f58 - + be: cc d0 rcall .+408 ; 0x258 + // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); - 1dc0: 07 b6 in r0, 0x37 ; 55 - 1dc2: 00 fc sbrc r0, 0 - 1dc4: fd cf rjmp .-6 ; 0x1dc0 + c0: 07 b6 in r0, 0x37 ; 55 + c2: 00 fc sbrc r0, 0 + c4: fd cf rjmp .-6 ; 0xc0 <__SREG__+0x81> #ifdef VIRTUAL_BOOT_PARTITION if ((uint16_t)(void*)address == 0) { - 1dc6: 80 91 80 01 lds r24, 0x0180 - 1dca: 90 91 81 01 lds r25, 0x0181 - 1dce: 89 2b or r24, r25 - 1dd0: 41 f5 brne .+80 ; 0x1e22 + c6: 80 91 80 01 lds r24, 0x0180 + ca: 90 91 81 01 lds r25, 0x0181 + ce: 89 2b or r24, r25 + d0: 41 f5 brne .+80 ; 0x122 <__SREG__+0xe3> // This is the reset vector page. We need to live-patch the code so the // bootloader runs. // // Move RESET vector to WDT vector uint16_t vect = buff[0] | (buff[1]<<8); - 1dd2: 80 91 00 01 lds r24, 0x0100 - 1dd6: 20 91 01 01 lds r18, 0x0101 - 1dda: 30 e0 ldi r19, 0x00 ; 0 - 1ddc: 32 2f mov r19, r18 - 1dde: 22 27 eor r18, r18 - 1de0: 90 e0 ldi r25, 0x00 ; 0 - 1de2: 28 2b or r18, r24 - 1de4: 39 2b or r19, r25 + d2: 80 91 00 01 lds r24, 0x0100 + d6: 20 91 01 01 lds r18, 0x0101 + da: 30 e0 ldi r19, 0x00 ; 0 + dc: 32 2f mov r19, r18 + de: 22 27 eor r18, r18 + e0: 90 e0 ldi r25, 0x00 ; 0 + e2: 28 2b or r18, r24 + e4: 39 2b or r19, r25 rstVect = vect; - 1de6: 30 93 85 01 sts 0x0185, r19 - 1dea: 20 93 84 01 sts 0x0184, r18 + e6: 30 93 85 01 sts 0x0185, r19 + ea: 20 93 84 01 sts 0x0184, r18 wdtVect = buff[8] | (buff[9]<<8); - 1dee: 40 91 08 01 lds r20, 0x0108 - 1df2: 80 91 09 01 lds r24, 0x0109 - 1df6: 90 e0 ldi r25, 0x00 ; 0 - 1df8: 98 2f mov r25, r24 - 1dfa: 88 27 eor r24, r24 - 1dfc: 50 e0 ldi r21, 0x00 ; 0 - 1dfe: 84 2b or r24, r20 - 1e00: 95 2b or r25, r21 - 1e02: 90 93 87 01 sts 0x0187, r25 - 1e06: 80 93 86 01 sts 0x0186, r24 + ee: 40 91 08 01 lds r20, 0x0108 + f2: 80 91 09 01 lds r24, 0x0109 + f6: 90 e0 ldi r25, 0x00 ; 0 + f8: 98 2f mov r25, r24 + fa: 88 27 eor r24, r24 + fc: 50 e0 ldi r21, 0x00 ; 0 + fe: 84 2b or r24, r20 + 100: 95 2b or r25, r21 + 102: 90 93 87 01 sts 0x0187, r25 + 106: 80 93 86 01 sts 0x0186, r24 vect -= 4; // Instruction is a relative jump (rjmp), so recalculate. - 1e0a: 24 50 subi r18, 0x04 ; 4 - 1e0c: 30 40 sbci r19, 0x00 ; 0 + 10a: 24 50 subi r18, 0x04 ; 4 + 10c: 30 40 sbci r19, 0x00 ; 0 buff[8] = vect & 0xff; - 1e0e: 20 93 08 01 sts 0x0108, r18 + 10e: 20 93 08 01 sts 0x0108, r18 buff[9] = vect >> 8; - 1e12: 23 2f mov r18, r19 - 1e14: 33 27 eor r19, r19 - 1e16: 20 93 09 01 sts 0x0109, r18 + 112: 23 2f mov r18, r19 + 114: 33 27 eor r19, r19 + 116: 20 93 09 01 sts 0x0109, r18 // Add jump to bootloader at RESET vector buff[0] = 0x7f; - 1e1a: f0 92 00 01 sts 0x0100, r15 + 11a: f0 92 00 01 sts 0x0100, r15 buff[1] = 0xce; // rjmp 0x1d00 instruction - 1e1e: e0 92 01 01 sts 0x0101, r14 + 11e: e0 92 01 01 sts 0x0101, r14 } #endif // Copy buffer into programming buffer bufPtr = buff; addrPtr = (uint16_t)(void*)address; - 1e22: 40 91 80 01 lds r20, 0x0180 - 1e26: 50 91 81 01 lds r21, 0x0181 - 1e2a: a0 e0 ldi r26, 0x00 ; 0 - 1e2c: b1 e0 ldi r27, 0x01 ; 1 + 122: 40 91 80 01 lds r20, 0x0180 + 126: 50 91 81 01 lds r21, 0x0181 + 12a: a0 e0 ldi r26, 0x00 ; 0 + 12c: b1 e0 ldi r27, 0x01 ; 1 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; - 1e2e: 2c 91 ld r18, X - 1e30: 30 e0 ldi r19, 0x00 ; 0 + 12e: 2c 91 ld r18, X + 130: 30 e0 ldi r19, 0x00 ; 0 a |= (*bufPtr++) << 8; - 1e32: 11 96 adiw r26, 0x01 ; 1 - 1e34: 8c 91 ld r24, X - 1e36: 11 97 sbiw r26, 0x01 ; 1 - 1e38: 90 e0 ldi r25, 0x00 ; 0 - 1e3a: 98 2f mov r25, r24 - 1e3c: 88 27 eor r24, r24 - 1e3e: 82 2b or r24, r18 - 1e40: 93 2b or r25, r19 + 132: 11 96 adiw r26, 0x01 ; 1 + 134: 8c 91 ld r24, X + 136: 11 97 sbiw r26, 0x01 ; 1 + 138: 90 e0 ldi r25, 0x00 ; 0 + 13a: 98 2f mov r25, r24 + 13c: 88 27 eor r24, r24 + 13e: 82 2b or r24, r18 + 140: 93 2b or r25, r19 #define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) #define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif /* main program starts here */ int main(void) { - 1e42: 12 96 adiw r26, 0x02 ; 2 + 142: 12 96 adiw r26, 0x02 ; 2 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; a |= (*bufPtr++) << 8; __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - 1e44: fa 01 movw r30, r20 - 1e46: 0c 01 movw r0, r24 - 1e48: d7 be out 0x37, r13 ; 55 - 1e4a: e8 95 spm - 1e4c: 11 24 eor r1, r1 + 144: fa 01 movw r30, r20 + 146: 0c 01 movw r0, r24 + 148: d7 be out 0x37, r13 ; 55 + 14a: e8 95 spm + 14c: 11 24 eor r1, r1 addrPtr += 2; - 1e4e: 4e 5f subi r20, 0xFE ; 254 - 1e50: 5f 4f sbci r21, 0xFF ; 255 + 14e: 4e 5f subi r20, 0xFE ; 254 + 150: 5f 4f sbci r21, 0xFF ; 255 } while (--ch); - 1e52: f1 e0 ldi r31, 0x01 ; 1 - 1e54: a0 34 cpi r26, 0x40 ; 64 - 1e56: bf 07 cpc r27, r31 - 1e58: 51 f7 brne .-44 ; 0x1e2e - + 152: f1 e0 ldi r31, 0x01 ; 1 + 154: a0 34 cpi r26, 0x40 ; 64 + 156: bf 07 cpc r27, r31 + 158: 51 f7 brne .-44 ; 0x12e <__SREG__+0xef> + // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); - 1e5a: e0 91 80 01 lds r30, 0x0180 - 1e5e: f0 91 81 01 lds r31, 0x0181 - 1e62: c7 be out 0x37, r12 ; 55 - 1e64: e8 95 spm + 15a: e0 91 80 01 lds r30, 0x0180 + 15e: f0 91 81 01 lds r31, 0x0181 + 162: c7 be out 0x37, r12 ; 55 + 164: e8 95 spm boot_spm_busy_wait(); - 1e66: 07 b6 in r0, 0x37 ; 55 - 1e68: 00 fc sbrc r0, 0 - 1e6a: fd cf rjmp .-6 ; 0x1e66 - 1e6c: 41 c0 rjmp .+130 ; 0x1ef0 + 166: 07 b6 in r0, 0x37 ; 55 + 168: 00 fc sbrc r0, 0 + 16a: fd cf rjmp .-6 ; 0x166 <__SREG__+0x127> + 16c: 41 c0 rjmp .+130 ; 0x1f0 <__SREG__+0x1b1> boot_rww_enable(); #endif } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { - 1e6e: 84 37 cpi r24, 0x74 ; 116 - 1e70: 89 f5 brne .+98 ; 0x1ed4 + 16e: 84 37 cpi r24, 0x74 ; 116 + 170: 89 f5 brne .+98 ; 0x1d4 <__SREG__+0x195> // READ PAGE - we only read flash getLen(); - 1e72: 64 d0 rcall .+200 ; 0x1f3c + 172: 64 d0 rcall .+200 ; 0x23c verifySpace(); - 1e74: 71 d0 rcall .+226 ; 0x1f58 + 174: 71 d0 rcall .+226 ; 0x258 #ifdef VIRTUAL_BOOT_PARTITION do { // Undo vector patch in bottom page so verify passes if (address == 0) ch=rstVect & 0xff; - 1e76: e0 91 80 01 lds r30, 0x0180 - 1e7a: f0 91 81 01 lds r31, 0x0181 - 1e7e: 30 97 sbiw r30, 0x00 ; 0 - 1e80: 19 f4 brne .+6 ; 0x1e88 - 1e82: 20 91 84 01 lds r18, 0x0184 - 1e86: 13 c0 rjmp .+38 ; 0x1eae + 176: e0 91 80 01 lds r30, 0x0180 + 17a: f0 91 81 01 lds r31, 0x0181 + 17e: 30 97 sbiw r30, 0x00 ; 0 + 180: 19 f4 brne .+6 ; 0x188 <__SREG__+0x149> + 182: 20 91 84 01 lds r18, 0x0184 + 186: 13 c0 rjmp .+38 ; 0x1ae <__SREG__+0x16f> else if (address == 1) ch=rstVect >> 8; - 1e88: e1 30 cpi r30, 0x01 ; 1 - 1e8a: f1 05 cpc r31, r1 - 1e8c: 19 f4 brne .+6 ; 0x1e94 - 1e8e: 20 91 85 01 lds r18, 0x0185 - 1e92: 0d c0 rjmp .+26 ; 0x1eae + 188: e1 30 cpi r30, 0x01 ; 1 + 18a: f1 05 cpc r31, r1 + 18c: 19 f4 brne .+6 ; 0x194 <__SREG__+0x155> + 18e: 20 91 85 01 lds r18, 0x0185 + 192: 0d c0 rjmp .+26 ; 0x1ae <__SREG__+0x16f> else if (address == 8) ch=wdtVect & 0xff; - 1e94: e8 30 cpi r30, 0x08 ; 8 - 1e96: f1 05 cpc r31, r1 - 1e98: 19 f4 brne .+6 ; 0x1ea0 - 1e9a: 20 91 86 01 lds r18, 0x0186 - 1e9e: 07 c0 rjmp .+14 ; 0x1eae + 194: e8 30 cpi r30, 0x08 ; 8 + 196: f1 05 cpc r31, r1 + 198: 19 f4 brne .+6 ; 0x1a0 <__SREG__+0x161> + 19a: 20 91 86 01 lds r18, 0x0186 + 19e: 07 c0 rjmp .+14 ; 0x1ae <__SREG__+0x16f> else if (address == 9) ch=wdtVect >> 8; - 1ea0: e9 30 cpi r30, 0x09 ; 9 - 1ea2: f1 05 cpc r31, r1 - 1ea4: 19 f4 brne .+6 ; 0x1eac - 1ea6: 20 91 87 01 lds r18, 0x0187 - 1eaa: 01 c0 rjmp .+2 ; 0x1eae + 1a0: e9 30 cpi r30, 0x09 ; 9 + 1a2: f1 05 cpc r31, r1 + 1a4: 19 f4 brne .+6 ; 0x1ac <__SREG__+0x16d> + 1a6: 20 91 87 01 lds r18, 0x0187 + 1aa: 01 c0 rjmp .+2 ; 0x1ae <__SREG__+0x16f> else ch = pgm_read_byte_near(address); - 1eac: 24 91 lpm r18, Z+ + 1ac: 24 91 lpm r18, Z+ address++; - 1eae: 80 91 80 01 lds r24, 0x0180 - 1eb2: 90 91 81 01 lds r25, 0x0181 - 1eb6: 01 96 adiw r24, 0x01 ; 1 - 1eb8: 90 93 81 01 sts 0x0181, r25 - 1ebc: 80 93 80 01 sts 0x0180, r24 + 1ae: 80 91 80 01 lds r24, 0x0180 + 1b2: 90 91 81 01 lds r25, 0x0181 + 1b6: 01 96 adiw r24, 0x01 ; 1 + 1b8: 90 93 81 01 sts 0x0181, r25 + 1bc: 80 93 80 01 sts 0x0180, r24 putch(ch); - 1ec0: 82 2f mov r24, r18 - 1ec2: 19 d0 rcall .+50 ; 0x1ef6 + 1c0: 82 2f mov r24, r18 + 1c2: 19 d0 rcall .+50 ; 0x1f6 } while (--length); - 1ec4: 80 91 82 01 lds r24, 0x0182 - 1ec8: 81 50 subi r24, 0x01 ; 1 - 1eca: 80 93 82 01 sts 0x0182, r24 - 1ece: 88 23 and r24, r24 - 1ed0: 91 f6 brne .-92 ; 0x1e76 - 1ed2: 0e c0 rjmp .+28 ; 0x1ef0 + 1c4: 80 91 82 01 lds r24, 0x0182 + 1c8: 81 50 subi r24, 0x01 ; 1 + 1ca: 80 93 82 01 sts 0x0182, r24 + 1ce: 88 23 and r24, r24 + 1d0: 91 f6 brne .-92 ; 0x176 <__SREG__+0x137> + 1d2: 0e c0 rjmp .+28 ; 0x1f0 <__SREG__+0x1b1> #endif #endif } /* Get device signature bytes */ else if(ch == STK_READ_SIGN) { - 1ed4: 85 37 cpi r24, 0x75 ; 117 - 1ed6: 39 f4 brne .+14 ; 0x1ee6 + 1d4: 85 37 cpi r24, 0x75 ; 117 + 1d6: 39 f4 brne .+14 ; 0x1e6 <__SREG__+0x1a7> // READ SIGN - return what Avrdude wants to hear verifySpace(); - 1ed8: 3f d0 rcall .+126 ; 0x1f58 + 1d8: 3f d0 rcall .+126 ; 0x258 putch(SIGNATURE_0); - 1eda: 8e e1 ldi r24, 0x1E ; 30 - 1edc: 0c d0 rcall .+24 ; 0x1ef6 + 1da: 8e e1 ldi r24, 0x1E ; 30 + 1dc: 0c d0 rcall .+24 ; 0x1f6 putch(SIGNATURE_1); - 1ede: 83 e9 ldi r24, 0x93 ; 147 - 1ee0: 0a d0 rcall .+20 ; 0x1ef6 + 1de: 83 e9 ldi r24, 0x93 ; 147 + 1e0: 0a d0 rcall .+20 ; 0x1f6 putch(SIGNATURE_2); - 1ee2: 8c e0 ldi r24, 0x0C ; 12 - 1ee4: 54 cf rjmp .-344 ; 0x1d8e + 1e2: 8c e0 ldi r24, 0x0C ; 12 + 1e4: 54 cf rjmp .-344 ; 0x8e <__SREG__+0x4f> } else if (ch == 'Q') { - 1ee6: 81 35 cpi r24, 0x51 ; 81 - 1ee8: 11 f4 brne .+4 ; 0x1eee + 1e6: 81 35 cpi r24, 0x51 ; 81 + 1e8: 11 f4 brne .+4 ; 0x1ee <__SREG__+0x1af> // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); - 1eea: 88 e0 ldi r24, 0x08 ; 8 - 1eec: 2c d0 rcall .+88 ; 0x1f46 + 1ea: 88 e0 ldi r24, 0x08 ; 8 + 1ec: 2c d0 rcall .+88 ; 0x246 verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 1eee: 34 d0 rcall .+104 ; 0x1f58 + 1ee: 34 d0 rcall .+104 ; 0x258 } putch(STK_OK); - 1ef0: 80 e1 ldi r24, 0x10 ; 16 - 1ef2: 01 d0 rcall .+2 ; 0x1ef6 - 1ef4: 25 cf rjmp .-438 ; 0x1d40 + 1f0: 80 e1 ldi r24, 0x10 ; 16 + 1f2: 01 d0 rcall .+2 ; 0x1f6 + 1f4: 25 cf rjmp .-438 ; 0x40 <__SREG__+0x1> -00001ef6 : +000001f6 : void putch(char ch) { #ifndef SOFT_UART while (!(UCSR0A & _BV(UDRE0))); UDR0 = ch; #else __asm__ __volatile__ ( - 1ef6: 2a e0 ldi r18, 0x0A ; 10 - 1ef8: 30 e0 ldi r19, 0x00 ; 0 - 1efa: 80 95 com r24 - 1efc: 08 94 sec - 1efe: 10 f4 brcc .+4 ; 0x1f04 - 1f00: da 98 cbi 0x1b, 2 ; 27 - 1f02: 02 c0 rjmp .+4 ; 0x1f08 - 1f04: da 9a sbi 0x1b, 2 ; 27 - 1f06: 00 00 nop - 1f08: 15 d0 rcall .+42 ; 0x1f34 - 1f0a: 14 d0 rcall .+40 ; 0x1f34 - 1f0c: 86 95 lsr r24 - 1f0e: 2a 95 dec r18 - 1f10: b1 f7 brne .-20 ; 0x1efe + 1f6: 2a e0 ldi r18, 0x0A ; 10 + 1f8: 30 e0 ldi r19, 0x00 ; 0 + 1fa: 80 95 com r24 + 1fc: 08 94 sec + 1fe: 10 f4 brcc .+4 ; 0x204 + 200: da 98 cbi 0x1b, 2 ; 27 + 202: 02 c0 rjmp .+4 ; 0x208 + 204: da 9a sbi 0x1b, 2 ; 27 + 206: 00 00 nop + 208: 15 d0 rcall .+42 ; 0x234 + 20a: 14 d0 rcall .+40 ; 0x234 + 20c: 86 95 lsr r24 + 20e: 2a 95 dec r18 + 210: b1 f7 brne .-20 ; 0x1fe [uartBit] "I" (UART_TX_BIT) : "r25" ); #endif } - 1f12: 08 95 ret + 212: 08 95 ret -00001f14 : +00000214 : return getch(); } // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 1f14: a8 95 wdr + 214: a8 95 wdr LED_PIN |= _BV(LED); #endif #endif return ch; } - 1f16: 29 e0 ldi r18, 0x09 ; 9 - 1f18: 30 e0 ldi r19, 0x00 ; 0 - 1f1a: cb 99 sbic 0x19, 3 ; 25 - 1f1c: fe cf rjmp .-4 ; 0x1f1a - 1f1e: 0a d0 rcall .+20 ; 0x1f34 - 1f20: 09 d0 rcall .+18 ; 0x1f34 - 1f22: 08 d0 rcall .+16 ; 0x1f34 - 1f24: 88 94 clc - 1f26: cb 99 sbic 0x19, 3 ; 25 - 1f28: 08 94 sec - 1f2a: 2a 95 dec r18 - 1f2c: 11 f0 breq .+4 ; 0x1f32 - 1f2e: 87 95 ror r24 - 1f30: f7 cf rjmp .-18 ; 0x1f20 - 1f32: 08 95 ret + 216: 29 e0 ldi r18, 0x09 ; 9 + 218: 30 e0 ldi r19, 0x00 ; 0 + 21a: cb 99 sbic 0x19, 3 ; 25 + 21c: fe cf rjmp .-4 ; 0x21a + 21e: 0a d0 rcall .+20 ; 0x234 + 220: 09 d0 rcall .+18 ; 0x234 + 222: 08 d0 rcall .+16 ; 0x234 + 224: 88 94 clc + 226: cb 99 sbic 0x19, 3 ; 25 + 228: 08 94 sec + 22a: 2a 95 dec r18 + 22c: 11 f0 breq .+4 ; 0x232 + 22e: 87 95 ror r24 + 230: f7 cf rjmp .-18 ; 0x220 + 232: 08 95 ret -00001f34 : +00000234 : #if UART_B_VALUE > 255 #error Baud rate too slow for soft UART #endif void uartDelay() { __asm__ __volatile__ ( - 1f34: 9e e0 ldi r25, 0x0E ; 14 - 1f36: 9a 95 dec r25 - 1f38: f1 f7 brne .-4 ; 0x1f36 - 1f3a: 08 95 ret + 234: 9e e0 ldi r25, 0x0E ; 14 + 236: 9a 95 dec r25 + 238: f1 f7 brne .-4 ; 0x236 + 23a: 08 95 ret -00001f3c : +0000023c : } while (--count); } #endif uint8_t getLen() { getch(); - 1f3c: eb df rcall .-42 ; 0x1f14 + 23c: eb df rcall .-42 ; 0x214 length = getch(); - 1f3e: ea df rcall .-44 ; 0x1f14 - 1f40: 80 93 82 01 sts 0x0182, r24 + 23e: ea df rcall .-44 ; 0x214 + 240: 80 93 82 01 sts 0x0182, r24 return getch(); } - 1f44: e7 cf rjmp .-50 ; 0x1f14 + 244: e7 cf rjmp .-50 ; 0x214 -00001f46 : +00000246 : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 1f46: 98 e1 ldi r25, 0x18 ; 24 - 1f48: 91 bd out 0x21, r25 ; 33 + 246: 98 e1 ldi r25, 0x18 ; 24 + 248: 91 bd out 0x21, r25 ; 33 WDTCSR = x; - 1f4a: 81 bd out 0x21, r24 ; 33 + 24a: 81 bd out 0x21, r24 ; 33 } - 1f4c: 08 95 ret + 24c: 08 95 ret -00001f4e : +0000024e : void appStart() { watchdogConfig(WATCHDOG_OFF); - 1f4e: 80 e0 ldi r24, 0x00 ; 0 - 1f50: fa df rcall .-12 ; 0x1f46 + 24e: 80 e0 ldi r24, 0x00 ; 0 + 250: fa df rcall .-12 ; 0x246 __asm__ __volatile__ ( - 1f52: e4 e0 ldi r30, 0x04 ; 4 - 1f54: ff 27 eor r31, r31 - 1f56: 09 94 ijmp + 252: e4 e0 ldi r30, 0x04 ; 4 + 254: ff 27 eor r31, r31 + 256: 09 94 ijmp -00001f58 : +00000258 : do getch(); while (--count); verifySpace(); } void verifySpace() { if (getch() != CRC_EOP) appStart(); - 1f58: dd df rcall .-70 ; 0x1f14 - 1f5a: 80 32 cpi r24, 0x20 ; 32 - 1f5c: 09 f0 breq .+2 ; 0x1f60 - 1f5e: f7 df rcall .-18 ; 0x1f4e + 258: dd df rcall .-70 ; 0x214 + 25a: 80 32 cpi r24, 0x20 ; 32 + 25c: 09 f0 breq .+2 ; 0x260 + 25e: f7 df rcall .-18 ; 0x24e putch(STK_INSYNC); - 1f60: 84 e1 ldi r24, 0x14 ; 20 + 260: 84 e1 ldi r24, 0x14 ; 20 } - 1f62: c9 cf rjmp .-110 ; 0x1ef6 + 262: c9 cf rjmp .-110 ; 0x1f6 -00001f64 : +00000264 : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 1f64: 1f 93 push r17 - 1f66: 18 2f mov r17, r24 + 264: 1f 93 push r17 + 266: 18 2f mov r17, r24 do getch(); while (--count); - 1f68: d5 df rcall .-86 ; 0x1f14 - 1f6a: 11 50 subi r17, 0x01 ; 1 - 1f6c: e9 f7 brne .-6 ; 0x1f68 + 268: d5 df rcall .-86 ; 0x214 + 26a: 11 50 subi r17, 0x01 ; 1 + 26c: e9 f7 brne .-6 ; 0x268 verifySpace(); - 1f6e: f4 df rcall .-24 ; 0x1f58 + 26e: f4 df rcall .-24 ; 0x258 } - 1f70: 1f 91 pop r17 - 1f72: 08 95 ret + 270: 1f 91 pop r17 + 272: 08 95 ret diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.hex b/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.hex index 2b4a582a4..3ac0de204 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.hex @@ -30,5 +30,6 @@ :103FD00090838083089580E0F8DFEE27FF2709941F :103FE000E7DF803209F0F7DF84E1DACF1F93182F83 :0C3FF000DFDF1150E9F7F4DF1F910895A6 +:023FFE000104BC :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.lst b/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.lst index 25dc46bc0..516bed833 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.lst @@ -5,23 +5,25 @@ Sections: Idx Name Size VMA LMA File off Algn 0 .text 000001fc 00003e00 00003e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .debug_aranges 00000028 00000000 00000000 00000250 2**0 + 1 .version 00000002 00003ffe 00003ffe 00000250 2**0 + CONTENTS, READONLY + 2 .debug_aranges 00000028 00000000 00000000 00000252 2**0 CONTENTS, READONLY, DEBUGGING - 2 .debug_pubnames 0000006a 00000000 00000000 00000278 2**0 + 3 .debug_pubnames 0000006a 00000000 00000000 0000027a 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_info 00000284 00000000 00000000 000002e2 2**0 + 4 .debug_info 00000285 00000000 00000000 000002e4 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_abbrev 000001ae 00000000 00000000 00000566 2**0 + 5 .debug_abbrev 0000019f 00000000 00000000 00000569 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_line 00000450 00000000 00000000 00000714 2**0 + 6 .debug_line 00000453 00000000 00000000 00000708 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_frame 00000090 00000000 00000000 00000b64 2**2 + 7 .debug_frame 00000090 00000000 00000000 00000b5c 2**2 CONTENTS, READONLY, DEBUGGING - 7 .debug_str 00000141 00000000 00000000 00000bf4 2**0 + 8 .debug_str 00000141 00000000 00000000 00000bec 2**0 CONTENTS, READONLY, DEBUGGING - 8 .debug_loc 000001e1 00000000 00000000 00000d35 2**0 + 9 .debug_loc 000001e1 00000000 00000000 00000d2d 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_ranges 00000068 00000000 00000000 00000f16 2**0 + 10 .debug_ranges 00000068 00000000 00000000 00000f0e 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: @@ -135,7 +137,7 @@ void watchdogReset() { __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); - + // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); 3e50: a5 e0 ldi r26, 0x05 ; 5 @@ -249,7 +251,7 @@ void watchdogReset() { 3ec6: e8 95 spm 3ec8: c0 e0 ldi r28, 0x00 ; 0 3eca: d1 e0 ldi r29, 0x01 ; 1 - + // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); @@ -278,7 +280,7 @@ void watchdogReset() { // Read command terminator, start reply verifySpace(); 3ef4: 75 d0 rcall .+234 ; 0x3fe0 - + // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); @@ -336,7 +338,7 @@ int main(void) { 3f2e: a0 38 cpi r26, 0x80 ; 128 3f30: bf 07 cpc r27, r31 3f32: 51 f7 brne .-44 ; 0x3f08 - + // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); 3f34: e0 91 00 02 lds r30, 0x0200 diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.hex b/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.hex index d147f8f7d..01c974c6e 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.hex @@ -30,5 +30,6 @@ :103FD00090838083089580E0F8DFEE27FF2709941F :103FE000E7DF803209F0F7DF84E1DACF1F93182F83 :0C3FF000DFDF1150E9F7F4DF1F910895A6 +:023FFE000104BC :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.lst b/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.lst index 1868d16d0..ba7b6b6ff 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.lst @@ -5,23 +5,25 @@ Sections: Idx Name Size VMA LMA File off Algn 0 .text 000001fc 00003e00 00003e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .debug_aranges 00000028 00000000 00000000 00000250 2**0 + 1 .version 00000002 00003ffe 00003ffe 00000250 2**0 + CONTENTS, READONLY + 2 .debug_aranges 00000028 00000000 00000000 00000252 2**0 CONTENTS, READONLY, DEBUGGING - 2 .debug_pubnames 0000006a 00000000 00000000 00000278 2**0 + 3 .debug_pubnames 0000006a 00000000 00000000 0000027a 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_info 00000284 00000000 00000000 000002e2 2**0 + 4 .debug_info 00000285 00000000 00000000 000002e4 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_abbrev 000001ae 00000000 00000000 00000566 2**0 + 5 .debug_abbrev 0000019f 00000000 00000000 00000569 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_line 00000450 00000000 00000000 00000714 2**0 + 6 .debug_line 00000453 00000000 00000000 00000708 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_frame 00000090 00000000 00000000 00000b64 2**2 + 7 .debug_frame 00000090 00000000 00000000 00000b5c 2**2 CONTENTS, READONLY, DEBUGGING - 7 .debug_str 00000141 00000000 00000000 00000bf4 2**0 + 8 .debug_str 00000141 00000000 00000000 00000bec 2**0 CONTENTS, READONLY, DEBUGGING - 8 .debug_loc 000001e1 00000000 00000000 00000d35 2**0 + 9 .debug_loc 000001e1 00000000 00000000 00000d2d 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_ranges 00000068 00000000 00000000 00000f16 2**0 + 10 .debug_ranges 00000068 00000000 00000000 00000f0e 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: @@ -135,7 +137,7 @@ void watchdogReset() { __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); - + // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); 3e50: a5 e0 ldi r26, 0x05 ; 5 @@ -249,7 +251,7 @@ void watchdogReset() { 3ec6: e8 95 spm 3ec8: c0 e0 ldi r28, 0x00 ; 0 3eca: d1 e0 ldi r29, 0x01 ; 1 - + // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); @@ -278,7 +280,7 @@ void watchdogReset() { // Read command terminator, start reply verifySpace(); 3ef4: 75 d0 rcall .+234 ; 0x3fe0 - + // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); @@ -336,7 +338,7 @@ int main(void) { 3f2e: a0 38 cpi r26, 0x80 ; 128 3f30: bf 07 cpc r27, r31 3f32: 51 f7 brne .-44 ; 0x3f08 - + // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); 3f34: e0 91 00 02 lds r30, 0x0200 diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.hex b/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.hex index 757928697..77897e798 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.hex @@ -30,5 +30,6 @@ :103FD00090838083089580E0F8DFEE27FF2709941F :103FE000E7DF803209F0F7DF84E1DACF1F93182F83 :0C3FF000DFDF1150E9F7F4DF1F910895A6 +:023FFE000104BC :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.lst b/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.lst index 25a4bd24c..23d5e1a10 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.lst @@ -5,23 +5,25 @@ Sections: Idx Name Size VMA LMA File off Algn 0 .text 000001fc 00003e00 00003e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .debug_aranges 00000028 00000000 00000000 00000250 2**0 + 1 .version 00000002 00003ffe 00003ffe 00000250 2**0 + CONTENTS, READONLY + 2 .debug_aranges 00000028 00000000 00000000 00000252 2**0 CONTENTS, READONLY, DEBUGGING - 2 .debug_pubnames 0000006a 00000000 00000000 00000278 2**0 + 3 .debug_pubnames 0000006a 00000000 00000000 0000027a 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_info 00000284 00000000 00000000 000002e2 2**0 + 4 .debug_info 00000285 00000000 00000000 000002e4 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_abbrev 000001ae 00000000 00000000 00000566 2**0 + 5 .debug_abbrev 0000019f 00000000 00000000 00000569 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_line 00000450 00000000 00000000 00000714 2**0 + 6 .debug_line 00000453 00000000 00000000 00000708 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_frame 00000090 00000000 00000000 00000b64 2**2 + 7 .debug_frame 00000090 00000000 00000000 00000b5c 2**2 CONTENTS, READONLY, DEBUGGING - 7 .debug_str 00000141 00000000 00000000 00000bf4 2**0 + 8 .debug_str 00000141 00000000 00000000 00000bec 2**0 CONTENTS, READONLY, DEBUGGING - 8 .debug_loc 000001e1 00000000 00000000 00000d35 2**0 + 9 .debug_loc 000001e1 00000000 00000000 00000d2d 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_ranges 00000068 00000000 00000000 00000f16 2**0 + 10 .debug_ranges 00000068 00000000 00000000 00000f0e 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: @@ -135,7 +137,7 @@ void watchdogReset() { __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); - + // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); 3e50: a5 e0 ldi r26, 0x05 ; 5 @@ -249,7 +251,7 @@ void watchdogReset() { 3ec6: e8 95 spm 3ec8: c0 e0 ldi r28, 0x00 ; 0 3eca: d1 e0 ldi r29, 0x01 ; 1 - + // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); @@ -278,7 +280,7 @@ void watchdogReset() { // Read command terminator, start reply verifySpace(); 3ef4: 75 d0 rcall .+234 ; 0x3fe0 - + // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); @@ -336,7 +338,7 @@ int main(void) { 3f2e: a0 38 cpi r26, 0x80 ; 128 3f30: bf 07 cpc r27, r31 3f32: 51 f7 brne .-44 ; 0x3f08 - + // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); 3f34: e0 91 00 02 lds r30, 0x0200 From 6f7687b0f925cb07447cbbcc692766c51c02f700 Mon Sep 17 00:00:00 2001 From: WestfW Date: Fri, 10 Jun 2011 23:02:25 -0700 Subject: [PATCH 24/33] Shrink code by using registers for variables "length" and "address" http://code.google.com/p/optiboot/issues/detail?id=33 Fix high-value watchdog timeouts on ATmega8 http://code.google.com/p/optiboot/issues/detail?id=38 Change "start app on bad commands" code to start the app via the watchdog timer, so that the app is always started with the chip in fully reset state. http://code.google.com/p/optiboot/issues/detail?id=37 --- .../arduino/bootloaders/optiboot/optiboot.c | 34 +- .../optiboot/optiboot_atmega328.hex | 58 +- .../optiboot/optiboot_atmega328.lst | 439 +++++++------- .../optiboot/optiboot_atmega328_pro_8MHz.hex | 58 +- .../optiboot/optiboot_atmega328_pro_8MHz.lst | 439 +++++++------- .../optiboot/optiboot_diecimila.hex | 58 +- .../optiboot/optiboot_diecimila.lst | 439 +++++++------- .../bootloaders/optiboot/optiboot_lilypad.hex | 58 +- .../bootloaders/optiboot/optiboot_lilypad.lst | 439 +++++++------- .../optiboot/optiboot_lilypad_resonator.hex | 58 +- .../optiboot/optiboot_lilypad_resonator.lst | 439 +++++++------- .../bootloaders/optiboot/optiboot_luminet.hex | 75 ++- .../bootloaders/optiboot/optiboot_luminet.lst | 572 +++++++++--------- .../optiboot/optiboot_pro_16MHz.hex | 58 +- .../optiboot/optiboot_pro_16MHz.lst | 439 +++++++------- .../optiboot/optiboot_pro_20mhz.hex | 58 +- .../optiboot/optiboot_pro_20mhz.lst | 439 +++++++------- .../optiboot/optiboot_pro_8MHz.hex | 58 +- .../optiboot/optiboot_pro_8MHz.lst | 439 +++++++------- 19 files changed, 2343 insertions(+), 2314 deletions(-) diff --git a/hardware/arduino/bootloaders/optiboot/optiboot.c b/hardware/arduino/bootloaders/optiboot/optiboot.c index ece8b43a7..89403591b 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot.c +++ b/hardware/arduino/bootloaders/optiboot/optiboot.c @@ -198,8 +198,8 @@ asm(" .section .version\n" #define WATCHDOG_1S (_BV(WDP2) | _BV(WDP1) | _BV(WDE)) #define WATCHDOG_2S (_BV(WDP2) | _BV(WDP1) | _BV(WDP0) | _BV(WDE)) #ifndef __AVR_ATmega8__ -#define WATCHDOG_4S (_BV(WDE3) | _BV(WDE)) -#define WATCHDOG_8S (_BV(WDE3) | _BV(WDE0) | _BV(WDE)) +#define WATCHDOG_4S (_BV(WDP3) | _BV(WDE)) +#define WATCHDOG_8S (_BV(WDP3) | _BV(WDP0) | _BV(WDE)) #endif /* Function Prototypes */ @@ -244,8 +244,6 @@ void appStart() __attribute__ ((naked)); /* These definitions are NOT zero initialised, but that doesn't matter */ /* This allows us to drop the zero init code, saving us memory */ #define buff ((uint8_t*)(RAMSTART)) -#define address (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2)) -#define length (*(uint8_t*)(RAMSTART+SPM_PAGESIZE*2+2)) #ifdef VIRTUAL_BOOT_PARTITION #define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) #define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) @@ -255,6 +253,13 @@ void appStart() __attribute__ ((naked)); int main(void) { uint8_t ch; + /* + * Making these local and in registers prevents the need for initializing + * them, and also saves space because code no longer stores to memory. + */ + register uint16_t address; + register uint8_t length; + // After the zero init loop, this is the first code to run. // // This code makes the following assumptions: @@ -350,7 +355,9 @@ int main(void) { uint8_t *bufPtr; uint16_t addrPtr; - getLen(); + getch(); /* getlen() */ + length = getch(); + getch(); // If we are in RWW section, immediately start page erase if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); @@ -415,7 +422,10 @@ int main(void) { /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { // READ PAGE - we only read flash - getLen(); + getch(); /* getlen() */ + length = getch(); + getch(); + verifySpace(); #ifdef VIRTUAL_BOOT_PARTITION do { @@ -575,7 +585,11 @@ void getNch(uint8_t count) { } void verifySpace() { - if (getch() != CRC_EOP) appStart(); + if (getch() != CRC_EOP) { + watchdogConfig(WATCHDOG_16MS); // shorten WD timeout + while (1) // and busy-loop so that WD causes + ; // a reset and app start. + } putch(STK_INSYNC); } @@ -595,12 +609,6 @@ void flash_led(uint8_t count) { } #endif -uint8_t getLen() { - getch(); - length = getch(); - return getch(); -} - // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.hex b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.hex index 7286e0d6a..11819d6b5 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.hex @@ -1,35 +1,33 @@ -:107E0000112484B714BE81FFE6D085E08093810001 +:107E0000112484B714BE81FFE3D085E08093810004 :107E100082E08093C00088E18093C10086E0809377 -:107E2000C20080E18093C4008EE0CFD0259A86E026 +:107E2000C20080E18093C4008EE0BCD0259A86E039 :107E300020E33CEF91E0309385002093840096BBD3 -:107E4000B09BFECF1D9AA8958150A9F7DD24D3944D -:107E5000A5E0EA2EF1E1FF2EABD0813421F481E0E0 -:107E6000C5D083E020C0823411F484E103C085349E -:107E700019F485E0BBD091C0853581F499D0082FE5 -:107E800010E096D090E0982F8827802B912B880FB8 -:107E9000991F90930102809300027EC0863529F4D9 -:107EA00084E0A4D080E07CD078C0843609F04EC055 -:107EB00087D0E0910002F091010280E7E030F807FE -:107EC00018F483E087BFE895C0E0D1E071D08993D2 -:107ED000809102028150809302028823B9F7E091D9 -:107EE0000002F091010280E7E030F80718F083E02B -:107EF00087BFE89575D007B600FCFDCF4091000222 -:107F000050910102A0E0B1E02C9130E011968C91EB -:107F1000119790E0982F8827822B932B1296FA01C5 -:107F20000C01D7BEE89511244E5F5F4FF1E0A038F9 -:107F3000BF0751F7E0910002F0910102E7BEE8951A -:107F400007B600FCFDCFF7BEE89527C08437B9F42B -:107F500037D046D0E0910002F09101023196F093C3 -:107F60000102E09300023197E4918E2F19D08091A5 -:107F70000202815080930202882361F70EC0853788 -:107F800039F42ED08EE10CD085E90AD08FE08BCF6A -:107F9000813511F488E019D023D080E101D05CCF85 -:107FA000982F8091C00085FFFCCF9093C600089564 -:107FB000A8958091C00087FFFCCF8091C6000895EE -:107FC000F7DFF6DF80930202F3CFE0E6F0E098E11E -:107FD00090838083089580E0F8DFEE27FF270994DF -:107FE000E7DF803209F0F7DF84E1DACF1F93182F43 -:0C7FF000DFDF1150E9F7F4DF1F91089566 +:107E4000B09BFECF1D9AA8958150A9F799249394D1 +:107E5000A5E0AA2EF1E1BF2E9DD0813421F481E06E +:107E6000AFD083E01FC0823411F484E103C08534B5 +:107E700019F485E0A5D083C0853579F48BD0E82E40 +:107E8000FF2488D0082F10E0102F00270E291F296B +:107E9000000F111F8DD0680172C0863529F484E06F +:107EA0008FD080E06FD06BC0843609F042C072D0B2 +:107EB00071D0082F6FD080E0C81680E7D80620F474 +:107EC00083E0F60187BFE895C0E0D1E063D08993F5 +:107ED0000C17E1F7F0E0CF16F0E7DF0620F083E0C3 +:107EE000F60187BFE89564D007B600FCFDCFA60178 +:107EF000A0E0B1E02C9130E011968C91119790E0C8 +:107F0000982F8827822B932B1296FA010C0197BE8B +:107F1000E89511244E5F5F4FF1E0A038BF0751F79D +:107F2000F601A7BEE89507B600FCFDCFB7BEE89501 +:107F300026C08437B1F42ED02DD0F82E2BD038D0D7 +:107F4000F601EF2C8F010F5F1F4F84911BD0EA9435 +:107F5000F801C1F70894C11CD11CFA94CF0CD11CB4 +:107F60000EC0853739F424D08EE10CD085E90AD0D3 +:107F70008FE098CF813511F488E014D019D080E1DA +:107F800001D06ACF982F8091C00085FFFCCF9093DD +:107F9000C6000895A8958091C00087FFFCCF80910E +:107FA000C6000895E0E6F0E098E1908380830895AC +:107FB000F1DF803219F088E0F5DFFFCF84E1E2CF16 +:107FC0001F93182FE7DF1150E9F7F2DF1F91089593 +:0A7FD00080E0E8DFEE27FF270994A8 :027FFE0001047C :0400000300007E007B :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.lst b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.lst index 0da8aafe0..7876b9691 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.lst @@ -3,27 +3,27 @@ optiboot_atmega328.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .text 000001fc 00007e00 00007e00 00000054 2**1 + 0 .text 000001da 00007e00 00007e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .version 00000002 00007ffe 00007ffe 00000250 2**0 + 1 .version 00000002 00007ffe 00007ffe 0000022e 2**0 CONTENTS, READONLY - 2 .debug_aranges 00000028 00000000 00000000 00000252 2**0 + 2 .debug_aranges 00000028 00000000 00000000 00000230 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_pubnames 0000006a 00000000 00000000 0000027a 2**0 + 3 .debug_pubnames 0000005f 00000000 00000000 00000258 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_info 00000285 00000000 00000000 000002e4 2**0 + 4 .debug_info 0000028c 00000000 00000000 000002b7 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 0000019f 00000000 00000000 00000569 2**0 + 5 .debug_abbrev 00000199 00000000 00000000 00000543 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_line 00000453 00000000 00000000 00000708 2**0 + 6 .debug_line 00000456 00000000 00000000 000006dc 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000090 00000000 00000000 00000b5c 2**2 + 7 .debug_frame 00000080 00000000 00000000 00000b34 2**2 CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000141 00000000 00000000 00000bec 2**0 + 8 .debug_str 00000149 00000000 00000000 00000bb4 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 000001e1 00000000 00000000 00000d2d 2**0 + 9 .debug_loc 0000027e 00000000 00000000 00000cfd 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000068 00000000 00000000 00000f0e 2**0 + 10 .debug_ranges 00000060 00000000 00000000 00000f7b 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: @@ -47,7 +47,7 @@ int main(void) { 7e04: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); 7e06: 81 ff sbrs r24, 1 - 7e08: e6 d0 rcall .+460 ; 0x7fd6 + 7e08: e3 d0 rcall .+454 ; 0x7fd0 #if LED_START_FLASHES > 0 // Set up Timer 1 for timeout counter @@ -77,7 +77,7 @@ int main(void) { // Set up watchdog to trigger after 500ms watchdogConfig(WATCHDOG_1S); 7e28: 8e e0 ldi r24, 0x0E ; 14 - 7e2a: cf d0 rcall .+414 ; 0x7fca + 7e2a: bc d0 rcall .+376 ; 0x7fa4 /* Set LED pin as output */ LED_DDR |= _BV(LED); @@ -111,8 +111,8 @@ void flash_led(uint8_t count) { #else LED_PIN |= _BV(LED); 7e44: 1d 9a sbi 0x03, 5 ; 3 - return getch(); } +#endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { @@ -132,8 +132,8 @@ void watchdogReset() { if(ch == STK_GET_PARAMETER) { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 7e4c: dd 24 eor r13, r13 - 7e4e: d3 94 inc r13 + 7e4c: 99 24 eor r9, r9 + 7e4e: 93 94 inc r9 __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); @@ -141,21 +141,21 @@ void watchdogReset() { // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); 7e50: a5 e0 ldi r26, 0x05 ; 5 - 7e52: ea 2e mov r14, r26 + 7e52: aa 2e mov r10, r26 boot_spm_busy_wait(); #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); 7e54: f1 e1 ldi r31, 0x11 ; 17 - 7e56: ff 2e mov r15, r31 + 7e56: bf 2e mov r11, r31 #endif /* Forever loop */ for (;;) { /* get character from UART */ ch = getch(); - 7e58: ab d0 rcall .+342 ; 0x7fb0 + 7e58: 9d d0 rcall .+314 ; 0x7f94 if(ch == STK_GET_PARAMETER) { 7e5a: 81 34 cpi r24, 0x41 ; 65 @@ -163,10 +163,10 @@ void watchdogReset() { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); 7e5e: 81 e0 ldi r24, 0x01 ; 1 - 7e60: c5 d0 rcall .+394 ; 0x7fec + 7e60: af d0 rcall .+350 ; 0x7fc0 putch(0x03); 7e62: 83 e0 ldi r24, 0x03 ; 3 - 7e64: 20 c0 rjmp .+64 ; 0x7ea6 + 7e64: 1f c0 rjmp .+62 ; 0x7ea4 } else if(ch == STK_SET_DEVICE) { 7e66: 82 34 cpi r24, 0x42 ; 66 @@ -182,71 +182,77 @@ void watchdogReset() { // SET DEVICE EXT is ignored getNch(5); 7e72: 85 e0 ldi r24, 0x05 ; 5 - 7e74: bb d0 rcall .+374 ; 0x7fec - 7e76: 91 c0 rjmp .+290 ; 0x7f9a + 7e74: a5 d0 rcall .+330 ; 0x7fc0 + 7e76: 83 c0 rjmp .+262 ; 0x7f7e } else if(ch == STK_LOAD_ADDRESS) { 7e78: 85 35 cpi r24, 0x55 ; 85 - 7e7a: 81 f4 brne .+32 ; 0x7e9c + 7e7a: 79 f4 brne .+30 ; 0x7e9a // LOAD ADDRESS uint16_t newAddress; newAddress = getch(); - 7e7c: 99 d0 rcall .+306 ; 0x7fb0 + 7e7c: 8b d0 rcall .+278 ; 0x7f94 newAddress = (newAddress & 0xff) | (getch() << 8); - 7e7e: 08 2f mov r16, r24 - 7e80: 10 e0 ldi r17, 0x00 ; 0 - 7e82: 96 d0 rcall .+300 ; 0x7fb0 - 7e84: 90 e0 ldi r25, 0x00 ; 0 - 7e86: 98 2f mov r25, r24 - 7e88: 88 27 eor r24, r24 - 7e8a: 80 2b or r24, r16 - 7e8c: 91 2b or r25, r17 + 7e7e: e8 2e mov r14, r24 + 7e80: ff 24 eor r15, r15 + 7e82: 88 d0 rcall .+272 ; 0x7f94 + 7e84: 08 2f mov r16, r24 + 7e86: 10 e0 ldi r17, 0x00 ; 0 + 7e88: 10 2f mov r17, r16 + 7e8a: 00 27 eor r16, r16 + 7e8c: 0e 29 or r16, r14 + 7e8e: 1f 29 or r17, r15 #ifdef RAMPZ // Transfer top bit to RAMPZ RAMPZ = (newAddress & 0x8000) ? 1 : 0; #endif newAddress += newAddress; // Convert from word address to byte address - 7e8e: 88 0f add r24, r24 - 7e90: 99 1f adc r25, r25 + 7e90: 00 0f add r16, r16 + 7e92: 11 1f adc r17, r17 address = newAddress; - 7e92: 90 93 01 02 sts 0x0201, r25 - 7e96: 80 93 00 02 sts 0x0200, r24 - 7e9a: 7e c0 rjmp .+252 ; 0x7f98 verifySpace(); + 7e94: 8d d0 rcall .+282 ; 0x7fb0 + 7e96: 68 01 movw r12, r16 + 7e98: 72 c0 rjmp .+228 ; 0x7f7e } else if(ch == STK_UNIVERSAL) { - 7e9c: 86 35 cpi r24, 0x56 ; 86 - 7e9e: 29 f4 brne .+10 ; 0x7eaa + 7e9a: 86 35 cpi r24, 0x56 ; 86 + 7e9c: 29 f4 brne .+10 ; 0x7ea8 // UNIVERSAL command is ignored getNch(4); - 7ea0: 84 e0 ldi r24, 0x04 ; 4 - 7ea2: a4 d0 rcall .+328 ; 0x7fec + 7e9e: 84 e0 ldi r24, 0x04 ; 4 + 7ea0: 8f d0 rcall .+286 ; 0x7fc0 putch(0x00); - 7ea4: 80 e0 ldi r24, 0x00 ; 0 - 7ea6: 7c d0 rcall .+248 ; 0x7fa0 - 7ea8: 78 c0 rjmp .+240 ; 0x7f9a + 7ea2: 80 e0 ldi r24, 0x00 ; 0 + 7ea4: 6f d0 rcall .+222 ; 0x7f84 + 7ea6: 6b c0 rjmp .+214 ; 0x7f7e } /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { - 7eaa: 84 36 cpi r24, 0x64 ; 100 - 7eac: 09 f0 breq .+2 ; 0x7eb0 - 7eae: 4e c0 rjmp .+156 ; 0x7f4c + 7ea8: 84 36 cpi r24, 0x64 ; 100 + 7eaa: 09 f0 breq .+2 ; 0x7eae + 7eac: 42 c0 rjmp .+132 ; 0x7f32 // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t *bufPtr; uint16_t addrPtr; - getLen(); - 7eb0: 87 d0 rcall .+270 ; 0x7fc0 + getch(); /* getlen() */ + 7eae: 72 d0 rcall .+228 ; 0x7f94 + length = getch(); + 7eb0: 71 d0 rcall .+226 ; 0x7f94 + 7eb2: 08 2f mov r16, r24 + getch(); + 7eb4: 6f d0 rcall .+222 ; 0x7f94 // If we are in RWW section, immediately start page erase if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 7eb2: e0 91 00 02 lds r30, 0x0200 - 7eb6: f0 91 01 02 lds r31, 0x0201 + 7eb6: 80 e0 ldi r24, 0x00 ; 0 + 7eb8: c8 16 cp r12, r24 7eba: 80 e7 ldi r24, 0x70 ; 112 - 7ebc: e0 30 cpi r30, 0x00 ; 0 - 7ebe: f8 07 cpc r31, r24 - 7ec0: 18 f4 brcc .+6 ; 0x7ec8 - 7ec2: 83 e0 ldi r24, 0x03 ; 3 + 7ebc: d8 06 cpc r13, r24 + 7ebe: 20 f4 brcc .+8 ; 0x7ec8 + 7ec0: 83 e0 ldi r24, 0x03 ; 3 + 7ec2: f6 01 movw r30, r12 7ec4: 87 bf out 0x37, r24 ; 55 7ec6: e8 95 spm 7ec8: c0 e0 ldi r28, 0x00 ; 0 @@ -255,302 +261,301 @@ void watchdogReset() { // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); - 7ecc: 71 d0 rcall .+226 ; 0x7fb0 + 7ecc: 63 d0 rcall .+198 ; 0x7f94 7ece: 89 93 st Y+, r24 while (--length); - 7ed0: 80 91 02 02 lds r24, 0x0202 - 7ed4: 81 50 subi r24, 0x01 ; 1 - 7ed6: 80 93 02 02 sts 0x0202, r24 - 7eda: 88 23 and r24, r24 - 7edc: b9 f7 brne .-18 ; 0x7ecc + 7ed0: 0c 17 cp r16, r28 + 7ed2: e1 f7 brne .-8 ; 0x7ecc // If we are in NRWW section, page erase has to be delayed until now. // Todo: Take RAMPZ into account if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 7ede: e0 91 00 02 lds r30, 0x0200 - 7ee2: f0 91 01 02 lds r31, 0x0201 - 7ee6: 80 e7 ldi r24, 0x70 ; 112 - 7ee8: e0 30 cpi r30, 0x00 ; 0 - 7eea: f8 07 cpc r31, r24 - 7eec: 18 f0 brcs .+6 ; 0x7ef4 - 7eee: 83 e0 ldi r24, 0x03 ; 3 - 7ef0: 87 bf out 0x37, r24 ; 55 - 7ef2: e8 95 spm + 7ed4: f0 e0 ldi r31, 0x00 ; 0 + 7ed6: cf 16 cp r12, r31 + 7ed8: f0 e7 ldi r31, 0x70 ; 112 + 7eda: df 06 cpc r13, r31 + 7edc: 20 f0 brcs .+8 ; 0x7ee6 + 7ede: 83 e0 ldi r24, 0x03 ; 3 + 7ee0: f6 01 movw r30, r12 + 7ee2: 87 bf out 0x37, r24 ; 55 + 7ee4: e8 95 spm // Read command terminator, start reply verifySpace(); - 7ef4: 75 d0 rcall .+234 ; 0x7fe0 + 7ee6: 64 d0 rcall .+200 ; 0x7fb0 // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); - 7ef6: 07 b6 in r0, 0x37 ; 55 - 7ef8: 00 fc sbrc r0, 0 - 7efa: fd cf rjmp .-6 ; 0x7ef6 - } -#endif - - // Copy buffer into programming buffer + 7ee8: 07 b6 in r0, 0x37 ; 55 + 7eea: 00 fc sbrc r0, 0 + 7eec: fd cf rjmp .-6 ; 0x7ee8 + 7eee: a6 01 movw r20, r12 + 7ef0: a0 e0 ldi r26, 0x00 ; 0 + 7ef2: b1 e0 ldi r27, 0x01 ; 1 bufPtr = buff; addrPtr = (uint16_t)(void*)address; - 7efc: 40 91 00 02 lds r20, 0x0200 - 7f00: 50 91 01 02 lds r21, 0x0201 - 7f04: a0 e0 ldi r26, 0x00 ; 0 - 7f06: b1 e0 ldi r27, 0x01 ; 1 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; - 7f08: 2c 91 ld r18, X - 7f0a: 30 e0 ldi r19, 0x00 ; 0 + 7ef4: 2c 91 ld r18, X + 7ef6: 30 e0 ldi r19, 0x00 ; 0 a |= (*bufPtr++) << 8; - 7f0c: 11 96 adiw r26, 0x01 ; 1 - 7f0e: 8c 91 ld r24, X - 7f10: 11 97 sbiw r26, 0x01 ; 1 - 7f12: 90 e0 ldi r25, 0x00 ; 0 - 7f14: 98 2f mov r25, r24 - 7f16: 88 27 eor r24, r24 - 7f18: 82 2b or r24, r18 - 7f1a: 93 2b or r25, r19 + 7ef8: 11 96 adiw r26, 0x01 ; 1 + 7efa: 8c 91 ld r24, X + 7efc: 11 97 sbiw r26, 0x01 ; 1 + 7efe: 90 e0 ldi r25, 0x00 ; 0 + 7f00: 98 2f mov r25, r24 + 7f02: 88 27 eor r24, r24 + 7f04: 82 2b or r24, r18 + 7f06: 93 2b or r25, r19 #define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) #define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif /* main program starts here */ int main(void) { - 7f1c: 12 96 adiw r26, 0x02 ; 2 + 7f08: 12 96 adiw r26, 0x02 ; 2 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; a |= (*bufPtr++) << 8; __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - 7f1e: fa 01 movw r30, r20 - 7f20: 0c 01 movw r0, r24 - 7f22: d7 be out 0x37, r13 ; 55 - 7f24: e8 95 spm - 7f26: 11 24 eor r1, r1 + 7f0a: fa 01 movw r30, r20 + 7f0c: 0c 01 movw r0, r24 + 7f0e: 97 be out 0x37, r9 ; 55 + 7f10: e8 95 spm + 7f12: 11 24 eor r1, r1 addrPtr += 2; - 7f28: 4e 5f subi r20, 0xFE ; 254 - 7f2a: 5f 4f sbci r21, 0xFF ; 255 + 7f14: 4e 5f subi r20, 0xFE ; 254 + 7f16: 5f 4f sbci r21, 0xFF ; 255 } while (--ch); - 7f2c: f1 e0 ldi r31, 0x01 ; 1 - 7f2e: a0 38 cpi r26, 0x80 ; 128 - 7f30: bf 07 cpc r27, r31 - 7f32: 51 f7 brne .-44 ; 0x7f08 + 7f18: f1 e0 ldi r31, 0x01 ; 1 + 7f1a: a0 38 cpi r26, 0x80 ; 128 + 7f1c: bf 07 cpc r27, r31 + 7f1e: 51 f7 brne .-44 ; 0x7ef4 // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); - 7f34: e0 91 00 02 lds r30, 0x0200 - 7f38: f0 91 01 02 lds r31, 0x0201 - 7f3c: e7 be out 0x37, r14 ; 55 - 7f3e: e8 95 spm + 7f20: f6 01 movw r30, r12 + 7f22: a7 be out 0x37, r10 ; 55 + 7f24: e8 95 spm boot_spm_busy_wait(); - 7f40: 07 b6 in r0, 0x37 ; 55 - 7f42: 00 fc sbrc r0, 0 - 7f44: fd cf rjmp .-6 ; 0x7f40 + 7f26: 07 b6 in r0, 0x37 ; 55 + 7f28: 00 fc sbrc r0, 0 + 7f2a: fd cf rjmp .-6 ; 0x7f26 #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 7f46: f7 be out 0x37, r15 ; 55 - 7f48: e8 95 spm - 7f4a: 27 c0 rjmp .+78 ; 0x7f9a + 7f2c: b7 be out 0x37, r11 ; 55 + 7f2e: e8 95 spm + 7f30: 26 c0 rjmp .+76 ; 0x7f7e #endif } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { - 7f4c: 84 37 cpi r24, 0x74 ; 116 - 7f4e: b9 f4 brne .+46 ; 0x7f7e + 7f32: 84 37 cpi r24, 0x74 ; 116 + 7f34: b1 f4 brne .+44 ; 0x7f62 // READ PAGE - we only read flash - getLen(); - 7f50: 37 d0 rcall .+110 ; 0x7fc0 + getch(); /* getlen() */ + 7f36: 2e d0 rcall .+92 ; 0x7f94 + length = getch(); + 7f38: 2d d0 rcall .+90 ; 0x7f94 + 7f3a: f8 2e mov r15, r24 + getch(); + 7f3c: 2b d0 rcall .+86 ; 0x7f94 + verifySpace(); - 7f52: 46 d0 rcall .+140 ; 0x7fe0 + 7f3e: 38 d0 rcall .+112 ; 0x7fb0 + 7f40: f6 01 movw r30, r12 + 7f42: ef 2c mov r14, r15 putch(result); address++; } while (--length); #else do putch(pgm_read_byte_near(address++)); - 7f54: e0 91 00 02 lds r30, 0x0200 - 7f58: f0 91 01 02 lds r31, 0x0201 - 7f5c: 31 96 adiw r30, 0x01 ; 1 - 7f5e: f0 93 01 02 sts 0x0201, r31 - 7f62: e0 93 00 02 sts 0x0200, r30 - 7f66: 31 97 sbiw r30, 0x01 ; 1 - 7f68: e4 91 lpm r30, Z+ - 7f6a: 8e 2f mov r24, r30 - 7f6c: 19 d0 rcall .+50 ; 0x7fa0 + 7f44: 8f 01 movw r16, r30 + 7f46: 0f 5f subi r16, 0xFF ; 255 + 7f48: 1f 4f sbci r17, 0xFF ; 255 + 7f4a: 84 91 lpm r24, Z+ + 7f4c: 1b d0 rcall .+54 ; 0x7f84 while (--length); - 7f6e: 80 91 02 02 lds r24, 0x0202 - 7f72: 81 50 subi r24, 0x01 ; 1 - 7f74: 80 93 02 02 sts 0x0202, r24 - 7f78: 88 23 and r24, r24 - 7f7a: 61 f7 brne .-40 ; 0x7f54 - 7f7c: 0e c0 rjmp .+28 ; 0x7f9a + 7f4e: ea 94 dec r14 + 7f50: f8 01 movw r30, r16 + 7f52: c1 f7 brne .-16 ; 0x7f44 +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) +#endif + +/* main program starts here */ +int main(void) { + 7f54: 08 94 sec + 7f56: c1 1c adc r12, r1 + 7f58: d1 1c adc r13, r1 + 7f5a: fa 94 dec r15 + 7f5c: cf 0c add r12, r15 + 7f5e: d1 1c adc r13, r1 + 7f60: 0e c0 rjmp .+28 ; 0x7f7e #endif #endif } /* Get device signature bytes */ else if(ch == STK_READ_SIGN) { - 7f7e: 85 37 cpi r24, 0x75 ; 117 - 7f80: 39 f4 brne .+14 ; 0x7f90 + 7f62: 85 37 cpi r24, 0x75 ; 117 + 7f64: 39 f4 brne .+14 ; 0x7f74 // READ SIGN - return what Avrdude wants to hear verifySpace(); - 7f82: 2e d0 rcall .+92 ; 0x7fe0 + 7f66: 24 d0 rcall .+72 ; 0x7fb0 putch(SIGNATURE_0); - 7f84: 8e e1 ldi r24, 0x1E ; 30 - 7f86: 0c d0 rcall .+24 ; 0x7fa0 + 7f68: 8e e1 ldi r24, 0x1E ; 30 + 7f6a: 0c d0 rcall .+24 ; 0x7f84 putch(SIGNATURE_1); - 7f88: 85 e9 ldi r24, 0x95 ; 149 - 7f8a: 0a d0 rcall .+20 ; 0x7fa0 + 7f6c: 85 e9 ldi r24, 0x95 ; 149 + 7f6e: 0a d0 rcall .+20 ; 0x7f84 putch(SIGNATURE_2); - 7f8c: 8f e0 ldi r24, 0x0F ; 15 - 7f8e: 8b cf rjmp .-234 ; 0x7ea6 + 7f70: 8f e0 ldi r24, 0x0F ; 15 + 7f72: 98 cf rjmp .-208 ; 0x7ea4 } else if (ch == 'Q') { - 7f90: 81 35 cpi r24, 0x51 ; 81 - 7f92: 11 f4 brne .+4 ; 0x7f98 + 7f74: 81 35 cpi r24, 0x51 ; 81 + 7f76: 11 f4 brne .+4 ; 0x7f7c // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); - 7f94: 88 e0 ldi r24, 0x08 ; 8 - 7f96: 19 d0 rcall .+50 ; 0x7fca + 7f78: 88 e0 ldi r24, 0x08 ; 8 + 7f7a: 14 d0 rcall .+40 ; 0x7fa4 verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 7f98: 23 d0 rcall .+70 ; 0x7fe0 + 7f7c: 19 d0 rcall .+50 ; 0x7fb0 } putch(STK_OK); - 7f9a: 80 e1 ldi r24, 0x10 ; 16 - 7f9c: 01 d0 rcall .+2 ; 0x7fa0 - 7f9e: 5c cf rjmp .-328 ; 0x7e58 + 7f7e: 80 e1 ldi r24, 0x10 ; 16 + 7f80: 01 d0 rcall .+2 ; 0x7f84 + 7f82: 6a cf rjmp .-300 ; 0x7e58 -00007fa0 : +00007f84 : } } void putch(char ch) { - 7fa0: 98 2f mov r25, r24 + 7f84: 98 2f mov r25, r24 #ifndef SOFT_UART while (!(UCSR0A & _BV(UDRE0))); - 7fa2: 80 91 c0 00 lds r24, 0x00C0 - 7fa6: 85 ff sbrs r24, 5 - 7fa8: fc cf rjmp .-8 ; 0x7fa2 + 7f86: 80 91 c0 00 lds r24, 0x00C0 + 7f8a: 85 ff sbrs r24, 5 + 7f8c: fc cf rjmp .-8 ; 0x7f86 UDR0 = ch; - 7faa: 90 93 c6 00 sts 0x00C6, r25 + 7f8e: 90 93 c6 00 sts 0x00C6, r25 [uartBit] "I" (UART_TX_BIT) : "r25" ); #endif } - 7fae: 08 95 ret + 7f92: 08 95 ret -00007fb0 : - return getch(); +00007f94 : } +#endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 7fb0: a8 95 wdr + 7f94: a8 95 wdr [uartBit] "I" (UART_RX_BIT) : "r25" ); #else while(!(UCSR0A & _BV(RXC0))); - 7fb2: 80 91 c0 00 lds r24, 0x00C0 - 7fb6: 87 ff sbrs r24, 7 - 7fb8: fc cf rjmp .-8 ; 0x7fb2 + 7f96: 80 91 c0 00 lds r24, 0x00C0 + 7f9a: 87 ff sbrs r24, 7 + 7f9c: fc cf rjmp .-8 ; 0x7f96 ch = UDR0; - 7fba: 80 91 c6 00 lds r24, 0x00C6 + 7f9e: 80 91 c6 00 lds r24, 0x00C6 LED_PIN |= _BV(LED); #endif #endif return ch; } - 7fbe: 08 95 ret + 7fa2: 08 95 ret -00007fc0 : - } while (--count); -} -#endif - -uint8_t getLen() { - getch(); - 7fc0: f7 df rcall .-18 ; 0x7fb0 - length = getch(); - 7fc2: f6 df rcall .-20 ; 0x7fb0 - 7fc4: 80 93 02 02 sts 0x0202, r24 - return getch(); -} - 7fc8: f3 cf rjmp .-26 ; 0x7fb0 - -00007fca : +00007fa4 : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 7fca: e0 e6 ldi r30, 0x60 ; 96 - 7fcc: f0 e0 ldi r31, 0x00 ; 0 - 7fce: 98 e1 ldi r25, 0x18 ; 24 - 7fd0: 90 83 st Z, r25 + 7fa4: e0 e6 ldi r30, 0x60 ; 96 + 7fa6: f0 e0 ldi r31, 0x00 ; 0 + 7fa8: 98 e1 ldi r25, 0x18 ; 24 + 7faa: 90 83 st Z, r25 WDTCSR = x; - 7fd2: 80 83 st Z, r24 + 7fac: 80 83 st Z, r24 } - 7fd4: 08 95 ret + 7fae: 08 95 ret -00007fd6 : - -void appStart() { - watchdogConfig(WATCHDOG_OFF); - 7fd6: 80 e0 ldi r24, 0x00 ; 0 - 7fd8: f8 df rcall .-16 ; 0x7fca - __asm__ __volatile__ ( - 7fda: ee 27 eor r30, r30 - 7fdc: ff 27 eor r31, r31 - 7fde: 09 94 ijmp - -00007fe0 : +00007fb0 : do getch(); while (--count); verifySpace(); } void verifySpace() { - if (getch() != CRC_EOP) appStart(); - 7fe0: e7 df rcall .-50 ; 0x7fb0 - 7fe2: 80 32 cpi r24, 0x20 ; 32 - 7fe4: 09 f0 breq .+2 ; 0x7fe8 - 7fe6: f7 df rcall .-18 ; 0x7fd6 + if (getch() != CRC_EOP) { + 7fb0: f1 df rcall .-30 ; 0x7f94 + 7fb2: 80 32 cpi r24, 0x20 ; 32 + 7fb4: 19 f0 breq .+6 ; 0x7fbc + watchdogConfig(WATCHDOG_16MS); // shorten WD timeout + 7fb6: 88 e0 ldi r24, 0x08 ; 8 + 7fb8: f5 df rcall .-22 ; 0x7fa4 + 7fba: ff cf rjmp .-2 ; 0x7fba + while (1) // and busy-loop so that WD causes + ; // a reset and app start. + } putch(STK_INSYNC); - 7fe8: 84 e1 ldi r24, 0x14 ; 20 + 7fbc: 84 e1 ldi r24, 0x14 ; 20 } - 7fea: da cf rjmp .-76 ; 0x7fa0 + 7fbe: e2 cf rjmp .-60 ; 0x7f84 -00007fec : +00007fc0 : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 7fec: 1f 93 push r17 - 7fee: 18 2f mov r17, r24 + 7fc0: 1f 93 push r17 + 7fc2: 18 2f mov r17, r24 do getch(); while (--count); - 7ff0: df df rcall .-66 ; 0x7fb0 - 7ff2: 11 50 subi r17, 0x01 ; 1 - 7ff4: e9 f7 brne .-6 ; 0x7ff0 + 7fc4: e7 df rcall .-50 ; 0x7f94 + 7fc6: 11 50 subi r17, 0x01 ; 1 + 7fc8: e9 f7 brne .-6 ; 0x7fc4 verifySpace(); - 7ff6: f4 df rcall .-24 ; 0x7fe0 + 7fca: f2 df rcall .-28 ; 0x7fb0 } - 7ff8: 1f 91 pop r17 - 7ffa: 08 95 ret + 7fcc: 1f 91 pop r17 + 7fce: 08 95 ret + +00007fd0 : + WDTCSR = _BV(WDCE) | _BV(WDE); + WDTCSR = x; +} + +void appStart() { + watchdogConfig(WATCHDOG_OFF); + 7fd0: 80 e0 ldi r24, 0x00 ; 0 + 7fd2: e8 df rcall .-48 ; 0x7fa4 + __asm__ __volatile__ ( + 7fd4: ee 27 eor r30, r30 + 7fd6: ff 27 eor r31, r31 + 7fd8: 09 94 ijmp diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.hex b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.hex index 1e5683914..a181f0b6d 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.hex @@ -1,34 +1,32 @@ -:10000000112484B714BE81FFE6D085E0809381007F +:10000000112484B714BE81FFE3D085E08093810082 :1000100082E08093C00088E18093C10086E08093F5 -:10002000C20088E08093C4008EE0CFD0259A86E09D +:10002000C20088E08093C4008EE0BCD0259A86E0B0 :1000300028E13EEF91E0309385002093840096BB49 -:10004000B09BFECF1D9AA8958150A9F7DD24D394CB -:10005000A5E0EA2EF1E1FF2EABD0813421F481E05E -:10006000C5D083E020C0823411F484E103C085341C -:1000700019F485E0BBD091C0853581F499D0082F63 -:1000800010E096D090E0982F8827802B912B880F36 -:10009000991F90930102809300027EC0863529F457 -:1000A00084E0A4D080E07CD078C0843609F04EC0D3 -:1000B00087D0E0910002F091010280E7E030F8077C -:1000C00018F483E087BFE895C0E0D1E071D0899350 -:1000D000809102028150809302028823B9F7E09157 -:1000E0000002F091010280E7E030F80718F083E0A9 -:1000F00087BFE89575D007B600FCFDCF40910002A0 -:1001000050910102A0E0B1E02C9130E011968C9169 -:10011000119790E0982F8827822B932B1296FA0143 -:100120000C01D7BEE89511244E5F5F4FF1E0A03877 -:10013000BF0751F7E0910002F0910102E7BEE89598 -:1001400007B600FCFDCFF7BEE89527C08437B9F4A9 -:1001500037D046D0E0910002F09101023196F09341 -:100160000102E09300023197E4918E2F19D0809123 -:100170000202815080930202882361F70EC0853706 -:1001800039F42ED08EE10CD085E90AD08FE08BCFE8 -:10019000813511F488E019D023D080E101D05CCF03 -:1001A000982F8091C00085FFFCCF9093C6000895E2 -:1001B000A8958091C00087FFFCCF8091C60008956C -:1001C000F7DFF6DF80930202F3CFE0E6F0E098E19C -:1001D00090838083089580E0F8DFEE27FF2709945D -:1001E000E7DF803209F0F7DF84E1DACF1F93182FC1 -:0C01F000DFDF1150E9F7F4DF1F910895E4 +:10004000B09BFECF1D9AA8958150A9F7992493944F +:10005000A5E0AA2EF1E1BF2E9DD0813421F481E0EC +:10006000AFD083E01FC0823411F484E103C0853433 +:1000700019F485E0A5D083C0853579F48BD0E82EBE +:10008000FF2488D0082F10E0102F00270E291F29E9 +:10009000000F111F8DD0680172C0863529F484E0ED +:1000A0008FD080E06FD06BC0843609F042C072D030 +:1000B00071D0082F6FD080E0C81680E7D80620F4F2 +:1000C00083E0F60187BFE895C0E0D1E063D0899373 +:1000D0000C17E1F7F0E0CF16F0E7DF0620F083E041 +:1000E000F60187BFE89564D007B600FCFDCFA601F6 +:1000F000A0E0B1E02C9130E011968C91119790E046 +:10010000982F8827822B932B1296FA010C0197BE09 +:10011000E89511244E5F5F4FF1E0A038BF0751F71B +:10012000F601A7BEE89507B600FCFDCFB7BEE8957F +:1001300026C08437B1F42ED02DD0F82E2BD038D055 +:10014000F601EF2C8F010F5F1F4F84911BD0EA94B3 +:10015000F801C1F70894C11CD11CFA94CF0CD11C32 +:100160000EC0853739F424D08EE10CD085E90AD051 +:100170008FE098CF813511F488E014D019D080E158 +:1001800001D06ACF982F8091C00085FFFCCF90935B +:10019000C6000895A8958091C00087FFFCCF80918C +:1001A000C6000895E0E6F0E098E19083808308952A +:1001B000F1DF803219F088E0F5DFFFCF84E1E2CF94 +:1001C0001F93182FE7DF1150E9F7F2DF1F91089511 +:0A01D00080E0E8DFEE27FF27099426 :027FFE0001047C :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.lst b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.lst index d7ce99102..a4da506ba 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.lst @@ -3,27 +3,27 @@ optiboot_atmega328_pro_8MHz.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .text 000001fc 00000000 00000000 00000054 2**1 + 0 .text 000001da 00000000 00000000 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .version 00000002 00007ffe 00007ffe 00000250 2**0 + 1 .version 00000002 00007ffe 00007ffe 0000022e 2**0 CONTENTS, READONLY - 2 .debug_aranges 00000028 00000000 00000000 00000252 2**0 + 2 .debug_aranges 00000028 00000000 00000000 00000230 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_pubnames 0000006a 00000000 00000000 0000027a 2**0 + 3 .debug_pubnames 0000005f 00000000 00000000 00000258 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_info 00000285 00000000 00000000 000002e4 2**0 + 4 .debug_info 0000028c 00000000 00000000 000002b7 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 0000019f 00000000 00000000 00000569 2**0 + 5 .debug_abbrev 00000199 00000000 00000000 00000543 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_line 00000453 00000000 00000000 00000708 2**0 + 6 .debug_line 00000456 00000000 00000000 000006dc 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000090 00000000 00000000 00000b5c 2**2 + 7 .debug_frame 00000080 00000000 00000000 00000b34 2**2 CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000141 00000000 00000000 00000bec 2**0 + 8 .debug_str 00000149 00000000 00000000 00000bb4 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 000001e1 00000000 00000000 00000d2d 2**0 + 9 .debug_loc 0000027e 00000000 00000000 00000cfd 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000068 00000000 00000000 00000f0e 2**0 + 10 .debug_ranges 00000060 00000000 00000000 00000f7b 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: @@ -47,7 +47,7 @@ int main(void) { 4: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); 6: 81 ff sbrs r24, 1 - 8: e6 d0 rcall .+460 ; 0x1d6 + 8: e3 d0 rcall .+454 ; 0x1d0 #if LED_START_FLASHES > 0 // Set up Timer 1 for timeout counter @@ -77,7 +77,7 @@ int main(void) { // Set up watchdog to trigger after 500ms watchdogConfig(WATCHDOG_1S); 28: 8e e0 ldi r24, 0x0E ; 14 - 2a: cf d0 rcall .+414 ; 0x1ca + 2a: bc d0 rcall .+376 ; 0x1a4 /* Set LED pin as output */ LED_DDR |= _BV(LED); @@ -111,8 +111,8 @@ void flash_led(uint8_t count) { #else LED_PIN |= _BV(LED); 44: 1d 9a sbi 0x03, 5 ; 3 - return getch(); } +#endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { @@ -132,8 +132,8 @@ void watchdogReset() { if(ch == STK_GET_PARAMETER) { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 4c: dd 24 eor r13, r13 - 4e: d3 94 inc r13 + 4c: 99 24 eor r9, r9 + 4e: 93 94 inc r9 __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); @@ -141,21 +141,21 @@ void watchdogReset() { // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); 50: a5 e0 ldi r26, 0x05 ; 5 - 52: ea 2e mov r14, r26 + 52: aa 2e mov r10, r26 boot_spm_busy_wait(); #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); 54: f1 e1 ldi r31, 0x11 ; 17 - 56: ff 2e mov r15, r31 + 56: bf 2e mov r11, r31 #endif /* Forever loop */ for (;;) { /* get character from UART */ ch = getch(); - 58: ab d0 rcall .+342 ; 0x1b0 + 58: 9d d0 rcall .+314 ; 0x194 if(ch == STK_GET_PARAMETER) { 5a: 81 34 cpi r24, 0x41 ; 65 @@ -163,10 +163,10 @@ void watchdogReset() { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); 5e: 81 e0 ldi r24, 0x01 ; 1 - 60: c5 d0 rcall .+394 ; 0x1ec + 60: af d0 rcall .+350 ; 0x1c0 putch(0x03); 62: 83 e0 ldi r24, 0x03 ; 3 - 64: 20 c0 rjmp .+64 ; 0xa6 <__SREG__+0x67> + 64: 1f c0 rjmp .+62 ; 0xa4 <__SREG__+0x65> } else if(ch == STK_SET_DEVICE) { 66: 82 34 cpi r24, 0x42 ; 66 @@ -182,71 +182,77 @@ void watchdogReset() { // SET DEVICE EXT is ignored getNch(5); 72: 85 e0 ldi r24, 0x05 ; 5 - 74: bb d0 rcall .+374 ; 0x1ec - 76: 91 c0 rjmp .+290 ; 0x19a <__SREG__+0x15b> + 74: a5 d0 rcall .+330 ; 0x1c0 + 76: 83 c0 rjmp .+262 ; 0x17e <__SREG__+0x13f> } else if(ch == STK_LOAD_ADDRESS) { 78: 85 35 cpi r24, 0x55 ; 85 - 7a: 81 f4 brne .+32 ; 0x9c <__SREG__+0x5d> + 7a: 79 f4 brne .+30 ; 0x9a <__SREG__+0x5b> // LOAD ADDRESS uint16_t newAddress; newAddress = getch(); - 7c: 99 d0 rcall .+306 ; 0x1b0 + 7c: 8b d0 rcall .+278 ; 0x194 newAddress = (newAddress & 0xff) | (getch() << 8); - 7e: 08 2f mov r16, r24 - 80: 10 e0 ldi r17, 0x00 ; 0 - 82: 96 d0 rcall .+300 ; 0x1b0 - 84: 90 e0 ldi r25, 0x00 ; 0 - 86: 98 2f mov r25, r24 - 88: 88 27 eor r24, r24 - 8a: 80 2b or r24, r16 - 8c: 91 2b or r25, r17 + 7e: e8 2e mov r14, r24 + 80: ff 24 eor r15, r15 + 82: 88 d0 rcall .+272 ; 0x194 + 84: 08 2f mov r16, r24 + 86: 10 e0 ldi r17, 0x00 ; 0 + 88: 10 2f mov r17, r16 + 8a: 00 27 eor r16, r16 + 8c: 0e 29 or r16, r14 + 8e: 1f 29 or r17, r15 #ifdef RAMPZ // Transfer top bit to RAMPZ RAMPZ = (newAddress & 0x8000) ? 1 : 0; #endif newAddress += newAddress; // Convert from word address to byte address - 8e: 88 0f add r24, r24 - 90: 99 1f adc r25, r25 + 90: 00 0f add r16, r16 + 92: 11 1f adc r17, r17 address = newAddress; - 92: 90 93 01 02 sts 0x0201, r25 - 96: 80 93 00 02 sts 0x0200, r24 - 9a: 7e c0 rjmp .+252 ; 0x198 <__SREG__+0x159> verifySpace(); + 94: 8d d0 rcall .+282 ; 0x1b0 + 96: 68 01 movw r12, r16 + 98: 72 c0 rjmp .+228 ; 0x17e <__SREG__+0x13f> } else if(ch == STK_UNIVERSAL) { - 9c: 86 35 cpi r24, 0x56 ; 86 - 9e: 29 f4 brne .+10 ; 0xaa <__SREG__+0x6b> + 9a: 86 35 cpi r24, 0x56 ; 86 + 9c: 29 f4 brne .+10 ; 0xa8 <__SREG__+0x69> // UNIVERSAL command is ignored getNch(4); - a0: 84 e0 ldi r24, 0x04 ; 4 - a2: a4 d0 rcall .+328 ; 0x1ec + 9e: 84 e0 ldi r24, 0x04 ; 4 + a0: 8f d0 rcall .+286 ; 0x1c0 putch(0x00); - a4: 80 e0 ldi r24, 0x00 ; 0 - a6: 7c d0 rcall .+248 ; 0x1a0 - a8: 78 c0 rjmp .+240 ; 0x19a <__SREG__+0x15b> + a2: 80 e0 ldi r24, 0x00 ; 0 + a4: 6f d0 rcall .+222 ; 0x184 + a6: 6b c0 rjmp .+214 ; 0x17e <__SREG__+0x13f> } /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { - aa: 84 36 cpi r24, 0x64 ; 100 - ac: 09 f0 breq .+2 ; 0xb0 <__SREG__+0x71> - ae: 4e c0 rjmp .+156 ; 0x14c <__SREG__+0x10d> + a8: 84 36 cpi r24, 0x64 ; 100 + aa: 09 f0 breq .+2 ; 0xae <__SREG__+0x6f> + ac: 42 c0 rjmp .+132 ; 0x132 <__SREG__+0xf3> // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t *bufPtr; uint16_t addrPtr; - getLen(); - b0: 87 d0 rcall .+270 ; 0x1c0 + getch(); /* getlen() */ + ae: 72 d0 rcall .+228 ; 0x194 + length = getch(); + b0: 71 d0 rcall .+226 ; 0x194 + b2: 08 2f mov r16, r24 + getch(); + b4: 6f d0 rcall .+222 ; 0x194 // If we are in RWW section, immediately start page erase if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - b2: e0 91 00 02 lds r30, 0x0200 - b6: f0 91 01 02 lds r31, 0x0201 + b6: 80 e0 ldi r24, 0x00 ; 0 + b8: c8 16 cp r12, r24 ba: 80 e7 ldi r24, 0x70 ; 112 - bc: e0 30 cpi r30, 0x00 ; 0 - be: f8 07 cpc r31, r24 - c0: 18 f4 brcc .+6 ; 0xc8 <__SREG__+0x89> - c2: 83 e0 ldi r24, 0x03 ; 3 + bc: d8 06 cpc r13, r24 + be: 20 f4 brcc .+8 ; 0xc8 <__SREG__+0x89> + c0: 83 e0 ldi r24, 0x03 ; 3 + c2: f6 01 movw r30, r12 c4: 87 bf out 0x37, r24 ; 55 c6: e8 95 spm c8: c0 e0 ldi r28, 0x00 ; 0 @@ -255,302 +261,301 @@ void watchdogReset() { // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); - cc: 71 d0 rcall .+226 ; 0x1b0 + cc: 63 d0 rcall .+198 ; 0x194 ce: 89 93 st Y+, r24 while (--length); - d0: 80 91 02 02 lds r24, 0x0202 - d4: 81 50 subi r24, 0x01 ; 1 - d6: 80 93 02 02 sts 0x0202, r24 - da: 88 23 and r24, r24 - dc: b9 f7 brne .-18 ; 0xcc <__SREG__+0x8d> + d0: 0c 17 cp r16, r28 + d2: e1 f7 brne .-8 ; 0xcc <__SREG__+0x8d> // If we are in NRWW section, page erase has to be delayed until now. // Todo: Take RAMPZ into account if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - de: e0 91 00 02 lds r30, 0x0200 - e2: f0 91 01 02 lds r31, 0x0201 - e6: 80 e7 ldi r24, 0x70 ; 112 - e8: e0 30 cpi r30, 0x00 ; 0 - ea: f8 07 cpc r31, r24 - ec: 18 f0 brcs .+6 ; 0xf4 <__SREG__+0xb5> - ee: 83 e0 ldi r24, 0x03 ; 3 - f0: 87 bf out 0x37, r24 ; 55 - f2: e8 95 spm + d4: f0 e0 ldi r31, 0x00 ; 0 + d6: cf 16 cp r12, r31 + d8: f0 e7 ldi r31, 0x70 ; 112 + da: df 06 cpc r13, r31 + dc: 20 f0 brcs .+8 ; 0xe6 <__SREG__+0xa7> + de: 83 e0 ldi r24, 0x03 ; 3 + e0: f6 01 movw r30, r12 + e2: 87 bf out 0x37, r24 ; 55 + e4: e8 95 spm // Read command terminator, start reply verifySpace(); - f4: 75 d0 rcall .+234 ; 0x1e0 + e6: 64 d0 rcall .+200 ; 0x1b0 // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); - f6: 07 b6 in r0, 0x37 ; 55 - f8: 00 fc sbrc r0, 0 - fa: fd cf rjmp .-6 ; 0xf6 <__SREG__+0xb7> - } -#endif - - // Copy buffer into programming buffer + e8: 07 b6 in r0, 0x37 ; 55 + ea: 00 fc sbrc r0, 0 + ec: fd cf rjmp .-6 ; 0xe8 <__SREG__+0xa9> + ee: a6 01 movw r20, r12 + f0: a0 e0 ldi r26, 0x00 ; 0 + f2: b1 e0 ldi r27, 0x01 ; 1 bufPtr = buff; addrPtr = (uint16_t)(void*)address; - fc: 40 91 00 02 lds r20, 0x0200 - 100: 50 91 01 02 lds r21, 0x0201 - 104: a0 e0 ldi r26, 0x00 ; 0 - 106: b1 e0 ldi r27, 0x01 ; 1 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; - 108: 2c 91 ld r18, X - 10a: 30 e0 ldi r19, 0x00 ; 0 + f4: 2c 91 ld r18, X + f6: 30 e0 ldi r19, 0x00 ; 0 a |= (*bufPtr++) << 8; - 10c: 11 96 adiw r26, 0x01 ; 1 - 10e: 8c 91 ld r24, X - 110: 11 97 sbiw r26, 0x01 ; 1 - 112: 90 e0 ldi r25, 0x00 ; 0 - 114: 98 2f mov r25, r24 - 116: 88 27 eor r24, r24 - 118: 82 2b or r24, r18 - 11a: 93 2b or r25, r19 + f8: 11 96 adiw r26, 0x01 ; 1 + fa: 8c 91 ld r24, X + fc: 11 97 sbiw r26, 0x01 ; 1 + fe: 90 e0 ldi r25, 0x00 ; 0 + 100: 98 2f mov r25, r24 + 102: 88 27 eor r24, r24 + 104: 82 2b or r24, r18 + 106: 93 2b or r25, r19 #define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) #define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif /* main program starts here */ int main(void) { - 11c: 12 96 adiw r26, 0x02 ; 2 + 108: 12 96 adiw r26, 0x02 ; 2 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; a |= (*bufPtr++) << 8; __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - 11e: fa 01 movw r30, r20 - 120: 0c 01 movw r0, r24 - 122: d7 be out 0x37, r13 ; 55 - 124: e8 95 spm - 126: 11 24 eor r1, r1 + 10a: fa 01 movw r30, r20 + 10c: 0c 01 movw r0, r24 + 10e: 97 be out 0x37, r9 ; 55 + 110: e8 95 spm + 112: 11 24 eor r1, r1 addrPtr += 2; - 128: 4e 5f subi r20, 0xFE ; 254 - 12a: 5f 4f sbci r21, 0xFF ; 255 + 114: 4e 5f subi r20, 0xFE ; 254 + 116: 5f 4f sbci r21, 0xFF ; 255 } while (--ch); - 12c: f1 e0 ldi r31, 0x01 ; 1 - 12e: a0 38 cpi r26, 0x80 ; 128 - 130: bf 07 cpc r27, r31 - 132: 51 f7 brne .-44 ; 0x108 <__SREG__+0xc9> + 118: f1 e0 ldi r31, 0x01 ; 1 + 11a: a0 38 cpi r26, 0x80 ; 128 + 11c: bf 07 cpc r27, r31 + 11e: 51 f7 brne .-44 ; 0xf4 <__SREG__+0xb5> // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); - 134: e0 91 00 02 lds r30, 0x0200 - 138: f0 91 01 02 lds r31, 0x0201 - 13c: e7 be out 0x37, r14 ; 55 - 13e: e8 95 spm + 120: f6 01 movw r30, r12 + 122: a7 be out 0x37, r10 ; 55 + 124: e8 95 spm boot_spm_busy_wait(); - 140: 07 b6 in r0, 0x37 ; 55 - 142: 00 fc sbrc r0, 0 - 144: fd cf rjmp .-6 ; 0x140 <__SREG__+0x101> + 126: 07 b6 in r0, 0x37 ; 55 + 128: 00 fc sbrc r0, 0 + 12a: fd cf rjmp .-6 ; 0x126 <__SREG__+0xe7> #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 146: f7 be out 0x37, r15 ; 55 - 148: e8 95 spm - 14a: 27 c0 rjmp .+78 ; 0x19a <__SREG__+0x15b> + 12c: b7 be out 0x37, r11 ; 55 + 12e: e8 95 spm + 130: 26 c0 rjmp .+76 ; 0x17e <__SREG__+0x13f> #endif } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { - 14c: 84 37 cpi r24, 0x74 ; 116 - 14e: b9 f4 brne .+46 ; 0x17e <__SREG__+0x13f> + 132: 84 37 cpi r24, 0x74 ; 116 + 134: b1 f4 brne .+44 ; 0x162 <__SREG__+0x123> // READ PAGE - we only read flash - getLen(); - 150: 37 d0 rcall .+110 ; 0x1c0 + getch(); /* getlen() */ + 136: 2e d0 rcall .+92 ; 0x194 + length = getch(); + 138: 2d d0 rcall .+90 ; 0x194 + 13a: f8 2e mov r15, r24 + getch(); + 13c: 2b d0 rcall .+86 ; 0x194 + verifySpace(); - 152: 46 d0 rcall .+140 ; 0x1e0 + 13e: 38 d0 rcall .+112 ; 0x1b0 + 140: f6 01 movw r30, r12 + 142: ef 2c mov r14, r15 putch(result); address++; } while (--length); #else do putch(pgm_read_byte_near(address++)); - 154: e0 91 00 02 lds r30, 0x0200 - 158: f0 91 01 02 lds r31, 0x0201 - 15c: 31 96 adiw r30, 0x01 ; 1 - 15e: f0 93 01 02 sts 0x0201, r31 - 162: e0 93 00 02 sts 0x0200, r30 - 166: 31 97 sbiw r30, 0x01 ; 1 - 168: e4 91 lpm r30, Z+ - 16a: 8e 2f mov r24, r30 - 16c: 19 d0 rcall .+50 ; 0x1a0 + 144: 8f 01 movw r16, r30 + 146: 0f 5f subi r16, 0xFF ; 255 + 148: 1f 4f sbci r17, 0xFF ; 255 + 14a: 84 91 lpm r24, Z+ + 14c: 1b d0 rcall .+54 ; 0x184 while (--length); - 16e: 80 91 02 02 lds r24, 0x0202 - 172: 81 50 subi r24, 0x01 ; 1 - 174: 80 93 02 02 sts 0x0202, r24 - 178: 88 23 and r24, r24 - 17a: 61 f7 brne .-40 ; 0x154 <__SREG__+0x115> - 17c: 0e c0 rjmp .+28 ; 0x19a <__SREG__+0x15b> + 14e: ea 94 dec r14 + 150: f8 01 movw r30, r16 + 152: c1 f7 brne .-16 ; 0x144 <__SREG__+0x105> +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) +#endif + +/* main program starts here */ +int main(void) { + 154: 08 94 sec + 156: c1 1c adc r12, r1 + 158: d1 1c adc r13, r1 + 15a: fa 94 dec r15 + 15c: cf 0c add r12, r15 + 15e: d1 1c adc r13, r1 + 160: 0e c0 rjmp .+28 ; 0x17e <__SREG__+0x13f> #endif #endif } /* Get device signature bytes */ else if(ch == STK_READ_SIGN) { - 17e: 85 37 cpi r24, 0x75 ; 117 - 180: 39 f4 brne .+14 ; 0x190 <__SREG__+0x151> + 162: 85 37 cpi r24, 0x75 ; 117 + 164: 39 f4 brne .+14 ; 0x174 <__SREG__+0x135> // READ SIGN - return what Avrdude wants to hear verifySpace(); - 182: 2e d0 rcall .+92 ; 0x1e0 + 166: 24 d0 rcall .+72 ; 0x1b0 putch(SIGNATURE_0); - 184: 8e e1 ldi r24, 0x1E ; 30 - 186: 0c d0 rcall .+24 ; 0x1a0 + 168: 8e e1 ldi r24, 0x1E ; 30 + 16a: 0c d0 rcall .+24 ; 0x184 putch(SIGNATURE_1); - 188: 85 e9 ldi r24, 0x95 ; 149 - 18a: 0a d0 rcall .+20 ; 0x1a0 + 16c: 85 e9 ldi r24, 0x95 ; 149 + 16e: 0a d0 rcall .+20 ; 0x184 putch(SIGNATURE_2); - 18c: 8f e0 ldi r24, 0x0F ; 15 - 18e: 8b cf rjmp .-234 ; 0xa6 <__SREG__+0x67> + 170: 8f e0 ldi r24, 0x0F ; 15 + 172: 98 cf rjmp .-208 ; 0xa4 <__SREG__+0x65> } else if (ch == 'Q') { - 190: 81 35 cpi r24, 0x51 ; 81 - 192: 11 f4 brne .+4 ; 0x198 <__SREG__+0x159> + 174: 81 35 cpi r24, 0x51 ; 81 + 176: 11 f4 brne .+4 ; 0x17c <__SREG__+0x13d> // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); - 194: 88 e0 ldi r24, 0x08 ; 8 - 196: 19 d0 rcall .+50 ; 0x1ca + 178: 88 e0 ldi r24, 0x08 ; 8 + 17a: 14 d0 rcall .+40 ; 0x1a4 verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 198: 23 d0 rcall .+70 ; 0x1e0 + 17c: 19 d0 rcall .+50 ; 0x1b0 } putch(STK_OK); - 19a: 80 e1 ldi r24, 0x10 ; 16 - 19c: 01 d0 rcall .+2 ; 0x1a0 - 19e: 5c cf rjmp .-328 ; 0x58 <__SREG__+0x19> + 17e: 80 e1 ldi r24, 0x10 ; 16 + 180: 01 d0 rcall .+2 ; 0x184 + 182: 6a cf rjmp .-300 ; 0x58 <__SREG__+0x19> -000001a0 : +00000184 : } } void putch(char ch) { - 1a0: 98 2f mov r25, r24 + 184: 98 2f mov r25, r24 #ifndef SOFT_UART while (!(UCSR0A & _BV(UDRE0))); - 1a2: 80 91 c0 00 lds r24, 0x00C0 - 1a6: 85 ff sbrs r24, 5 - 1a8: fc cf rjmp .-8 ; 0x1a2 + 186: 80 91 c0 00 lds r24, 0x00C0 + 18a: 85 ff sbrs r24, 5 + 18c: fc cf rjmp .-8 ; 0x186 UDR0 = ch; - 1aa: 90 93 c6 00 sts 0x00C6, r25 + 18e: 90 93 c6 00 sts 0x00C6, r25 [uartBit] "I" (UART_TX_BIT) : "r25" ); #endif } - 1ae: 08 95 ret + 192: 08 95 ret -000001b0 : - return getch(); +00000194 : } +#endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 1b0: a8 95 wdr + 194: a8 95 wdr [uartBit] "I" (UART_RX_BIT) : "r25" ); #else while(!(UCSR0A & _BV(RXC0))); - 1b2: 80 91 c0 00 lds r24, 0x00C0 - 1b6: 87 ff sbrs r24, 7 - 1b8: fc cf rjmp .-8 ; 0x1b2 + 196: 80 91 c0 00 lds r24, 0x00C0 + 19a: 87 ff sbrs r24, 7 + 19c: fc cf rjmp .-8 ; 0x196 ch = UDR0; - 1ba: 80 91 c6 00 lds r24, 0x00C6 + 19e: 80 91 c6 00 lds r24, 0x00C6 LED_PIN |= _BV(LED); #endif #endif return ch; } - 1be: 08 95 ret + 1a2: 08 95 ret -000001c0 : - } while (--count); -} -#endif - -uint8_t getLen() { - getch(); - 1c0: f7 df rcall .-18 ; 0x1b0 - length = getch(); - 1c2: f6 df rcall .-20 ; 0x1b0 - 1c4: 80 93 02 02 sts 0x0202, r24 - return getch(); -} - 1c8: f3 cf rjmp .-26 ; 0x1b0 - -000001ca : +000001a4 : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 1ca: e0 e6 ldi r30, 0x60 ; 96 - 1cc: f0 e0 ldi r31, 0x00 ; 0 - 1ce: 98 e1 ldi r25, 0x18 ; 24 - 1d0: 90 83 st Z, r25 + 1a4: e0 e6 ldi r30, 0x60 ; 96 + 1a6: f0 e0 ldi r31, 0x00 ; 0 + 1a8: 98 e1 ldi r25, 0x18 ; 24 + 1aa: 90 83 st Z, r25 WDTCSR = x; - 1d2: 80 83 st Z, r24 + 1ac: 80 83 st Z, r24 } - 1d4: 08 95 ret + 1ae: 08 95 ret -000001d6 : - -void appStart() { - watchdogConfig(WATCHDOG_OFF); - 1d6: 80 e0 ldi r24, 0x00 ; 0 - 1d8: f8 df rcall .-16 ; 0x1ca - __asm__ __volatile__ ( - 1da: ee 27 eor r30, r30 - 1dc: ff 27 eor r31, r31 - 1de: 09 94 ijmp - -000001e0 : +000001b0 : do getch(); while (--count); verifySpace(); } void verifySpace() { - if (getch() != CRC_EOP) appStart(); - 1e0: e7 df rcall .-50 ; 0x1b0 - 1e2: 80 32 cpi r24, 0x20 ; 32 - 1e4: 09 f0 breq .+2 ; 0x1e8 - 1e6: f7 df rcall .-18 ; 0x1d6 + if (getch() != CRC_EOP) { + 1b0: f1 df rcall .-30 ; 0x194 + 1b2: 80 32 cpi r24, 0x20 ; 32 + 1b4: 19 f0 breq .+6 ; 0x1bc + watchdogConfig(WATCHDOG_16MS); // shorten WD timeout + 1b6: 88 e0 ldi r24, 0x08 ; 8 + 1b8: f5 df rcall .-22 ; 0x1a4 + 1ba: ff cf rjmp .-2 ; 0x1ba + while (1) // and busy-loop so that WD causes + ; // a reset and app start. + } putch(STK_INSYNC); - 1e8: 84 e1 ldi r24, 0x14 ; 20 + 1bc: 84 e1 ldi r24, 0x14 ; 20 } - 1ea: da cf rjmp .-76 ; 0x1a0 + 1be: e2 cf rjmp .-60 ; 0x184 -000001ec : +000001c0 : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 1ec: 1f 93 push r17 - 1ee: 18 2f mov r17, r24 + 1c0: 1f 93 push r17 + 1c2: 18 2f mov r17, r24 do getch(); while (--count); - 1f0: df df rcall .-66 ; 0x1b0 - 1f2: 11 50 subi r17, 0x01 ; 1 - 1f4: e9 f7 brne .-6 ; 0x1f0 + 1c4: e7 df rcall .-50 ; 0x194 + 1c6: 11 50 subi r17, 0x01 ; 1 + 1c8: e9 f7 brne .-6 ; 0x1c4 verifySpace(); - 1f6: f4 df rcall .-24 ; 0x1e0 + 1ca: f2 df rcall .-28 ; 0x1b0 } - 1f8: 1f 91 pop r17 - 1fa: 08 95 ret + 1cc: 1f 91 pop r17 + 1ce: 08 95 ret + +000001d0 : + WDTCSR = _BV(WDCE) | _BV(WDE); + WDTCSR = x; +} + +void appStart() { + watchdogConfig(WATCHDOG_OFF); + 1d0: 80 e0 ldi r24, 0x00 ; 0 + 1d2: e8 df rcall .-48 ; 0x1a4 + __asm__ __volatile__ ( + 1d4: ee 27 eor r30, r30 + 1d6: ff 27 eor r31, r31 + 1d8: 09 94 ijmp diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.hex b/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.hex index 3ac0de204..733a1397e 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.hex @@ -1,35 +1,33 @@ -:103E0000112484B714BE81FFE6D085E08093810041 +:103E0000112484B714BE81FFE3D085E08093810044 :103E100082E08093C00088E18093C10086E08093B7 -:103E2000C20080E18093C4008EE0CFD0259A86E066 +:103E2000C20080E18093C4008EE0BCD0259A86E079 :103E300020E33CEF91E0309385002093840096BB13 -:103E4000B09BFECF1D9AA8958150A9F7DD24D3948D -:103E5000A5E0EA2EF1E1FF2EABD0813421F481E020 -:103E6000C5D083E020C0823411F484E103C08534DE -:103E700019F485E0BBD091C0853581F499D0082F25 -:103E800010E096D090E0982F8827802B912B880FF8 -:103E9000991F90930102809300027EC0863529F419 -:103EA00084E0A4D080E07CD078C0843609F04EC095 -:103EB00087D0E0910002F091010288E3E030F8073A -:103EC00018F483E087BFE895C0E0D1E071D0899312 -:103ED000809102028150809302028823B9F7E09119 -:103EE0000002F091010288E3E030F80718F083E067 -:103EF00087BFE89575D007B600FCFDCF4091000262 -:103F000050910102A0E0B1E02C9130E011968C912B -:103F1000119790E0982F8827822B932B1296FA0105 -:103F20000C01D7BEE89511244E5F5F4FF1E0A03839 -:103F3000BF0751F7E0910002F0910102E7BEE8955A -:103F400007B600FCFDCFF7BEE89527C08437B9F46B -:103F500037D046D0E0910002F09101023196F09303 -:103F60000102E09300023197E4918E2F19D08091E5 -:103F70000202815080930202882361F70EC08537C8 -:103F800039F42ED08EE10CD084E90AD086E08BCFB4 -:103F9000813511F488E019D023D080E101D05CCFC5 -:103FA000982F8091C00085FFFCCF9093C6000895A4 -:103FB000A8958091C00087FFFCCF8091C60008952E -:103FC000F7DFF6DF80930202F3CFE0E6F0E098E15E -:103FD00090838083089580E0F8DFEE27FF2709941F -:103FE000E7DF803209F0F7DF84E1DACF1F93182F83 -:0C3FF000DFDF1150E9F7F4DF1F910895A6 +:103E4000B09BFECF1D9AA8958150A9F79924939411 +:103E5000A5E0AA2EF1E1BF2E9DD0813421F481E0AE +:103E6000AFD083E01FC0823411F484E103C08534F5 +:103E700019F485E0A5D083C0853579F48BD0E82E80 +:103E8000FF2488D0082F10E0102F00270E291F29AB +:103E9000000F111F8DD0680172C0863529F484E0AF +:103EA0008FD080E06FD06BC0843609F042C072D0F2 +:103EB00071D0082F6FD080E0C81688E3D80620F4B0 +:103EC00083E0F60187BFE895C0E0D1E063D0899335 +:103ED0000C17E1F7F0E0CF16F8E3DF0620F083E0FF +:103EE000F60187BFE89564D007B600FCFDCFA601B8 +:103EF000A0E0B1E02C9130E011968C91119790E008 +:103F0000982F8827822B932B1296FA010C0197BECB +:103F1000E89511244E5F5F4FF1E0A038BF0751F7DD +:103F2000F601A7BEE89507B600FCFDCFB7BEE89541 +:103F300026C08437B1F42ED02DD0F82E2BD038D017 +:103F4000F601EF2C8F010F5F1F4F84911BD0EA9475 +:103F5000F801C1F70894C11CD11CFA94CF0CD11CF4 +:103F60000EC0853739F424D08EE10CD084E90AD014 +:103F700086E098CF813511F488E014D019D080E123 +:103F800001D06ACF982F8091C00085FFFCCF90931D +:103F9000C6000895A8958091C00087FFFCCF80914E +:103FA000C6000895E0E6F0E098E1908380830895EC +:103FB000F1DF803219F088E0F5DFFFCF84E1E2CF56 +:103FC0001F93182FE7DF1150E9F7F2DF1F910895D3 +:0A3FD00080E0E8DFEE27FF270994E8 :023FFE000104BC :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.lst b/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.lst index 8b1736859..edd9cb369 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.lst @@ -3,27 +3,27 @@ optiboot_diecimila.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .text 000001fc 00003e00 00003e00 00000054 2**1 + 0 .text 000001da 00003e00 00003e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .version 00000002 00003ffe 00003ffe 00000250 2**0 + 1 .version 00000002 00003ffe 00003ffe 0000022e 2**0 CONTENTS, READONLY - 2 .debug_aranges 00000028 00000000 00000000 00000252 2**0 + 2 .debug_aranges 00000028 00000000 00000000 00000230 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_pubnames 0000006a 00000000 00000000 0000027a 2**0 + 3 .debug_pubnames 0000005f 00000000 00000000 00000258 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_info 00000285 00000000 00000000 000002e4 2**0 + 4 .debug_info 0000028c 00000000 00000000 000002b7 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 0000019f 00000000 00000000 00000569 2**0 + 5 .debug_abbrev 00000199 00000000 00000000 00000543 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_line 00000453 00000000 00000000 00000708 2**0 + 6 .debug_line 00000456 00000000 00000000 000006dc 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000090 00000000 00000000 00000b5c 2**2 + 7 .debug_frame 00000080 00000000 00000000 00000b34 2**2 CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000141 00000000 00000000 00000bec 2**0 + 8 .debug_str 00000149 00000000 00000000 00000bb4 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 000001e1 00000000 00000000 00000d2d 2**0 + 9 .debug_loc 0000027e 00000000 00000000 00000cfd 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000068 00000000 00000000 00000f0e 2**0 + 10 .debug_ranges 00000060 00000000 00000000 00000f7b 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: @@ -47,7 +47,7 @@ int main(void) { 3e04: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); 3e06: 81 ff sbrs r24, 1 - 3e08: e6 d0 rcall .+460 ; 0x3fd6 + 3e08: e3 d0 rcall .+454 ; 0x3fd0 #if LED_START_FLASHES > 0 // Set up Timer 1 for timeout counter @@ -77,7 +77,7 @@ int main(void) { // Set up watchdog to trigger after 500ms watchdogConfig(WATCHDOG_1S); 3e28: 8e e0 ldi r24, 0x0E ; 14 - 3e2a: cf d0 rcall .+414 ; 0x3fca + 3e2a: bc d0 rcall .+376 ; 0x3fa4 /* Set LED pin as output */ LED_DDR |= _BV(LED); @@ -111,8 +111,8 @@ void flash_led(uint8_t count) { #else LED_PIN |= _BV(LED); 3e44: 1d 9a sbi 0x03, 5 ; 3 - return getch(); } +#endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { @@ -132,8 +132,8 @@ void watchdogReset() { if(ch == STK_GET_PARAMETER) { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 3e4c: dd 24 eor r13, r13 - 3e4e: d3 94 inc r13 + 3e4c: 99 24 eor r9, r9 + 3e4e: 93 94 inc r9 __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); @@ -141,21 +141,21 @@ void watchdogReset() { // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); 3e50: a5 e0 ldi r26, 0x05 ; 5 - 3e52: ea 2e mov r14, r26 + 3e52: aa 2e mov r10, r26 boot_spm_busy_wait(); #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); 3e54: f1 e1 ldi r31, 0x11 ; 17 - 3e56: ff 2e mov r15, r31 + 3e56: bf 2e mov r11, r31 #endif /* Forever loop */ for (;;) { /* get character from UART */ ch = getch(); - 3e58: ab d0 rcall .+342 ; 0x3fb0 + 3e58: 9d d0 rcall .+314 ; 0x3f94 if(ch == STK_GET_PARAMETER) { 3e5a: 81 34 cpi r24, 0x41 ; 65 @@ -163,10 +163,10 @@ void watchdogReset() { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); 3e5e: 81 e0 ldi r24, 0x01 ; 1 - 3e60: c5 d0 rcall .+394 ; 0x3fec + 3e60: af d0 rcall .+350 ; 0x3fc0 putch(0x03); 3e62: 83 e0 ldi r24, 0x03 ; 3 - 3e64: 20 c0 rjmp .+64 ; 0x3ea6 + 3e64: 1f c0 rjmp .+62 ; 0x3ea4 } else if(ch == STK_SET_DEVICE) { 3e66: 82 34 cpi r24, 0x42 ; 66 @@ -182,71 +182,77 @@ void watchdogReset() { // SET DEVICE EXT is ignored getNch(5); 3e72: 85 e0 ldi r24, 0x05 ; 5 - 3e74: bb d0 rcall .+374 ; 0x3fec - 3e76: 91 c0 rjmp .+290 ; 0x3f9a + 3e74: a5 d0 rcall .+330 ; 0x3fc0 + 3e76: 83 c0 rjmp .+262 ; 0x3f7e } else if(ch == STK_LOAD_ADDRESS) { 3e78: 85 35 cpi r24, 0x55 ; 85 - 3e7a: 81 f4 brne .+32 ; 0x3e9c + 3e7a: 79 f4 brne .+30 ; 0x3e9a // LOAD ADDRESS uint16_t newAddress; newAddress = getch(); - 3e7c: 99 d0 rcall .+306 ; 0x3fb0 + 3e7c: 8b d0 rcall .+278 ; 0x3f94 newAddress = (newAddress & 0xff) | (getch() << 8); - 3e7e: 08 2f mov r16, r24 - 3e80: 10 e0 ldi r17, 0x00 ; 0 - 3e82: 96 d0 rcall .+300 ; 0x3fb0 - 3e84: 90 e0 ldi r25, 0x00 ; 0 - 3e86: 98 2f mov r25, r24 - 3e88: 88 27 eor r24, r24 - 3e8a: 80 2b or r24, r16 - 3e8c: 91 2b or r25, r17 + 3e7e: e8 2e mov r14, r24 + 3e80: ff 24 eor r15, r15 + 3e82: 88 d0 rcall .+272 ; 0x3f94 + 3e84: 08 2f mov r16, r24 + 3e86: 10 e0 ldi r17, 0x00 ; 0 + 3e88: 10 2f mov r17, r16 + 3e8a: 00 27 eor r16, r16 + 3e8c: 0e 29 or r16, r14 + 3e8e: 1f 29 or r17, r15 #ifdef RAMPZ // Transfer top bit to RAMPZ RAMPZ = (newAddress & 0x8000) ? 1 : 0; #endif newAddress += newAddress; // Convert from word address to byte address - 3e8e: 88 0f add r24, r24 - 3e90: 99 1f adc r25, r25 + 3e90: 00 0f add r16, r16 + 3e92: 11 1f adc r17, r17 address = newAddress; - 3e92: 90 93 01 02 sts 0x0201, r25 - 3e96: 80 93 00 02 sts 0x0200, r24 - 3e9a: 7e c0 rjmp .+252 ; 0x3f98 verifySpace(); + 3e94: 8d d0 rcall .+282 ; 0x3fb0 + 3e96: 68 01 movw r12, r16 + 3e98: 72 c0 rjmp .+228 ; 0x3f7e } else if(ch == STK_UNIVERSAL) { - 3e9c: 86 35 cpi r24, 0x56 ; 86 - 3e9e: 29 f4 brne .+10 ; 0x3eaa + 3e9a: 86 35 cpi r24, 0x56 ; 86 + 3e9c: 29 f4 brne .+10 ; 0x3ea8 // UNIVERSAL command is ignored getNch(4); - 3ea0: 84 e0 ldi r24, 0x04 ; 4 - 3ea2: a4 d0 rcall .+328 ; 0x3fec + 3e9e: 84 e0 ldi r24, 0x04 ; 4 + 3ea0: 8f d0 rcall .+286 ; 0x3fc0 putch(0x00); - 3ea4: 80 e0 ldi r24, 0x00 ; 0 - 3ea6: 7c d0 rcall .+248 ; 0x3fa0 - 3ea8: 78 c0 rjmp .+240 ; 0x3f9a + 3ea2: 80 e0 ldi r24, 0x00 ; 0 + 3ea4: 6f d0 rcall .+222 ; 0x3f84 + 3ea6: 6b c0 rjmp .+214 ; 0x3f7e } /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { - 3eaa: 84 36 cpi r24, 0x64 ; 100 - 3eac: 09 f0 breq .+2 ; 0x3eb0 - 3eae: 4e c0 rjmp .+156 ; 0x3f4c + 3ea8: 84 36 cpi r24, 0x64 ; 100 + 3eaa: 09 f0 breq .+2 ; 0x3eae + 3eac: 42 c0 rjmp .+132 ; 0x3f32 // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t *bufPtr; uint16_t addrPtr; - getLen(); - 3eb0: 87 d0 rcall .+270 ; 0x3fc0 + getch(); /* getlen() */ + 3eae: 72 d0 rcall .+228 ; 0x3f94 + length = getch(); + 3eb0: 71 d0 rcall .+226 ; 0x3f94 + 3eb2: 08 2f mov r16, r24 + getch(); + 3eb4: 6f d0 rcall .+222 ; 0x3f94 // If we are in RWW section, immediately start page erase if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 3eb2: e0 91 00 02 lds r30, 0x0200 - 3eb6: f0 91 01 02 lds r31, 0x0201 + 3eb6: 80 e0 ldi r24, 0x00 ; 0 + 3eb8: c8 16 cp r12, r24 3eba: 88 e3 ldi r24, 0x38 ; 56 - 3ebc: e0 30 cpi r30, 0x00 ; 0 - 3ebe: f8 07 cpc r31, r24 - 3ec0: 18 f4 brcc .+6 ; 0x3ec8 - 3ec2: 83 e0 ldi r24, 0x03 ; 3 + 3ebc: d8 06 cpc r13, r24 + 3ebe: 20 f4 brcc .+8 ; 0x3ec8 + 3ec0: 83 e0 ldi r24, 0x03 ; 3 + 3ec2: f6 01 movw r30, r12 3ec4: 87 bf out 0x37, r24 ; 55 3ec6: e8 95 spm 3ec8: c0 e0 ldi r28, 0x00 ; 0 @@ -255,302 +261,301 @@ void watchdogReset() { // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); - 3ecc: 71 d0 rcall .+226 ; 0x3fb0 + 3ecc: 63 d0 rcall .+198 ; 0x3f94 3ece: 89 93 st Y+, r24 while (--length); - 3ed0: 80 91 02 02 lds r24, 0x0202 - 3ed4: 81 50 subi r24, 0x01 ; 1 - 3ed6: 80 93 02 02 sts 0x0202, r24 - 3eda: 88 23 and r24, r24 - 3edc: b9 f7 brne .-18 ; 0x3ecc + 3ed0: 0c 17 cp r16, r28 + 3ed2: e1 f7 brne .-8 ; 0x3ecc // If we are in NRWW section, page erase has to be delayed until now. // Todo: Take RAMPZ into account if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 3ede: e0 91 00 02 lds r30, 0x0200 - 3ee2: f0 91 01 02 lds r31, 0x0201 - 3ee6: 88 e3 ldi r24, 0x38 ; 56 - 3ee8: e0 30 cpi r30, 0x00 ; 0 - 3eea: f8 07 cpc r31, r24 - 3eec: 18 f0 brcs .+6 ; 0x3ef4 - 3eee: 83 e0 ldi r24, 0x03 ; 3 - 3ef0: 87 bf out 0x37, r24 ; 55 - 3ef2: e8 95 spm + 3ed4: f0 e0 ldi r31, 0x00 ; 0 + 3ed6: cf 16 cp r12, r31 + 3ed8: f8 e3 ldi r31, 0x38 ; 56 + 3eda: df 06 cpc r13, r31 + 3edc: 20 f0 brcs .+8 ; 0x3ee6 + 3ede: 83 e0 ldi r24, 0x03 ; 3 + 3ee0: f6 01 movw r30, r12 + 3ee2: 87 bf out 0x37, r24 ; 55 + 3ee4: e8 95 spm // Read command terminator, start reply verifySpace(); - 3ef4: 75 d0 rcall .+234 ; 0x3fe0 + 3ee6: 64 d0 rcall .+200 ; 0x3fb0 // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); - 3ef6: 07 b6 in r0, 0x37 ; 55 - 3ef8: 00 fc sbrc r0, 0 - 3efa: fd cf rjmp .-6 ; 0x3ef6 - } -#endif - - // Copy buffer into programming buffer + 3ee8: 07 b6 in r0, 0x37 ; 55 + 3eea: 00 fc sbrc r0, 0 + 3eec: fd cf rjmp .-6 ; 0x3ee8 + 3eee: a6 01 movw r20, r12 + 3ef0: a0 e0 ldi r26, 0x00 ; 0 + 3ef2: b1 e0 ldi r27, 0x01 ; 1 bufPtr = buff; addrPtr = (uint16_t)(void*)address; - 3efc: 40 91 00 02 lds r20, 0x0200 - 3f00: 50 91 01 02 lds r21, 0x0201 - 3f04: a0 e0 ldi r26, 0x00 ; 0 - 3f06: b1 e0 ldi r27, 0x01 ; 1 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; - 3f08: 2c 91 ld r18, X - 3f0a: 30 e0 ldi r19, 0x00 ; 0 + 3ef4: 2c 91 ld r18, X + 3ef6: 30 e0 ldi r19, 0x00 ; 0 a |= (*bufPtr++) << 8; - 3f0c: 11 96 adiw r26, 0x01 ; 1 - 3f0e: 8c 91 ld r24, X - 3f10: 11 97 sbiw r26, 0x01 ; 1 - 3f12: 90 e0 ldi r25, 0x00 ; 0 - 3f14: 98 2f mov r25, r24 - 3f16: 88 27 eor r24, r24 - 3f18: 82 2b or r24, r18 - 3f1a: 93 2b or r25, r19 + 3ef8: 11 96 adiw r26, 0x01 ; 1 + 3efa: 8c 91 ld r24, X + 3efc: 11 97 sbiw r26, 0x01 ; 1 + 3efe: 90 e0 ldi r25, 0x00 ; 0 + 3f00: 98 2f mov r25, r24 + 3f02: 88 27 eor r24, r24 + 3f04: 82 2b or r24, r18 + 3f06: 93 2b or r25, r19 #define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) #define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif /* main program starts here */ int main(void) { - 3f1c: 12 96 adiw r26, 0x02 ; 2 + 3f08: 12 96 adiw r26, 0x02 ; 2 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; a |= (*bufPtr++) << 8; __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - 3f1e: fa 01 movw r30, r20 - 3f20: 0c 01 movw r0, r24 - 3f22: d7 be out 0x37, r13 ; 55 - 3f24: e8 95 spm - 3f26: 11 24 eor r1, r1 + 3f0a: fa 01 movw r30, r20 + 3f0c: 0c 01 movw r0, r24 + 3f0e: 97 be out 0x37, r9 ; 55 + 3f10: e8 95 spm + 3f12: 11 24 eor r1, r1 addrPtr += 2; - 3f28: 4e 5f subi r20, 0xFE ; 254 - 3f2a: 5f 4f sbci r21, 0xFF ; 255 + 3f14: 4e 5f subi r20, 0xFE ; 254 + 3f16: 5f 4f sbci r21, 0xFF ; 255 } while (--ch); - 3f2c: f1 e0 ldi r31, 0x01 ; 1 - 3f2e: a0 38 cpi r26, 0x80 ; 128 - 3f30: bf 07 cpc r27, r31 - 3f32: 51 f7 brne .-44 ; 0x3f08 + 3f18: f1 e0 ldi r31, 0x01 ; 1 + 3f1a: a0 38 cpi r26, 0x80 ; 128 + 3f1c: bf 07 cpc r27, r31 + 3f1e: 51 f7 brne .-44 ; 0x3ef4 // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); - 3f34: e0 91 00 02 lds r30, 0x0200 - 3f38: f0 91 01 02 lds r31, 0x0201 - 3f3c: e7 be out 0x37, r14 ; 55 - 3f3e: e8 95 spm + 3f20: f6 01 movw r30, r12 + 3f22: a7 be out 0x37, r10 ; 55 + 3f24: e8 95 spm boot_spm_busy_wait(); - 3f40: 07 b6 in r0, 0x37 ; 55 - 3f42: 00 fc sbrc r0, 0 - 3f44: fd cf rjmp .-6 ; 0x3f40 + 3f26: 07 b6 in r0, 0x37 ; 55 + 3f28: 00 fc sbrc r0, 0 + 3f2a: fd cf rjmp .-6 ; 0x3f26 #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 3f46: f7 be out 0x37, r15 ; 55 - 3f48: e8 95 spm - 3f4a: 27 c0 rjmp .+78 ; 0x3f9a + 3f2c: b7 be out 0x37, r11 ; 55 + 3f2e: e8 95 spm + 3f30: 26 c0 rjmp .+76 ; 0x3f7e #endif } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { - 3f4c: 84 37 cpi r24, 0x74 ; 116 - 3f4e: b9 f4 brne .+46 ; 0x3f7e + 3f32: 84 37 cpi r24, 0x74 ; 116 + 3f34: b1 f4 brne .+44 ; 0x3f62 // READ PAGE - we only read flash - getLen(); - 3f50: 37 d0 rcall .+110 ; 0x3fc0 + getch(); /* getlen() */ + 3f36: 2e d0 rcall .+92 ; 0x3f94 + length = getch(); + 3f38: 2d d0 rcall .+90 ; 0x3f94 + 3f3a: f8 2e mov r15, r24 + getch(); + 3f3c: 2b d0 rcall .+86 ; 0x3f94 + verifySpace(); - 3f52: 46 d0 rcall .+140 ; 0x3fe0 + 3f3e: 38 d0 rcall .+112 ; 0x3fb0 + 3f40: f6 01 movw r30, r12 + 3f42: ef 2c mov r14, r15 putch(result); address++; } while (--length); #else do putch(pgm_read_byte_near(address++)); - 3f54: e0 91 00 02 lds r30, 0x0200 - 3f58: f0 91 01 02 lds r31, 0x0201 - 3f5c: 31 96 adiw r30, 0x01 ; 1 - 3f5e: f0 93 01 02 sts 0x0201, r31 - 3f62: e0 93 00 02 sts 0x0200, r30 - 3f66: 31 97 sbiw r30, 0x01 ; 1 - 3f68: e4 91 lpm r30, Z+ - 3f6a: 8e 2f mov r24, r30 - 3f6c: 19 d0 rcall .+50 ; 0x3fa0 + 3f44: 8f 01 movw r16, r30 + 3f46: 0f 5f subi r16, 0xFF ; 255 + 3f48: 1f 4f sbci r17, 0xFF ; 255 + 3f4a: 84 91 lpm r24, Z+ + 3f4c: 1b d0 rcall .+54 ; 0x3f84 while (--length); - 3f6e: 80 91 02 02 lds r24, 0x0202 - 3f72: 81 50 subi r24, 0x01 ; 1 - 3f74: 80 93 02 02 sts 0x0202, r24 - 3f78: 88 23 and r24, r24 - 3f7a: 61 f7 brne .-40 ; 0x3f54 - 3f7c: 0e c0 rjmp .+28 ; 0x3f9a + 3f4e: ea 94 dec r14 + 3f50: f8 01 movw r30, r16 + 3f52: c1 f7 brne .-16 ; 0x3f44 +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) +#endif + +/* main program starts here */ +int main(void) { + 3f54: 08 94 sec + 3f56: c1 1c adc r12, r1 + 3f58: d1 1c adc r13, r1 + 3f5a: fa 94 dec r15 + 3f5c: cf 0c add r12, r15 + 3f5e: d1 1c adc r13, r1 + 3f60: 0e c0 rjmp .+28 ; 0x3f7e #endif #endif } /* Get device signature bytes */ else if(ch == STK_READ_SIGN) { - 3f7e: 85 37 cpi r24, 0x75 ; 117 - 3f80: 39 f4 brne .+14 ; 0x3f90 + 3f62: 85 37 cpi r24, 0x75 ; 117 + 3f64: 39 f4 brne .+14 ; 0x3f74 // READ SIGN - return what Avrdude wants to hear verifySpace(); - 3f82: 2e d0 rcall .+92 ; 0x3fe0 + 3f66: 24 d0 rcall .+72 ; 0x3fb0 putch(SIGNATURE_0); - 3f84: 8e e1 ldi r24, 0x1E ; 30 - 3f86: 0c d0 rcall .+24 ; 0x3fa0 + 3f68: 8e e1 ldi r24, 0x1E ; 30 + 3f6a: 0c d0 rcall .+24 ; 0x3f84 putch(SIGNATURE_1); - 3f88: 84 e9 ldi r24, 0x94 ; 148 - 3f8a: 0a d0 rcall .+20 ; 0x3fa0 + 3f6c: 84 e9 ldi r24, 0x94 ; 148 + 3f6e: 0a d0 rcall .+20 ; 0x3f84 putch(SIGNATURE_2); - 3f8c: 86 e0 ldi r24, 0x06 ; 6 - 3f8e: 8b cf rjmp .-234 ; 0x3ea6 + 3f70: 86 e0 ldi r24, 0x06 ; 6 + 3f72: 98 cf rjmp .-208 ; 0x3ea4 } else if (ch == 'Q') { - 3f90: 81 35 cpi r24, 0x51 ; 81 - 3f92: 11 f4 brne .+4 ; 0x3f98 + 3f74: 81 35 cpi r24, 0x51 ; 81 + 3f76: 11 f4 brne .+4 ; 0x3f7c // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); - 3f94: 88 e0 ldi r24, 0x08 ; 8 - 3f96: 19 d0 rcall .+50 ; 0x3fca + 3f78: 88 e0 ldi r24, 0x08 ; 8 + 3f7a: 14 d0 rcall .+40 ; 0x3fa4 verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 3f98: 23 d0 rcall .+70 ; 0x3fe0 + 3f7c: 19 d0 rcall .+50 ; 0x3fb0 } putch(STK_OK); - 3f9a: 80 e1 ldi r24, 0x10 ; 16 - 3f9c: 01 d0 rcall .+2 ; 0x3fa0 - 3f9e: 5c cf rjmp .-328 ; 0x3e58 + 3f7e: 80 e1 ldi r24, 0x10 ; 16 + 3f80: 01 d0 rcall .+2 ; 0x3f84 + 3f82: 6a cf rjmp .-300 ; 0x3e58 -00003fa0 : +00003f84 : } } void putch(char ch) { - 3fa0: 98 2f mov r25, r24 + 3f84: 98 2f mov r25, r24 #ifndef SOFT_UART while (!(UCSR0A & _BV(UDRE0))); - 3fa2: 80 91 c0 00 lds r24, 0x00C0 - 3fa6: 85 ff sbrs r24, 5 - 3fa8: fc cf rjmp .-8 ; 0x3fa2 + 3f86: 80 91 c0 00 lds r24, 0x00C0 + 3f8a: 85 ff sbrs r24, 5 + 3f8c: fc cf rjmp .-8 ; 0x3f86 UDR0 = ch; - 3faa: 90 93 c6 00 sts 0x00C6, r25 + 3f8e: 90 93 c6 00 sts 0x00C6, r25 [uartBit] "I" (UART_TX_BIT) : "r25" ); #endif } - 3fae: 08 95 ret + 3f92: 08 95 ret -00003fb0 : - return getch(); +00003f94 : } +#endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 3fb0: a8 95 wdr + 3f94: a8 95 wdr [uartBit] "I" (UART_RX_BIT) : "r25" ); #else while(!(UCSR0A & _BV(RXC0))); - 3fb2: 80 91 c0 00 lds r24, 0x00C0 - 3fb6: 87 ff sbrs r24, 7 - 3fb8: fc cf rjmp .-8 ; 0x3fb2 + 3f96: 80 91 c0 00 lds r24, 0x00C0 + 3f9a: 87 ff sbrs r24, 7 + 3f9c: fc cf rjmp .-8 ; 0x3f96 ch = UDR0; - 3fba: 80 91 c6 00 lds r24, 0x00C6 + 3f9e: 80 91 c6 00 lds r24, 0x00C6 LED_PIN |= _BV(LED); #endif #endif return ch; } - 3fbe: 08 95 ret + 3fa2: 08 95 ret -00003fc0 : - } while (--count); -} -#endif - -uint8_t getLen() { - getch(); - 3fc0: f7 df rcall .-18 ; 0x3fb0 - length = getch(); - 3fc2: f6 df rcall .-20 ; 0x3fb0 - 3fc4: 80 93 02 02 sts 0x0202, r24 - return getch(); -} - 3fc8: f3 cf rjmp .-26 ; 0x3fb0 - -00003fca : +00003fa4 : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 3fca: e0 e6 ldi r30, 0x60 ; 96 - 3fcc: f0 e0 ldi r31, 0x00 ; 0 - 3fce: 98 e1 ldi r25, 0x18 ; 24 - 3fd0: 90 83 st Z, r25 + 3fa4: e0 e6 ldi r30, 0x60 ; 96 + 3fa6: f0 e0 ldi r31, 0x00 ; 0 + 3fa8: 98 e1 ldi r25, 0x18 ; 24 + 3faa: 90 83 st Z, r25 WDTCSR = x; - 3fd2: 80 83 st Z, r24 + 3fac: 80 83 st Z, r24 } - 3fd4: 08 95 ret + 3fae: 08 95 ret -00003fd6 : - -void appStart() { - watchdogConfig(WATCHDOG_OFF); - 3fd6: 80 e0 ldi r24, 0x00 ; 0 - 3fd8: f8 df rcall .-16 ; 0x3fca - __asm__ __volatile__ ( - 3fda: ee 27 eor r30, r30 - 3fdc: ff 27 eor r31, r31 - 3fde: 09 94 ijmp - -00003fe0 : +00003fb0 : do getch(); while (--count); verifySpace(); } void verifySpace() { - if (getch() != CRC_EOP) appStart(); - 3fe0: e7 df rcall .-50 ; 0x3fb0 - 3fe2: 80 32 cpi r24, 0x20 ; 32 - 3fe4: 09 f0 breq .+2 ; 0x3fe8 - 3fe6: f7 df rcall .-18 ; 0x3fd6 + if (getch() != CRC_EOP) { + 3fb0: f1 df rcall .-30 ; 0x3f94 + 3fb2: 80 32 cpi r24, 0x20 ; 32 + 3fb4: 19 f0 breq .+6 ; 0x3fbc + watchdogConfig(WATCHDOG_16MS); // shorten WD timeout + 3fb6: 88 e0 ldi r24, 0x08 ; 8 + 3fb8: f5 df rcall .-22 ; 0x3fa4 + 3fba: ff cf rjmp .-2 ; 0x3fba + while (1) // and busy-loop so that WD causes + ; // a reset and app start. + } putch(STK_INSYNC); - 3fe8: 84 e1 ldi r24, 0x14 ; 20 + 3fbc: 84 e1 ldi r24, 0x14 ; 20 } - 3fea: da cf rjmp .-76 ; 0x3fa0 + 3fbe: e2 cf rjmp .-60 ; 0x3f84 -00003fec : +00003fc0 : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 3fec: 1f 93 push r17 - 3fee: 18 2f mov r17, r24 + 3fc0: 1f 93 push r17 + 3fc2: 18 2f mov r17, r24 do getch(); while (--count); - 3ff0: df df rcall .-66 ; 0x3fb0 - 3ff2: 11 50 subi r17, 0x01 ; 1 - 3ff4: e9 f7 brne .-6 ; 0x3ff0 + 3fc4: e7 df rcall .-50 ; 0x3f94 + 3fc6: 11 50 subi r17, 0x01 ; 1 + 3fc8: e9 f7 brne .-6 ; 0x3fc4 verifySpace(); - 3ff6: f4 df rcall .-24 ; 0x3fe0 + 3fca: f2 df rcall .-28 ; 0x3fb0 } - 3ff8: 1f 91 pop r17 - 3ffa: 08 95 ret + 3fcc: 1f 91 pop r17 + 3fce: 08 95 ret + +00003fd0 : + WDTCSR = _BV(WDCE) | _BV(WDE); + WDTCSR = x; +} + +void appStart() { + watchdogConfig(WATCHDOG_OFF); + 3fd0: 80 e0 ldi r24, 0x00 ; 0 + 3fd2: e8 df rcall .-48 ; 0x3fa4 + __asm__ __volatile__ ( + 3fd4: ee 27 eor r30, r30 + 3fd6: ff 27 eor r31, r31 + 3fd8: 09 94 ijmp diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.hex b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.hex index 77897e798..dcdbbb44f 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.hex @@ -1,35 +1,33 @@ -:103E0000112484B714BE81FFE6D085E08093810041 +:103E0000112484B714BE81FFE3D085E08093810044 :103E100082E08093C00088E18093C10086E08093B7 -:103E2000C20088E08093C4008EE0CFD0259A86E05F +:103E2000C20088E08093C4008EE0BCD0259A86E072 :103E300028E13EEF91E0309385002093840096BB0B -:103E4000B09BFECF1D9AA8958150A9F7DD24D3948D -:103E5000A5E0EA2EF1E1FF2EABD0813421F481E020 -:103E6000C5D083E020C0823411F484E103C08534DE -:103E700019F485E0BBD091C0853581F499D0082F25 -:103E800010E096D090E0982F8827802B912B880FF8 -:103E9000991F90930102809300027EC0863529F419 -:103EA00084E0A4D080E07CD078C0843609F04EC095 -:103EB00087D0E0910002F091010288E3E030F8073A -:103EC00018F483E087BFE895C0E0D1E071D0899312 -:103ED000809102028150809302028823B9F7E09119 -:103EE0000002F091010288E3E030F80718F083E067 -:103EF00087BFE89575D007B600FCFDCF4091000262 -:103F000050910102A0E0B1E02C9130E011968C912B -:103F1000119790E0982F8827822B932B1296FA0105 -:103F20000C01D7BEE89511244E5F5F4FF1E0A03839 -:103F3000BF0751F7E0910002F0910102E7BEE8955A -:103F400007B600FCFDCFF7BEE89527C08437B9F46B -:103F500037D046D0E0910002F09101023196F09303 -:103F60000102E09300023197E4918E2F19D08091E5 -:103F70000202815080930202882361F70EC08537C8 -:103F800039F42ED08EE10CD084E90AD086E08BCFB4 -:103F9000813511F488E019D023D080E101D05CCFC5 -:103FA000982F8091C00085FFFCCF9093C6000895A4 -:103FB000A8958091C00087FFFCCF8091C60008952E -:103FC000F7DFF6DF80930202F3CFE0E6F0E098E15E -:103FD00090838083089580E0F8DFEE27FF2709941F -:103FE000E7DF803209F0F7DF84E1DACF1F93182F83 -:0C3FF000DFDF1150E9F7F4DF1F910895A6 +:103E4000B09BFECF1D9AA8958150A9F79924939411 +:103E5000A5E0AA2EF1E1BF2E9DD0813421F481E0AE +:103E6000AFD083E01FC0823411F484E103C08534F5 +:103E700019F485E0A5D083C0853579F48BD0E82E80 +:103E8000FF2488D0082F10E0102F00270E291F29AB +:103E9000000F111F8DD0680172C0863529F484E0AF +:103EA0008FD080E06FD06BC0843609F042C072D0F2 +:103EB00071D0082F6FD080E0C81688E3D80620F4B0 +:103EC00083E0F60187BFE895C0E0D1E063D0899335 +:103ED0000C17E1F7F0E0CF16F8E3DF0620F083E0FF +:103EE000F60187BFE89564D007B600FCFDCFA601B8 +:103EF000A0E0B1E02C9130E011968C91119790E008 +:103F0000982F8827822B932B1296FA010C0197BECB +:103F1000E89511244E5F5F4FF1E0A038BF0751F7DD +:103F2000F601A7BEE89507B600FCFDCFB7BEE89541 +:103F300026C08437B1F42ED02DD0F82E2BD038D017 +:103F4000F601EF2C8F010F5F1F4F84911BD0EA9475 +:103F5000F801C1F70894C11CD11CFA94CF0CD11CF4 +:103F60000EC0853739F424D08EE10CD084E90AD014 +:103F700086E098CF813511F488E014D019D080E123 +:103F800001D06ACF982F8091C00085FFFCCF90931D +:103F9000C6000895A8958091C00087FFFCCF80914E +:103FA000C6000895E0E6F0E098E1908380830895EC +:103FB000F1DF803219F088E0F5DFFFCF84E1E2CF56 +:103FC0001F93182FE7DF1150E9F7F2DF1F910895D3 +:0A3FD00080E0E8DFEE27FF270994E8 :023FFE000104BC :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.lst b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.lst index 75180bc30..a70713ab5 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.lst @@ -3,27 +3,27 @@ optiboot_lilypad.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .text 000001fc 00003e00 00003e00 00000054 2**1 + 0 .text 000001da 00003e00 00003e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .version 00000002 00003ffe 00003ffe 00000250 2**0 + 1 .version 00000002 00003ffe 00003ffe 0000022e 2**0 CONTENTS, READONLY - 2 .debug_aranges 00000028 00000000 00000000 00000252 2**0 + 2 .debug_aranges 00000028 00000000 00000000 00000230 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_pubnames 0000006a 00000000 00000000 0000027a 2**0 + 3 .debug_pubnames 0000005f 00000000 00000000 00000258 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_info 00000285 00000000 00000000 000002e4 2**0 + 4 .debug_info 0000028c 00000000 00000000 000002b7 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 0000019f 00000000 00000000 00000569 2**0 + 5 .debug_abbrev 00000199 00000000 00000000 00000543 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_line 00000453 00000000 00000000 00000708 2**0 + 6 .debug_line 00000456 00000000 00000000 000006dc 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000090 00000000 00000000 00000b5c 2**2 + 7 .debug_frame 00000080 00000000 00000000 00000b34 2**2 CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000141 00000000 00000000 00000bec 2**0 + 8 .debug_str 00000149 00000000 00000000 00000bb4 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 000001e1 00000000 00000000 00000d2d 2**0 + 9 .debug_loc 0000027e 00000000 00000000 00000cfd 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000068 00000000 00000000 00000f0e 2**0 + 10 .debug_ranges 00000060 00000000 00000000 00000f7b 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: @@ -47,7 +47,7 @@ int main(void) { 3e04: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); 3e06: 81 ff sbrs r24, 1 - 3e08: e6 d0 rcall .+460 ; 0x3fd6 + 3e08: e3 d0 rcall .+454 ; 0x3fd0 #if LED_START_FLASHES > 0 // Set up Timer 1 for timeout counter @@ -77,7 +77,7 @@ int main(void) { // Set up watchdog to trigger after 500ms watchdogConfig(WATCHDOG_1S); 3e28: 8e e0 ldi r24, 0x0E ; 14 - 3e2a: cf d0 rcall .+414 ; 0x3fca + 3e2a: bc d0 rcall .+376 ; 0x3fa4 /* Set LED pin as output */ LED_DDR |= _BV(LED); @@ -111,8 +111,8 @@ void flash_led(uint8_t count) { #else LED_PIN |= _BV(LED); 3e44: 1d 9a sbi 0x03, 5 ; 3 - return getch(); } +#endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { @@ -132,8 +132,8 @@ void watchdogReset() { if(ch == STK_GET_PARAMETER) { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 3e4c: dd 24 eor r13, r13 - 3e4e: d3 94 inc r13 + 3e4c: 99 24 eor r9, r9 + 3e4e: 93 94 inc r9 __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); @@ -141,21 +141,21 @@ void watchdogReset() { // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); 3e50: a5 e0 ldi r26, 0x05 ; 5 - 3e52: ea 2e mov r14, r26 + 3e52: aa 2e mov r10, r26 boot_spm_busy_wait(); #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); 3e54: f1 e1 ldi r31, 0x11 ; 17 - 3e56: ff 2e mov r15, r31 + 3e56: bf 2e mov r11, r31 #endif /* Forever loop */ for (;;) { /* get character from UART */ ch = getch(); - 3e58: ab d0 rcall .+342 ; 0x3fb0 + 3e58: 9d d0 rcall .+314 ; 0x3f94 if(ch == STK_GET_PARAMETER) { 3e5a: 81 34 cpi r24, 0x41 ; 65 @@ -163,10 +163,10 @@ void watchdogReset() { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); 3e5e: 81 e0 ldi r24, 0x01 ; 1 - 3e60: c5 d0 rcall .+394 ; 0x3fec + 3e60: af d0 rcall .+350 ; 0x3fc0 putch(0x03); 3e62: 83 e0 ldi r24, 0x03 ; 3 - 3e64: 20 c0 rjmp .+64 ; 0x3ea6 + 3e64: 1f c0 rjmp .+62 ; 0x3ea4 } else if(ch == STK_SET_DEVICE) { 3e66: 82 34 cpi r24, 0x42 ; 66 @@ -182,71 +182,77 @@ void watchdogReset() { // SET DEVICE EXT is ignored getNch(5); 3e72: 85 e0 ldi r24, 0x05 ; 5 - 3e74: bb d0 rcall .+374 ; 0x3fec - 3e76: 91 c0 rjmp .+290 ; 0x3f9a + 3e74: a5 d0 rcall .+330 ; 0x3fc0 + 3e76: 83 c0 rjmp .+262 ; 0x3f7e } else if(ch == STK_LOAD_ADDRESS) { 3e78: 85 35 cpi r24, 0x55 ; 85 - 3e7a: 81 f4 brne .+32 ; 0x3e9c + 3e7a: 79 f4 brne .+30 ; 0x3e9a // LOAD ADDRESS uint16_t newAddress; newAddress = getch(); - 3e7c: 99 d0 rcall .+306 ; 0x3fb0 + 3e7c: 8b d0 rcall .+278 ; 0x3f94 newAddress = (newAddress & 0xff) | (getch() << 8); - 3e7e: 08 2f mov r16, r24 - 3e80: 10 e0 ldi r17, 0x00 ; 0 - 3e82: 96 d0 rcall .+300 ; 0x3fb0 - 3e84: 90 e0 ldi r25, 0x00 ; 0 - 3e86: 98 2f mov r25, r24 - 3e88: 88 27 eor r24, r24 - 3e8a: 80 2b or r24, r16 - 3e8c: 91 2b or r25, r17 + 3e7e: e8 2e mov r14, r24 + 3e80: ff 24 eor r15, r15 + 3e82: 88 d0 rcall .+272 ; 0x3f94 + 3e84: 08 2f mov r16, r24 + 3e86: 10 e0 ldi r17, 0x00 ; 0 + 3e88: 10 2f mov r17, r16 + 3e8a: 00 27 eor r16, r16 + 3e8c: 0e 29 or r16, r14 + 3e8e: 1f 29 or r17, r15 #ifdef RAMPZ // Transfer top bit to RAMPZ RAMPZ = (newAddress & 0x8000) ? 1 : 0; #endif newAddress += newAddress; // Convert from word address to byte address - 3e8e: 88 0f add r24, r24 - 3e90: 99 1f adc r25, r25 + 3e90: 00 0f add r16, r16 + 3e92: 11 1f adc r17, r17 address = newAddress; - 3e92: 90 93 01 02 sts 0x0201, r25 - 3e96: 80 93 00 02 sts 0x0200, r24 - 3e9a: 7e c0 rjmp .+252 ; 0x3f98 verifySpace(); + 3e94: 8d d0 rcall .+282 ; 0x3fb0 + 3e96: 68 01 movw r12, r16 + 3e98: 72 c0 rjmp .+228 ; 0x3f7e } else if(ch == STK_UNIVERSAL) { - 3e9c: 86 35 cpi r24, 0x56 ; 86 - 3e9e: 29 f4 brne .+10 ; 0x3eaa + 3e9a: 86 35 cpi r24, 0x56 ; 86 + 3e9c: 29 f4 brne .+10 ; 0x3ea8 // UNIVERSAL command is ignored getNch(4); - 3ea0: 84 e0 ldi r24, 0x04 ; 4 - 3ea2: a4 d0 rcall .+328 ; 0x3fec + 3e9e: 84 e0 ldi r24, 0x04 ; 4 + 3ea0: 8f d0 rcall .+286 ; 0x3fc0 putch(0x00); - 3ea4: 80 e0 ldi r24, 0x00 ; 0 - 3ea6: 7c d0 rcall .+248 ; 0x3fa0 - 3ea8: 78 c0 rjmp .+240 ; 0x3f9a + 3ea2: 80 e0 ldi r24, 0x00 ; 0 + 3ea4: 6f d0 rcall .+222 ; 0x3f84 + 3ea6: 6b c0 rjmp .+214 ; 0x3f7e } /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { - 3eaa: 84 36 cpi r24, 0x64 ; 100 - 3eac: 09 f0 breq .+2 ; 0x3eb0 - 3eae: 4e c0 rjmp .+156 ; 0x3f4c + 3ea8: 84 36 cpi r24, 0x64 ; 100 + 3eaa: 09 f0 breq .+2 ; 0x3eae + 3eac: 42 c0 rjmp .+132 ; 0x3f32 // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t *bufPtr; uint16_t addrPtr; - getLen(); - 3eb0: 87 d0 rcall .+270 ; 0x3fc0 + getch(); /* getlen() */ + 3eae: 72 d0 rcall .+228 ; 0x3f94 + length = getch(); + 3eb0: 71 d0 rcall .+226 ; 0x3f94 + 3eb2: 08 2f mov r16, r24 + getch(); + 3eb4: 6f d0 rcall .+222 ; 0x3f94 // If we are in RWW section, immediately start page erase if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 3eb2: e0 91 00 02 lds r30, 0x0200 - 3eb6: f0 91 01 02 lds r31, 0x0201 + 3eb6: 80 e0 ldi r24, 0x00 ; 0 + 3eb8: c8 16 cp r12, r24 3eba: 88 e3 ldi r24, 0x38 ; 56 - 3ebc: e0 30 cpi r30, 0x00 ; 0 - 3ebe: f8 07 cpc r31, r24 - 3ec0: 18 f4 brcc .+6 ; 0x3ec8 - 3ec2: 83 e0 ldi r24, 0x03 ; 3 + 3ebc: d8 06 cpc r13, r24 + 3ebe: 20 f4 brcc .+8 ; 0x3ec8 + 3ec0: 83 e0 ldi r24, 0x03 ; 3 + 3ec2: f6 01 movw r30, r12 3ec4: 87 bf out 0x37, r24 ; 55 3ec6: e8 95 spm 3ec8: c0 e0 ldi r28, 0x00 ; 0 @@ -255,302 +261,301 @@ void watchdogReset() { // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); - 3ecc: 71 d0 rcall .+226 ; 0x3fb0 + 3ecc: 63 d0 rcall .+198 ; 0x3f94 3ece: 89 93 st Y+, r24 while (--length); - 3ed0: 80 91 02 02 lds r24, 0x0202 - 3ed4: 81 50 subi r24, 0x01 ; 1 - 3ed6: 80 93 02 02 sts 0x0202, r24 - 3eda: 88 23 and r24, r24 - 3edc: b9 f7 brne .-18 ; 0x3ecc + 3ed0: 0c 17 cp r16, r28 + 3ed2: e1 f7 brne .-8 ; 0x3ecc // If we are in NRWW section, page erase has to be delayed until now. // Todo: Take RAMPZ into account if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 3ede: e0 91 00 02 lds r30, 0x0200 - 3ee2: f0 91 01 02 lds r31, 0x0201 - 3ee6: 88 e3 ldi r24, 0x38 ; 56 - 3ee8: e0 30 cpi r30, 0x00 ; 0 - 3eea: f8 07 cpc r31, r24 - 3eec: 18 f0 brcs .+6 ; 0x3ef4 - 3eee: 83 e0 ldi r24, 0x03 ; 3 - 3ef0: 87 bf out 0x37, r24 ; 55 - 3ef2: e8 95 spm + 3ed4: f0 e0 ldi r31, 0x00 ; 0 + 3ed6: cf 16 cp r12, r31 + 3ed8: f8 e3 ldi r31, 0x38 ; 56 + 3eda: df 06 cpc r13, r31 + 3edc: 20 f0 brcs .+8 ; 0x3ee6 + 3ede: 83 e0 ldi r24, 0x03 ; 3 + 3ee0: f6 01 movw r30, r12 + 3ee2: 87 bf out 0x37, r24 ; 55 + 3ee4: e8 95 spm // Read command terminator, start reply verifySpace(); - 3ef4: 75 d0 rcall .+234 ; 0x3fe0 + 3ee6: 64 d0 rcall .+200 ; 0x3fb0 // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); - 3ef6: 07 b6 in r0, 0x37 ; 55 - 3ef8: 00 fc sbrc r0, 0 - 3efa: fd cf rjmp .-6 ; 0x3ef6 - } -#endif - - // Copy buffer into programming buffer + 3ee8: 07 b6 in r0, 0x37 ; 55 + 3eea: 00 fc sbrc r0, 0 + 3eec: fd cf rjmp .-6 ; 0x3ee8 + 3eee: a6 01 movw r20, r12 + 3ef0: a0 e0 ldi r26, 0x00 ; 0 + 3ef2: b1 e0 ldi r27, 0x01 ; 1 bufPtr = buff; addrPtr = (uint16_t)(void*)address; - 3efc: 40 91 00 02 lds r20, 0x0200 - 3f00: 50 91 01 02 lds r21, 0x0201 - 3f04: a0 e0 ldi r26, 0x00 ; 0 - 3f06: b1 e0 ldi r27, 0x01 ; 1 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; - 3f08: 2c 91 ld r18, X - 3f0a: 30 e0 ldi r19, 0x00 ; 0 + 3ef4: 2c 91 ld r18, X + 3ef6: 30 e0 ldi r19, 0x00 ; 0 a |= (*bufPtr++) << 8; - 3f0c: 11 96 adiw r26, 0x01 ; 1 - 3f0e: 8c 91 ld r24, X - 3f10: 11 97 sbiw r26, 0x01 ; 1 - 3f12: 90 e0 ldi r25, 0x00 ; 0 - 3f14: 98 2f mov r25, r24 - 3f16: 88 27 eor r24, r24 - 3f18: 82 2b or r24, r18 - 3f1a: 93 2b or r25, r19 + 3ef8: 11 96 adiw r26, 0x01 ; 1 + 3efa: 8c 91 ld r24, X + 3efc: 11 97 sbiw r26, 0x01 ; 1 + 3efe: 90 e0 ldi r25, 0x00 ; 0 + 3f00: 98 2f mov r25, r24 + 3f02: 88 27 eor r24, r24 + 3f04: 82 2b or r24, r18 + 3f06: 93 2b or r25, r19 #define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) #define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif /* main program starts here */ int main(void) { - 3f1c: 12 96 adiw r26, 0x02 ; 2 + 3f08: 12 96 adiw r26, 0x02 ; 2 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; a |= (*bufPtr++) << 8; __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - 3f1e: fa 01 movw r30, r20 - 3f20: 0c 01 movw r0, r24 - 3f22: d7 be out 0x37, r13 ; 55 - 3f24: e8 95 spm - 3f26: 11 24 eor r1, r1 + 3f0a: fa 01 movw r30, r20 + 3f0c: 0c 01 movw r0, r24 + 3f0e: 97 be out 0x37, r9 ; 55 + 3f10: e8 95 spm + 3f12: 11 24 eor r1, r1 addrPtr += 2; - 3f28: 4e 5f subi r20, 0xFE ; 254 - 3f2a: 5f 4f sbci r21, 0xFF ; 255 + 3f14: 4e 5f subi r20, 0xFE ; 254 + 3f16: 5f 4f sbci r21, 0xFF ; 255 } while (--ch); - 3f2c: f1 e0 ldi r31, 0x01 ; 1 - 3f2e: a0 38 cpi r26, 0x80 ; 128 - 3f30: bf 07 cpc r27, r31 - 3f32: 51 f7 brne .-44 ; 0x3f08 + 3f18: f1 e0 ldi r31, 0x01 ; 1 + 3f1a: a0 38 cpi r26, 0x80 ; 128 + 3f1c: bf 07 cpc r27, r31 + 3f1e: 51 f7 brne .-44 ; 0x3ef4 // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); - 3f34: e0 91 00 02 lds r30, 0x0200 - 3f38: f0 91 01 02 lds r31, 0x0201 - 3f3c: e7 be out 0x37, r14 ; 55 - 3f3e: e8 95 spm + 3f20: f6 01 movw r30, r12 + 3f22: a7 be out 0x37, r10 ; 55 + 3f24: e8 95 spm boot_spm_busy_wait(); - 3f40: 07 b6 in r0, 0x37 ; 55 - 3f42: 00 fc sbrc r0, 0 - 3f44: fd cf rjmp .-6 ; 0x3f40 + 3f26: 07 b6 in r0, 0x37 ; 55 + 3f28: 00 fc sbrc r0, 0 + 3f2a: fd cf rjmp .-6 ; 0x3f26 #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 3f46: f7 be out 0x37, r15 ; 55 - 3f48: e8 95 spm - 3f4a: 27 c0 rjmp .+78 ; 0x3f9a + 3f2c: b7 be out 0x37, r11 ; 55 + 3f2e: e8 95 spm + 3f30: 26 c0 rjmp .+76 ; 0x3f7e #endif } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { - 3f4c: 84 37 cpi r24, 0x74 ; 116 - 3f4e: b9 f4 brne .+46 ; 0x3f7e + 3f32: 84 37 cpi r24, 0x74 ; 116 + 3f34: b1 f4 brne .+44 ; 0x3f62 // READ PAGE - we only read flash - getLen(); - 3f50: 37 d0 rcall .+110 ; 0x3fc0 + getch(); /* getlen() */ + 3f36: 2e d0 rcall .+92 ; 0x3f94 + length = getch(); + 3f38: 2d d0 rcall .+90 ; 0x3f94 + 3f3a: f8 2e mov r15, r24 + getch(); + 3f3c: 2b d0 rcall .+86 ; 0x3f94 + verifySpace(); - 3f52: 46 d0 rcall .+140 ; 0x3fe0 + 3f3e: 38 d0 rcall .+112 ; 0x3fb0 + 3f40: f6 01 movw r30, r12 + 3f42: ef 2c mov r14, r15 putch(result); address++; } while (--length); #else do putch(pgm_read_byte_near(address++)); - 3f54: e0 91 00 02 lds r30, 0x0200 - 3f58: f0 91 01 02 lds r31, 0x0201 - 3f5c: 31 96 adiw r30, 0x01 ; 1 - 3f5e: f0 93 01 02 sts 0x0201, r31 - 3f62: e0 93 00 02 sts 0x0200, r30 - 3f66: 31 97 sbiw r30, 0x01 ; 1 - 3f68: e4 91 lpm r30, Z+ - 3f6a: 8e 2f mov r24, r30 - 3f6c: 19 d0 rcall .+50 ; 0x3fa0 + 3f44: 8f 01 movw r16, r30 + 3f46: 0f 5f subi r16, 0xFF ; 255 + 3f48: 1f 4f sbci r17, 0xFF ; 255 + 3f4a: 84 91 lpm r24, Z+ + 3f4c: 1b d0 rcall .+54 ; 0x3f84 while (--length); - 3f6e: 80 91 02 02 lds r24, 0x0202 - 3f72: 81 50 subi r24, 0x01 ; 1 - 3f74: 80 93 02 02 sts 0x0202, r24 - 3f78: 88 23 and r24, r24 - 3f7a: 61 f7 brne .-40 ; 0x3f54 - 3f7c: 0e c0 rjmp .+28 ; 0x3f9a + 3f4e: ea 94 dec r14 + 3f50: f8 01 movw r30, r16 + 3f52: c1 f7 brne .-16 ; 0x3f44 +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) +#endif + +/* main program starts here */ +int main(void) { + 3f54: 08 94 sec + 3f56: c1 1c adc r12, r1 + 3f58: d1 1c adc r13, r1 + 3f5a: fa 94 dec r15 + 3f5c: cf 0c add r12, r15 + 3f5e: d1 1c adc r13, r1 + 3f60: 0e c0 rjmp .+28 ; 0x3f7e #endif #endif } /* Get device signature bytes */ else if(ch == STK_READ_SIGN) { - 3f7e: 85 37 cpi r24, 0x75 ; 117 - 3f80: 39 f4 brne .+14 ; 0x3f90 + 3f62: 85 37 cpi r24, 0x75 ; 117 + 3f64: 39 f4 brne .+14 ; 0x3f74 // READ SIGN - return what Avrdude wants to hear verifySpace(); - 3f82: 2e d0 rcall .+92 ; 0x3fe0 + 3f66: 24 d0 rcall .+72 ; 0x3fb0 putch(SIGNATURE_0); - 3f84: 8e e1 ldi r24, 0x1E ; 30 - 3f86: 0c d0 rcall .+24 ; 0x3fa0 + 3f68: 8e e1 ldi r24, 0x1E ; 30 + 3f6a: 0c d0 rcall .+24 ; 0x3f84 putch(SIGNATURE_1); - 3f88: 84 e9 ldi r24, 0x94 ; 148 - 3f8a: 0a d0 rcall .+20 ; 0x3fa0 + 3f6c: 84 e9 ldi r24, 0x94 ; 148 + 3f6e: 0a d0 rcall .+20 ; 0x3f84 putch(SIGNATURE_2); - 3f8c: 86 e0 ldi r24, 0x06 ; 6 - 3f8e: 8b cf rjmp .-234 ; 0x3ea6 + 3f70: 86 e0 ldi r24, 0x06 ; 6 + 3f72: 98 cf rjmp .-208 ; 0x3ea4 } else if (ch == 'Q') { - 3f90: 81 35 cpi r24, 0x51 ; 81 - 3f92: 11 f4 brne .+4 ; 0x3f98 + 3f74: 81 35 cpi r24, 0x51 ; 81 + 3f76: 11 f4 brne .+4 ; 0x3f7c // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); - 3f94: 88 e0 ldi r24, 0x08 ; 8 - 3f96: 19 d0 rcall .+50 ; 0x3fca + 3f78: 88 e0 ldi r24, 0x08 ; 8 + 3f7a: 14 d0 rcall .+40 ; 0x3fa4 verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 3f98: 23 d0 rcall .+70 ; 0x3fe0 + 3f7c: 19 d0 rcall .+50 ; 0x3fb0 } putch(STK_OK); - 3f9a: 80 e1 ldi r24, 0x10 ; 16 - 3f9c: 01 d0 rcall .+2 ; 0x3fa0 - 3f9e: 5c cf rjmp .-328 ; 0x3e58 + 3f7e: 80 e1 ldi r24, 0x10 ; 16 + 3f80: 01 d0 rcall .+2 ; 0x3f84 + 3f82: 6a cf rjmp .-300 ; 0x3e58 -00003fa0 : +00003f84 : } } void putch(char ch) { - 3fa0: 98 2f mov r25, r24 + 3f84: 98 2f mov r25, r24 #ifndef SOFT_UART while (!(UCSR0A & _BV(UDRE0))); - 3fa2: 80 91 c0 00 lds r24, 0x00C0 - 3fa6: 85 ff sbrs r24, 5 - 3fa8: fc cf rjmp .-8 ; 0x3fa2 + 3f86: 80 91 c0 00 lds r24, 0x00C0 + 3f8a: 85 ff sbrs r24, 5 + 3f8c: fc cf rjmp .-8 ; 0x3f86 UDR0 = ch; - 3faa: 90 93 c6 00 sts 0x00C6, r25 + 3f8e: 90 93 c6 00 sts 0x00C6, r25 [uartBit] "I" (UART_TX_BIT) : "r25" ); #endif } - 3fae: 08 95 ret + 3f92: 08 95 ret -00003fb0 : - return getch(); +00003f94 : } +#endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 3fb0: a8 95 wdr + 3f94: a8 95 wdr [uartBit] "I" (UART_RX_BIT) : "r25" ); #else while(!(UCSR0A & _BV(RXC0))); - 3fb2: 80 91 c0 00 lds r24, 0x00C0 - 3fb6: 87 ff sbrs r24, 7 - 3fb8: fc cf rjmp .-8 ; 0x3fb2 + 3f96: 80 91 c0 00 lds r24, 0x00C0 + 3f9a: 87 ff sbrs r24, 7 + 3f9c: fc cf rjmp .-8 ; 0x3f96 ch = UDR0; - 3fba: 80 91 c6 00 lds r24, 0x00C6 + 3f9e: 80 91 c6 00 lds r24, 0x00C6 LED_PIN |= _BV(LED); #endif #endif return ch; } - 3fbe: 08 95 ret + 3fa2: 08 95 ret -00003fc0 : - } while (--count); -} -#endif - -uint8_t getLen() { - getch(); - 3fc0: f7 df rcall .-18 ; 0x3fb0 - length = getch(); - 3fc2: f6 df rcall .-20 ; 0x3fb0 - 3fc4: 80 93 02 02 sts 0x0202, r24 - return getch(); -} - 3fc8: f3 cf rjmp .-26 ; 0x3fb0 - -00003fca : +00003fa4 : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 3fca: e0 e6 ldi r30, 0x60 ; 96 - 3fcc: f0 e0 ldi r31, 0x00 ; 0 - 3fce: 98 e1 ldi r25, 0x18 ; 24 - 3fd0: 90 83 st Z, r25 + 3fa4: e0 e6 ldi r30, 0x60 ; 96 + 3fa6: f0 e0 ldi r31, 0x00 ; 0 + 3fa8: 98 e1 ldi r25, 0x18 ; 24 + 3faa: 90 83 st Z, r25 WDTCSR = x; - 3fd2: 80 83 st Z, r24 + 3fac: 80 83 st Z, r24 } - 3fd4: 08 95 ret + 3fae: 08 95 ret -00003fd6 : - -void appStart() { - watchdogConfig(WATCHDOG_OFF); - 3fd6: 80 e0 ldi r24, 0x00 ; 0 - 3fd8: f8 df rcall .-16 ; 0x3fca - __asm__ __volatile__ ( - 3fda: ee 27 eor r30, r30 - 3fdc: ff 27 eor r31, r31 - 3fde: 09 94 ijmp - -00003fe0 : +00003fb0 : do getch(); while (--count); verifySpace(); } void verifySpace() { - if (getch() != CRC_EOP) appStart(); - 3fe0: e7 df rcall .-50 ; 0x3fb0 - 3fe2: 80 32 cpi r24, 0x20 ; 32 - 3fe4: 09 f0 breq .+2 ; 0x3fe8 - 3fe6: f7 df rcall .-18 ; 0x3fd6 + if (getch() != CRC_EOP) { + 3fb0: f1 df rcall .-30 ; 0x3f94 + 3fb2: 80 32 cpi r24, 0x20 ; 32 + 3fb4: 19 f0 breq .+6 ; 0x3fbc + watchdogConfig(WATCHDOG_16MS); // shorten WD timeout + 3fb6: 88 e0 ldi r24, 0x08 ; 8 + 3fb8: f5 df rcall .-22 ; 0x3fa4 + 3fba: ff cf rjmp .-2 ; 0x3fba + while (1) // and busy-loop so that WD causes + ; // a reset and app start. + } putch(STK_INSYNC); - 3fe8: 84 e1 ldi r24, 0x14 ; 20 + 3fbc: 84 e1 ldi r24, 0x14 ; 20 } - 3fea: da cf rjmp .-76 ; 0x3fa0 + 3fbe: e2 cf rjmp .-60 ; 0x3f84 -00003fec : +00003fc0 : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 3fec: 1f 93 push r17 - 3fee: 18 2f mov r17, r24 + 3fc0: 1f 93 push r17 + 3fc2: 18 2f mov r17, r24 do getch(); while (--count); - 3ff0: df df rcall .-66 ; 0x3fb0 - 3ff2: 11 50 subi r17, 0x01 ; 1 - 3ff4: e9 f7 brne .-6 ; 0x3ff0 + 3fc4: e7 df rcall .-50 ; 0x3f94 + 3fc6: 11 50 subi r17, 0x01 ; 1 + 3fc8: e9 f7 brne .-6 ; 0x3fc4 verifySpace(); - 3ff6: f4 df rcall .-24 ; 0x3fe0 + 3fca: f2 df rcall .-28 ; 0x3fb0 } - 3ff8: 1f 91 pop r17 - 3ffa: 08 95 ret + 3fcc: 1f 91 pop r17 + 3fce: 08 95 ret + +00003fd0 : + WDTCSR = _BV(WDCE) | _BV(WDE); + WDTCSR = x; +} + +void appStart() { + watchdogConfig(WATCHDOG_OFF); + 3fd0: 80 e0 ldi r24, 0x00 ; 0 + 3fd2: e8 df rcall .-48 ; 0x3fa4 + __asm__ __volatile__ ( + 3fd4: ee 27 eor r30, r30 + 3fd6: ff 27 eor r31, r31 + 3fd8: 09 94 ijmp diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.hex b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.hex index 77897e798..dcdbbb44f 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.hex @@ -1,35 +1,33 @@ -:103E0000112484B714BE81FFE6D085E08093810041 +:103E0000112484B714BE81FFE3D085E08093810044 :103E100082E08093C00088E18093C10086E08093B7 -:103E2000C20088E08093C4008EE0CFD0259A86E05F +:103E2000C20088E08093C4008EE0BCD0259A86E072 :103E300028E13EEF91E0309385002093840096BB0B -:103E4000B09BFECF1D9AA8958150A9F7DD24D3948D -:103E5000A5E0EA2EF1E1FF2EABD0813421F481E020 -:103E6000C5D083E020C0823411F484E103C08534DE -:103E700019F485E0BBD091C0853581F499D0082F25 -:103E800010E096D090E0982F8827802B912B880FF8 -:103E9000991F90930102809300027EC0863529F419 -:103EA00084E0A4D080E07CD078C0843609F04EC095 -:103EB00087D0E0910002F091010288E3E030F8073A -:103EC00018F483E087BFE895C0E0D1E071D0899312 -:103ED000809102028150809302028823B9F7E09119 -:103EE0000002F091010288E3E030F80718F083E067 -:103EF00087BFE89575D007B600FCFDCF4091000262 -:103F000050910102A0E0B1E02C9130E011968C912B -:103F1000119790E0982F8827822B932B1296FA0105 -:103F20000C01D7BEE89511244E5F5F4FF1E0A03839 -:103F3000BF0751F7E0910002F0910102E7BEE8955A -:103F400007B600FCFDCFF7BEE89527C08437B9F46B -:103F500037D046D0E0910002F09101023196F09303 -:103F60000102E09300023197E4918E2F19D08091E5 -:103F70000202815080930202882361F70EC08537C8 -:103F800039F42ED08EE10CD084E90AD086E08BCFB4 -:103F9000813511F488E019D023D080E101D05CCFC5 -:103FA000982F8091C00085FFFCCF9093C6000895A4 -:103FB000A8958091C00087FFFCCF8091C60008952E -:103FC000F7DFF6DF80930202F3CFE0E6F0E098E15E -:103FD00090838083089580E0F8DFEE27FF2709941F -:103FE000E7DF803209F0F7DF84E1DACF1F93182F83 -:0C3FF000DFDF1150E9F7F4DF1F910895A6 +:103E4000B09BFECF1D9AA8958150A9F79924939411 +:103E5000A5E0AA2EF1E1BF2E9DD0813421F481E0AE +:103E6000AFD083E01FC0823411F484E103C08534F5 +:103E700019F485E0A5D083C0853579F48BD0E82E80 +:103E8000FF2488D0082F10E0102F00270E291F29AB +:103E9000000F111F8DD0680172C0863529F484E0AF +:103EA0008FD080E06FD06BC0843609F042C072D0F2 +:103EB00071D0082F6FD080E0C81688E3D80620F4B0 +:103EC00083E0F60187BFE895C0E0D1E063D0899335 +:103ED0000C17E1F7F0E0CF16F8E3DF0620F083E0FF +:103EE000F60187BFE89564D007B600FCFDCFA601B8 +:103EF000A0E0B1E02C9130E011968C91119790E008 +:103F0000982F8827822B932B1296FA010C0197BECB +:103F1000E89511244E5F5F4FF1E0A038BF0751F7DD +:103F2000F601A7BEE89507B600FCFDCFB7BEE89541 +:103F300026C08437B1F42ED02DD0F82E2BD038D017 +:103F4000F601EF2C8F010F5F1F4F84911BD0EA9475 +:103F5000F801C1F70894C11CD11CFA94CF0CD11CF4 +:103F60000EC0853739F424D08EE10CD084E90AD014 +:103F700086E098CF813511F488E014D019D080E123 +:103F800001D06ACF982F8091C00085FFFCCF90931D +:103F9000C6000895A8958091C00087FFFCCF80914E +:103FA000C6000895E0E6F0E098E1908380830895EC +:103FB000F1DF803219F088E0F5DFFFCF84E1E2CF56 +:103FC0001F93182FE7DF1150E9F7F2DF1F910895D3 +:0A3FD00080E0E8DFEE27FF270994E8 :023FFE000104BC :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.lst b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.lst index 48c2778ac..267683838 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.lst @@ -3,27 +3,27 @@ optiboot_lilypad_resonator.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .text 000001fc 00003e00 00003e00 00000054 2**1 + 0 .text 000001da 00003e00 00003e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .version 00000002 00003ffe 00003ffe 00000250 2**0 + 1 .version 00000002 00003ffe 00003ffe 0000022e 2**0 CONTENTS, READONLY - 2 .debug_aranges 00000028 00000000 00000000 00000252 2**0 + 2 .debug_aranges 00000028 00000000 00000000 00000230 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_pubnames 0000006a 00000000 00000000 0000027a 2**0 + 3 .debug_pubnames 0000005f 00000000 00000000 00000258 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_info 00000285 00000000 00000000 000002e4 2**0 + 4 .debug_info 0000028c 00000000 00000000 000002b7 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 0000019f 00000000 00000000 00000569 2**0 + 5 .debug_abbrev 00000199 00000000 00000000 00000543 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_line 00000453 00000000 00000000 00000708 2**0 + 6 .debug_line 00000456 00000000 00000000 000006dc 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000090 00000000 00000000 00000b5c 2**2 + 7 .debug_frame 00000080 00000000 00000000 00000b34 2**2 CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000141 00000000 00000000 00000bec 2**0 + 8 .debug_str 00000149 00000000 00000000 00000bb4 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 000001e1 00000000 00000000 00000d2d 2**0 + 9 .debug_loc 0000027e 00000000 00000000 00000cfd 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000068 00000000 00000000 00000f0e 2**0 + 10 .debug_ranges 00000060 00000000 00000000 00000f7b 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: @@ -47,7 +47,7 @@ int main(void) { 3e04: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); 3e06: 81 ff sbrs r24, 1 - 3e08: e6 d0 rcall .+460 ; 0x3fd6 + 3e08: e3 d0 rcall .+454 ; 0x3fd0 #if LED_START_FLASHES > 0 // Set up Timer 1 for timeout counter @@ -77,7 +77,7 @@ int main(void) { // Set up watchdog to trigger after 500ms watchdogConfig(WATCHDOG_1S); 3e28: 8e e0 ldi r24, 0x0E ; 14 - 3e2a: cf d0 rcall .+414 ; 0x3fca + 3e2a: bc d0 rcall .+376 ; 0x3fa4 /* Set LED pin as output */ LED_DDR |= _BV(LED); @@ -111,8 +111,8 @@ void flash_led(uint8_t count) { #else LED_PIN |= _BV(LED); 3e44: 1d 9a sbi 0x03, 5 ; 3 - return getch(); } +#endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { @@ -132,8 +132,8 @@ void watchdogReset() { if(ch == STK_GET_PARAMETER) { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 3e4c: dd 24 eor r13, r13 - 3e4e: d3 94 inc r13 + 3e4c: 99 24 eor r9, r9 + 3e4e: 93 94 inc r9 __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); @@ -141,21 +141,21 @@ void watchdogReset() { // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); 3e50: a5 e0 ldi r26, 0x05 ; 5 - 3e52: ea 2e mov r14, r26 + 3e52: aa 2e mov r10, r26 boot_spm_busy_wait(); #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); 3e54: f1 e1 ldi r31, 0x11 ; 17 - 3e56: ff 2e mov r15, r31 + 3e56: bf 2e mov r11, r31 #endif /* Forever loop */ for (;;) { /* get character from UART */ ch = getch(); - 3e58: ab d0 rcall .+342 ; 0x3fb0 + 3e58: 9d d0 rcall .+314 ; 0x3f94 if(ch == STK_GET_PARAMETER) { 3e5a: 81 34 cpi r24, 0x41 ; 65 @@ -163,10 +163,10 @@ void watchdogReset() { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); 3e5e: 81 e0 ldi r24, 0x01 ; 1 - 3e60: c5 d0 rcall .+394 ; 0x3fec + 3e60: af d0 rcall .+350 ; 0x3fc0 putch(0x03); 3e62: 83 e0 ldi r24, 0x03 ; 3 - 3e64: 20 c0 rjmp .+64 ; 0x3ea6 + 3e64: 1f c0 rjmp .+62 ; 0x3ea4 } else if(ch == STK_SET_DEVICE) { 3e66: 82 34 cpi r24, 0x42 ; 66 @@ -182,71 +182,77 @@ void watchdogReset() { // SET DEVICE EXT is ignored getNch(5); 3e72: 85 e0 ldi r24, 0x05 ; 5 - 3e74: bb d0 rcall .+374 ; 0x3fec - 3e76: 91 c0 rjmp .+290 ; 0x3f9a + 3e74: a5 d0 rcall .+330 ; 0x3fc0 + 3e76: 83 c0 rjmp .+262 ; 0x3f7e } else if(ch == STK_LOAD_ADDRESS) { 3e78: 85 35 cpi r24, 0x55 ; 85 - 3e7a: 81 f4 brne .+32 ; 0x3e9c + 3e7a: 79 f4 brne .+30 ; 0x3e9a // LOAD ADDRESS uint16_t newAddress; newAddress = getch(); - 3e7c: 99 d0 rcall .+306 ; 0x3fb0 + 3e7c: 8b d0 rcall .+278 ; 0x3f94 newAddress = (newAddress & 0xff) | (getch() << 8); - 3e7e: 08 2f mov r16, r24 - 3e80: 10 e0 ldi r17, 0x00 ; 0 - 3e82: 96 d0 rcall .+300 ; 0x3fb0 - 3e84: 90 e0 ldi r25, 0x00 ; 0 - 3e86: 98 2f mov r25, r24 - 3e88: 88 27 eor r24, r24 - 3e8a: 80 2b or r24, r16 - 3e8c: 91 2b or r25, r17 + 3e7e: e8 2e mov r14, r24 + 3e80: ff 24 eor r15, r15 + 3e82: 88 d0 rcall .+272 ; 0x3f94 + 3e84: 08 2f mov r16, r24 + 3e86: 10 e0 ldi r17, 0x00 ; 0 + 3e88: 10 2f mov r17, r16 + 3e8a: 00 27 eor r16, r16 + 3e8c: 0e 29 or r16, r14 + 3e8e: 1f 29 or r17, r15 #ifdef RAMPZ // Transfer top bit to RAMPZ RAMPZ = (newAddress & 0x8000) ? 1 : 0; #endif newAddress += newAddress; // Convert from word address to byte address - 3e8e: 88 0f add r24, r24 - 3e90: 99 1f adc r25, r25 + 3e90: 00 0f add r16, r16 + 3e92: 11 1f adc r17, r17 address = newAddress; - 3e92: 90 93 01 02 sts 0x0201, r25 - 3e96: 80 93 00 02 sts 0x0200, r24 - 3e9a: 7e c0 rjmp .+252 ; 0x3f98 verifySpace(); + 3e94: 8d d0 rcall .+282 ; 0x3fb0 + 3e96: 68 01 movw r12, r16 + 3e98: 72 c0 rjmp .+228 ; 0x3f7e } else if(ch == STK_UNIVERSAL) { - 3e9c: 86 35 cpi r24, 0x56 ; 86 - 3e9e: 29 f4 brne .+10 ; 0x3eaa + 3e9a: 86 35 cpi r24, 0x56 ; 86 + 3e9c: 29 f4 brne .+10 ; 0x3ea8 // UNIVERSAL command is ignored getNch(4); - 3ea0: 84 e0 ldi r24, 0x04 ; 4 - 3ea2: a4 d0 rcall .+328 ; 0x3fec + 3e9e: 84 e0 ldi r24, 0x04 ; 4 + 3ea0: 8f d0 rcall .+286 ; 0x3fc0 putch(0x00); - 3ea4: 80 e0 ldi r24, 0x00 ; 0 - 3ea6: 7c d0 rcall .+248 ; 0x3fa0 - 3ea8: 78 c0 rjmp .+240 ; 0x3f9a + 3ea2: 80 e0 ldi r24, 0x00 ; 0 + 3ea4: 6f d0 rcall .+222 ; 0x3f84 + 3ea6: 6b c0 rjmp .+214 ; 0x3f7e } /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { - 3eaa: 84 36 cpi r24, 0x64 ; 100 - 3eac: 09 f0 breq .+2 ; 0x3eb0 - 3eae: 4e c0 rjmp .+156 ; 0x3f4c + 3ea8: 84 36 cpi r24, 0x64 ; 100 + 3eaa: 09 f0 breq .+2 ; 0x3eae + 3eac: 42 c0 rjmp .+132 ; 0x3f32 // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t *bufPtr; uint16_t addrPtr; - getLen(); - 3eb0: 87 d0 rcall .+270 ; 0x3fc0 + getch(); /* getlen() */ + 3eae: 72 d0 rcall .+228 ; 0x3f94 + length = getch(); + 3eb0: 71 d0 rcall .+226 ; 0x3f94 + 3eb2: 08 2f mov r16, r24 + getch(); + 3eb4: 6f d0 rcall .+222 ; 0x3f94 // If we are in RWW section, immediately start page erase if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 3eb2: e0 91 00 02 lds r30, 0x0200 - 3eb6: f0 91 01 02 lds r31, 0x0201 + 3eb6: 80 e0 ldi r24, 0x00 ; 0 + 3eb8: c8 16 cp r12, r24 3eba: 88 e3 ldi r24, 0x38 ; 56 - 3ebc: e0 30 cpi r30, 0x00 ; 0 - 3ebe: f8 07 cpc r31, r24 - 3ec0: 18 f4 brcc .+6 ; 0x3ec8 - 3ec2: 83 e0 ldi r24, 0x03 ; 3 + 3ebc: d8 06 cpc r13, r24 + 3ebe: 20 f4 brcc .+8 ; 0x3ec8 + 3ec0: 83 e0 ldi r24, 0x03 ; 3 + 3ec2: f6 01 movw r30, r12 3ec4: 87 bf out 0x37, r24 ; 55 3ec6: e8 95 spm 3ec8: c0 e0 ldi r28, 0x00 ; 0 @@ -255,302 +261,301 @@ void watchdogReset() { // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); - 3ecc: 71 d0 rcall .+226 ; 0x3fb0 + 3ecc: 63 d0 rcall .+198 ; 0x3f94 3ece: 89 93 st Y+, r24 while (--length); - 3ed0: 80 91 02 02 lds r24, 0x0202 - 3ed4: 81 50 subi r24, 0x01 ; 1 - 3ed6: 80 93 02 02 sts 0x0202, r24 - 3eda: 88 23 and r24, r24 - 3edc: b9 f7 brne .-18 ; 0x3ecc + 3ed0: 0c 17 cp r16, r28 + 3ed2: e1 f7 brne .-8 ; 0x3ecc // If we are in NRWW section, page erase has to be delayed until now. // Todo: Take RAMPZ into account if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 3ede: e0 91 00 02 lds r30, 0x0200 - 3ee2: f0 91 01 02 lds r31, 0x0201 - 3ee6: 88 e3 ldi r24, 0x38 ; 56 - 3ee8: e0 30 cpi r30, 0x00 ; 0 - 3eea: f8 07 cpc r31, r24 - 3eec: 18 f0 brcs .+6 ; 0x3ef4 - 3eee: 83 e0 ldi r24, 0x03 ; 3 - 3ef0: 87 bf out 0x37, r24 ; 55 - 3ef2: e8 95 spm + 3ed4: f0 e0 ldi r31, 0x00 ; 0 + 3ed6: cf 16 cp r12, r31 + 3ed8: f8 e3 ldi r31, 0x38 ; 56 + 3eda: df 06 cpc r13, r31 + 3edc: 20 f0 brcs .+8 ; 0x3ee6 + 3ede: 83 e0 ldi r24, 0x03 ; 3 + 3ee0: f6 01 movw r30, r12 + 3ee2: 87 bf out 0x37, r24 ; 55 + 3ee4: e8 95 spm // Read command terminator, start reply verifySpace(); - 3ef4: 75 d0 rcall .+234 ; 0x3fe0 + 3ee6: 64 d0 rcall .+200 ; 0x3fb0 // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); - 3ef6: 07 b6 in r0, 0x37 ; 55 - 3ef8: 00 fc sbrc r0, 0 - 3efa: fd cf rjmp .-6 ; 0x3ef6 - } -#endif - - // Copy buffer into programming buffer + 3ee8: 07 b6 in r0, 0x37 ; 55 + 3eea: 00 fc sbrc r0, 0 + 3eec: fd cf rjmp .-6 ; 0x3ee8 + 3eee: a6 01 movw r20, r12 + 3ef0: a0 e0 ldi r26, 0x00 ; 0 + 3ef2: b1 e0 ldi r27, 0x01 ; 1 bufPtr = buff; addrPtr = (uint16_t)(void*)address; - 3efc: 40 91 00 02 lds r20, 0x0200 - 3f00: 50 91 01 02 lds r21, 0x0201 - 3f04: a0 e0 ldi r26, 0x00 ; 0 - 3f06: b1 e0 ldi r27, 0x01 ; 1 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; - 3f08: 2c 91 ld r18, X - 3f0a: 30 e0 ldi r19, 0x00 ; 0 + 3ef4: 2c 91 ld r18, X + 3ef6: 30 e0 ldi r19, 0x00 ; 0 a |= (*bufPtr++) << 8; - 3f0c: 11 96 adiw r26, 0x01 ; 1 - 3f0e: 8c 91 ld r24, X - 3f10: 11 97 sbiw r26, 0x01 ; 1 - 3f12: 90 e0 ldi r25, 0x00 ; 0 - 3f14: 98 2f mov r25, r24 - 3f16: 88 27 eor r24, r24 - 3f18: 82 2b or r24, r18 - 3f1a: 93 2b or r25, r19 + 3ef8: 11 96 adiw r26, 0x01 ; 1 + 3efa: 8c 91 ld r24, X + 3efc: 11 97 sbiw r26, 0x01 ; 1 + 3efe: 90 e0 ldi r25, 0x00 ; 0 + 3f00: 98 2f mov r25, r24 + 3f02: 88 27 eor r24, r24 + 3f04: 82 2b or r24, r18 + 3f06: 93 2b or r25, r19 #define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) #define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif /* main program starts here */ int main(void) { - 3f1c: 12 96 adiw r26, 0x02 ; 2 + 3f08: 12 96 adiw r26, 0x02 ; 2 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; a |= (*bufPtr++) << 8; __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - 3f1e: fa 01 movw r30, r20 - 3f20: 0c 01 movw r0, r24 - 3f22: d7 be out 0x37, r13 ; 55 - 3f24: e8 95 spm - 3f26: 11 24 eor r1, r1 + 3f0a: fa 01 movw r30, r20 + 3f0c: 0c 01 movw r0, r24 + 3f0e: 97 be out 0x37, r9 ; 55 + 3f10: e8 95 spm + 3f12: 11 24 eor r1, r1 addrPtr += 2; - 3f28: 4e 5f subi r20, 0xFE ; 254 - 3f2a: 5f 4f sbci r21, 0xFF ; 255 + 3f14: 4e 5f subi r20, 0xFE ; 254 + 3f16: 5f 4f sbci r21, 0xFF ; 255 } while (--ch); - 3f2c: f1 e0 ldi r31, 0x01 ; 1 - 3f2e: a0 38 cpi r26, 0x80 ; 128 - 3f30: bf 07 cpc r27, r31 - 3f32: 51 f7 brne .-44 ; 0x3f08 + 3f18: f1 e0 ldi r31, 0x01 ; 1 + 3f1a: a0 38 cpi r26, 0x80 ; 128 + 3f1c: bf 07 cpc r27, r31 + 3f1e: 51 f7 brne .-44 ; 0x3ef4 // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); - 3f34: e0 91 00 02 lds r30, 0x0200 - 3f38: f0 91 01 02 lds r31, 0x0201 - 3f3c: e7 be out 0x37, r14 ; 55 - 3f3e: e8 95 spm + 3f20: f6 01 movw r30, r12 + 3f22: a7 be out 0x37, r10 ; 55 + 3f24: e8 95 spm boot_spm_busy_wait(); - 3f40: 07 b6 in r0, 0x37 ; 55 - 3f42: 00 fc sbrc r0, 0 - 3f44: fd cf rjmp .-6 ; 0x3f40 + 3f26: 07 b6 in r0, 0x37 ; 55 + 3f28: 00 fc sbrc r0, 0 + 3f2a: fd cf rjmp .-6 ; 0x3f26 #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 3f46: f7 be out 0x37, r15 ; 55 - 3f48: e8 95 spm - 3f4a: 27 c0 rjmp .+78 ; 0x3f9a + 3f2c: b7 be out 0x37, r11 ; 55 + 3f2e: e8 95 spm + 3f30: 26 c0 rjmp .+76 ; 0x3f7e #endif } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { - 3f4c: 84 37 cpi r24, 0x74 ; 116 - 3f4e: b9 f4 brne .+46 ; 0x3f7e + 3f32: 84 37 cpi r24, 0x74 ; 116 + 3f34: b1 f4 brne .+44 ; 0x3f62 // READ PAGE - we only read flash - getLen(); - 3f50: 37 d0 rcall .+110 ; 0x3fc0 + getch(); /* getlen() */ + 3f36: 2e d0 rcall .+92 ; 0x3f94 + length = getch(); + 3f38: 2d d0 rcall .+90 ; 0x3f94 + 3f3a: f8 2e mov r15, r24 + getch(); + 3f3c: 2b d0 rcall .+86 ; 0x3f94 + verifySpace(); - 3f52: 46 d0 rcall .+140 ; 0x3fe0 + 3f3e: 38 d0 rcall .+112 ; 0x3fb0 + 3f40: f6 01 movw r30, r12 + 3f42: ef 2c mov r14, r15 putch(result); address++; } while (--length); #else do putch(pgm_read_byte_near(address++)); - 3f54: e0 91 00 02 lds r30, 0x0200 - 3f58: f0 91 01 02 lds r31, 0x0201 - 3f5c: 31 96 adiw r30, 0x01 ; 1 - 3f5e: f0 93 01 02 sts 0x0201, r31 - 3f62: e0 93 00 02 sts 0x0200, r30 - 3f66: 31 97 sbiw r30, 0x01 ; 1 - 3f68: e4 91 lpm r30, Z+ - 3f6a: 8e 2f mov r24, r30 - 3f6c: 19 d0 rcall .+50 ; 0x3fa0 + 3f44: 8f 01 movw r16, r30 + 3f46: 0f 5f subi r16, 0xFF ; 255 + 3f48: 1f 4f sbci r17, 0xFF ; 255 + 3f4a: 84 91 lpm r24, Z+ + 3f4c: 1b d0 rcall .+54 ; 0x3f84 while (--length); - 3f6e: 80 91 02 02 lds r24, 0x0202 - 3f72: 81 50 subi r24, 0x01 ; 1 - 3f74: 80 93 02 02 sts 0x0202, r24 - 3f78: 88 23 and r24, r24 - 3f7a: 61 f7 brne .-40 ; 0x3f54 - 3f7c: 0e c0 rjmp .+28 ; 0x3f9a + 3f4e: ea 94 dec r14 + 3f50: f8 01 movw r30, r16 + 3f52: c1 f7 brne .-16 ; 0x3f44 +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) +#endif + +/* main program starts here */ +int main(void) { + 3f54: 08 94 sec + 3f56: c1 1c adc r12, r1 + 3f58: d1 1c adc r13, r1 + 3f5a: fa 94 dec r15 + 3f5c: cf 0c add r12, r15 + 3f5e: d1 1c adc r13, r1 + 3f60: 0e c0 rjmp .+28 ; 0x3f7e #endif #endif } /* Get device signature bytes */ else if(ch == STK_READ_SIGN) { - 3f7e: 85 37 cpi r24, 0x75 ; 117 - 3f80: 39 f4 brne .+14 ; 0x3f90 + 3f62: 85 37 cpi r24, 0x75 ; 117 + 3f64: 39 f4 brne .+14 ; 0x3f74 // READ SIGN - return what Avrdude wants to hear verifySpace(); - 3f82: 2e d0 rcall .+92 ; 0x3fe0 + 3f66: 24 d0 rcall .+72 ; 0x3fb0 putch(SIGNATURE_0); - 3f84: 8e e1 ldi r24, 0x1E ; 30 - 3f86: 0c d0 rcall .+24 ; 0x3fa0 + 3f68: 8e e1 ldi r24, 0x1E ; 30 + 3f6a: 0c d0 rcall .+24 ; 0x3f84 putch(SIGNATURE_1); - 3f88: 84 e9 ldi r24, 0x94 ; 148 - 3f8a: 0a d0 rcall .+20 ; 0x3fa0 + 3f6c: 84 e9 ldi r24, 0x94 ; 148 + 3f6e: 0a d0 rcall .+20 ; 0x3f84 putch(SIGNATURE_2); - 3f8c: 86 e0 ldi r24, 0x06 ; 6 - 3f8e: 8b cf rjmp .-234 ; 0x3ea6 + 3f70: 86 e0 ldi r24, 0x06 ; 6 + 3f72: 98 cf rjmp .-208 ; 0x3ea4 } else if (ch == 'Q') { - 3f90: 81 35 cpi r24, 0x51 ; 81 - 3f92: 11 f4 brne .+4 ; 0x3f98 + 3f74: 81 35 cpi r24, 0x51 ; 81 + 3f76: 11 f4 brne .+4 ; 0x3f7c // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); - 3f94: 88 e0 ldi r24, 0x08 ; 8 - 3f96: 19 d0 rcall .+50 ; 0x3fca + 3f78: 88 e0 ldi r24, 0x08 ; 8 + 3f7a: 14 d0 rcall .+40 ; 0x3fa4 verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 3f98: 23 d0 rcall .+70 ; 0x3fe0 + 3f7c: 19 d0 rcall .+50 ; 0x3fb0 } putch(STK_OK); - 3f9a: 80 e1 ldi r24, 0x10 ; 16 - 3f9c: 01 d0 rcall .+2 ; 0x3fa0 - 3f9e: 5c cf rjmp .-328 ; 0x3e58 + 3f7e: 80 e1 ldi r24, 0x10 ; 16 + 3f80: 01 d0 rcall .+2 ; 0x3f84 + 3f82: 6a cf rjmp .-300 ; 0x3e58 -00003fa0 : +00003f84 : } } void putch(char ch) { - 3fa0: 98 2f mov r25, r24 + 3f84: 98 2f mov r25, r24 #ifndef SOFT_UART while (!(UCSR0A & _BV(UDRE0))); - 3fa2: 80 91 c0 00 lds r24, 0x00C0 - 3fa6: 85 ff sbrs r24, 5 - 3fa8: fc cf rjmp .-8 ; 0x3fa2 + 3f86: 80 91 c0 00 lds r24, 0x00C0 + 3f8a: 85 ff sbrs r24, 5 + 3f8c: fc cf rjmp .-8 ; 0x3f86 UDR0 = ch; - 3faa: 90 93 c6 00 sts 0x00C6, r25 + 3f8e: 90 93 c6 00 sts 0x00C6, r25 [uartBit] "I" (UART_TX_BIT) : "r25" ); #endif } - 3fae: 08 95 ret + 3f92: 08 95 ret -00003fb0 : - return getch(); +00003f94 : } +#endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 3fb0: a8 95 wdr + 3f94: a8 95 wdr [uartBit] "I" (UART_RX_BIT) : "r25" ); #else while(!(UCSR0A & _BV(RXC0))); - 3fb2: 80 91 c0 00 lds r24, 0x00C0 - 3fb6: 87 ff sbrs r24, 7 - 3fb8: fc cf rjmp .-8 ; 0x3fb2 + 3f96: 80 91 c0 00 lds r24, 0x00C0 + 3f9a: 87 ff sbrs r24, 7 + 3f9c: fc cf rjmp .-8 ; 0x3f96 ch = UDR0; - 3fba: 80 91 c6 00 lds r24, 0x00C6 + 3f9e: 80 91 c6 00 lds r24, 0x00C6 LED_PIN |= _BV(LED); #endif #endif return ch; } - 3fbe: 08 95 ret + 3fa2: 08 95 ret -00003fc0 : - } while (--count); -} -#endif - -uint8_t getLen() { - getch(); - 3fc0: f7 df rcall .-18 ; 0x3fb0 - length = getch(); - 3fc2: f6 df rcall .-20 ; 0x3fb0 - 3fc4: 80 93 02 02 sts 0x0202, r24 - return getch(); -} - 3fc8: f3 cf rjmp .-26 ; 0x3fb0 - -00003fca : +00003fa4 : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 3fca: e0 e6 ldi r30, 0x60 ; 96 - 3fcc: f0 e0 ldi r31, 0x00 ; 0 - 3fce: 98 e1 ldi r25, 0x18 ; 24 - 3fd0: 90 83 st Z, r25 + 3fa4: e0 e6 ldi r30, 0x60 ; 96 + 3fa6: f0 e0 ldi r31, 0x00 ; 0 + 3fa8: 98 e1 ldi r25, 0x18 ; 24 + 3faa: 90 83 st Z, r25 WDTCSR = x; - 3fd2: 80 83 st Z, r24 + 3fac: 80 83 st Z, r24 } - 3fd4: 08 95 ret + 3fae: 08 95 ret -00003fd6 : - -void appStart() { - watchdogConfig(WATCHDOG_OFF); - 3fd6: 80 e0 ldi r24, 0x00 ; 0 - 3fd8: f8 df rcall .-16 ; 0x3fca - __asm__ __volatile__ ( - 3fda: ee 27 eor r30, r30 - 3fdc: ff 27 eor r31, r31 - 3fde: 09 94 ijmp - -00003fe0 : +00003fb0 : do getch(); while (--count); verifySpace(); } void verifySpace() { - if (getch() != CRC_EOP) appStart(); - 3fe0: e7 df rcall .-50 ; 0x3fb0 - 3fe2: 80 32 cpi r24, 0x20 ; 32 - 3fe4: 09 f0 breq .+2 ; 0x3fe8 - 3fe6: f7 df rcall .-18 ; 0x3fd6 + if (getch() != CRC_EOP) { + 3fb0: f1 df rcall .-30 ; 0x3f94 + 3fb2: 80 32 cpi r24, 0x20 ; 32 + 3fb4: 19 f0 breq .+6 ; 0x3fbc + watchdogConfig(WATCHDOG_16MS); // shorten WD timeout + 3fb6: 88 e0 ldi r24, 0x08 ; 8 + 3fb8: f5 df rcall .-22 ; 0x3fa4 + 3fba: ff cf rjmp .-2 ; 0x3fba + while (1) // and busy-loop so that WD causes + ; // a reset and app start. + } putch(STK_INSYNC); - 3fe8: 84 e1 ldi r24, 0x14 ; 20 + 3fbc: 84 e1 ldi r24, 0x14 ; 20 } - 3fea: da cf rjmp .-76 ; 0x3fa0 + 3fbe: e2 cf rjmp .-60 ; 0x3f84 -00003fec : +00003fc0 : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 3fec: 1f 93 push r17 - 3fee: 18 2f mov r17, r24 + 3fc0: 1f 93 push r17 + 3fc2: 18 2f mov r17, r24 do getch(); while (--count); - 3ff0: df df rcall .-66 ; 0x3fb0 - 3ff2: 11 50 subi r17, 0x01 ; 1 - 3ff4: e9 f7 brne .-6 ; 0x3ff0 + 3fc4: e7 df rcall .-50 ; 0x3f94 + 3fc6: 11 50 subi r17, 0x01 ; 1 + 3fc8: e9 f7 brne .-6 ; 0x3fc4 verifySpace(); - 3ff6: f4 df rcall .-24 ; 0x3fe0 + 3fca: f2 df rcall .-28 ; 0x3fb0 } - 3ff8: 1f 91 pop r17 - 3ffa: 08 95 ret + 3fcc: 1f 91 pop r17 + 3fce: 08 95 ret + +00003fd0 : + WDTCSR = _BV(WDCE) | _BV(WDE); + WDTCSR = x; +} + +void appStart() { + watchdogConfig(WATCHDOG_OFF); + 3fd0: 80 e0 ldi r24, 0x00 ; 0 + 3fd2: e8 df rcall .-48 ; 0x3fa4 + __asm__ __volatile__ ( + 3fd4: ee 27 eor r30, r30 + 3fd6: ff 27 eor r31, r31 + 3fd8: 09 94 ijmp diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_luminet.hex b/hardware/arduino/bootloaders/optiboot/optiboot_luminet.hex index 0f901f4ee..843b2ef81 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_luminet.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_luminet.hex @@ -1,42 +1,39 @@ -:10000000112484B714BE81FF22D185E08EBD8EE01D -:100010001AD1D49AD29A86E023EC3FEF91E03DBD0D +:10000000112484B714BE81FF18D185E08EBD8EE027 +:1000100000D1D49AD29A86E023EC3FEF91E03DBD27 :100020002CBD9BB9589BFECFCC9AA8958150B9F7AF -:10003000DD24D39485E0C82E0FE7F02E1EECE12ED0 -:10004000E9D0813421F481E00DD183E020C08234F5 -:1000500011F484E103C0853419F485E003D1C8C0EC -:10006000853581F4D7D0082F10E0D4D090E0982FB8 -:100070008827802B912B880F991F90938101809363 -:100080008001B5C0863529F484E0ECD080E0B3D09F -:10009000AFC0843609F06BC0D1D0C0E0D1E0BAD097 -:1000A0008993809182018150809382018823B9F7DE -:1000B000E0918001F091810183E087BFE895CCD089 -:1000C00007B600FCFDCF8091800190918101892BC2 -:1000D00041F5809100012091010130E0322F22276B -:1000E00090E0282B392B3093850120938401409197 -:1000F00008018091090190E0982F882750E0842B17 -:10010000952B909387018093860124503040209353 -:100110000801232F332720930901F0920001E09278 -:1001200001014091800150918101A0E0B1E02C914A -:1001300030E011968C91119790E0982F8827822BB0 -:10014000932B1296FA010C01D7BEE89511244E5F4D -:100150005F4FF1E0A034BF0751F7E0918001F091CB -:100160008101C7BEE89507B600FCFDCF41C08437CA -:1001700089F564D071D0E0918001F09181013097D0 -:1001800019F42091840113C0E130F10519F4209194 -:1001900085010DC0E830F10519F42091860107C0F2 -:1001A000E930F10519F42091870101C02491809173 -:1001B000800190918101019690938101809380014B -:1001C000822F19D0809182018150809382018823EF -:1001D00091F60EC0853739F43FD08EE10CD083E91B -:1001E0000AD08CE054CF813511F488E02CD034D083 -:1001F00080E101D025CF2AE030E08095089410F40A -:10020000DA9802C0DA9A000015D014D086952A95A3 -:10021000B1F70895A89529E030E0CB99FECF0AD038 -:1002200009D008D08894CB9908942A9511F0879525 -:10023000F7CF08959EE09A95F1F70895EBDFEADF96 -:1002400080938201E7CF98E191BD81BD089580E060 -:10025000FADFE4E0FF270994DDDF803209F0F7DF01 -:1002600084E1C9CF1F93182FD5DF1150E9F7F4DFD0 -:040270001F9108953D +:10003000BB24B39425E0A22E9FE7D92E8EECC82EC8 +:10004000D4D0813421F481E0F0D083E0B5C0823493 +:1000500011F484E103C0853419F485E0E6D0B3C01F +:10006000853569F4C2D0E82EFF24BFD0082F10E0F8 +:10007000102F00270E291F29000F111FA3C086353E +:1000800021F484E0D2D080E097C0843609F060C0CB +:10009000ACD0ABD0F82EA9D0C0E0D1E0A6D08993E7 +:1000A000FC16E1F783E0F80187BFE895B6D007B604 +:1000B00000FCFDCF0115110511F0A8012AC08091A7 +:1000C00000012091010130E0322F222790E0282BFF +:1000D000392B309385012093840140910801809150 +:1000E000090190E0982F882750E0842B952B90935E +:1000F0008701809386012450304020930801232FEC +:10010000332720930901D0920001C092010140E001 +:1001100050E0A0E0B1E02C9130E011968C91119765 +:1001200090E0982F8827822B932B1296FA010C01CE +:10013000B7BEE89511244E5F5F4FF1E0A034BF07D2 +:1001400051F7F801A7BEE89507B600FCFDCF3BC00C +:10015000843751F54AD049D0F82E47D05ED0E80117 +:10016000EF2C209719F48091840114C0C130D1057F +:1001700019F4809185010EC0C830D10519F4809121 +:10018000860108C0C930D10519F48091870102C0E9 +:10019000FE01849121961AD0EA9419F70F5F1F4F40 +:1001A000FA940F0D111D0FC0853741F436D08EE142 +:1001B0000DD083E90BD08CE009D005C0813511F456 +:1001C00088E027D02AD080E101D03ACF2AE030E081 +:1001D0008095089410F4DA9802C0DA9A000015D0DD +:1001E00014D086952A95B1F70895A89529E030E0B6 +:1001F000CB99FECF0AD009D008D08894CB99089427 +:100200002A9511F08795F7CF08959EE09A95F1F71A +:10021000089598E191BD81BD0895E7DF803219F01E +:1002200088E0F7DFFFCF84E1D1CF1F93182FDDDF08 +:100230001150E9F7F2DF1F91089580E0EADFE4E072 +:04024000FF270994F7 :021EFE000104DD :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_luminet.lst b/hardware/arduino/bootloaders/optiboot/optiboot_luminet.lst index 1be7e4fab..83336701c 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_luminet.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_luminet.lst @@ -3,27 +3,27 @@ optiboot_luminet.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .version 00000002 00001efe 00001efe 000002c8 2**0 + 0 .version 00000002 00001efe 00001efe 00000298 2**0 CONTENTS, READONLY - 1 .text 00000274 00000000 00000000 00000054 2**1 + 1 .text 00000244 00000000 00000000 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 2 .debug_aranges 00000028 00000000 00000000 000002ca 2**0 + 2 .debug_aranges 00000028 00000000 00000000 0000029a 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_pubnames 00000078 00000000 00000000 000002f2 2**0 + 3 .debug_pubnames 0000006d 00000000 00000000 000002c2 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_info 000002a5 00000000 00000000 0000036a 2**0 + 4 .debug_info 000002b0 00000000 00000000 0000032f 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 0000019d 00000000 00000000 0000060f 2**0 + 5 .debug_abbrev 00000197 00000000 00000000 000005df 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_line 000004ac 00000000 00000000 000007ac 2**0 + 6 .debug_line 000004a7 00000000 00000000 00000776 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 000000a0 00000000 00000000 00000c58 2**2 + 7 .debug_frame 00000090 00000000 00000000 00000c20 2**2 CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000150 00000000 00000000 00000cf8 2**0 + 8 .debug_str 00000158 00000000 00000000 00000cb0 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 00000194 00000000 00000000 00000e48 2**0 + 9 .debug_loc 00000268 00000000 00000000 00000e08 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000088 00000000 00000000 00000fdc 2**0 + 10 .debug_ranges 00000080 00000000 00000000 00001070 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: @@ -47,7 +47,7 @@ int main(void) { 4: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); 6: 81 ff sbrs r24, 1 - 8: 22 d1 rcall .+580 ; 0x24e + 8: 18 d1 rcall .+560 ; 0x23a #if LED_START_FLASHES > 0 // Set up Timer 1 for timeout counter @@ -61,7 +61,7 @@ int main(void) { // Set up watchdog to trigger after 500ms watchdogConfig(WATCHDOG_1S); e: 8e e0 ldi r24, 0x0E ; 14 - 10: 1a d1 rcall .+564 ; 0x246 + 10: 00 d1 rcall .+512 ; 0x212 /* Set LED pin as output */ LED_DDR |= _BV(LED); @@ -100,8 +100,8 @@ void flash_led(uint8_t count) { #else LED_PIN |= _BV(LED); 28: cc 9a sbi 0x19, 4 ; 25 - return getch(); } +#endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { @@ -121,34 +121,34 @@ void watchdogReset() { if(ch == STK_GET_PARAMETER) { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 30: dd 24 eor r13, r13 - 32: d3 94 inc r13 + 30: bb 24 eor r11, r11 + 32: b3 94 inc r11 __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); - 34: 85 e0 ldi r24, 0x05 ; 5 - 36: c8 2e mov r12, r24 + 34: 25 e0 ldi r18, 0x05 ; 5 + 36: a2 2e mov r10, r18 vect -= 4; // Instruction is a relative jump (rjmp), so recalculate. buff[8] = vect & 0xff; buff[9] = vect >> 8; // Add jump to bootloader at RESET vector buff[0] = 0x7f; - 38: 0f e7 ldi r16, 0x7F ; 127 - 3a: f0 2e mov r15, r16 + 38: 9f e7 ldi r25, 0x7F ; 127 + 3a: d9 2e mov r13, r25 buff[1] = 0xce; // rjmp 0x1d00 instruction - 3c: 1e ec ldi r17, 0xCE ; 206 - 3e: e1 2e mov r14, r17 + 3c: 8e ec ldi r24, 0xCE ; 206 + 3e: c8 2e mov r12, r24 #endif /* Forever loop */ for (;;) { /* get character from UART */ ch = getch(); - 40: e9 d0 rcall .+466 ; 0x214 + 40: d4 d0 rcall .+424 ; 0x1ea if(ch == STK_GET_PARAMETER) { 42: 81 34 cpi r24, 0x41 ; 65 @@ -156,10 +156,10 @@ void watchdogReset() { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); 46: 81 e0 ldi r24, 0x01 ; 1 - 48: 0d d1 rcall .+538 ; 0x264 + 48: f0 d0 rcall .+480 ; 0x22a putch(0x03); 4a: 83 e0 ldi r24, 0x03 ; 3 - 4c: 20 c0 rjmp .+64 ; 0x8e <__SREG__+0x4f> + 4c: b5 c0 rjmp .+362 ; 0x1b8 <__SREG__+0x179> } else if(ch == STK_SET_DEVICE) { 4e: 82 34 cpi r24, 0x42 ; 66 @@ -175,450 +175,450 @@ void watchdogReset() { // SET DEVICE EXT is ignored getNch(5); 5a: 85 e0 ldi r24, 0x05 ; 5 - 5c: 03 d1 rcall .+518 ; 0x264 - 5e: c8 c0 rjmp .+400 ; 0x1f0 <__SREG__+0x1b1> + 5c: e6 d0 rcall .+460 ; 0x22a + 5e: b3 c0 rjmp .+358 ; 0x1c6 <__SREG__+0x187> } else if(ch == STK_LOAD_ADDRESS) { 60: 85 35 cpi r24, 0x55 ; 85 - 62: 81 f4 brne .+32 ; 0x84 <__SREG__+0x45> + 62: 69 f4 brne .+26 ; 0x7e <__SREG__+0x3f> // LOAD ADDRESS uint16_t newAddress; newAddress = getch(); - 64: d7 d0 rcall .+430 ; 0x214 + 64: c2 d0 rcall .+388 ; 0x1ea newAddress = (newAddress & 0xff) | (getch() << 8); - 66: 08 2f mov r16, r24 - 68: 10 e0 ldi r17, 0x00 ; 0 - 6a: d4 d0 rcall .+424 ; 0x214 - 6c: 90 e0 ldi r25, 0x00 ; 0 - 6e: 98 2f mov r25, r24 - 70: 88 27 eor r24, r24 - 72: 80 2b or r24, r16 - 74: 91 2b or r25, r17 + 66: e8 2e mov r14, r24 + 68: ff 24 eor r15, r15 + 6a: bf d0 rcall .+382 ; 0x1ea + 6c: 08 2f mov r16, r24 + 6e: 10 e0 ldi r17, 0x00 ; 0 + 70: 10 2f mov r17, r16 + 72: 00 27 eor r16, r16 + 74: 0e 29 or r16, r14 + 76: 1f 29 or r17, r15 #ifdef RAMPZ // Transfer top bit to RAMPZ RAMPZ = (newAddress & 0x8000) ? 1 : 0; #endif newAddress += newAddress; // Convert from word address to byte address - 76: 88 0f add r24, r24 - 78: 99 1f adc r25, r25 + 78: 00 0f add r16, r16 + 7a: 11 1f adc r17, r17 + 7c: a3 c0 rjmp .+326 ; 0x1c4 <__SREG__+0x185> address = newAddress; - 7a: 90 93 81 01 sts 0x0181, r25 - 7e: 80 93 80 01 sts 0x0180, r24 - 82: b5 c0 rjmp .+362 ; 0x1ee <__SREG__+0x1af> verifySpace(); } else if(ch == STK_UNIVERSAL) { - 84: 86 35 cpi r24, 0x56 ; 86 - 86: 29 f4 brne .+10 ; 0x92 <__SREG__+0x53> + 7e: 86 35 cpi r24, 0x56 ; 86 + 80: 21 f4 brne .+8 ; 0x8a <__SREG__+0x4b> // UNIVERSAL command is ignored getNch(4); - 88: 84 e0 ldi r24, 0x04 ; 4 - 8a: ec d0 rcall .+472 ; 0x264 + 82: 84 e0 ldi r24, 0x04 ; 4 + 84: d2 d0 rcall .+420 ; 0x22a putch(0x00); - 8c: 80 e0 ldi r24, 0x00 ; 0 - 8e: b3 d0 rcall .+358 ; 0x1f6 - 90: af c0 rjmp .+350 ; 0x1f0 <__SREG__+0x1b1> + 86: 80 e0 ldi r24, 0x00 ; 0 + 88: 97 c0 rjmp .+302 ; 0x1b8 <__SREG__+0x179> } /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { - 92: 84 36 cpi r24, 0x64 ; 100 - 94: 09 f0 breq .+2 ; 0x98 <__SREG__+0x59> - 96: 6b c0 rjmp .+214 ; 0x16e <__SREG__+0x12f> + 8a: 84 36 cpi r24, 0x64 ; 100 + 8c: 09 f0 breq .+2 ; 0x90 <__SREG__+0x51> + 8e: 60 c0 rjmp .+192 ; 0x150 <__SREG__+0x111> // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t *bufPtr; uint16_t addrPtr; - getLen(); - 98: d1 d0 rcall .+418 ; 0x23c - 9a: c0 e0 ldi r28, 0x00 ; 0 - 9c: d1 e0 ldi r29, 0x01 ; 1 + getch(); /* getlen() */ + 90: ac d0 rcall .+344 ; 0x1ea + length = getch(); + 92: ab d0 rcall .+342 ; 0x1ea + 94: f8 2e mov r15, r24 + getch(); + 96: a9 d0 rcall .+338 ; 0x1ea + 98: c0 e0 ldi r28, 0x00 ; 0 + 9a: d1 e0 ldi r29, 0x01 ; 1 // If we are in RWW section, immediately start page erase if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); - 9e: ba d0 rcall .+372 ; 0x214 - a0: 89 93 st Y+, r24 + 9c: a6 d0 rcall .+332 ; 0x1ea + 9e: 89 93 st Y+, r24 while (--length); - a2: 80 91 82 01 lds r24, 0x0182 - a6: 81 50 subi r24, 0x01 ; 1 - a8: 80 93 82 01 sts 0x0182, r24 - ac: 88 23 and r24, r24 - ae: b9 f7 brne .-18 ; 0x9e <__SREG__+0x5f> + a0: fc 16 cp r15, r28 + a2: e1 f7 brne .-8 ; 0x9c <__SREG__+0x5d> // If we are in NRWW section, page erase has to be delayed until now. // Todo: Take RAMPZ into account if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - b0: e0 91 80 01 lds r30, 0x0180 - b4: f0 91 81 01 lds r31, 0x0181 - b8: 83 e0 ldi r24, 0x03 ; 3 - ba: 87 bf out 0x37, r24 ; 55 - bc: e8 95 spm + a4: 83 e0 ldi r24, 0x03 ; 3 + a6: f8 01 movw r30, r16 + a8: 87 bf out 0x37, r24 ; 55 + aa: e8 95 spm // Read command terminator, start reply verifySpace(); - be: cc d0 rcall .+408 ; 0x258 + ac: b6 d0 rcall .+364 ; 0x21a // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); - c0: 07 b6 in r0, 0x37 ; 55 - c2: 00 fc sbrc r0, 0 - c4: fd cf rjmp .-6 ; 0xc0 <__SREG__+0x81> + ae: 07 b6 in r0, 0x37 ; 55 + b0: 00 fc sbrc r0, 0 + b2: fd cf rjmp .-6 ; 0xae <__SREG__+0x6f> #ifdef VIRTUAL_BOOT_PARTITION if ((uint16_t)(void*)address == 0) { - c6: 80 91 80 01 lds r24, 0x0180 - ca: 90 91 81 01 lds r25, 0x0181 - ce: 89 2b or r24, r25 - d0: 41 f5 brne .+80 ; 0x122 <__SREG__+0xe3> + b4: 01 15 cp r16, r1 + b6: 11 05 cpc r17, r1 + b8: 11 f0 breq .+4 ; 0xbe <__SREG__+0x7f> + ba: a8 01 movw r20, r16 + bc: 2a c0 rjmp .+84 ; 0x112 <__SREG__+0xd3> // This is the reset vector page. We need to live-patch the code so the // bootloader runs. // // Move RESET vector to WDT vector uint16_t vect = buff[0] | (buff[1]<<8); - d2: 80 91 00 01 lds r24, 0x0100 - d6: 20 91 01 01 lds r18, 0x0101 - da: 30 e0 ldi r19, 0x00 ; 0 - dc: 32 2f mov r19, r18 - de: 22 27 eor r18, r18 - e0: 90 e0 ldi r25, 0x00 ; 0 - e2: 28 2b or r18, r24 - e4: 39 2b or r19, r25 + be: 80 91 00 01 lds r24, 0x0100 + c2: 20 91 01 01 lds r18, 0x0101 + c6: 30 e0 ldi r19, 0x00 ; 0 + c8: 32 2f mov r19, r18 + ca: 22 27 eor r18, r18 + cc: 90 e0 ldi r25, 0x00 ; 0 + ce: 28 2b or r18, r24 + d0: 39 2b or r19, r25 rstVect = vect; - e6: 30 93 85 01 sts 0x0185, r19 - ea: 20 93 84 01 sts 0x0184, r18 + d2: 30 93 85 01 sts 0x0185, r19 + d6: 20 93 84 01 sts 0x0184, r18 wdtVect = buff[8] | (buff[9]<<8); - ee: 40 91 08 01 lds r20, 0x0108 - f2: 80 91 09 01 lds r24, 0x0109 - f6: 90 e0 ldi r25, 0x00 ; 0 - f8: 98 2f mov r25, r24 - fa: 88 27 eor r24, r24 - fc: 50 e0 ldi r21, 0x00 ; 0 - fe: 84 2b or r24, r20 - 100: 95 2b or r25, r21 - 102: 90 93 87 01 sts 0x0187, r25 - 106: 80 93 86 01 sts 0x0186, r24 + da: 40 91 08 01 lds r20, 0x0108 + de: 80 91 09 01 lds r24, 0x0109 + e2: 90 e0 ldi r25, 0x00 ; 0 + e4: 98 2f mov r25, r24 + e6: 88 27 eor r24, r24 + e8: 50 e0 ldi r21, 0x00 ; 0 + ea: 84 2b or r24, r20 + ec: 95 2b or r25, r21 + ee: 90 93 87 01 sts 0x0187, r25 + f2: 80 93 86 01 sts 0x0186, r24 vect -= 4; // Instruction is a relative jump (rjmp), so recalculate. - 10a: 24 50 subi r18, 0x04 ; 4 - 10c: 30 40 sbci r19, 0x00 ; 0 + f6: 24 50 subi r18, 0x04 ; 4 + f8: 30 40 sbci r19, 0x00 ; 0 buff[8] = vect & 0xff; - 10e: 20 93 08 01 sts 0x0108, r18 + fa: 20 93 08 01 sts 0x0108, r18 buff[9] = vect >> 8; - 112: 23 2f mov r18, r19 - 114: 33 27 eor r19, r19 - 116: 20 93 09 01 sts 0x0109, r18 + fe: 23 2f mov r18, r19 + 100: 33 27 eor r19, r19 + 102: 20 93 09 01 sts 0x0109, r18 // Add jump to bootloader at RESET vector buff[0] = 0x7f; - 11a: f0 92 00 01 sts 0x0100, r15 + 106: d0 92 00 01 sts 0x0100, r13 buff[1] = 0xce; // rjmp 0x1d00 instruction - 11e: e0 92 01 01 sts 0x0101, r14 - } -#endif - - // Copy buffer into programming buffer + 10a: c0 92 01 01 sts 0x0101, r12 + 10e: 40 e0 ldi r20, 0x00 ; 0 + 110: 50 e0 ldi r21, 0x00 ; 0 + 112: a0 e0 ldi r26, 0x00 ; 0 + 114: b1 e0 ldi r27, 0x01 ; 1 bufPtr = buff; addrPtr = (uint16_t)(void*)address; - 122: 40 91 80 01 lds r20, 0x0180 - 126: 50 91 81 01 lds r21, 0x0181 - 12a: a0 e0 ldi r26, 0x00 ; 0 - 12c: b1 e0 ldi r27, 0x01 ; 1 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; - 12e: 2c 91 ld r18, X - 130: 30 e0 ldi r19, 0x00 ; 0 + 116: 2c 91 ld r18, X + 118: 30 e0 ldi r19, 0x00 ; 0 a |= (*bufPtr++) << 8; - 132: 11 96 adiw r26, 0x01 ; 1 - 134: 8c 91 ld r24, X - 136: 11 97 sbiw r26, 0x01 ; 1 - 138: 90 e0 ldi r25, 0x00 ; 0 - 13a: 98 2f mov r25, r24 - 13c: 88 27 eor r24, r24 - 13e: 82 2b or r24, r18 - 140: 93 2b or r25, r19 + 11a: 11 96 adiw r26, 0x01 ; 1 + 11c: 8c 91 ld r24, X + 11e: 11 97 sbiw r26, 0x01 ; 1 + 120: 90 e0 ldi r25, 0x00 ; 0 + 122: 98 2f mov r25, r24 + 124: 88 27 eor r24, r24 + 126: 82 2b or r24, r18 + 128: 93 2b or r25, r19 #define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) #define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif /* main program starts here */ int main(void) { - 142: 12 96 adiw r26, 0x02 ; 2 + 12a: 12 96 adiw r26, 0x02 ; 2 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; a |= (*bufPtr++) << 8; __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - 144: fa 01 movw r30, r20 - 146: 0c 01 movw r0, r24 - 148: d7 be out 0x37, r13 ; 55 - 14a: e8 95 spm - 14c: 11 24 eor r1, r1 + 12c: fa 01 movw r30, r20 + 12e: 0c 01 movw r0, r24 + 130: b7 be out 0x37, r11 ; 55 + 132: e8 95 spm + 134: 11 24 eor r1, r1 addrPtr += 2; - 14e: 4e 5f subi r20, 0xFE ; 254 - 150: 5f 4f sbci r21, 0xFF ; 255 + 136: 4e 5f subi r20, 0xFE ; 254 + 138: 5f 4f sbci r21, 0xFF ; 255 } while (--ch); - 152: f1 e0 ldi r31, 0x01 ; 1 - 154: a0 34 cpi r26, 0x40 ; 64 - 156: bf 07 cpc r27, r31 - 158: 51 f7 brne .-44 ; 0x12e <__SREG__+0xef> + 13a: f1 e0 ldi r31, 0x01 ; 1 + 13c: a0 34 cpi r26, 0x40 ; 64 + 13e: bf 07 cpc r27, r31 + 140: 51 f7 brne .-44 ; 0x116 <__SREG__+0xd7> // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); - 15a: e0 91 80 01 lds r30, 0x0180 - 15e: f0 91 81 01 lds r31, 0x0181 - 162: c7 be out 0x37, r12 ; 55 - 164: e8 95 spm + 142: f8 01 movw r30, r16 + 144: a7 be out 0x37, r10 ; 55 + 146: e8 95 spm boot_spm_busy_wait(); - 166: 07 b6 in r0, 0x37 ; 55 - 168: 00 fc sbrc r0, 0 - 16a: fd cf rjmp .-6 ; 0x166 <__SREG__+0x127> - 16c: 41 c0 rjmp .+130 ; 0x1f0 <__SREG__+0x1b1> + 148: 07 b6 in r0, 0x37 ; 55 + 14a: 00 fc sbrc r0, 0 + 14c: fd cf rjmp .-6 ; 0x148 <__SREG__+0x109> + 14e: 3b c0 rjmp .+118 ; 0x1c6 <__SREG__+0x187> boot_rww_enable(); #endif } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { - 16e: 84 37 cpi r24, 0x74 ; 116 - 170: 89 f5 brne .+98 ; 0x1d4 <__SREG__+0x195> + 150: 84 37 cpi r24, 0x74 ; 116 + 152: 51 f5 brne .+84 ; 0x1a8 <__SREG__+0x169> // READ PAGE - we only read flash - getLen(); - 172: 64 d0 rcall .+200 ; 0x23c + getch(); /* getlen() */ + 154: 4a d0 rcall .+148 ; 0x1ea + length = getch(); + 156: 49 d0 rcall .+146 ; 0x1ea + 158: f8 2e mov r15, r24 + getch(); + 15a: 47 d0 rcall .+142 ; 0x1ea + verifySpace(); - 174: 71 d0 rcall .+226 ; 0x258 + 15c: 5e d0 rcall .+188 ; 0x21a + 15e: e8 01 movw r28, r16 + 160: ef 2c mov r14, r15 #ifdef VIRTUAL_BOOT_PARTITION do { // Undo vector patch in bottom page so verify passes if (address == 0) ch=rstVect & 0xff; - 176: e0 91 80 01 lds r30, 0x0180 - 17a: f0 91 81 01 lds r31, 0x0181 - 17e: 30 97 sbiw r30, 0x00 ; 0 - 180: 19 f4 brne .+6 ; 0x188 <__SREG__+0x149> - 182: 20 91 84 01 lds r18, 0x0184 - 186: 13 c0 rjmp .+38 ; 0x1ae <__SREG__+0x16f> + 162: 20 97 sbiw r28, 0x00 ; 0 + 164: 19 f4 brne .+6 ; 0x16c <__SREG__+0x12d> + 166: 80 91 84 01 lds r24, 0x0184 + 16a: 14 c0 rjmp .+40 ; 0x194 <__SREG__+0x155> else if (address == 1) ch=rstVect >> 8; - 188: e1 30 cpi r30, 0x01 ; 1 - 18a: f1 05 cpc r31, r1 - 18c: 19 f4 brne .+6 ; 0x194 <__SREG__+0x155> - 18e: 20 91 85 01 lds r18, 0x0185 - 192: 0d c0 rjmp .+26 ; 0x1ae <__SREG__+0x16f> + 16c: c1 30 cpi r28, 0x01 ; 1 + 16e: d1 05 cpc r29, r1 + 170: 19 f4 brne .+6 ; 0x178 <__SREG__+0x139> + 172: 80 91 85 01 lds r24, 0x0185 + 176: 0e c0 rjmp .+28 ; 0x194 <__SREG__+0x155> else if (address == 8) ch=wdtVect & 0xff; - 194: e8 30 cpi r30, 0x08 ; 8 - 196: f1 05 cpc r31, r1 - 198: 19 f4 brne .+6 ; 0x1a0 <__SREG__+0x161> - 19a: 20 91 86 01 lds r18, 0x0186 - 19e: 07 c0 rjmp .+14 ; 0x1ae <__SREG__+0x16f> + 178: c8 30 cpi r28, 0x08 ; 8 + 17a: d1 05 cpc r29, r1 + 17c: 19 f4 brne .+6 ; 0x184 <__SREG__+0x145> + 17e: 80 91 86 01 lds r24, 0x0186 + 182: 08 c0 rjmp .+16 ; 0x194 <__SREG__+0x155> else if (address == 9) ch=wdtVect >> 8; - 1a0: e9 30 cpi r30, 0x09 ; 9 - 1a2: f1 05 cpc r31, r1 - 1a4: 19 f4 brne .+6 ; 0x1ac <__SREG__+0x16d> - 1a6: 20 91 87 01 lds r18, 0x0187 - 1aa: 01 c0 rjmp .+2 ; 0x1ae <__SREG__+0x16f> + 184: c9 30 cpi r28, 0x09 ; 9 + 186: d1 05 cpc r29, r1 + 188: 19 f4 brne .+6 ; 0x190 <__SREG__+0x151> + 18a: 80 91 87 01 lds r24, 0x0187 + 18e: 02 c0 rjmp .+4 ; 0x194 <__SREG__+0x155> else ch = pgm_read_byte_near(address); - 1ac: 24 91 lpm r18, Z+ + 190: fe 01 movw r30, r28 + 192: 84 91 lpm r24, Z+ address++; - 1ae: 80 91 80 01 lds r24, 0x0180 - 1b2: 90 91 81 01 lds r25, 0x0181 - 1b6: 01 96 adiw r24, 0x01 ; 1 - 1b8: 90 93 81 01 sts 0x0181, r25 - 1bc: 80 93 80 01 sts 0x0180, r24 + 194: 21 96 adiw r28, 0x01 ; 1 putch(ch); - 1c0: 82 2f mov r24, r18 - 1c2: 19 d0 rcall .+50 ; 0x1f6 + 196: 1a d0 rcall .+52 ; 0x1cc } while (--length); - 1c4: 80 91 82 01 lds r24, 0x0182 - 1c8: 81 50 subi r24, 0x01 ; 1 - 1ca: 80 93 82 01 sts 0x0182, r24 - 1ce: 88 23 and r24, r24 - 1d0: 91 f6 brne .-92 ; 0x176 <__SREG__+0x137> - 1d2: 0e c0 rjmp .+28 ; 0x1f0 <__SREG__+0x1b1> + 198: ea 94 dec r14 + 19a: 19 f7 brne .-58 ; 0x162 <__SREG__+0x123> +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) +#endif + +/* main program starts here */ +int main(void) { + 19c: 0f 5f subi r16, 0xFF ; 255 + 19e: 1f 4f sbci r17, 0xFF ; 255 + 1a0: fa 94 dec r15 + 1a2: 0f 0d add r16, r15 + 1a4: 11 1d adc r17, r1 + 1a6: 0f c0 rjmp .+30 ; 0x1c6 <__SREG__+0x187> #endif #endif } /* Get device signature bytes */ else if(ch == STK_READ_SIGN) { - 1d4: 85 37 cpi r24, 0x75 ; 117 - 1d6: 39 f4 brne .+14 ; 0x1e6 <__SREG__+0x1a7> + 1a8: 85 37 cpi r24, 0x75 ; 117 + 1aa: 41 f4 brne .+16 ; 0x1bc <__SREG__+0x17d> // READ SIGN - return what Avrdude wants to hear verifySpace(); - 1d8: 3f d0 rcall .+126 ; 0x258 + 1ac: 36 d0 rcall .+108 ; 0x21a putch(SIGNATURE_0); - 1da: 8e e1 ldi r24, 0x1E ; 30 - 1dc: 0c d0 rcall .+24 ; 0x1f6 + 1ae: 8e e1 ldi r24, 0x1E ; 30 + 1b0: 0d d0 rcall .+26 ; 0x1cc putch(SIGNATURE_1); - 1de: 83 e9 ldi r24, 0x93 ; 147 - 1e0: 0a d0 rcall .+20 ; 0x1f6 + 1b2: 83 e9 ldi r24, 0x93 ; 147 + 1b4: 0b d0 rcall .+22 ; 0x1cc putch(SIGNATURE_2); - 1e2: 8c e0 ldi r24, 0x0C ; 12 - 1e4: 54 cf rjmp .-344 ; 0x8e <__SREG__+0x4f> + 1b6: 8c e0 ldi r24, 0x0C ; 12 + 1b8: 09 d0 rcall .+18 ; 0x1cc + 1ba: 05 c0 rjmp .+10 ; 0x1c6 <__SREG__+0x187> } else if (ch == 'Q') { - 1e6: 81 35 cpi r24, 0x51 ; 81 - 1e8: 11 f4 brne .+4 ; 0x1ee <__SREG__+0x1af> + 1bc: 81 35 cpi r24, 0x51 ; 81 + 1be: 11 f4 brne .+4 ; 0x1c4 <__SREG__+0x185> // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); - 1ea: 88 e0 ldi r24, 0x08 ; 8 - 1ec: 2c d0 rcall .+88 ; 0x246 + 1c0: 88 e0 ldi r24, 0x08 ; 8 + 1c2: 27 d0 rcall .+78 ; 0x212 verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 1ee: 34 d0 rcall .+104 ; 0x258 + 1c4: 2a d0 rcall .+84 ; 0x21a } putch(STK_OK); - 1f0: 80 e1 ldi r24, 0x10 ; 16 - 1f2: 01 d0 rcall .+2 ; 0x1f6 - 1f4: 25 cf rjmp .-438 ; 0x40 <__SREG__+0x1> + 1c6: 80 e1 ldi r24, 0x10 ; 16 + 1c8: 01 d0 rcall .+2 ; 0x1cc + 1ca: 3a cf rjmp .-396 ; 0x40 <__SREG__+0x1> -000001f6 : +000001cc : void putch(char ch) { #ifndef SOFT_UART while (!(UCSR0A & _BV(UDRE0))); UDR0 = ch; #else __asm__ __volatile__ ( - 1f6: 2a e0 ldi r18, 0x0A ; 10 - 1f8: 30 e0 ldi r19, 0x00 ; 0 - 1fa: 80 95 com r24 - 1fc: 08 94 sec - 1fe: 10 f4 brcc .+4 ; 0x204 - 200: da 98 cbi 0x1b, 2 ; 27 - 202: 02 c0 rjmp .+4 ; 0x208 - 204: da 9a sbi 0x1b, 2 ; 27 - 206: 00 00 nop - 208: 15 d0 rcall .+42 ; 0x234 - 20a: 14 d0 rcall .+40 ; 0x234 - 20c: 86 95 lsr r24 - 20e: 2a 95 dec r18 - 210: b1 f7 brne .-20 ; 0x1fe + 1cc: 2a e0 ldi r18, 0x0A ; 10 + 1ce: 30 e0 ldi r19, 0x00 ; 0 + 1d0: 80 95 com r24 + 1d2: 08 94 sec + 1d4: 10 f4 brcc .+4 ; 0x1da + 1d6: da 98 cbi 0x1b, 2 ; 27 + 1d8: 02 c0 rjmp .+4 ; 0x1de + 1da: da 9a sbi 0x1b, 2 ; 27 + 1dc: 00 00 nop + 1de: 15 d0 rcall .+42 ; 0x20a + 1e0: 14 d0 rcall .+40 ; 0x20a + 1e2: 86 95 lsr r24 + 1e4: 2a 95 dec r18 + 1e6: b1 f7 brne .-20 ; 0x1d4 [uartBit] "I" (UART_TX_BIT) : "r25" ); #endif } - 212: 08 95 ret + 1e8: 08 95 ret -00000214 : - return getch(); +000001ea : } +#endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 214: a8 95 wdr + 1ea: a8 95 wdr LED_PIN |= _BV(LED); #endif #endif return ch; } - 216: 29 e0 ldi r18, 0x09 ; 9 - 218: 30 e0 ldi r19, 0x00 ; 0 - 21a: cb 99 sbic 0x19, 3 ; 25 - 21c: fe cf rjmp .-4 ; 0x21a - 21e: 0a d0 rcall .+20 ; 0x234 - 220: 09 d0 rcall .+18 ; 0x234 - 222: 08 d0 rcall .+16 ; 0x234 - 224: 88 94 clc - 226: cb 99 sbic 0x19, 3 ; 25 - 228: 08 94 sec - 22a: 2a 95 dec r18 - 22c: 11 f0 breq .+4 ; 0x232 - 22e: 87 95 ror r24 - 230: f7 cf rjmp .-18 ; 0x220 - 232: 08 95 ret + 1ec: 29 e0 ldi r18, 0x09 ; 9 + 1ee: 30 e0 ldi r19, 0x00 ; 0 + 1f0: cb 99 sbic 0x19, 3 ; 25 + 1f2: fe cf rjmp .-4 ; 0x1f0 + 1f4: 0a d0 rcall .+20 ; 0x20a + 1f6: 09 d0 rcall .+18 ; 0x20a + 1f8: 08 d0 rcall .+16 ; 0x20a + 1fa: 88 94 clc + 1fc: cb 99 sbic 0x19, 3 ; 25 + 1fe: 08 94 sec + 200: 2a 95 dec r18 + 202: 11 f0 breq .+4 ; 0x208 + 204: 87 95 ror r24 + 206: f7 cf rjmp .-18 ; 0x1f6 + 208: 08 95 ret -00000234 : +0000020a : #if UART_B_VALUE > 255 #error Baud rate too slow for soft UART #endif void uartDelay() { __asm__ __volatile__ ( - 234: 9e e0 ldi r25, 0x0E ; 14 - 236: 9a 95 dec r25 - 238: f1 f7 brne .-4 ; 0x236 - 23a: 08 95 ret + 20a: 9e e0 ldi r25, 0x0E ; 14 + 20c: 9a 95 dec r25 + 20e: f1 f7 brne .-4 ; 0x20c + 210: 08 95 ret -0000023c : - } while (--count); -} -#endif - -uint8_t getLen() { - getch(); - 23c: eb df rcall .-42 ; 0x214 - length = getch(); - 23e: ea df rcall .-44 ; 0x214 - 240: 80 93 82 01 sts 0x0182, r24 - return getch(); -} - 244: e7 cf rjmp .-50 ; 0x214 - -00000246 : +00000212 : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 246: 98 e1 ldi r25, 0x18 ; 24 - 248: 91 bd out 0x21, r25 ; 33 + 212: 98 e1 ldi r25, 0x18 ; 24 + 214: 91 bd out 0x21, r25 ; 33 WDTCSR = x; - 24a: 81 bd out 0x21, r24 ; 33 + 216: 81 bd out 0x21, r24 ; 33 } - 24c: 08 95 ret + 218: 08 95 ret -0000024e : - -void appStart() { - watchdogConfig(WATCHDOG_OFF); - 24e: 80 e0 ldi r24, 0x00 ; 0 - 250: fa df rcall .-12 ; 0x246 - __asm__ __volatile__ ( - 252: e4 e0 ldi r30, 0x04 ; 4 - 254: ff 27 eor r31, r31 - 256: 09 94 ijmp - -00000258 : +0000021a : do getch(); while (--count); verifySpace(); } void verifySpace() { - if (getch() != CRC_EOP) appStart(); - 258: dd df rcall .-70 ; 0x214 - 25a: 80 32 cpi r24, 0x20 ; 32 - 25c: 09 f0 breq .+2 ; 0x260 - 25e: f7 df rcall .-18 ; 0x24e + if (getch() != CRC_EOP) { + 21a: e7 df rcall .-50 ; 0x1ea + 21c: 80 32 cpi r24, 0x20 ; 32 + 21e: 19 f0 breq .+6 ; 0x226 + watchdogConfig(WATCHDOG_16MS); // shorten WD timeout + 220: 88 e0 ldi r24, 0x08 ; 8 + 222: f7 df rcall .-18 ; 0x212 + 224: ff cf rjmp .-2 ; 0x224 + while (1) // and busy-loop so that WD causes + ; // a reset and app start. + } putch(STK_INSYNC); - 260: 84 e1 ldi r24, 0x14 ; 20 + 226: 84 e1 ldi r24, 0x14 ; 20 } - 262: c9 cf rjmp .-110 ; 0x1f6 + 228: d1 cf rjmp .-94 ; 0x1cc -00000264 : +0000022a : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 264: 1f 93 push r17 - 266: 18 2f mov r17, r24 + 22a: 1f 93 push r17 + 22c: 18 2f mov r17, r24 do getch(); while (--count); - 268: d5 df rcall .-86 ; 0x214 - 26a: 11 50 subi r17, 0x01 ; 1 - 26c: e9 f7 brne .-6 ; 0x268 + 22e: dd df rcall .-70 ; 0x1ea + 230: 11 50 subi r17, 0x01 ; 1 + 232: e9 f7 brne .-6 ; 0x22e verifySpace(); - 26e: f4 df rcall .-24 ; 0x258 + 234: f2 df rcall .-28 ; 0x21a } - 270: 1f 91 pop r17 - 272: 08 95 ret + 236: 1f 91 pop r17 + 238: 08 95 ret + +0000023a : + WDTCSR = _BV(WDCE) | _BV(WDE); + WDTCSR = x; +} + +void appStart() { + watchdogConfig(WATCHDOG_OFF); + 23a: 80 e0 ldi r24, 0x00 ; 0 + 23c: ea df rcall .-44 ; 0x212 + __asm__ __volatile__ ( + 23e: e4 e0 ldi r30, 0x04 ; 4 + 240: ff 27 eor r31, r31 + 242: 09 94 ijmp diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.hex b/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.hex index 3ac0de204..733a1397e 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.hex @@ -1,35 +1,33 @@ -:103E0000112484B714BE81FFE6D085E08093810041 +:103E0000112484B714BE81FFE3D085E08093810044 :103E100082E08093C00088E18093C10086E08093B7 -:103E2000C20080E18093C4008EE0CFD0259A86E066 +:103E2000C20080E18093C4008EE0BCD0259A86E079 :103E300020E33CEF91E0309385002093840096BB13 -:103E4000B09BFECF1D9AA8958150A9F7DD24D3948D -:103E5000A5E0EA2EF1E1FF2EABD0813421F481E020 -:103E6000C5D083E020C0823411F484E103C08534DE -:103E700019F485E0BBD091C0853581F499D0082F25 -:103E800010E096D090E0982F8827802B912B880FF8 -:103E9000991F90930102809300027EC0863529F419 -:103EA00084E0A4D080E07CD078C0843609F04EC095 -:103EB00087D0E0910002F091010288E3E030F8073A -:103EC00018F483E087BFE895C0E0D1E071D0899312 -:103ED000809102028150809302028823B9F7E09119 -:103EE0000002F091010288E3E030F80718F083E067 -:103EF00087BFE89575D007B600FCFDCF4091000262 -:103F000050910102A0E0B1E02C9130E011968C912B -:103F1000119790E0982F8827822B932B1296FA0105 -:103F20000C01D7BEE89511244E5F5F4FF1E0A03839 -:103F3000BF0751F7E0910002F0910102E7BEE8955A -:103F400007B600FCFDCFF7BEE89527C08437B9F46B -:103F500037D046D0E0910002F09101023196F09303 -:103F60000102E09300023197E4918E2F19D08091E5 -:103F70000202815080930202882361F70EC08537C8 -:103F800039F42ED08EE10CD084E90AD086E08BCFB4 -:103F9000813511F488E019D023D080E101D05CCFC5 -:103FA000982F8091C00085FFFCCF9093C6000895A4 -:103FB000A8958091C00087FFFCCF8091C60008952E -:103FC000F7DFF6DF80930202F3CFE0E6F0E098E15E -:103FD00090838083089580E0F8DFEE27FF2709941F -:103FE000E7DF803209F0F7DF84E1DACF1F93182F83 -:0C3FF000DFDF1150E9F7F4DF1F910895A6 +:103E4000B09BFECF1D9AA8958150A9F79924939411 +:103E5000A5E0AA2EF1E1BF2E9DD0813421F481E0AE +:103E6000AFD083E01FC0823411F484E103C08534F5 +:103E700019F485E0A5D083C0853579F48BD0E82E80 +:103E8000FF2488D0082F10E0102F00270E291F29AB +:103E9000000F111F8DD0680172C0863529F484E0AF +:103EA0008FD080E06FD06BC0843609F042C072D0F2 +:103EB00071D0082F6FD080E0C81688E3D80620F4B0 +:103EC00083E0F60187BFE895C0E0D1E063D0899335 +:103ED0000C17E1F7F0E0CF16F8E3DF0620F083E0FF +:103EE000F60187BFE89564D007B600FCFDCFA601B8 +:103EF000A0E0B1E02C9130E011968C91119790E008 +:103F0000982F8827822B932B1296FA010C0197BECB +:103F1000E89511244E5F5F4FF1E0A038BF0751F7DD +:103F2000F601A7BEE89507B600FCFDCFB7BEE89541 +:103F300026C08437B1F42ED02DD0F82E2BD038D017 +:103F4000F601EF2C8F010F5F1F4F84911BD0EA9475 +:103F5000F801C1F70894C11CD11CFA94CF0CD11CF4 +:103F60000EC0853739F424D08EE10CD084E90AD014 +:103F700086E098CF813511F488E014D019D080E123 +:103F800001D06ACF982F8091C00085FFFCCF90931D +:103F9000C6000895A8958091C00087FFFCCF80914E +:103FA000C6000895E0E6F0E098E1908380830895EC +:103FB000F1DF803219F088E0F5DFFFCF84E1E2CF56 +:103FC0001F93182FE7DF1150E9F7F2DF1F910895D3 +:0A3FD00080E0E8DFEE27FF270994E8 :023FFE000104BC :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.lst b/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.lst index 516bed833..b1d8c1b69 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.lst @@ -3,27 +3,27 @@ optiboot_pro_16MHz.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .text 000001fc 00003e00 00003e00 00000054 2**1 + 0 .text 000001da 00003e00 00003e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .version 00000002 00003ffe 00003ffe 00000250 2**0 + 1 .version 00000002 00003ffe 00003ffe 0000022e 2**0 CONTENTS, READONLY - 2 .debug_aranges 00000028 00000000 00000000 00000252 2**0 + 2 .debug_aranges 00000028 00000000 00000000 00000230 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_pubnames 0000006a 00000000 00000000 0000027a 2**0 + 3 .debug_pubnames 0000005f 00000000 00000000 00000258 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_info 00000285 00000000 00000000 000002e4 2**0 + 4 .debug_info 0000028c 00000000 00000000 000002b7 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 0000019f 00000000 00000000 00000569 2**0 + 5 .debug_abbrev 00000199 00000000 00000000 00000543 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_line 00000453 00000000 00000000 00000708 2**0 + 6 .debug_line 00000456 00000000 00000000 000006dc 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000090 00000000 00000000 00000b5c 2**2 + 7 .debug_frame 00000080 00000000 00000000 00000b34 2**2 CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000141 00000000 00000000 00000bec 2**0 + 8 .debug_str 00000149 00000000 00000000 00000bb4 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 000001e1 00000000 00000000 00000d2d 2**0 + 9 .debug_loc 0000027e 00000000 00000000 00000cfd 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000068 00000000 00000000 00000f0e 2**0 + 10 .debug_ranges 00000060 00000000 00000000 00000f7b 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: @@ -47,7 +47,7 @@ int main(void) { 3e04: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); 3e06: 81 ff sbrs r24, 1 - 3e08: e6 d0 rcall .+460 ; 0x3fd6 + 3e08: e3 d0 rcall .+454 ; 0x3fd0 #if LED_START_FLASHES > 0 // Set up Timer 1 for timeout counter @@ -77,7 +77,7 @@ int main(void) { // Set up watchdog to trigger after 500ms watchdogConfig(WATCHDOG_1S); 3e28: 8e e0 ldi r24, 0x0E ; 14 - 3e2a: cf d0 rcall .+414 ; 0x3fca + 3e2a: bc d0 rcall .+376 ; 0x3fa4 /* Set LED pin as output */ LED_DDR |= _BV(LED); @@ -111,8 +111,8 @@ void flash_led(uint8_t count) { #else LED_PIN |= _BV(LED); 3e44: 1d 9a sbi 0x03, 5 ; 3 - return getch(); } +#endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { @@ -132,8 +132,8 @@ void watchdogReset() { if(ch == STK_GET_PARAMETER) { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 3e4c: dd 24 eor r13, r13 - 3e4e: d3 94 inc r13 + 3e4c: 99 24 eor r9, r9 + 3e4e: 93 94 inc r9 __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); @@ -141,21 +141,21 @@ void watchdogReset() { // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); 3e50: a5 e0 ldi r26, 0x05 ; 5 - 3e52: ea 2e mov r14, r26 + 3e52: aa 2e mov r10, r26 boot_spm_busy_wait(); #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); 3e54: f1 e1 ldi r31, 0x11 ; 17 - 3e56: ff 2e mov r15, r31 + 3e56: bf 2e mov r11, r31 #endif /* Forever loop */ for (;;) { /* get character from UART */ ch = getch(); - 3e58: ab d0 rcall .+342 ; 0x3fb0 + 3e58: 9d d0 rcall .+314 ; 0x3f94 if(ch == STK_GET_PARAMETER) { 3e5a: 81 34 cpi r24, 0x41 ; 65 @@ -163,10 +163,10 @@ void watchdogReset() { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); 3e5e: 81 e0 ldi r24, 0x01 ; 1 - 3e60: c5 d0 rcall .+394 ; 0x3fec + 3e60: af d0 rcall .+350 ; 0x3fc0 putch(0x03); 3e62: 83 e0 ldi r24, 0x03 ; 3 - 3e64: 20 c0 rjmp .+64 ; 0x3ea6 + 3e64: 1f c0 rjmp .+62 ; 0x3ea4 } else if(ch == STK_SET_DEVICE) { 3e66: 82 34 cpi r24, 0x42 ; 66 @@ -182,71 +182,77 @@ void watchdogReset() { // SET DEVICE EXT is ignored getNch(5); 3e72: 85 e0 ldi r24, 0x05 ; 5 - 3e74: bb d0 rcall .+374 ; 0x3fec - 3e76: 91 c0 rjmp .+290 ; 0x3f9a + 3e74: a5 d0 rcall .+330 ; 0x3fc0 + 3e76: 83 c0 rjmp .+262 ; 0x3f7e } else if(ch == STK_LOAD_ADDRESS) { 3e78: 85 35 cpi r24, 0x55 ; 85 - 3e7a: 81 f4 brne .+32 ; 0x3e9c + 3e7a: 79 f4 brne .+30 ; 0x3e9a // LOAD ADDRESS uint16_t newAddress; newAddress = getch(); - 3e7c: 99 d0 rcall .+306 ; 0x3fb0 + 3e7c: 8b d0 rcall .+278 ; 0x3f94 newAddress = (newAddress & 0xff) | (getch() << 8); - 3e7e: 08 2f mov r16, r24 - 3e80: 10 e0 ldi r17, 0x00 ; 0 - 3e82: 96 d0 rcall .+300 ; 0x3fb0 - 3e84: 90 e0 ldi r25, 0x00 ; 0 - 3e86: 98 2f mov r25, r24 - 3e88: 88 27 eor r24, r24 - 3e8a: 80 2b or r24, r16 - 3e8c: 91 2b or r25, r17 + 3e7e: e8 2e mov r14, r24 + 3e80: ff 24 eor r15, r15 + 3e82: 88 d0 rcall .+272 ; 0x3f94 + 3e84: 08 2f mov r16, r24 + 3e86: 10 e0 ldi r17, 0x00 ; 0 + 3e88: 10 2f mov r17, r16 + 3e8a: 00 27 eor r16, r16 + 3e8c: 0e 29 or r16, r14 + 3e8e: 1f 29 or r17, r15 #ifdef RAMPZ // Transfer top bit to RAMPZ RAMPZ = (newAddress & 0x8000) ? 1 : 0; #endif newAddress += newAddress; // Convert from word address to byte address - 3e8e: 88 0f add r24, r24 - 3e90: 99 1f adc r25, r25 + 3e90: 00 0f add r16, r16 + 3e92: 11 1f adc r17, r17 address = newAddress; - 3e92: 90 93 01 02 sts 0x0201, r25 - 3e96: 80 93 00 02 sts 0x0200, r24 - 3e9a: 7e c0 rjmp .+252 ; 0x3f98 verifySpace(); + 3e94: 8d d0 rcall .+282 ; 0x3fb0 + 3e96: 68 01 movw r12, r16 + 3e98: 72 c0 rjmp .+228 ; 0x3f7e } else if(ch == STK_UNIVERSAL) { - 3e9c: 86 35 cpi r24, 0x56 ; 86 - 3e9e: 29 f4 brne .+10 ; 0x3eaa + 3e9a: 86 35 cpi r24, 0x56 ; 86 + 3e9c: 29 f4 brne .+10 ; 0x3ea8 // UNIVERSAL command is ignored getNch(4); - 3ea0: 84 e0 ldi r24, 0x04 ; 4 - 3ea2: a4 d0 rcall .+328 ; 0x3fec + 3e9e: 84 e0 ldi r24, 0x04 ; 4 + 3ea0: 8f d0 rcall .+286 ; 0x3fc0 putch(0x00); - 3ea4: 80 e0 ldi r24, 0x00 ; 0 - 3ea6: 7c d0 rcall .+248 ; 0x3fa0 - 3ea8: 78 c0 rjmp .+240 ; 0x3f9a + 3ea2: 80 e0 ldi r24, 0x00 ; 0 + 3ea4: 6f d0 rcall .+222 ; 0x3f84 + 3ea6: 6b c0 rjmp .+214 ; 0x3f7e } /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { - 3eaa: 84 36 cpi r24, 0x64 ; 100 - 3eac: 09 f0 breq .+2 ; 0x3eb0 - 3eae: 4e c0 rjmp .+156 ; 0x3f4c + 3ea8: 84 36 cpi r24, 0x64 ; 100 + 3eaa: 09 f0 breq .+2 ; 0x3eae + 3eac: 42 c0 rjmp .+132 ; 0x3f32 // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t *bufPtr; uint16_t addrPtr; - getLen(); - 3eb0: 87 d0 rcall .+270 ; 0x3fc0 + getch(); /* getlen() */ + 3eae: 72 d0 rcall .+228 ; 0x3f94 + length = getch(); + 3eb0: 71 d0 rcall .+226 ; 0x3f94 + 3eb2: 08 2f mov r16, r24 + getch(); + 3eb4: 6f d0 rcall .+222 ; 0x3f94 // If we are in RWW section, immediately start page erase if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 3eb2: e0 91 00 02 lds r30, 0x0200 - 3eb6: f0 91 01 02 lds r31, 0x0201 + 3eb6: 80 e0 ldi r24, 0x00 ; 0 + 3eb8: c8 16 cp r12, r24 3eba: 88 e3 ldi r24, 0x38 ; 56 - 3ebc: e0 30 cpi r30, 0x00 ; 0 - 3ebe: f8 07 cpc r31, r24 - 3ec0: 18 f4 brcc .+6 ; 0x3ec8 - 3ec2: 83 e0 ldi r24, 0x03 ; 3 + 3ebc: d8 06 cpc r13, r24 + 3ebe: 20 f4 brcc .+8 ; 0x3ec8 + 3ec0: 83 e0 ldi r24, 0x03 ; 3 + 3ec2: f6 01 movw r30, r12 3ec4: 87 bf out 0x37, r24 ; 55 3ec6: e8 95 spm 3ec8: c0 e0 ldi r28, 0x00 ; 0 @@ -255,302 +261,301 @@ void watchdogReset() { // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); - 3ecc: 71 d0 rcall .+226 ; 0x3fb0 + 3ecc: 63 d0 rcall .+198 ; 0x3f94 3ece: 89 93 st Y+, r24 while (--length); - 3ed0: 80 91 02 02 lds r24, 0x0202 - 3ed4: 81 50 subi r24, 0x01 ; 1 - 3ed6: 80 93 02 02 sts 0x0202, r24 - 3eda: 88 23 and r24, r24 - 3edc: b9 f7 brne .-18 ; 0x3ecc + 3ed0: 0c 17 cp r16, r28 + 3ed2: e1 f7 brne .-8 ; 0x3ecc // If we are in NRWW section, page erase has to be delayed until now. // Todo: Take RAMPZ into account if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 3ede: e0 91 00 02 lds r30, 0x0200 - 3ee2: f0 91 01 02 lds r31, 0x0201 - 3ee6: 88 e3 ldi r24, 0x38 ; 56 - 3ee8: e0 30 cpi r30, 0x00 ; 0 - 3eea: f8 07 cpc r31, r24 - 3eec: 18 f0 brcs .+6 ; 0x3ef4 - 3eee: 83 e0 ldi r24, 0x03 ; 3 - 3ef0: 87 bf out 0x37, r24 ; 55 - 3ef2: e8 95 spm + 3ed4: f0 e0 ldi r31, 0x00 ; 0 + 3ed6: cf 16 cp r12, r31 + 3ed8: f8 e3 ldi r31, 0x38 ; 56 + 3eda: df 06 cpc r13, r31 + 3edc: 20 f0 brcs .+8 ; 0x3ee6 + 3ede: 83 e0 ldi r24, 0x03 ; 3 + 3ee0: f6 01 movw r30, r12 + 3ee2: 87 bf out 0x37, r24 ; 55 + 3ee4: e8 95 spm // Read command terminator, start reply verifySpace(); - 3ef4: 75 d0 rcall .+234 ; 0x3fe0 + 3ee6: 64 d0 rcall .+200 ; 0x3fb0 // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); - 3ef6: 07 b6 in r0, 0x37 ; 55 - 3ef8: 00 fc sbrc r0, 0 - 3efa: fd cf rjmp .-6 ; 0x3ef6 - } -#endif - - // Copy buffer into programming buffer + 3ee8: 07 b6 in r0, 0x37 ; 55 + 3eea: 00 fc sbrc r0, 0 + 3eec: fd cf rjmp .-6 ; 0x3ee8 + 3eee: a6 01 movw r20, r12 + 3ef0: a0 e0 ldi r26, 0x00 ; 0 + 3ef2: b1 e0 ldi r27, 0x01 ; 1 bufPtr = buff; addrPtr = (uint16_t)(void*)address; - 3efc: 40 91 00 02 lds r20, 0x0200 - 3f00: 50 91 01 02 lds r21, 0x0201 - 3f04: a0 e0 ldi r26, 0x00 ; 0 - 3f06: b1 e0 ldi r27, 0x01 ; 1 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; - 3f08: 2c 91 ld r18, X - 3f0a: 30 e0 ldi r19, 0x00 ; 0 + 3ef4: 2c 91 ld r18, X + 3ef6: 30 e0 ldi r19, 0x00 ; 0 a |= (*bufPtr++) << 8; - 3f0c: 11 96 adiw r26, 0x01 ; 1 - 3f0e: 8c 91 ld r24, X - 3f10: 11 97 sbiw r26, 0x01 ; 1 - 3f12: 90 e0 ldi r25, 0x00 ; 0 - 3f14: 98 2f mov r25, r24 - 3f16: 88 27 eor r24, r24 - 3f18: 82 2b or r24, r18 - 3f1a: 93 2b or r25, r19 + 3ef8: 11 96 adiw r26, 0x01 ; 1 + 3efa: 8c 91 ld r24, X + 3efc: 11 97 sbiw r26, 0x01 ; 1 + 3efe: 90 e0 ldi r25, 0x00 ; 0 + 3f00: 98 2f mov r25, r24 + 3f02: 88 27 eor r24, r24 + 3f04: 82 2b or r24, r18 + 3f06: 93 2b or r25, r19 #define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) #define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif /* main program starts here */ int main(void) { - 3f1c: 12 96 adiw r26, 0x02 ; 2 + 3f08: 12 96 adiw r26, 0x02 ; 2 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; a |= (*bufPtr++) << 8; __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - 3f1e: fa 01 movw r30, r20 - 3f20: 0c 01 movw r0, r24 - 3f22: d7 be out 0x37, r13 ; 55 - 3f24: e8 95 spm - 3f26: 11 24 eor r1, r1 + 3f0a: fa 01 movw r30, r20 + 3f0c: 0c 01 movw r0, r24 + 3f0e: 97 be out 0x37, r9 ; 55 + 3f10: e8 95 spm + 3f12: 11 24 eor r1, r1 addrPtr += 2; - 3f28: 4e 5f subi r20, 0xFE ; 254 - 3f2a: 5f 4f sbci r21, 0xFF ; 255 + 3f14: 4e 5f subi r20, 0xFE ; 254 + 3f16: 5f 4f sbci r21, 0xFF ; 255 } while (--ch); - 3f2c: f1 e0 ldi r31, 0x01 ; 1 - 3f2e: a0 38 cpi r26, 0x80 ; 128 - 3f30: bf 07 cpc r27, r31 - 3f32: 51 f7 brne .-44 ; 0x3f08 + 3f18: f1 e0 ldi r31, 0x01 ; 1 + 3f1a: a0 38 cpi r26, 0x80 ; 128 + 3f1c: bf 07 cpc r27, r31 + 3f1e: 51 f7 brne .-44 ; 0x3ef4 // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); - 3f34: e0 91 00 02 lds r30, 0x0200 - 3f38: f0 91 01 02 lds r31, 0x0201 - 3f3c: e7 be out 0x37, r14 ; 55 - 3f3e: e8 95 spm + 3f20: f6 01 movw r30, r12 + 3f22: a7 be out 0x37, r10 ; 55 + 3f24: e8 95 spm boot_spm_busy_wait(); - 3f40: 07 b6 in r0, 0x37 ; 55 - 3f42: 00 fc sbrc r0, 0 - 3f44: fd cf rjmp .-6 ; 0x3f40 + 3f26: 07 b6 in r0, 0x37 ; 55 + 3f28: 00 fc sbrc r0, 0 + 3f2a: fd cf rjmp .-6 ; 0x3f26 #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 3f46: f7 be out 0x37, r15 ; 55 - 3f48: e8 95 spm - 3f4a: 27 c0 rjmp .+78 ; 0x3f9a + 3f2c: b7 be out 0x37, r11 ; 55 + 3f2e: e8 95 spm + 3f30: 26 c0 rjmp .+76 ; 0x3f7e #endif } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { - 3f4c: 84 37 cpi r24, 0x74 ; 116 - 3f4e: b9 f4 brne .+46 ; 0x3f7e + 3f32: 84 37 cpi r24, 0x74 ; 116 + 3f34: b1 f4 brne .+44 ; 0x3f62 // READ PAGE - we only read flash - getLen(); - 3f50: 37 d0 rcall .+110 ; 0x3fc0 + getch(); /* getlen() */ + 3f36: 2e d0 rcall .+92 ; 0x3f94 + length = getch(); + 3f38: 2d d0 rcall .+90 ; 0x3f94 + 3f3a: f8 2e mov r15, r24 + getch(); + 3f3c: 2b d0 rcall .+86 ; 0x3f94 + verifySpace(); - 3f52: 46 d0 rcall .+140 ; 0x3fe0 + 3f3e: 38 d0 rcall .+112 ; 0x3fb0 + 3f40: f6 01 movw r30, r12 + 3f42: ef 2c mov r14, r15 putch(result); address++; } while (--length); #else do putch(pgm_read_byte_near(address++)); - 3f54: e0 91 00 02 lds r30, 0x0200 - 3f58: f0 91 01 02 lds r31, 0x0201 - 3f5c: 31 96 adiw r30, 0x01 ; 1 - 3f5e: f0 93 01 02 sts 0x0201, r31 - 3f62: e0 93 00 02 sts 0x0200, r30 - 3f66: 31 97 sbiw r30, 0x01 ; 1 - 3f68: e4 91 lpm r30, Z+ - 3f6a: 8e 2f mov r24, r30 - 3f6c: 19 d0 rcall .+50 ; 0x3fa0 + 3f44: 8f 01 movw r16, r30 + 3f46: 0f 5f subi r16, 0xFF ; 255 + 3f48: 1f 4f sbci r17, 0xFF ; 255 + 3f4a: 84 91 lpm r24, Z+ + 3f4c: 1b d0 rcall .+54 ; 0x3f84 while (--length); - 3f6e: 80 91 02 02 lds r24, 0x0202 - 3f72: 81 50 subi r24, 0x01 ; 1 - 3f74: 80 93 02 02 sts 0x0202, r24 - 3f78: 88 23 and r24, r24 - 3f7a: 61 f7 brne .-40 ; 0x3f54 - 3f7c: 0e c0 rjmp .+28 ; 0x3f9a + 3f4e: ea 94 dec r14 + 3f50: f8 01 movw r30, r16 + 3f52: c1 f7 brne .-16 ; 0x3f44 +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) +#endif + +/* main program starts here */ +int main(void) { + 3f54: 08 94 sec + 3f56: c1 1c adc r12, r1 + 3f58: d1 1c adc r13, r1 + 3f5a: fa 94 dec r15 + 3f5c: cf 0c add r12, r15 + 3f5e: d1 1c adc r13, r1 + 3f60: 0e c0 rjmp .+28 ; 0x3f7e #endif #endif } /* Get device signature bytes */ else if(ch == STK_READ_SIGN) { - 3f7e: 85 37 cpi r24, 0x75 ; 117 - 3f80: 39 f4 brne .+14 ; 0x3f90 + 3f62: 85 37 cpi r24, 0x75 ; 117 + 3f64: 39 f4 brne .+14 ; 0x3f74 // READ SIGN - return what Avrdude wants to hear verifySpace(); - 3f82: 2e d0 rcall .+92 ; 0x3fe0 + 3f66: 24 d0 rcall .+72 ; 0x3fb0 putch(SIGNATURE_0); - 3f84: 8e e1 ldi r24, 0x1E ; 30 - 3f86: 0c d0 rcall .+24 ; 0x3fa0 + 3f68: 8e e1 ldi r24, 0x1E ; 30 + 3f6a: 0c d0 rcall .+24 ; 0x3f84 putch(SIGNATURE_1); - 3f88: 84 e9 ldi r24, 0x94 ; 148 - 3f8a: 0a d0 rcall .+20 ; 0x3fa0 + 3f6c: 84 e9 ldi r24, 0x94 ; 148 + 3f6e: 0a d0 rcall .+20 ; 0x3f84 putch(SIGNATURE_2); - 3f8c: 86 e0 ldi r24, 0x06 ; 6 - 3f8e: 8b cf rjmp .-234 ; 0x3ea6 + 3f70: 86 e0 ldi r24, 0x06 ; 6 + 3f72: 98 cf rjmp .-208 ; 0x3ea4 } else if (ch == 'Q') { - 3f90: 81 35 cpi r24, 0x51 ; 81 - 3f92: 11 f4 brne .+4 ; 0x3f98 + 3f74: 81 35 cpi r24, 0x51 ; 81 + 3f76: 11 f4 brne .+4 ; 0x3f7c // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); - 3f94: 88 e0 ldi r24, 0x08 ; 8 - 3f96: 19 d0 rcall .+50 ; 0x3fca + 3f78: 88 e0 ldi r24, 0x08 ; 8 + 3f7a: 14 d0 rcall .+40 ; 0x3fa4 verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 3f98: 23 d0 rcall .+70 ; 0x3fe0 + 3f7c: 19 d0 rcall .+50 ; 0x3fb0 } putch(STK_OK); - 3f9a: 80 e1 ldi r24, 0x10 ; 16 - 3f9c: 01 d0 rcall .+2 ; 0x3fa0 - 3f9e: 5c cf rjmp .-328 ; 0x3e58 + 3f7e: 80 e1 ldi r24, 0x10 ; 16 + 3f80: 01 d0 rcall .+2 ; 0x3f84 + 3f82: 6a cf rjmp .-300 ; 0x3e58 -00003fa0 : +00003f84 : } } void putch(char ch) { - 3fa0: 98 2f mov r25, r24 + 3f84: 98 2f mov r25, r24 #ifndef SOFT_UART while (!(UCSR0A & _BV(UDRE0))); - 3fa2: 80 91 c0 00 lds r24, 0x00C0 - 3fa6: 85 ff sbrs r24, 5 - 3fa8: fc cf rjmp .-8 ; 0x3fa2 + 3f86: 80 91 c0 00 lds r24, 0x00C0 + 3f8a: 85 ff sbrs r24, 5 + 3f8c: fc cf rjmp .-8 ; 0x3f86 UDR0 = ch; - 3faa: 90 93 c6 00 sts 0x00C6, r25 + 3f8e: 90 93 c6 00 sts 0x00C6, r25 [uartBit] "I" (UART_TX_BIT) : "r25" ); #endif } - 3fae: 08 95 ret + 3f92: 08 95 ret -00003fb0 : - return getch(); +00003f94 : } +#endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 3fb0: a8 95 wdr + 3f94: a8 95 wdr [uartBit] "I" (UART_RX_BIT) : "r25" ); #else while(!(UCSR0A & _BV(RXC0))); - 3fb2: 80 91 c0 00 lds r24, 0x00C0 - 3fb6: 87 ff sbrs r24, 7 - 3fb8: fc cf rjmp .-8 ; 0x3fb2 + 3f96: 80 91 c0 00 lds r24, 0x00C0 + 3f9a: 87 ff sbrs r24, 7 + 3f9c: fc cf rjmp .-8 ; 0x3f96 ch = UDR0; - 3fba: 80 91 c6 00 lds r24, 0x00C6 + 3f9e: 80 91 c6 00 lds r24, 0x00C6 LED_PIN |= _BV(LED); #endif #endif return ch; } - 3fbe: 08 95 ret + 3fa2: 08 95 ret -00003fc0 : - } while (--count); -} -#endif - -uint8_t getLen() { - getch(); - 3fc0: f7 df rcall .-18 ; 0x3fb0 - length = getch(); - 3fc2: f6 df rcall .-20 ; 0x3fb0 - 3fc4: 80 93 02 02 sts 0x0202, r24 - return getch(); -} - 3fc8: f3 cf rjmp .-26 ; 0x3fb0 - -00003fca : +00003fa4 : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 3fca: e0 e6 ldi r30, 0x60 ; 96 - 3fcc: f0 e0 ldi r31, 0x00 ; 0 - 3fce: 98 e1 ldi r25, 0x18 ; 24 - 3fd0: 90 83 st Z, r25 + 3fa4: e0 e6 ldi r30, 0x60 ; 96 + 3fa6: f0 e0 ldi r31, 0x00 ; 0 + 3fa8: 98 e1 ldi r25, 0x18 ; 24 + 3faa: 90 83 st Z, r25 WDTCSR = x; - 3fd2: 80 83 st Z, r24 + 3fac: 80 83 st Z, r24 } - 3fd4: 08 95 ret + 3fae: 08 95 ret -00003fd6 : - -void appStart() { - watchdogConfig(WATCHDOG_OFF); - 3fd6: 80 e0 ldi r24, 0x00 ; 0 - 3fd8: f8 df rcall .-16 ; 0x3fca - __asm__ __volatile__ ( - 3fda: ee 27 eor r30, r30 - 3fdc: ff 27 eor r31, r31 - 3fde: 09 94 ijmp - -00003fe0 : +00003fb0 : do getch(); while (--count); verifySpace(); } void verifySpace() { - if (getch() != CRC_EOP) appStart(); - 3fe0: e7 df rcall .-50 ; 0x3fb0 - 3fe2: 80 32 cpi r24, 0x20 ; 32 - 3fe4: 09 f0 breq .+2 ; 0x3fe8 - 3fe6: f7 df rcall .-18 ; 0x3fd6 + if (getch() != CRC_EOP) { + 3fb0: f1 df rcall .-30 ; 0x3f94 + 3fb2: 80 32 cpi r24, 0x20 ; 32 + 3fb4: 19 f0 breq .+6 ; 0x3fbc + watchdogConfig(WATCHDOG_16MS); // shorten WD timeout + 3fb6: 88 e0 ldi r24, 0x08 ; 8 + 3fb8: f5 df rcall .-22 ; 0x3fa4 + 3fba: ff cf rjmp .-2 ; 0x3fba + while (1) // and busy-loop so that WD causes + ; // a reset and app start. + } putch(STK_INSYNC); - 3fe8: 84 e1 ldi r24, 0x14 ; 20 + 3fbc: 84 e1 ldi r24, 0x14 ; 20 } - 3fea: da cf rjmp .-76 ; 0x3fa0 + 3fbe: e2 cf rjmp .-60 ; 0x3f84 -00003fec : +00003fc0 : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 3fec: 1f 93 push r17 - 3fee: 18 2f mov r17, r24 + 3fc0: 1f 93 push r17 + 3fc2: 18 2f mov r17, r24 do getch(); while (--count); - 3ff0: df df rcall .-66 ; 0x3fb0 - 3ff2: 11 50 subi r17, 0x01 ; 1 - 3ff4: e9 f7 brne .-6 ; 0x3ff0 + 3fc4: e7 df rcall .-50 ; 0x3f94 + 3fc6: 11 50 subi r17, 0x01 ; 1 + 3fc8: e9 f7 brne .-6 ; 0x3fc4 verifySpace(); - 3ff6: f4 df rcall .-24 ; 0x3fe0 + 3fca: f2 df rcall .-28 ; 0x3fb0 } - 3ff8: 1f 91 pop r17 - 3ffa: 08 95 ret + 3fcc: 1f 91 pop r17 + 3fce: 08 95 ret + +00003fd0 : + WDTCSR = _BV(WDCE) | _BV(WDE); + WDTCSR = x; +} + +void appStart() { + watchdogConfig(WATCHDOG_OFF); + 3fd0: 80 e0 ldi r24, 0x00 ; 0 + 3fd2: e8 df rcall .-48 ; 0x3fa4 + __asm__ __volatile__ ( + 3fd4: ee 27 eor r30, r30 + 3fd6: ff 27 eor r31, r31 + 3fd8: 09 94 ijmp diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.hex b/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.hex index 01c974c6e..58ed1dcc4 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.hex @@ -1,35 +1,33 @@ -:103E0000112484B714BE81FFE6D085E08093810041 +:103E0000112484B714BE81FFE3D085E08093810044 :103E100082E08093C00088E18093C10086E08093B7 -:103E2000C20085E18093C4008EE0CFD0259A86E061 +:103E2000C20085E18093C4008EE0BCD0259A86E074 :103E30002CE33BEF91E0309385002093840096BB08 -:103E4000B09BFECF1D9AA8958150A9F7DD24D3948D -:103E5000A5E0EA2EF1E1FF2EABD0813421F481E020 -:103E6000C5D083E020C0823411F484E103C08534DE -:103E700019F485E0BBD091C0853581F499D0082F25 -:103E800010E096D090E0982F8827802B912B880FF8 -:103E9000991F90930102809300027EC0863529F419 -:103EA00084E0A4D080E07CD078C0843609F04EC095 -:103EB00087D0E0910002F091010288E3E030F8073A -:103EC00018F483E087BFE895C0E0D1E071D0899312 -:103ED000809102028150809302028823B9F7E09119 -:103EE0000002F091010288E3E030F80718F083E067 -:103EF00087BFE89575D007B600FCFDCF4091000262 -:103F000050910102A0E0B1E02C9130E011968C912B -:103F1000119790E0982F8827822B932B1296FA0105 -:103F20000C01D7BEE89511244E5F5F4FF1E0A03839 -:103F3000BF0751F7E0910002F0910102E7BEE8955A -:103F400007B600FCFDCFF7BEE89527C08437B9F46B -:103F500037D046D0E0910002F09101023196F09303 -:103F60000102E09300023197E4918E2F19D08091E5 -:103F70000202815080930202882361F70EC08537C8 -:103F800039F42ED08EE10CD084E90AD086E08BCFB4 -:103F9000813511F488E019D023D080E101D05CCFC5 -:103FA000982F8091C00085FFFCCF9093C6000895A4 -:103FB000A8958091C00087FFFCCF8091C60008952E -:103FC000F7DFF6DF80930202F3CFE0E6F0E098E15E -:103FD00090838083089580E0F8DFEE27FF2709941F -:103FE000E7DF803209F0F7DF84E1DACF1F93182F83 -:0C3FF000DFDF1150E9F7F4DF1F910895A6 +:103E4000B09BFECF1D9AA8958150A9F79924939411 +:103E5000A5E0AA2EF1E1BF2E9DD0813421F481E0AE +:103E6000AFD083E01FC0823411F484E103C08534F5 +:103E700019F485E0A5D083C0853579F48BD0E82E80 +:103E8000FF2488D0082F10E0102F00270E291F29AB +:103E9000000F111F8DD0680172C0863529F484E0AF +:103EA0008FD080E06FD06BC0843609F042C072D0F2 +:103EB00071D0082F6FD080E0C81688E3D80620F4B0 +:103EC00083E0F60187BFE895C0E0D1E063D0899335 +:103ED0000C17E1F7F0E0CF16F8E3DF0620F083E0FF +:103EE000F60187BFE89564D007B600FCFDCFA601B8 +:103EF000A0E0B1E02C9130E011968C91119790E008 +:103F0000982F8827822B932B1296FA010C0197BECB +:103F1000E89511244E5F5F4FF1E0A038BF0751F7DD +:103F2000F601A7BEE89507B600FCFDCFB7BEE89541 +:103F300026C08437B1F42ED02DD0F82E2BD038D017 +:103F4000F601EF2C8F010F5F1F4F84911BD0EA9475 +:103F5000F801C1F70894C11CD11CFA94CF0CD11CF4 +:103F60000EC0853739F424D08EE10CD084E90AD014 +:103F700086E098CF813511F488E014D019D080E123 +:103F800001D06ACF982F8091C00085FFFCCF90931D +:103F9000C6000895A8958091C00087FFFCCF80914E +:103FA000C6000895E0E6F0E098E1908380830895EC +:103FB000F1DF803219F088E0F5DFFFCF84E1E2CF56 +:103FC0001F93182FE7DF1150E9F7F2DF1F910895D3 +:0A3FD00080E0E8DFEE27FF270994E8 :023FFE000104BC :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.lst b/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.lst index ba7b6b6ff..cd2d66a64 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.lst @@ -3,27 +3,27 @@ optiboot_pro_20mhz.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .text 000001fc 00003e00 00003e00 00000054 2**1 + 0 .text 000001da 00003e00 00003e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .version 00000002 00003ffe 00003ffe 00000250 2**0 + 1 .version 00000002 00003ffe 00003ffe 0000022e 2**0 CONTENTS, READONLY - 2 .debug_aranges 00000028 00000000 00000000 00000252 2**0 + 2 .debug_aranges 00000028 00000000 00000000 00000230 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_pubnames 0000006a 00000000 00000000 0000027a 2**0 + 3 .debug_pubnames 0000005f 00000000 00000000 00000258 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_info 00000285 00000000 00000000 000002e4 2**0 + 4 .debug_info 0000028c 00000000 00000000 000002b7 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 0000019f 00000000 00000000 00000569 2**0 + 5 .debug_abbrev 00000199 00000000 00000000 00000543 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_line 00000453 00000000 00000000 00000708 2**0 + 6 .debug_line 00000456 00000000 00000000 000006dc 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000090 00000000 00000000 00000b5c 2**2 + 7 .debug_frame 00000080 00000000 00000000 00000b34 2**2 CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000141 00000000 00000000 00000bec 2**0 + 8 .debug_str 00000149 00000000 00000000 00000bb4 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 000001e1 00000000 00000000 00000d2d 2**0 + 9 .debug_loc 0000027e 00000000 00000000 00000cfd 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000068 00000000 00000000 00000f0e 2**0 + 10 .debug_ranges 00000060 00000000 00000000 00000f7b 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: @@ -47,7 +47,7 @@ int main(void) { 3e04: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); 3e06: 81 ff sbrs r24, 1 - 3e08: e6 d0 rcall .+460 ; 0x3fd6 + 3e08: e3 d0 rcall .+454 ; 0x3fd0 #if LED_START_FLASHES > 0 // Set up Timer 1 for timeout counter @@ -77,7 +77,7 @@ int main(void) { // Set up watchdog to trigger after 500ms watchdogConfig(WATCHDOG_1S); 3e28: 8e e0 ldi r24, 0x0E ; 14 - 3e2a: cf d0 rcall .+414 ; 0x3fca + 3e2a: bc d0 rcall .+376 ; 0x3fa4 /* Set LED pin as output */ LED_DDR |= _BV(LED); @@ -111,8 +111,8 @@ void flash_led(uint8_t count) { #else LED_PIN |= _BV(LED); 3e44: 1d 9a sbi 0x03, 5 ; 3 - return getch(); } +#endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { @@ -132,8 +132,8 @@ void watchdogReset() { if(ch == STK_GET_PARAMETER) { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 3e4c: dd 24 eor r13, r13 - 3e4e: d3 94 inc r13 + 3e4c: 99 24 eor r9, r9 + 3e4e: 93 94 inc r9 __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); @@ -141,21 +141,21 @@ void watchdogReset() { // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); 3e50: a5 e0 ldi r26, 0x05 ; 5 - 3e52: ea 2e mov r14, r26 + 3e52: aa 2e mov r10, r26 boot_spm_busy_wait(); #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); 3e54: f1 e1 ldi r31, 0x11 ; 17 - 3e56: ff 2e mov r15, r31 + 3e56: bf 2e mov r11, r31 #endif /* Forever loop */ for (;;) { /* get character from UART */ ch = getch(); - 3e58: ab d0 rcall .+342 ; 0x3fb0 + 3e58: 9d d0 rcall .+314 ; 0x3f94 if(ch == STK_GET_PARAMETER) { 3e5a: 81 34 cpi r24, 0x41 ; 65 @@ -163,10 +163,10 @@ void watchdogReset() { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); 3e5e: 81 e0 ldi r24, 0x01 ; 1 - 3e60: c5 d0 rcall .+394 ; 0x3fec + 3e60: af d0 rcall .+350 ; 0x3fc0 putch(0x03); 3e62: 83 e0 ldi r24, 0x03 ; 3 - 3e64: 20 c0 rjmp .+64 ; 0x3ea6 + 3e64: 1f c0 rjmp .+62 ; 0x3ea4 } else if(ch == STK_SET_DEVICE) { 3e66: 82 34 cpi r24, 0x42 ; 66 @@ -182,71 +182,77 @@ void watchdogReset() { // SET DEVICE EXT is ignored getNch(5); 3e72: 85 e0 ldi r24, 0x05 ; 5 - 3e74: bb d0 rcall .+374 ; 0x3fec - 3e76: 91 c0 rjmp .+290 ; 0x3f9a + 3e74: a5 d0 rcall .+330 ; 0x3fc0 + 3e76: 83 c0 rjmp .+262 ; 0x3f7e } else if(ch == STK_LOAD_ADDRESS) { 3e78: 85 35 cpi r24, 0x55 ; 85 - 3e7a: 81 f4 brne .+32 ; 0x3e9c + 3e7a: 79 f4 brne .+30 ; 0x3e9a // LOAD ADDRESS uint16_t newAddress; newAddress = getch(); - 3e7c: 99 d0 rcall .+306 ; 0x3fb0 + 3e7c: 8b d0 rcall .+278 ; 0x3f94 newAddress = (newAddress & 0xff) | (getch() << 8); - 3e7e: 08 2f mov r16, r24 - 3e80: 10 e0 ldi r17, 0x00 ; 0 - 3e82: 96 d0 rcall .+300 ; 0x3fb0 - 3e84: 90 e0 ldi r25, 0x00 ; 0 - 3e86: 98 2f mov r25, r24 - 3e88: 88 27 eor r24, r24 - 3e8a: 80 2b or r24, r16 - 3e8c: 91 2b or r25, r17 + 3e7e: e8 2e mov r14, r24 + 3e80: ff 24 eor r15, r15 + 3e82: 88 d0 rcall .+272 ; 0x3f94 + 3e84: 08 2f mov r16, r24 + 3e86: 10 e0 ldi r17, 0x00 ; 0 + 3e88: 10 2f mov r17, r16 + 3e8a: 00 27 eor r16, r16 + 3e8c: 0e 29 or r16, r14 + 3e8e: 1f 29 or r17, r15 #ifdef RAMPZ // Transfer top bit to RAMPZ RAMPZ = (newAddress & 0x8000) ? 1 : 0; #endif newAddress += newAddress; // Convert from word address to byte address - 3e8e: 88 0f add r24, r24 - 3e90: 99 1f adc r25, r25 + 3e90: 00 0f add r16, r16 + 3e92: 11 1f adc r17, r17 address = newAddress; - 3e92: 90 93 01 02 sts 0x0201, r25 - 3e96: 80 93 00 02 sts 0x0200, r24 - 3e9a: 7e c0 rjmp .+252 ; 0x3f98 verifySpace(); + 3e94: 8d d0 rcall .+282 ; 0x3fb0 + 3e96: 68 01 movw r12, r16 + 3e98: 72 c0 rjmp .+228 ; 0x3f7e } else if(ch == STK_UNIVERSAL) { - 3e9c: 86 35 cpi r24, 0x56 ; 86 - 3e9e: 29 f4 brne .+10 ; 0x3eaa + 3e9a: 86 35 cpi r24, 0x56 ; 86 + 3e9c: 29 f4 brne .+10 ; 0x3ea8 // UNIVERSAL command is ignored getNch(4); - 3ea0: 84 e0 ldi r24, 0x04 ; 4 - 3ea2: a4 d0 rcall .+328 ; 0x3fec + 3e9e: 84 e0 ldi r24, 0x04 ; 4 + 3ea0: 8f d0 rcall .+286 ; 0x3fc0 putch(0x00); - 3ea4: 80 e0 ldi r24, 0x00 ; 0 - 3ea6: 7c d0 rcall .+248 ; 0x3fa0 - 3ea8: 78 c0 rjmp .+240 ; 0x3f9a + 3ea2: 80 e0 ldi r24, 0x00 ; 0 + 3ea4: 6f d0 rcall .+222 ; 0x3f84 + 3ea6: 6b c0 rjmp .+214 ; 0x3f7e } /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { - 3eaa: 84 36 cpi r24, 0x64 ; 100 - 3eac: 09 f0 breq .+2 ; 0x3eb0 - 3eae: 4e c0 rjmp .+156 ; 0x3f4c + 3ea8: 84 36 cpi r24, 0x64 ; 100 + 3eaa: 09 f0 breq .+2 ; 0x3eae + 3eac: 42 c0 rjmp .+132 ; 0x3f32 // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t *bufPtr; uint16_t addrPtr; - getLen(); - 3eb0: 87 d0 rcall .+270 ; 0x3fc0 + getch(); /* getlen() */ + 3eae: 72 d0 rcall .+228 ; 0x3f94 + length = getch(); + 3eb0: 71 d0 rcall .+226 ; 0x3f94 + 3eb2: 08 2f mov r16, r24 + getch(); + 3eb4: 6f d0 rcall .+222 ; 0x3f94 // If we are in RWW section, immediately start page erase if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 3eb2: e0 91 00 02 lds r30, 0x0200 - 3eb6: f0 91 01 02 lds r31, 0x0201 + 3eb6: 80 e0 ldi r24, 0x00 ; 0 + 3eb8: c8 16 cp r12, r24 3eba: 88 e3 ldi r24, 0x38 ; 56 - 3ebc: e0 30 cpi r30, 0x00 ; 0 - 3ebe: f8 07 cpc r31, r24 - 3ec0: 18 f4 brcc .+6 ; 0x3ec8 - 3ec2: 83 e0 ldi r24, 0x03 ; 3 + 3ebc: d8 06 cpc r13, r24 + 3ebe: 20 f4 brcc .+8 ; 0x3ec8 + 3ec0: 83 e0 ldi r24, 0x03 ; 3 + 3ec2: f6 01 movw r30, r12 3ec4: 87 bf out 0x37, r24 ; 55 3ec6: e8 95 spm 3ec8: c0 e0 ldi r28, 0x00 ; 0 @@ -255,302 +261,301 @@ void watchdogReset() { // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); - 3ecc: 71 d0 rcall .+226 ; 0x3fb0 + 3ecc: 63 d0 rcall .+198 ; 0x3f94 3ece: 89 93 st Y+, r24 while (--length); - 3ed0: 80 91 02 02 lds r24, 0x0202 - 3ed4: 81 50 subi r24, 0x01 ; 1 - 3ed6: 80 93 02 02 sts 0x0202, r24 - 3eda: 88 23 and r24, r24 - 3edc: b9 f7 brne .-18 ; 0x3ecc + 3ed0: 0c 17 cp r16, r28 + 3ed2: e1 f7 brne .-8 ; 0x3ecc // If we are in NRWW section, page erase has to be delayed until now. // Todo: Take RAMPZ into account if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 3ede: e0 91 00 02 lds r30, 0x0200 - 3ee2: f0 91 01 02 lds r31, 0x0201 - 3ee6: 88 e3 ldi r24, 0x38 ; 56 - 3ee8: e0 30 cpi r30, 0x00 ; 0 - 3eea: f8 07 cpc r31, r24 - 3eec: 18 f0 brcs .+6 ; 0x3ef4 - 3eee: 83 e0 ldi r24, 0x03 ; 3 - 3ef0: 87 bf out 0x37, r24 ; 55 - 3ef2: e8 95 spm + 3ed4: f0 e0 ldi r31, 0x00 ; 0 + 3ed6: cf 16 cp r12, r31 + 3ed8: f8 e3 ldi r31, 0x38 ; 56 + 3eda: df 06 cpc r13, r31 + 3edc: 20 f0 brcs .+8 ; 0x3ee6 + 3ede: 83 e0 ldi r24, 0x03 ; 3 + 3ee0: f6 01 movw r30, r12 + 3ee2: 87 bf out 0x37, r24 ; 55 + 3ee4: e8 95 spm // Read command terminator, start reply verifySpace(); - 3ef4: 75 d0 rcall .+234 ; 0x3fe0 + 3ee6: 64 d0 rcall .+200 ; 0x3fb0 // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); - 3ef6: 07 b6 in r0, 0x37 ; 55 - 3ef8: 00 fc sbrc r0, 0 - 3efa: fd cf rjmp .-6 ; 0x3ef6 - } -#endif - - // Copy buffer into programming buffer + 3ee8: 07 b6 in r0, 0x37 ; 55 + 3eea: 00 fc sbrc r0, 0 + 3eec: fd cf rjmp .-6 ; 0x3ee8 + 3eee: a6 01 movw r20, r12 + 3ef0: a0 e0 ldi r26, 0x00 ; 0 + 3ef2: b1 e0 ldi r27, 0x01 ; 1 bufPtr = buff; addrPtr = (uint16_t)(void*)address; - 3efc: 40 91 00 02 lds r20, 0x0200 - 3f00: 50 91 01 02 lds r21, 0x0201 - 3f04: a0 e0 ldi r26, 0x00 ; 0 - 3f06: b1 e0 ldi r27, 0x01 ; 1 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; - 3f08: 2c 91 ld r18, X - 3f0a: 30 e0 ldi r19, 0x00 ; 0 + 3ef4: 2c 91 ld r18, X + 3ef6: 30 e0 ldi r19, 0x00 ; 0 a |= (*bufPtr++) << 8; - 3f0c: 11 96 adiw r26, 0x01 ; 1 - 3f0e: 8c 91 ld r24, X - 3f10: 11 97 sbiw r26, 0x01 ; 1 - 3f12: 90 e0 ldi r25, 0x00 ; 0 - 3f14: 98 2f mov r25, r24 - 3f16: 88 27 eor r24, r24 - 3f18: 82 2b or r24, r18 - 3f1a: 93 2b or r25, r19 + 3ef8: 11 96 adiw r26, 0x01 ; 1 + 3efa: 8c 91 ld r24, X + 3efc: 11 97 sbiw r26, 0x01 ; 1 + 3efe: 90 e0 ldi r25, 0x00 ; 0 + 3f00: 98 2f mov r25, r24 + 3f02: 88 27 eor r24, r24 + 3f04: 82 2b or r24, r18 + 3f06: 93 2b or r25, r19 #define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) #define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif /* main program starts here */ int main(void) { - 3f1c: 12 96 adiw r26, 0x02 ; 2 + 3f08: 12 96 adiw r26, 0x02 ; 2 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; a |= (*bufPtr++) << 8; __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - 3f1e: fa 01 movw r30, r20 - 3f20: 0c 01 movw r0, r24 - 3f22: d7 be out 0x37, r13 ; 55 - 3f24: e8 95 spm - 3f26: 11 24 eor r1, r1 + 3f0a: fa 01 movw r30, r20 + 3f0c: 0c 01 movw r0, r24 + 3f0e: 97 be out 0x37, r9 ; 55 + 3f10: e8 95 spm + 3f12: 11 24 eor r1, r1 addrPtr += 2; - 3f28: 4e 5f subi r20, 0xFE ; 254 - 3f2a: 5f 4f sbci r21, 0xFF ; 255 + 3f14: 4e 5f subi r20, 0xFE ; 254 + 3f16: 5f 4f sbci r21, 0xFF ; 255 } while (--ch); - 3f2c: f1 e0 ldi r31, 0x01 ; 1 - 3f2e: a0 38 cpi r26, 0x80 ; 128 - 3f30: bf 07 cpc r27, r31 - 3f32: 51 f7 brne .-44 ; 0x3f08 + 3f18: f1 e0 ldi r31, 0x01 ; 1 + 3f1a: a0 38 cpi r26, 0x80 ; 128 + 3f1c: bf 07 cpc r27, r31 + 3f1e: 51 f7 brne .-44 ; 0x3ef4 // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); - 3f34: e0 91 00 02 lds r30, 0x0200 - 3f38: f0 91 01 02 lds r31, 0x0201 - 3f3c: e7 be out 0x37, r14 ; 55 - 3f3e: e8 95 spm + 3f20: f6 01 movw r30, r12 + 3f22: a7 be out 0x37, r10 ; 55 + 3f24: e8 95 spm boot_spm_busy_wait(); - 3f40: 07 b6 in r0, 0x37 ; 55 - 3f42: 00 fc sbrc r0, 0 - 3f44: fd cf rjmp .-6 ; 0x3f40 + 3f26: 07 b6 in r0, 0x37 ; 55 + 3f28: 00 fc sbrc r0, 0 + 3f2a: fd cf rjmp .-6 ; 0x3f26 #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 3f46: f7 be out 0x37, r15 ; 55 - 3f48: e8 95 spm - 3f4a: 27 c0 rjmp .+78 ; 0x3f9a + 3f2c: b7 be out 0x37, r11 ; 55 + 3f2e: e8 95 spm + 3f30: 26 c0 rjmp .+76 ; 0x3f7e #endif } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { - 3f4c: 84 37 cpi r24, 0x74 ; 116 - 3f4e: b9 f4 brne .+46 ; 0x3f7e + 3f32: 84 37 cpi r24, 0x74 ; 116 + 3f34: b1 f4 brne .+44 ; 0x3f62 // READ PAGE - we only read flash - getLen(); - 3f50: 37 d0 rcall .+110 ; 0x3fc0 + getch(); /* getlen() */ + 3f36: 2e d0 rcall .+92 ; 0x3f94 + length = getch(); + 3f38: 2d d0 rcall .+90 ; 0x3f94 + 3f3a: f8 2e mov r15, r24 + getch(); + 3f3c: 2b d0 rcall .+86 ; 0x3f94 + verifySpace(); - 3f52: 46 d0 rcall .+140 ; 0x3fe0 + 3f3e: 38 d0 rcall .+112 ; 0x3fb0 + 3f40: f6 01 movw r30, r12 + 3f42: ef 2c mov r14, r15 putch(result); address++; } while (--length); #else do putch(pgm_read_byte_near(address++)); - 3f54: e0 91 00 02 lds r30, 0x0200 - 3f58: f0 91 01 02 lds r31, 0x0201 - 3f5c: 31 96 adiw r30, 0x01 ; 1 - 3f5e: f0 93 01 02 sts 0x0201, r31 - 3f62: e0 93 00 02 sts 0x0200, r30 - 3f66: 31 97 sbiw r30, 0x01 ; 1 - 3f68: e4 91 lpm r30, Z+ - 3f6a: 8e 2f mov r24, r30 - 3f6c: 19 d0 rcall .+50 ; 0x3fa0 + 3f44: 8f 01 movw r16, r30 + 3f46: 0f 5f subi r16, 0xFF ; 255 + 3f48: 1f 4f sbci r17, 0xFF ; 255 + 3f4a: 84 91 lpm r24, Z+ + 3f4c: 1b d0 rcall .+54 ; 0x3f84 while (--length); - 3f6e: 80 91 02 02 lds r24, 0x0202 - 3f72: 81 50 subi r24, 0x01 ; 1 - 3f74: 80 93 02 02 sts 0x0202, r24 - 3f78: 88 23 and r24, r24 - 3f7a: 61 f7 brne .-40 ; 0x3f54 - 3f7c: 0e c0 rjmp .+28 ; 0x3f9a + 3f4e: ea 94 dec r14 + 3f50: f8 01 movw r30, r16 + 3f52: c1 f7 brne .-16 ; 0x3f44 +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) +#endif + +/* main program starts here */ +int main(void) { + 3f54: 08 94 sec + 3f56: c1 1c adc r12, r1 + 3f58: d1 1c adc r13, r1 + 3f5a: fa 94 dec r15 + 3f5c: cf 0c add r12, r15 + 3f5e: d1 1c adc r13, r1 + 3f60: 0e c0 rjmp .+28 ; 0x3f7e #endif #endif } /* Get device signature bytes */ else if(ch == STK_READ_SIGN) { - 3f7e: 85 37 cpi r24, 0x75 ; 117 - 3f80: 39 f4 brne .+14 ; 0x3f90 + 3f62: 85 37 cpi r24, 0x75 ; 117 + 3f64: 39 f4 brne .+14 ; 0x3f74 // READ SIGN - return what Avrdude wants to hear verifySpace(); - 3f82: 2e d0 rcall .+92 ; 0x3fe0 + 3f66: 24 d0 rcall .+72 ; 0x3fb0 putch(SIGNATURE_0); - 3f84: 8e e1 ldi r24, 0x1E ; 30 - 3f86: 0c d0 rcall .+24 ; 0x3fa0 + 3f68: 8e e1 ldi r24, 0x1E ; 30 + 3f6a: 0c d0 rcall .+24 ; 0x3f84 putch(SIGNATURE_1); - 3f88: 84 e9 ldi r24, 0x94 ; 148 - 3f8a: 0a d0 rcall .+20 ; 0x3fa0 + 3f6c: 84 e9 ldi r24, 0x94 ; 148 + 3f6e: 0a d0 rcall .+20 ; 0x3f84 putch(SIGNATURE_2); - 3f8c: 86 e0 ldi r24, 0x06 ; 6 - 3f8e: 8b cf rjmp .-234 ; 0x3ea6 + 3f70: 86 e0 ldi r24, 0x06 ; 6 + 3f72: 98 cf rjmp .-208 ; 0x3ea4 } else if (ch == 'Q') { - 3f90: 81 35 cpi r24, 0x51 ; 81 - 3f92: 11 f4 brne .+4 ; 0x3f98 + 3f74: 81 35 cpi r24, 0x51 ; 81 + 3f76: 11 f4 brne .+4 ; 0x3f7c // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); - 3f94: 88 e0 ldi r24, 0x08 ; 8 - 3f96: 19 d0 rcall .+50 ; 0x3fca + 3f78: 88 e0 ldi r24, 0x08 ; 8 + 3f7a: 14 d0 rcall .+40 ; 0x3fa4 verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 3f98: 23 d0 rcall .+70 ; 0x3fe0 + 3f7c: 19 d0 rcall .+50 ; 0x3fb0 } putch(STK_OK); - 3f9a: 80 e1 ldi r24, 0x10 ; 16 - 3f9c: 01 d0 rcall .+2 ; 0x3fa0 - 3f9e: 5c cf rjmp .-328 ; 0x3e58 + 3f7e: 80 e1 ldi r24, 0x10 ; 16 + 3f80: 01 d0 rcall .+2 ; 0x3f84 + 3f82: 6a cf rjmp .-300 ; 0x3e58 -00003fa0 : +00003f84 : } } void putch(char ch) { - 3fa0: 98 2f mov r25, r24 + 3f84: 98 2f mov r25, r24 #ifndef SOFT_UART while (!(UCSR0A & _BV(UDRE0))); - 3fa2: 80 91 c0 00 lds r24, 0x00C0 - 3fa6: 85 ff sbrs r24, 5 - 3fa8: fc cf rjmp .-8 ; 0x3fa2 + 3f86: 80 91 c0 00 lds r24, 0x00C0 + 3f8a: 85 ff sbrs r24, 5 + 3f8c: fc cf rjmp .-8 ; 0x3f86 UDR0 = ch; - 3faa: 90 93 c6 00 sts 0x00C6, r25 + 3f8e: 90 93 c6 00 sts 0x00C6, r25 [uartBit] "I" (UART_TX_BIT) : "r25" ); #endif } - 3fae: 08 95 ret + 3f92: 08 95 ret -00003fb0 : - return getch(); +00003f94 : } +#endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 3fb0: a8 95 wdr + 3f94: a8 95 wdr [uartBit] "I" (UART_RX_BIT) : "r25" ); #else while(!(UCSR0A & _BV(RXC0))); - 3fb2: 80 91 c0 00 lds r24, 0x00C0 - 3fb6: 87 ff sbrs r24, 7 - 3fb8: fc cf rjmp .-8 ; 0x3fb2 + 3f96: 80 91 c0 00 lds r24, 0x00C0 + 3f9a: 87 ff sbrs r24, 7 + 3f9c: fc cf rjmp .-8 ; 0x3f96 ch = UDR0; - 3fba: 80 91 c6 00 lds r24, 0x00C6 + 3f9e: 80 91 c6 00 lds r24, 0x00C6 LED_PIN |= _BV(LED); #endif #endif return ch; } - 3fbe: 08 95 ret + 3fa2: 08 95 ret -00003fc0 : - } while (--count); -} -#endif - -uint8_t getLen() { - getch(); - 3fc0: f7 df rcall .-18 ; 0x3fb0 - length = getch(); - 3fc2: f6 df rcall .-20 ; 0x3fb0 - 3fc4: 80 93 02 02 sts 0x0202, r24 - return getch(); -} - 3fc8: f3 cf rjmp .-26 ; 0x3fb0 - -00003fca : +00003fa4 : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 3fca: e0 e6 ldi r30, 0x60 ; 96 - 3fcc: f0 e0 ldi r31, 0x00 ; 0 - 3fce: 98 e1 ldi r25, 0x18 ; 24 - 3fd0: 90 83 st Z, r25 + 3fa4: e0 e6 ldi r30, 0x60 ; 96 + 3fa6: f0 e0 ldi r31, 0x00 ; 0 + 3fa8: 98 e1 ldi r25, 0x18 ; 24 + 3faa: 90 83 st Z, r25 WDTCSR = x; - 3fd2: 80 83 st Z, r24 + 3fac: 80 83 st Z, r24 } - 3fd4: 08 95 ret + 3fae: 08 95 ret -00003fd6 : - -void appStart() { - watchdogConfig(WATCHDOG_OFF); - 3fd6: 80 e0 ldi r24, 0x00 ; 0 - 3fd8: f8 df rcall .-16 ; 0x3fca - __asm__ __volatile__ ( - 3fda: ee 27 eor r30, r30 - 3fdc: ff 27 eor r31, r31 - 3fde: 09 94 ijmp - -00003fe0 : +00003fb0 : do getch(); while (--count); verifySpace(); } void verifySpace() { - if (getch() != CRC_EOP) appStart(); - 3fe0: e7 df rcall .-50 ; 0x3fb0 - 3fe2: 80 32 cpi r24, 0x20 ; 32 - 3fe4: 09 f0 breq .+2 ; 0x3fe8 - 3fe6: f7 df rcall .-18 ; 0x3fd6 + if (getch() != CRC_EOP) { + 3fb0: f1 df rcall .-30 ; 0x3f94 + 3fb2: 80 32 cpi r24, 0x20 ; 32 + 3fb4: 19 f0 breq .+6 ; 0x3fbc + watchdogConfig(WATCHDOG_16MS); // shorten WD timeout + 3fb6: 88 e0 ldi r24, 0x08 ; 8 + 3fb8: f5 df rcall .-22 ; 0x3fa4 + 3fba: ff cf rjmp .-2 ; 0x3fba + while (1) // and busy-loop so that WD causes + ; // a reset and app start. + } putch(STK_INSYNC); - 3fe8: 84 e1 ldi r24, 0x14 ; 20 + 3fbc: 84 e1 ldi r24, 0x14 ; 20 } - 3fea: da cf rjmp .-76 ; 0x3fa0 + 3fbe: e2 cf rjmp .-60 ; 0x3f84 -00003fec : +00003fc0 : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 3fec: 1f 93 push r17 - 3fee: 18 2f mov r17, r24 + 3fc0: 1f 93 push r17 + 3fc2: 18 2f mov r17, r24 do getch(); while (--count); - 3ff0: df df rcall .-66 ; 0x3fb0 - 3ff2: 11 50 subi r17, 0x01 ; 1 - 3ff4: e9 f7 brne .-6 ; 0x3ff0 + 3fc4: e7 df rcall .-50 ; 0x3f94 + 3fc6: 11 50 subi r17, 0x01 ; 1 + 3fc8: e9 f7 brne .-6 ; 0x3fc4 verifySpace(); - 3ff6: f4 df rcall .-24 ; 0x3fe0 + 3fca: f2 df rcall .-28 ; 0x3fb0 } - 3ff8: 1f 91 pop r17 - 3ffa: 08 95 ret + 3fcc: 1f 91 pop r17 + 3fce: 08 95 ret + +00003fd0 : + WDTCSR = _BV(WDCE) | _BV(WDE); + WDTCSR = x; +} + +void appStart() { + watchdogConfig(WATCHDOG_OFF); + 3fd0: 80 e0 ldi r24, 0x00 ; 0 + 3fd2: e8 df rcall .-48 ; 0x3fa4 + __asm__ __volatile__ ( + 3fd4: ee 27 eor r30, r30 + 3fd6: ff 27 eor r31, r31 + 3fd8: 09 94 ijmp diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.hex b/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.hex index 77897e798..dcdbbb44f 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.hex @@ -1,35 +1,33 @@ -:103E0000112484B714BE81FFE6D085E08093810041 +:103E0000112484B714BE81FFE3D085E08093810044 :103E100082E08093C00088E18093C10086E08093B7 -:103E2000C20088E08093C4008EE0CFD0259A86E05F +:103E2000C20088E08093C4008EE0BCD0259A86E072 :103E300028E13EEF91E0309385002093840096BB0B -:103E4000B09BFECF1D9AA8958150A9F7DD24D3948D -:103E5000A5E0EA2EF1E1FF2EABD0813421F481E020 -:103E6000C5D083E020C0823411F484E103C08534DE -:103E700019F485E0BBD091C0853581F499D0082F25 -:103E800010E096D090E0982F8827802B912B880FF8 -:103E9000991F90930102809300027EC0863529F419 -:103EA00084E0A4D080E07CD078C0843609F04EC095 -:103EB00087D0E0910002F091010288E3E030F8073A -:103EC00018F483E087BFE895C0E0D1E071D0899312 -:103ED000809102028150809302028823B9F7E09119 -:103EE0000002F091010288E3E030F80718F083E067 -:103EF00087BFE89575D007B600FCFDCF4091000262 -:103F000050910102A0E0B1E02C9130E011968C912B -:103F1000119790E0982F8827822B932B1296FA0105 -:103F20000C01D7BEE89511244E5F5F4FF1E0A03839 -:103F3000BF0751F7E0910002F0910102E7BEE8955A -:103F400007B600FCFDCFF7BEE89527C08437B9F46B -:103F500037D046D0E0910002F09101023196F09303 -:103F60000102E09300023197E4918E2F19D08091E5 -:103F70000202815080930202882361F70EC08537C8 -:103F800039F42ED08EE10CD084E90AD086E08BCFB4 -:103F9000813511F488E019D023D080E101D05CCFC5 -:103FA000982F8091C00085FFFCCF9093C6000895A4 -:103FB000A8958091C00087FFFCCF8091C60008952E -:103FC000F7DFF6DF80930202F3CFE0E6F0E098E15E -:103FD00090838083089580E0F8DFEE27FF2709941F -:103FE000E7DF803209F0F7DF84E1DACF1F93182F83 -:0C3FF000DFDF1150E9F7F4DF1F910895A6 +:103E4000B09BFECF1D9AA8958150A9F79924939411 +:103E5000A5E0AA2EF1E1BF2E9DD0813421F481E0AE +:103E6000AFD083E01FC0823411F484E103C08534F5 +:103E700019F485E0A5D083C0853579F48BD0E82E80 +:103E8000FF2488D0082F10E0102F00270E291F29AB +:103E9000000F111F8DD0680172C0863529F484E0AF +:103EA0008FD080E06FD06BC0843609F042C072D0F2 +:103EB00071D0082F6FD080E0C81688E3D80620F4B0 +:103EC00083E0F60187BFE895C0E0D1E063D0899335 +:103ED0000C17E1F7F0E0CF16F8E3DF0620F083E0FF +:103EE000F60187BFE89564D007B600FCFDCFA601B8 +:103EF000A0E0B1E02C9130E011968C91119790E008 +:103F0000982F8827822B932B1296FA010C0197BECB +:103F1000E89511244E5F5F4FF1E0A038BF0751F7DD +:103F2000F601A7BEE89507B600FCFDCFB7BEE89541 +:103F300026C08437B1F42ED02DD0F82E2BD038D017 +:103F4000F601EF2C8F010F5F1F4F84911BD0EA9475 +:103F5000F801C1F70894C11CD11CFA94CF0CD11CF4 +:103F60000EC0853739F424D08EE10CD084E90AD014 +:103F700086E098CF813511F488E014D019D080E123 +:103F800001D06ACF982F8091C00085FFFCCF90931D +:103F9000C6000895A8958091C00087FFFCCF80914E +:103FA000C6000895E0E6F0E098E1908380830895EC +:103FB000F1DF803219F088E0F5DFFFCF84E1E2CF56 +:103FC0001F93182FE7DF1150E9F7F2DF1F910895D3 +:0A3FD00080E0E8DFEE27FF270994E8 :023FFE000104BC :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.lst b/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.lst index 23d5e1a10..d3d760e5c 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.lst @@ -3,27 +3,27 @@ optiboot_pro_8MHz.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .text 000001fc 00003e00 00003e00 00000054 2**1 + 0 .text 000001da 00003e00 00003e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .version 00000002 00003ffe 00003ffe 00000250 2**0 + 1 .version 00000002 00003ffe 00003ffe 0000022e 2**0 CONTENTS, READONLY - 2 .debug_aranges 00000028 00000000 00000000 00000252 2**0 + 2 .debug_aranges 00000028 00000000 00000000 00000230 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_pubnames 0000006a 00000000 00000000 0000027a 2**0 + 3 .debug_pubnames 0000005f 00000000 00000000 00000258 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_info 00000285 00000000 00000000 000002e4 2**0 + 4 .debug_info 0000028c 00000000 00000000 000002b7 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 0000019f 00000000 00000000 00000569 2**0 + 5 .debug_abbrev 00000199 00000000 00000000 00000543 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_line 00000453 00000000 00000000 00000708 2**0 + 6 .debug_line 00000456 00000000 00000000 000006dc 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000090 00000000 00000000 00000b5c 2**2 + 7 .debug_frame 00000080 00000000 00000000 00000b34 2**2 CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000141 00000000 00000000 00000bec 2**0 + 8 .debug_str 00000149 00000000 00000000 00000bb4 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 000001e1 00000000 00000000 00000d2d 2**0 + 9 .debug_loc 0000027e 00000000 00000000 00000cfd 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000068 00000000 00000000 00000f0e 2**0 + 10 .debug_ranges 00000060 00000000 00000000 00000f7b 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: @@ -47,7 +47,7 @@ int main(void) { 3e04: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); 3e06: 81 ff sbrs r24, 1 - 3e08: e6 d0 rcall .+460 ; 0x3fd6 + 3e08: e3 d0 rcall .+454 ; 0x3fd0 #if LED_START_FLASHES > 0 // Set up Timer 1 for timeout counter @@ -77,7 +77,7 @@ int main(void) { // Set up watchdog to trigger after 500ms watchdogConfig(WATCHDOG_1S); 3e28: 8e e0 ldi r24, 0x0E ; 14 - 3e2a: cf d0 rcall .+414 ; 0x3fca + 3e2a: bc d0 rcall .+376 ; 0x3fa4 /* Set LED pin as output */ LED_DDR |= _BV(LED); @@ -111,8 +111,8 @@ void flash_led(uint8_t count) { #else LED_PIN |= _BV(LED); 3e44: 1d 9a sbi 0x03, 5 ; 3 - return getch(); } +#endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { @@ -132,8 +132,8 @@ void watchdogReset() { if(ch == STK_GET_PARAMETER) { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 3e4c: dd 24 eor r13, r13 - 3e4e: d3 94 inc r13 + 3e4c: 99 24 eor r9, r9 + 3e4e: 93 94 inc r9 __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); @@ -141,21 +141,21 @@ void watchdogReset() { // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); 3e50: a5 e0 ldi r26, 0x05 ; 5 - 3e52: ea 2e mov r14, r26 + 3e52: aa 2e mov r10, r26 boot_spm_busy_wait(); #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); 3e54: f1 e1 ldi r31, 0x11 ; 17 - 3e56: ff 2e mov r15, r31 + 3e56: bf 2e mov r11, r31 #endif /* Forever loop */ for (;;) { /* get character from UART */ ch = getch(); - 3e58: ab d0 rcall .+342 ; 0x3fb0 + 3e58: 9d d0 rcall .+314 ; 0x3f94 if(ch == STK_GET_PARAMETER) { 3e5a: 81 34 cpi r24, 0x41 ; 65 @@ -163,10 +163,10 @@ void watchdogReset() { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); 3e5e: 81 e0 ldi r24, 0x01 ; 1 - 3e60: c5 d0 rcall .+394 ; 0x3fec + 3e60: af d0 rcall .+350 ; 0x3fc0 putch(0x03); 3e62: 83 e0 ldi r24, 0x03 ; 3 - 3e64: 20 c0 rjmp .+64 ; 0x3ea6 + 3e64: 1f c0 rjmp .+62 ; 0x3ea4 } else if(ch == STK_SET_DEVICE) { 3e66: 82 34 cpi r24, 0x42 ; 66 @@ -182,71 +182,77 @@ void watchdogReset() { // SET DEVICE EXT is ignored getNch(5); 3e72: 85 e0 ldi r24, 0x05 ; 5 - 3e74: bb d0 rcall .+374 ; 0x3fec - 3e76: 91 c0 rjmp .+290 ; 0x3f9a + 3e74: a5 d0 rcall .+330 ; 0x3fc0 + 3e76: 83 c0 rjmp .+262 ; 0x3f7e } else if(ch == STK_LOAD_ADDRESS) { 3e78: 85 35 cpi r24, 0x55 ; 85 - 3e7a: 81 f4 brne .+32 ; 0x3e9c + 3e7a: 79 f4 brne .+30 ; 0x3e9a // LOAD ADDRESS uint16_t newAddress; newAddress = getch(); - 3e7c: 99 d0 rcall .+306 ; 0x3fb0 + 3e7c: 8b d0 rcall .+278 ; 0x3f94 newAddress = (newAddress & 0xff) | (getch() << 8); - 3e7e: 08 2f mov r16, r24 - 3e80: 10 e0 ldi r17, 0x00 ; 0 - 3e82: 96 d0 rcall .+300 ; 0x3fb0 - 3e84: 90 e0 ldi r25, 0x00 ; 0 - 3e86: 98 2f mov r25, r24 - 3e88: 88 27 eor r24, r24 - 3e8a: 80 2b or r24, r16 - 3e8c: 91 2b or r25, r17 + 3e7e: e8 2e mov r14, r24 + 3e80: ff 24 eor r15, r15 + 3e82: 88 d0 rcall .+272 ; 0x3f94 + 3e84: 08 2f mov r16, r24 + 3e86: 10 e0 ldi r17, 0x00 ; 0 + 3e88: 10 2f mov r17, r16 + 3e8a: 00 27 eor r16, r16 + 3e8c: 0e 29 or r16, r14 + 3e8e: 1f 29 or r17, r15 #ifdef RAMPZ // Transfer top bit to RAMPZ RAMPZ = (newAddress & 0x8000) ? 1 : 0; #endif newAddress += newAddress; // Convert from word address to byte address - 3e8e: 88 0f add r24, r24 - 3e90: 99 1f adc r25, r25 + 3e90: 00 0f add r16, r16 + 3e92: 11 1f adc r17, r17 address = newAddress; - 3e92: 90 93 01 02 sts 0x0201, r25 - 3e96: 80 93 00 02 sts 0x0200, r24 - 3e9a: 7e c0 rjmp .+252 ; 0x3f98 verifySpace(); + 3e94: 8d d0 rcall .+282 ; 0x3fb0 + 3e96: 68 01 movw r12, r16 + 3e98: 72 c0 rjmp .+228 ; 0x3f7e } else if(ch == STK_UNIVERSAL) { - 3e9c: 86 35 cpi r24, 0x56 ; 86 - 3e9e: 29 f4 brne .+10 ; 0x3eaa + 3e9a: 86 35 cpi r24, 0x56 ; 86 + 3e9c: 29 f4 brne .+10 ; 0x3ea8 // UNIVERSAL command is ignored getNch(4); - 3ea0: 84 e0 ldi r24, 0x04 ; 4 - 3ea2: a4 d0 rcall .+328 ; 0x3fec + 3e9e: 84 e0 ldi r24, 0x04 ; 4 + 3ea0: 8f d0 rcall .+286 ; 0x3fc0 putch(0x00); - 3ea4: 80 e0 ldi r24, 0x00 ; 0 - 3ea6: 7c d0 rcall .+248 ; 0x3fa0 - 3ea8: 78 c0 rjmp .+240 ; 0x3f9a + 3ea2: 80 e0 ldi r24, 0x00 ; 0 + 3ea4: 6f d0 rcall .+222 ; 0x3f84 + 3ea6: 6b c0 rjmp .+214 ; 0x3f7e } /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { - 3eaa: 84 36 cpi r24, 0x64 ; 100 - 3eac: 09 f0 breq .+2 ; 0x3eb0 - 3eae: 4e c0 rjmp .+156 ; 0x3f4c + 3ea8: 84 36 cpi r24, 0x64 ; 100 + 3eaa: 09 f0 breq .+2 ; 0x3eae + 3eac: 42 c0 rjmp .+132 ; 0x3f32 // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t *bufPtr; uint16_t addrPtr; - getLen(); - 3eb0: 87 d0 rcall .+270 ; 0x3fc0 + getch(); /* getlen() */ + 3eae: 72 d0 rcall .+228 ; 0x3f94 + length = getch(); + 3eb0: 71 d0 rcall .+226 ; 0x3f94 + 3eb2: 08 2f mov r16, r24 + getch(); + 3eb4: 6f d0 rcall .+222 ; 0x3f94 // If we are in RWW section, immediately start page erase if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 3eb2: e0 91 00 02 lds r30, 0x0200 - 3eb6: f0 91 01 02 lds r31, 0x0201 + 3eb6: 80 e0 ldi r24, 0x00 ; 0 + 3eb8: c8 16 cp r12, r24 3eba: 88 e3 ldi r24, 0x38 ; 56 - 3ebc: e0 30 cpi r30, 0x00 ; 0 - 3ebe: f8 07 cpc r31, r24 - 3ec0: 18 f4 brcc .+6 ; 0x3ec8 - 3ec2: 83 e0 ldi r24, 0x03 ; 3 + 3ebc: d8 06 cpc r13, r24 + 3ebe: 20 f4 brcc .+8 ; 0x3ec8 + 3ec0: 83 e0 ldi r24, 0x03 ; 3 + 3ec2: f6 01 movw r30, r12 3ec4: 87 bf out 0x37, r24 ; 55 3ec6: e8 95 spm 3ec8: c0 e0 ldi r28, 0x00 ; 0 @@ -255,302 +261,301 @@ void watchdogReset() { // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); - 3ecc: 71 d0 rcall .+226 ; 0x3fb0 + 3ecc: 63 d0 rcall .+198 ; 0x3f94 3ece: 89 93 st Y+, r24 while (--length); - 3ed0: 80 91 02 02 lds r24, 0x0202 - 3ed4: 81 50 subi r24, 0x01 ; 1 - 3ed6: 80 93 02 02 sts 0x0202, r24 - 3eda: 88 23 and r24, r24 - 3edc: b9 f7 brne .-18 ; 0x3ecc + 3ed0: 0c 17 cp r16, r28 + 3ed2: e1 f7 brne .-8 ; 0x3ecc // If we are in NRWW section, page erase has to be delayed until now. // Todo: Take RAMPZ into account if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 3ede: e0 91 00 02 lds r30, 0x0200 - 3ee2: f0 91 01 02 lds r31, 0x0201 - 3ee6: 88 e3 ldi r24, 0x38 ; 56 - 3ee8: e0 30 cpi r30, 0x00 ; 0 - 3eea: f8 07 cpc r31, r24 - 3eec: 18 f0 brcs .+6 ; 0x3ef4 - 3eee: 83 e0 ldi r24, 0x03 ; 3 - 3ef0: 87 bf out 0x37, r24 ; 55 - 3ef2: e8 95 spm + 3ed4: f0 e0 ldi r31, 0x00 ; 0 + 3ed6: cf 16 cp r12, r31 + 3ed8: f8 e3 ldi r31, 0x38 ; 56 + 3eda: df 06 cpc r13, r31 + 3edc: 20 f0 brcs .+8 ; 0x3ee6 + 3ede: 83 e0 ldi r24, 0x03 ; 3 + 3ee0: f6 01 movw r30, r12 + 3ee2: 87 bf out 0x37, r24 ; 55 + 3ee4: e8 95 spm // Read command terminator, start reply verifySpace(); - 3ef4: 75 d0 rcall .+234 ; 0x3fe0 + 3ee6: 64 d0 rcall .+200 ; 0x3fb0 // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); - 3ef6: 07 b6 in r0, 0x37 ; 55 - 3ef8: 00 fc sbrc r0, 0 - 3efa: fd cf rjmp .-6 ; 0x3ef6 - } -#endif - - // Copy buffer into programming buffer + 3ee8: 07 b6 in r0, 0x37 ; 55 + 3eea: 00 fc sbrc r0, 0 + 3eec: fd cf rjmp .-6 ; 0x3ee8 + 3eee: a6 01 movw r20, r12 + 3ef0: a0 e0 ldi r26, 0x00 ; 0 + 3ef2: b1 e0 ldi r27, 0x01 ; 1 bufPtr = buff; addrPtr = (uint16_t)(void*)address; - 3efc: 40 91 00 02 lds r20, 0x0200 - 3f00: 50 91 01 02 lds r21, 0x0201 - 3f04: a0 e0 ldi r26, 0x00 ; 0 - 3f06: b1 e0 ldi r27, 0x01 ; 1 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; - 3f08: 2c 91 ld r18, X - 3f0a: 30 e0 ldi r19, 0x00 ; 0 + 3ef4: 2c 91 ld r18, X + 3ef6: 30 e0 ldi r19, 0x00 ; 0 a |= (*bufPtr++) << 8; - 3f0c: 11 96 adiw r26, 0x01 ; 1 - 3f0e: 8c 91 ld r24, X - 3f10: 11 97 sbiw r26, 0x01 ; 1 - 3f12: 90 e0 ldi r25, 0x00 ; 0 - 3f14: 98 2f mov r25, r24 - 3f16: 88 27 eor r24, r24 - 3f18: 82 2b or r24, r18 - 3f1a: 93 2b or r25, r19 + 3ef8: 11 96 adiw r26, 0x01 ; 1 + 3efa: 8c 91 ld r24, X + 3efc: 11 97 sbiw r26, 0x01 ; 1 + 3efe: 90 e0 ldi r25, 0x00 ; 0 + 3f00: 98 2f mov r25, r24 + 3f02: 88 27 eor r24, r24 + 3f04: 82 2b or r24, r18 + 3f06: 93 2b or r25, r19 #define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) #define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif /* main program starts here */ int main(void) { - 3f1c: 12 96 adiw r26, 0x02 ; 2 + 3f08: 12 96 adiw r26, 0x02 ; 2 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; a |= (*bufPtr++) << 8; __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - 3f1e: fa 01 movw r30, r20 - 3f20: 0c 01 movw r0, r24 - 3f22: d7 be out 0x37, r13 ; 55 - 3f24: e8 95 spm - 3f26: 11 24 eor r1, r1 + 3f0a: fa 01 movw r30, r20 + 3f0c: 0c 01 movw r0, r24 + 3f0e: 97 be out 0x37, r9 ; 55 + 3f10: e8 95 spm + 3f12: 11 24 eor r1, r1 addrPtr += 2; - 3f28: 4e 5f subi r20, 0xFE ; 254 - 3f2a: 5f 4f sbci r21, 0xFF ; 255 + 3f14: 4e 5f subi r20, 0xFE ; 254 + 3f16: 5f 4f sbci r21, 0xFF ; 255 } while (--ch); - 3f2c: f1 e0 ldi r31, 0x01 ; 1 - 3f2e: a0 38 cpi r26, 0x80 ; 128 - 3f30: bf 07 cpc r27, r31 - 3f32: 51 f7 brne .-44 ; 0x3f08 + 3f18: f1 e0 ldi r31, 0x01 ; 1 + 3f1a: a0 38 cpi r26, 0x80 ; 128 + 3f1c: bf 07 cpc r27, r31 + 3f1e: 51 f7 brne .-44 ; 0x3ef4 // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); - 3f34: e0 91 00 02 lds r30, 0x0200 - 3f38: f0 91 01 02 lds r31, 0x0201 - 3f3c: e7 be out 0x37, r14 ; 55 - 3f3e: e8 95 spm + 3f20: f6 01 movw r30, r12 + 3f22: a7 be out 0x37, r10 ; 55 + 3f24: e8 95 spm boot_spm_busy_wait(); - 3f40: 07 b6 in r0, 0x37 ; 55 - 3f42: 00 fc sbrc r0, 0 - 3f44: fd cf rjmp .-6 ; 0x3f40 + 3f26: 07 b6 in r0, 0x37 ; 55 + 3f28: 00 fc sbrc r0, 0 + 3f2a: fd cf rjmp .-6 ; 0x3f26 #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 3f46: f7 be out 0x37, r15 ; 55 - 3f48: e8 95 spm - 3f4a: 27 c0 rjmp .+78 ; 0x3f9a + 3f2c: b7 be out 0x37, r11 ; 55 + 3f2e: e8 95 spm + 3f30: 26 c0 rjmp .+76 ; 0x3f7e #endif } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { - 3f4c: 84 37 cpi r24, 0x74 ; 116 - 3f4e: b9 f4 brne .+46 ; 0x3f7e + 3f32: 84 37 cpi r24, 0x74 ; 116 + 3f34: b1 f4 brne .+44 ; 0x3f62 // READ PAGE - we only read flash - getLen(); - 3f50: 37 d0 rcall .+110 ; 0x3fc0 + getch(); /* getlen() */ + 3f36: 2e d0 rcall .+92 ; 0x3f94 + length = getch(); + 3f38: 2d d0 rcall .+90 ; 0x3f94 + 3f3a: f8 2e mov r15, r24 + getch(); + 3f3c: 2b d0 rcall .+86 ; 0x3f94 + verifySpace(); - 3f52: 46 d0 rcall .+140 ; 0x3fe0 + 3f3e: 38 d0 rcall .+112 ; 0x3fb0 + 3f40: f6 01 movw r30, r12 + 3f42: ef 2c mov r14, r15 putch(result); address++; } while (--length); #else do putch(pgm_read_byte_near(address++)); - 3f54: e0 91 00 02 lds r30, 0x0200 - 3f58: f0 91 01 02 lds r31, 0x0201 - 3f5c: 31 96 adiw r30, 0x01 ; 1 - 3f5e: f0 93 01 02 sts 0x0201, r31 - 3f62: e0 93 00 02 sts 0x0200, r30 - 3f66: 31 97 sbiw r30, 0x01 ; 1 - 3f68: e4 91 lpm r30, Z+ - 3f6a: 8e 2f mov r24, r30 - 3f6c: 19 d0 rcall .+50 ; 0x3fa0 + 3f44: 8f 01 movw r16, r30 + 3f46: 0f 5f subi r16, 0xFF ; 255 + 3f48: 1f 4f sbci r17, 0xFF ; 255 + 3f4a: 84 91 lpm r24, Z+ + 3f4c: 1b d0 rcall .+54 ; 0x3f84 while (--length); - 3f6e: 80 91 02 02 lds r24, 0x0202 - 3f72: 81 50 subi r24, 0x01 ; 1 - 3f74: 80 93 02 02 sts 0x0202, r24 - 3f78: 88 23 and r24, r24 - 3f7a: 61 f7 brne .-40 ; 0x3f54 - 3f7c: 0e c0 rjmp .+28 ; 0x3f9a + 3f4e: ea 94 dec r14 + 3f50: f8 01 movw r30, r16 + 3f52: c1 f7 brne .-16 ; 0x3f44 +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) +#endif + +/* main program starts here */ +int main(void) { + 3f54: 08 94 sec + 3f56: c1 1c adc r12, r1 + 3f58: d1 1c adc r13, r1 + 3f5a: fa 94 dec r15 + 3f5c: cf 0c add r12, r15 + 3f5e: d1 1c adc r13, r1 + 3f60: 0e c0 rjmp .+28 ; 0x3f7e #endif #endif } /* Get device signature bytes */ else if(ch == STK_READ_SIGN) { - 3f7e: 85 37 cpi r24, 0x75 ; 117 - 3f80: 39 f4 brne .+14 ; 0x3f90 + 3f62: 85 37 cpi r24, 0x75 ; 117 + 3f64: 39 f4 brne .+14 ; 0x3f74 // READ SIGN - return what Avrdude wants to hear verifySpace(); - 3f82: 2e d0 rcall .+92 ; 0x3fe0 + 3f66: 24 d0 rcall .+72 ; 0x3fb0 putch(SIGNATURE_0); - 3f84: 8e e1 ldi r24, 0x1E ; 30 - 3f86: 0c d0 rcall .+24 ; 0x3fa0 + 3f68: 8e e1 ldi r24, 0x1E ; 30 + 3f6a: 0c d0 rcall .+24 ; 0x3f84 putch(SIGNATURE_1); - 3f88: 84 e9 ldi r24, 0x94 ; 148 - 3f8a: 0a d0 rcall .+20 ; 0x3fa0 + 3f6c: 84 e9 ldi r24, 0x94 ; 148 + 3f6e: 0a d0 rcall .+20 ; 0x3f84 putch(SIGNATURE_2); - 3f8c: 86 e0 ldi r24, 0x06 ; 6 - 3f8e: 8b cf rjmp .-234 ; 0x3ea6 + 3f70: 86 e0 ldi r24, 0x06 ; 6 + 3f72: 98 cf rjmp .-208 ; 0x3ea4 } else if (ch == 'Q') { - 3f90: 81 35 cpi r24, 0x51 ; 81 - 3f92: 11 f4 brne .+4 ; 0x3f98 + 3f74: 81 35 cpi r24, 0x51 ; 81 + 3f76: 11 f4 brne .+4 ; 0x3f7c // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); - 3f94: 88 e0 ldi r24, 0x08 ; 8 - 3f96: 19 d0 rcall .+50 ; 0x3fca + 3f78: 88 e0 ldi r24, 0x08 ; 8 + 3f7a: 14 d0 rcall .+40 ; 0x3fa4 verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 3f98: 23 d0 rcall .+70 ; 0x3fe0 + 3f7c: 19 d0 rcall .+50 ; 0x3fb0 } putch(STK_OK); - 3f9a: 80 e1 ldi r24, 0x10 ; 16 - 3f9c: 01 d0 rcall .+2 ; 0x3fa0 - 3f9e: 5c cf rjmp .-328 ; 0x3e58 + 3f7e: 80 e1 ldi r24, 0x10 ; 16 + 3f80: 01 d0 rcall .+2 ; 0x3f84 + 3f82: 6a cf rjmp .-300 ; 0x3e58 -00003fa0 : +00003f84 : } } void putch(char ch) { - 3fa0: 98 2f mov r25, r24 + 3f84: 98 2f mov r25, r24 #ifndef SOFT_UART while (!(UCSR0A & _BV(UDRE0))); - 3fa2: 80 91 c0 00 lds r24, 0x00C0 - 3fa6: 85 ff sbrs r24, 5 - 3fa8: fc cf rjmp .-8 ; 0x3fa2 + 3f86: 80 91 c0 00 lds r24, 0x00C0 + 3f8a: 85 ff sbrs r24, 5 + 3f8c: fc cf rjmp .-8 ; 0x3f86 UDR0 = ch; - 3faa: 90 93 c6 00 sts 0x00C6, r25 + 3f8e: 90 93 c6 00 sts 0x00C6, r25 [uartBit] "I" (UART_TX_BIT) : "r25" ); #endif } - 3fae: 08 95 ret + 3f92: 08 95 ret -00003fb0 : - return getch(); +00003f94 : } +#endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 3fb0: a8 95 wdr + 3f94: a8 95 wdr [uartBit] "I" (UART_RX_BIT) : "r25" ); #else while(!(UCSR0A & _BV(RXC0))); - 3fb2: 80 91 c0 00 lds r24, 0x00C0 - 3fb6: 87 ff sbrs r24, 7 - 3fb8: fc cf rjmp .-8 ; 0x3fb2 + 3f96: 80 91 c0 00 lds r24, 0x00C0 + 3f9a: 87 ff sbrs r24, 7 + 3f9c: fc cf rjmp .-8 ; 0x3f96 ch = UDR0; - 3fba: 80 91 c6 00 lds r24, 0x00C6 + 3f9e: 80 91 c6 00 lds r24, 0x00C6 LED_PIN |= _BV(LED); #endif #endif return ch; } - 3fbe: 08 95 ret + 3fa2: 08 95 ret -00003fc0 : - } while (--count); -} -#endif - -uint8_t getLen() { - getch(); - 3fc0: f7 df rcall .-18 ; 0x3fb0 - length = getch(); - 3fc2: f6 df rcall .-20 ; 0x3fb0 - 3fc4: 80 93 02 02 sts 0x0202, r24 - return getch(); -} - 3fc8: f3 cf rjmp .-26 ; 0x3fb0 - -00003fca : +00003fa4 : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 3fca: e0 e6 ldi r30, 0x60 ; 96 - 3fcc: f0 e0 ldi r31, 0x00 ; 0 - 3fce: 98 e1 ldi r25, 0x18 ; 24 - 3fd0: 90 83 st Z, r25 + 3fa4: e0 e6 ldi r30, 0x60 ; 96 + 3fa6: f0 e0 ldi r31, 0x00 ; 0 + 3fa8: 98 e1 ldi r25, 0x18 ; 24 + 3faa: 90 83 st Z, r25 WDTCSR = x; - 3fd2: 80 83 st Z, r24 + 3fac: 80 83 st Z, r24 } - 3fd4: 08 95 ret + 3fae: 08 95 ret -00003fd6 : - -void appStart() { - watchdogConfig(WATCHDOG_OFF); - 3fd6: 80 e0 ldi r24, 0x00 ; 0 - 3fd8: f8 df rcall .-16 ; 0x3fca - __asm__ __volatile__ ( - 3fda: ee 27 eor r30, r30 - 3fdc: ff 27 eor r31, r31 - 3fde: 09 94 ijmp - -00003fe0 : +00003fb0 : do getch(); while (--count); verifySpace(); } void verifySpace() { - if (getch() != CRC_EOP) appStart(); - 3fe0: e7 df rcall .-50 ; 0x3fb0 - 3fe2: 80 32 cpi r24, 0x20 ; 32 - 3fe4: 09 f0 breq .+2 ; 0x3fe8 - 3fe6: f7 df rcall .-18 ; 0x3fd6 + if (getch() != CRC_EOP) { + 3fb0: f1 df rcall .-30 ; 0x3f94 + 3fb2: 80 32 cpi r24, 0x20 ; 32 + 3fb4: 19 f0 breq .+6 ; 0x3fbc + watchdogConfig(WATCHDOG_16MS); // shorten WD timeout + 3fb6: 88 e0 ldi r24, 0x08 ; 8 + 3fb8: f5 df rcall .-22 ; 0x3fa4 + 3fba: ff cf rjmp .-2 ; 0x3fba + while (1) // and busy-loop so that WD causes + ; // a reset and app start. + } putch(STK_INSYNC); - 3fe8: 84 e1 ldi r24, 0x14 ; 20 + 3fbc: 84 e1 ldi r24, 0x14 ; 20 } - 3fea: da cf rjmp .-76 ; 0x3fa0 + 3fbe: e2 cf rjmp .-60 ; 0x3f84 -00003fec : +00003fc0 : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 3fec: 1f 93 push r17 - 3fee: 18 2f mov r17, r24 + 3fc0: 1f 93 push r17 + 3fc2: 18 2f mov r17, r24 do getch(); while (--count); - 3ff0: df df rcall .-66 ; 0x3fb0 - 3ff2: 11 50 subi r17, 0x01 ; 1 - 3ff4: e9 f7 brne .-6 ; 0x3ff0 + 3fc4: e7 df rcall .-50 ; 0x3f94 + 3fc6: 11 50 subi r17, 0x01 ; 1 + 3fc8: e9 f7 brne .-6 ; 0x3fc4 verifySpace(); - 3ff6: f4 df rcall .-24 ; 0x3fe0 + 3fca: f2 df rcall .-28 ; 0x3fb0 } - 3ff8: 1f 91 pop r17 - 3ffa: 08 95 ret + 3fcc: 1f 91 pop r17 + 3fce: 08 95 ret + +00003fd0 : + WDTCSR = _BV(WDCE) | _BV(WDE); + WDTCSR = x; +} + +void appStart() { + watchdogConfig(WATCHDOG_OFF); + 3fd0: 80 e0 ldi r24, 0x00 ; 0 + 3fd2: e8 df rcall .-48 ; 0x3fa4 + __asm__ __volatile__ ( + 3fd4: ee 27 eor r30, r30 + 3fd6: ff 27 eor r31, r31 + 3fd8: 09 94 ijmp From e28b716f88968477fa0f42dbd88c539573e91886 Mon Sep 17 00:00:00 2001 From: WestfW Date: Fri, 10 Jun 2011 23:16:21 -0700 Subject: [PATCH 25/33] Update version to reflect previous edit. Sigh. --- hardware/arduino/bootloaders/optiboot/optiboot.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hardware/arduino/bootloaders/optiboot/optiboot.c b/hardware/arduino/bootloaders/optiboot/optiboot.c index 89403591b..8dbe1bfbb 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot.c +++ b/hardware/arduino/bootloaders/optiboot/optiboot.c @@ -132,11 +132,13 @@ /**********************************************************/ /* Edit History: */ /* */ +/* 4.2 WestfW: reduce code size, fix timeouts, change */ +/* verifySpace to use WDT instead of appstart */ /* 4.1 WestfW: put version number in binary. */ /**********************************************************/ #define OPTIBOOT_MAJVER 4 -#define OPTIBOOT_MINVER 1 +#define OPTIBOOT_MINVER 2 #define MAKESTR(a) #a #define MAKEVER(a, b) MAKESTR(a*256+b) From 422398e08c8e011bf490b54af88271c54e56ddb9 Mon Sep 17 00:00:00 2001 From: WestfW Date: Sat, 11 Jun 2011 03:15:33 -0700 Subject: [PATCH 26/33] Fix errors in LDSECTIONS refactoring (found during atmega8 testing.) --- hardware/arduino/bootloaders/optiboot/Makefile | 14 +++++++------- .../bootloaders/optiboot/optiboot_atmega328.hex | 2 +- .../bootloaders/optiboot/optiboot_atmega328.lst | 14 +++++++------- .../bootloaders/optiboot/optiboot_diecimila.hex | 2 +- .../bootloaders/optiboot/optiboot_diecimila.lst | 14 +++++++------- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/hardware/arduino/bootloaders/optiboot/Makefile b/hardware/arduino/bootloaders/optiboot/Makefile index ce25ac397..f6ba3747f 100644 --- a/hardware/arduino/bootloaders/optiboot/Makefile +++ b/hardware/arduino/bootloaders/optiboot/Makefile @@ -129,7 +129,7 @@ virboot328: TARGET = atmega328 virboot328: MCU_TARGET = atmega328p virboot328: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' '-DVIRTUAL_BOOT' virboot328: AVR_FREQ = 16000000L -virboot328: LDSECTIONS = --section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe +virboot328: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe virboot328: $(PROGRAM)_atmega328.hex virboot328: $(PROGRAM)_atmega328.lst @@ -221,7 +221,7 @@ sanguino: TARGET = atmega644p sanguino: MCU_TARGET = atmega644p sanguino: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' '-DBIGBOOT' sanguino: AVR_FREQ = 16000000L -sanguino: LDSECTION = --section-start=.text=0xfc00 +sanguino: LDSECTIONS = -Wl,--section-start=.text=0xfc00 sanguino: $(PROGRAM)_atmega644p.hex sanguino: $(PROGRAM)_atmega644p.lst @@ -241,7 +241,7 @@ sanguino_isp: isp mega: MCU_TARGET = atmega1280 mega: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' '-DBIGBOOT' mega: AVR_FREQ = 16000000L -mega: LDSECTION = --section-start=.text=0x1fc00 +mega: LDSECTIONS = -Wl,--section-start=.text=0x1fc00 mega: $(PROGRAM)_atmega1280.hex mega: $(PROGRAM)_atmega1280.lst @@ -262,7 +262,7 @@ atmega8: TARGET = atmega8 atmega8: MCU_TARGET = atmega8 atmega8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' atmega8: AVR_FREQ = 16000000L -atmega8: LDSECTIONS = --section-start=.text=0x1e00 -Wl,--section-start=.version=0x1ffe +atmega8: LDSECTIONS = -Wl,--section-start=.text=0x1e00 -Wl,--section-start=.version=0x1ffe atmega8: $(PROGRAM)_atmega8.hex atmega8: $(PROGRAM)_atmega8.lst @@ -281,7 +281,7 @@ atmega88: TARGET = atmega88 atmega88: MCU_TARGET = atmega88 atmega88: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' atmega88: AVR_FREQ = 16000000L -atmega88: LDSECTIONS = --section-start=.text=0x1e00 -Wl,--section-start=.version=0x1ffe +atmega88: LDSECTIONS = -Wl,--section-start=.text=0x1e00 -Wl,--section-start=.version=0x1ffe atmega88: $(PROGRAM)_atmega88.hex atmega88: $(PROGRAM)_atmega88.lst @@ -357,7 +357,7 @@ atmega328_pro8: TARGET = atmega328_pro_8MHz atmega328_pro8: MCU_TARGET = atmega328p atmega328_pro8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' atmega328_pro8: AVR_FREQ = 8000000L -atmega328_pro8: LDSECTIONS = --section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe +atmega328_pro8: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.hex atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.lst @@ -382,7 +382,7 @@ luminet: MCU_TARGET = attiny84 luminet: CFLAGS += '-DLED_START_FLASHES=3' '-DSOFT_UART' '-DBAUD_RATE=9600' luminet: CFLAGS += '-DVIRTUAL_BOOT_PARTITION' luminet: AVR_FREQ = 1000000L -luminet: LDSECTIONS = --section-start=.text=0x1d00 -Wl,--section-start=.version=0x1efe +luminet: LDSECTIONS = -Wl,--section-start=.text=0x1d00 -Wl,--section-start=.version=0x1efe luminet: $(PROGRAM)_luminet.hex luminet: $(PROGRAM)_luminet.lst diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.hex b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.hex index 11819d6b5..10dcd6c80 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.hex @@ -28,6 +28,6 @@ :107FB000F1DF803219F088E0F5DFFFCF84E1E2CF16 :107FC0001F93182FE7DF1150E9F7F2DF1F91089593 :0A7FD00080E0E8DFEE27FF270994A8 -:027FFE0001047C +:027FFE0002047B :0400000300007E007B :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.lst b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.lst index 7876b9691..89577f685 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.lst @@ -11,19 +11,19 @@ Idx Name Size VMA LMA File off Algn CONTENTS, READONLY, DEBUGGING 3 .debug_pubnames 0000005f 00000000 00000000 00000258 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_info 0000028c 00000000 00000000 000002b7 2**0 + 4 .debug_info 0000028d 00000000 00000000 000002b7 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 00000199 00000000 00000000 00000543 2**0 + 5 .debug_abbrev 0000018a 00000000 00000000 00000544 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_line 00000456 00000000 00000000 000006dc 2**0 + 6 .debug_line 00000456 00000000 00000000 000006ce 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000080 00000000 00000000 00000b34 2**2 + 7 .debug_frame 00000080 00000000 00000000 00000b24 2**2 CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000149 00000000 00000000 00000bb4 2**0 + 8 .debug_str 00000149 00000000 00000000 00000ba4 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 0000027e 00000000 00000000 00000cfd 2**0 + 9 .debug_loc 0000027e 00000000 00000000 00000ced 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000060 00000000 00000000 00000f7b 2**0 + 10 .debug_ranges 00000060 00000000 00000000 00000f6b 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.hex b/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.hex index 733a1397e..26bbd4cdf 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.hex @@ -28,6 +28,6 @@ :103FB000F1DF803219F088E0F5DFFFCF84E1E2CF56 :103FC0001F93182FE7DF1150E9F7F2DF1F910895D3 :0A3FD00080E0E8DFEE27FF270994E8 -:023FFE000104BC +:023FFE000204BB :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.lst b/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.lst index edd9cb369..6e0843d6d 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.lst @@ -11,19 +11,19 @@ Idx Name Size VMA LMA File off Algn CONTENTS, READONLY, DEBUGGING 3 .debug_pubnames 0000005f 00000000 00000000 00000258 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_info 0000028c 00000000 00000000 000002b7 2**0 + 4 .debug_info 0000028d 00000000 00000000 000002b7 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 00000199 00000000 00000000 00000543 2**0 + 5 .debug_abbrev 0000018a 00000000 00000000 00000544 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_line 00000456 00000000 00000000 000006dc 2**0 + 6 .debug_line 00000456 00000000 00000000 000006ce 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000080 00000000 00000000 00000b34 2**2 + 7 .debug_frame 00000080 00000000 00000000 00000b24 2**2 CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000149 00000000 00000000 00000bb4 2**0 + 8 .debug_str 00000149 00000000 00000000 00000ba4 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 0000027e 00000000 00000000 00000cfd 2**0 + 9 .debug_loc 0000027e 00000000 00000000 00000ced 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000060 00000000 00000000 00000f7b 2**0 + 10 .debug_ranges 00000060 00000000 00000000 00000f6b 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: From ece29c380556878ba8efebce8801a7f076c61ada Mon Sep 17 00:00:00 2001 From: WestfW Date: Sat, 11 Jun 2011 03:17:38 -0700 Subject: [PATCH 27/33] (make sure .hex and .lst are updated as well.) --- .../optiboot/optiboot_atmega328_pro_8MHz.hex | 63 +- .../optiboot/optiboot_atmega328_pro_8MHz.lst | 482 +++++++-------- .../bootloaders/optiboot/optiboot_lilypad.hex | 2 +- .../bootloaders/optiboot/optiboot_lilypad.lst | 14 +- .../optiboot/optiboot_lilypad_resonator.hex | 2 +- .../optiboot/optiboot_lilypad_resonator.lst | 14 +- .../bootloaders/optiboot/optiboot_luminet.hex | 77 +-- .../bootloaders/optiboot/optiboot_luminet.lst | 584 +++++++++--------- .../optiboot/optiboot_pro_16MHz.hex | 2 +- .../optiboot/optiboot_pro_16MHz.lst | 14 +- .../optiboot/optiboot_pro_20mhz.hex | 2 +- .../optiboot/optiboot_pro_20mhz.lst | 14 +- .../optiboot/optiboot_pro_8MHz.hex | 2 +- .../optiboot/optiboot_pro_8MHz.lst | 14 +- 14 files changed, 644 insertions(+), 642 deletions(-) diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.hex b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.hex index a181f0b6d..3b543c1a3 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.hex @@ -1,32 +1,33 @@ -:10000000112484B714BE81FFE3D085E08093810082 -:1000100082E08093C00088E18093C10086E08093F5 -:10002000C20088E08093C4008EE0BCD0259A86E0B0 -:1000300028E13EEF91E0309385002093840096BB49 -:10004000B09BFECF1D9AA8958150A9F7992493944F -:10005000A5E0AA2EF1E1BF2E9DD0813421F481E0EC -:10006000AFD083E01FC0823411F484E103C0853433 -:1000700019F485E0A5D083C0853579F48BD0E82EBE -:10008000FF2488D0082F10E0102F00270E291F29E9 -:10009000000F111F8DD0680172C0863529F484E0ED -:1000A0008FD080E06FD06BC0843609F042C072D030 -:1000B00071D0082F6FD080E0C81680E7D80620F4F2 -:1000C00083E0F60187BFE895C0E0D1E063D0899373 -:1000D0000C17E1F7F0E0CF16F0E7DF0620F083E041 -:1000E000F60187BFE89564D007B600FCFDCFA601F6 -:1000F000A0E0B1E02C9130E011968C91119790E046 -:10010000982F8827822B932B1296FA010C0197BE09 -:10011000E89511244E5F5F4FF1E0A038BF0751F71B -:10012000F601A7BEE89507B600FCFDCFB7BEE8957F -:1001300026C08437B1F42ED02DD0F82E2BD038D055 -:10014000F601EF2C8F010F5F1F4F84911BD0EA94B3 -:10015000F801C1F70894C11CD11CFA94CF0CD11C32 -:100160000EC0853739F424D08EE10CD085E90AD051 -:100170008FE098CF813511F488E014D019D080E158 -:1001800001D06ACF982F8091C00085FFFCCF90935B -:10019000C6000895A8958091C00087FFFCCF80918C -:1001A000C6000895E0E6F0E098E19083808308952A -:1001B000F1DF803219F088E0F5DFFFCF84E1E2CF94 -:1001C0001F93182FE7DF1150E9F7F2DF1F91089511 -:0A01D00080E0E8DFEE27FF27099426 -:027FFE0001047C +:107E0000112484B714BE81FFE3D085E08093810004 +:107E100082E08093C00088E18093C10086E0809377 +:107E2000C20088E08093C4008EE0BCD0259A86E032 +:107E300028E13EEF91E0309385002093840096BBCB +:107E4000B09BFECF1D9AA8958150A9F799249394D1 +:107E5000A5E0AA2EF1E1BF2E9DD0813421F481E06E +:107E6000AFD083E01FC0823411F484E103C08534B5 +:107E700019F485E0A5D083C0853579F48BD0E82E40 +:107E8000FF2488D0082F10E0102F00270E291F296B +:107E9000000F111F8DD0680172C0863529F484E06F +:107EA0008FD080E06FD06BC0843609F042C072D0B2 +:107EB00071D0082F6FD080E0C81680E7D80620F474 +:107EC00083E0F60187BFE895C0E0D1E063D08993F5 +:107ED0000C17E1F7F0E0CF16F0E7DF0620F083E0C3 +:107EE000F60187BFE89564D007B600FCFDCFA60178 +:107EF000A0E0B1E02C9130E011968C91119790E0C8 +:107F0000982F8827822B932B1296FA010C0197BE8B +:107F1000E89511244E5F5F4FF1E0A038BF0751F79D +:107F2000F601A7BEE89507B600FCFDCFB7BEE89501 +:107F300026C08437B1F42ED02DD0F82E2BD038D0D7 +:107F4000F601EF2C8F010F5F1F4F84911BD0EA9435 +:107F5000F801C1F70894C11CD11CFA94CF0CD11CB4 +:107F60000EC0853739F424D08EE10CD085E90AD0D3 +:107F70008FE098CF813511F488E014D019D080E1DA +:107F800001D06ACF982F8091C00085FFFCCF9093DD +:107F9000C6000895A8958091C00087FFFCCF80910E +:107FA000C6000895E0E6F0E098E1908380830895AC +:107FB000F1DF803219F088E0F5DFFFCF84E1E2CF16 +:107FC0001F93182FE7DF1150E9F7F2DF1F91089593 +:0A7FD00080E0E8DFEE27FF270994A8 +:027FFE0002047B +:0400000300007E007B :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.lst b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.lst index a4da506ba..002f9a3dc 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.lst @@ -3,7 +3,7 @@ optiboot_atmega328_pro_8MHz.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .text 000001da 00000000 00000000 00000054 2**1 + 0 .text 000001da 00007e00 00007e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE 1 .version 00000002 00007ffe 00007ffe 0000022e 2**0 CONTENTS, READONLY @@ -11,551 +11,551 @@ Idx Name Size VMA LMA File off Algn CONTENTS, READONLY, DEBUGGING 3 .debug_pubnames 0000005f 00000000 00000000 00000258 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_info 0000028c 00000000 00000000 000002b7 2**0 + 4 .debug_info 0000028d 00000000 00000000 000002b7 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 00000199 00000000 00000000 00000543 2**0 + 5 .debug_abbrev 0000018a 00000000 00000000 00000544 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_line 00000456 00000000 00000000 000006dc 2**0 + 6 .debug_line 00000456 00000000 00000000 000006ce 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000080 00000000 00000000 00000b34 2**2 + 7 .debug_frame 00000080 00000000 00000000 00000b24 2**2 CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000149 00000000 00000000 00000bb4 2**0 + 8 .debug_str 00000149 00000000 00000000 00000ba4 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 0000027e 00000000 00000000 00000cfd 2**0 + 9 .debug_loc 0000027e 00000000 00000000 00000ced 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000060 00000000 00000000 00000f7b 2**0 + 10 .debug_ranges 00000060 00000000 00000000 00000f6b 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: -00000000
    : +00007e00
    : #define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) #define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif /* main program starts here */ int main(void) { - 0: 11 24 eor r1, r1 + 7e00: 11 24 eor r1, r1 #ifdef __AVR_ATmega8__ SP=RAMEND; // This is done by hardware reset #endif // Adaboot no-wait mod ch = MCUSR; - 2: 84 b7 in r24, 0x34 ; 52 + 7e02: 84 b7 in r24, 0x34 ; 52 MCUSR = 0; - 4: 14 be out 0x34, r1 ; 52 + 7e04: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); - 6: 81 ff sbrs r24, 1 - 8: e3 d0 rcall .+454 ; 0x1d0 + 7e06: 81 ff sbrs r24, 1 + 7e08: e3 d0 rcall .+454 ; 0x7fd0 #if LED_START_FLASHES > 0 // Set up Timer 1 for timeout counter TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 - a: 85 e0 ldi r24, 0x05 ; 5 - c: 80 93 81 00 sts 0x0081, r24 + 7e0a: 85 e0 ldi r24, 0x05 ; 5 + 7e0c: 80 93 81 00 sts 0x0081, r24 UCSRA = _BV(U2X); //Double speed mode USART UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); #else UCSR0A = _BV(U2X0); //Double speed mode USART0 - 10: 82 e0 ldi r24, 0x02 ; 2 - 12: 80 93 c0 00 sts 0x00C0, r24 + 7e10: 82 e0 ldi r24, 0x02 ; 2 + 7e12: 80 93 c0 00 sts 0x00C0, r24 UCSR0B = _BV(RXEN0) | _BV(TXEN0); - 16: 88 e1 ldi r24, 0x18 ; 24 - 18: 80 93 c1 00 sts 0x00C1, r24 + 7e16: 88 e1 ldi r24, 0x18 ; 24 + 7e18: 80 93 c1 00 sts 0x00C1, r24 UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); - 1c: 86 e0 ldi r24, 0x06 ; 6 - 1e: 80 93 c2 00 sts 0x00C2, r24 + 7e1c: 86 e0 ldi r24, 0x06 ; 6 + 7e1e: 80 93 c2 00 sts 0x00C2, r24 UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); - 22: 88 e0 ldi r24, 0x08 ; 8 - 24: 80 93 c4 00 sts 0x00C4, r24 + 7e22: 88 e0 ldi r24, 0x08 ; 8 + 7e24: 80 93 c4 00 sts 0x00C4, r24 #endif #endif // Set up watchdog to trigger after 500ms watchdogConfig(WATCHDOG_1S); - 28: 8e e0 ldi r24, 0x0E ; 14 - 2a: bc d0 rcall .+376 ; 0x1a4 + 7e28: 8e e0 ldi r24, 0x0E ; 14 + 7e2a: bc d0 rcall .+376 ; 0x7fa4 /* Set LED pin as output */ LED_DDR |= _BV(LED); - 2c: 25 9a sbi 0x04, 5 ; 4 - 2e: 86 e0 ldi r24, 0x06 ; 6 + 7e2c: 25 9a sbi 0x04, 5 ; 4 + 7e2e: 86 e0 ldi r24, 0x06 ; 6 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - 30: 28 e1 ldi r18, 0x18 ; 24 - 32: 3e ef ldi r19, 0xFE ; 254 + 7e30: 28 e1 ldi r18, 0x18 ; 24 + 7e32: 3e ef ldi r19, 0xFE ; 254 TIFR1 = _BV(TOV1); - 34: 91 e0 ldi r25, 0x01 ; 1 + 7e34: 91 e0 ldi r25, 0x01 ; 1 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - 36: 30 93 85 00 sts 0x0085, r19 - 3a: 20 93 84 00 sts 0x0084, r18 + 7e36: 30 93 85 00 sts 0x0085, r19 + 7e3a: 20 93 84 00 sts 0x0084, r18 TIFR1 = _BV(TOV1); - 3e: 96 bb out 0x16, r25 ; 22 + 7e3e: 96 bb out 0x16, r25 ; 22 while(!(TIFR1 & _BV(TOV1))); - 40: b0 9b sbis 0x16, 0 ; 22 - 42: fe cf rjmp .-4 ; 0x40 <__SREG__+0x1> + 7e40: b0 9b sbis 0x16, 0 ; 22 + 7e42: fe cf rjmp .-4 ; 0x7e40 #ifdef __AVR_ATmega8__ LED_PORT ^= _BV(LED); #else LED_PIN |= _BV(LED); - 44: 1d 9a sbi 0x03, 5 ; 3 + 7e44: 1d 9a sbi 0x03, 5 ; 3 } #endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 46: a8 95 wdr + 7e46: a8 95 wdr LED_PORT ^= _BV(LED); #else LED_PIN |= _BV(LED); #endif watchdogReset(); } while (--count); - 48: 81 50 subi r24, 0x01 ; 1 - 4a: a9 f7 brne .-22 ; 0x36 <__CCP__+0x2> + 7e48: 81 50 subi r24, 0x01 ; 1 + 7e4a: a9 f7 brne .-22 ; 0x7e36 /* get character from UART */ ch = getch(); if(ch == STK_GET_PARAMETER) { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 4c: 99 24 eor r9, r9 - 4e: 93 94 inc r9 + 7e4c: 99 24 eor r9, r9 + 7e4e: 93 94 inc r9 __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); - 50: a5 e0 ldi r26, 0x05 ; 5 - 52: aa 2e mov r10, r26 + 7e50: a5 e0 ldi r26, 0x05 ; 5 + 7e52: aa 2e mov r10, r26 boot_spm_busy_wait(); #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 54: f1 e1 ldi r31, 0x11 ; 17 - 56: bf 2e mov r11, r31 + 7e54: f1 e1 ldi r31, 0x11 ; 17 + 7e56: bf 2e mov r11, r31 #endif /* Forever loop */ for (;;) { /* get character from UART */ ch = getch(); - 58: 9d d0 rcall .+314 ; 0x194 + 7e58: 9d d0 rcall .+314 ; 0x7f94 if(ch == STK_GET_PARAMETER) { - 5a: 81 34 cpi r24, 0x41 ; 65 - 5c: 21 f4 brne .+8 ; 0x66 <__SREG__+0x27> + 7e5a: 81 34 cpi r24, 0x41 ; 65 + 7e5c: 21 f4 brne .+8 ; 0x7e66 // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 5e: 81 e0 ldi r24, 0x01 ; 1 - 60: af d0 rcall .+350 ; 0x1c0 + 7e5e: 81 e0 ldi r24, 0x01 ; 1 + 7e60: af d0 rcall .+350 ; 0x7fc0 putch(0x03); - 62: 83 e0 ldi r24, 0x03 ; 3 - 64: 1f c0 rjmp .+62 ; 0xa4 <__SREG__+0x65> + 7e62: 83 e0 ldi r24, 0x03 ; 3 + 7e64: 1f c0 rjmp .+62 ; 0x7ea4 } else if(ch == STK_SET_DEVICE) { - 66: 82 34 cpi r24, 0x42 ; 66 - 68: 11 f4 brne .+4 ; 0x6e <__SREG__+0x2f> + 7e66: 82 34 cpi r24, 0x42 ; 66 + 7e68: 11 f4 brne .+4 ; 0x7e6e // SET DEVICE is ignored getNch(20); - 6a: 84 e1 ldi r24, 0x14 ; 20 - 6c: 03 c0 rjmp .+6 ; 0x74 <__SREG__+0x35> + 7e6a: 84 e1 ldi r24, 0x14 ; 20 + 7e6c: 03 c0 rjmp .+6 ; 0x7e74 } else if(ch == STK_SET_DEVICE_EXT) { - 6e: 85 34 cpi r24, 0x45 ; 69 - 70: 19 f4 brne .+6 ; 0x78 <__SREG__+0x39> + 7e6e: 85 34 cpi r24, 0x45 ; 69 + 7e70: 19 f4 brne .+6 ; 0x7e78 // SET DEVICE EXT is ignored getNch(5); - 72: 85 e0 ldi r24, 0x05 ; 5 - 74: a5 d0 rcall .+330 ; 0x1c0 - 76: 83 c0 rjmp .+262 ; 0x17e <__SREG__+0x13f> + 7e72: 85 e0 ldi r24, 0x05 ; 5 + 7e74: a5 d0 rcall .+330 ; 0x7fc0 + 7e76: 83 c0 rjmp .+262 ; 0x7f7e } else if(ch == STK_LOAD_ADDRESS) { - 78: 85 35 cpi r24, 0x55 ; 85 - 7a: 79 f4 brne .+30 ; 0x9a <__SREG__+0x5b> + 7e78: 85 35 cpi r24, 0x55 ; 85 + 7e7a: 79 f4 brne .+30 ; 0x7e9a // LOAD ADDRESS uint16_t newAddress; newAddress = getch(); - 7c: 8b d0 rcall .+278 ; 0x194 + 7e7c: 8b d0 rcall .+278 ; 0x7f94 newAddress = (newAddress & 0xff) | (getch() << 8); - 7e: e8 2e mov r14, r24 - 80: ff 24 eor r15, r15 - 82: 88 d0 rcall .+272 ; 0x194 - 84: 08 2f mov r16, r24 - 86: 10 e0 ldi r17, 0x00 ; 0 - 88: 10 2f mov r17, r16 - 8a: 00 27 eor r16, r16 - 8c: 0e 29 or r16, r14 - 8e: 1f 29 or r17, r15 + 7e7e: e8 2e mov r14, r24 + 7e80: ff 24 eor r15, r15 + 7e82: 88 d0 rcall .+272 ; 0x7f94 + 7e84: 08 2f mov r16, r24 + 7e86: 10 e0 ldi r17, 0x00 ; 0 + 7e88: 10 2f mov r17, r16 + 7e8a: 00 27 eor r16, r16 + 7e8c: 0e 29 or r16, r14 + 7e8e: 1f 29 or r17, r15 #ifdef RAMPZ // Transfer top bit to RAMPZ RAMPZ = (newAddress & 0x8000) ? 1 : 0; #endif newAddress += newAddress; // Convert from word address to byte address - 90: 00 0f add r16, r16 - 92: 11 1f adc r17, r17 + 7e90: 00 0f add r16, r16 + 7e92: 11 1f adc r17, r17 address = newAddress; verifySpace(); - 94: 8d d0 rcall .+282 ; 0x1b0 - 96: 68 01 movw r12, r16 - 98: 72 c0 rjmp .+228 ; 0x17e <__SREG__+0x13f> + 7e94: 8d d0 rcall .+282 ; 0x7fb0 + 7e96: 68 01 movw r12, r16 + 7e98: 72 c0 rjmp .+228 ; 0x7f7e } else if(ch == STK_UNIVERSAL) { - 9a: 86 35 cpi r24, 0x56 ; 86 - 9c: 29 f4 brne .+10 ; 0xa8 <__SREG__+0x69> + 7e9a: 86 35 cpi r24, 0x56 ; 86 + 7e9c: 29 f4 brne .+10 ; 0x7ea8 // UNIVERSAL command is ignored getNch(4); - 9e: 84 e0 ldi r24, 0x04 ; 4 - a0: 8f d0 rcall .+286 ; 0x1c0 + 7e9e: 84 e0 ldi r24, 0x04 ; 4 + 7ea0: 8f d0 rcall .+286 ; 0x7fc0 putch(0x00); - a2: 80 e0 ldi r24, 0x00 ; 0 - a4: 6f d0 rcall .+222 ; 0x184 - a6: 6b c0 rjmp .+214 ; 0x17e <__SREG__+0x13f> + 7ea2: 80 e0 ldi r24, 0x00 ; 0 + 7ea4: 6f d0 rcall .+222 ; 0x7f84 + 7ea6: 6b c0 rjmp .+214 ; 0x7f7e } /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { - a8: 84 36 cpi r24, 0x64 ; 100 - aa: 09 f0 breq .+2 ; 0xae <__SREG__+0x6f> - ac: 42 c0 rjmp .+132 ; 0x132 <__SREG__+0xf3> + 7ea8: 84 36 cpi r24, 0x64 ; 100 + 7eaa: 09 f0 breq .+2 ; 0x7eae + 7eac: 42 c0 rjmp .+132 ; 0x7f32 // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t *bufPtr; uint16_t addrPtr; getch(); /* getlen() */ - ae: 72 d0 rcall .+228 ; 0x194 + 7eae: 72 d0 rcall .+228 ; 0x7f94 length = getch(); - b0: 71 d0 rcall .+226 ; 0x194 - b2: 08 2f mov r16, r24 + 7eb0: 71 d0 rcall .+226 ; 0x7f94 + 7eb2: 08 2f mov r16, r24 getch(); - b4: 6f d0 rcall .+222 ; 0x194 + 7eb4: 6f d0 rcall .+222 ; 0x7f94 // If we are in RWW section, immediately start page erase if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - b6: 80 e0 ldi r24, 0x00 ; 0 - b8: c8 16 cp r12, r24 - ba: 80 e7 ldi r24, 0x70 ; 112 - bc: d8 06 cpc r13, r24 - be: 20 f4 brcc .+8 ; 0xc8 <__SREG__+0x89> - c0: 83 e0 ldi r24, 0x03 ; 3 - c2: f6 01 movw r30, r12 - c4: 87 bf out 0x37, r24 ; 55 - c6: e8 95 spm - c8: c0 e0 ldi r28, 0x00 ; 0 - ca: d1 e0 ldi r29, 0x01 ; 1 + 7eb6: 80 e0 ldi r24, 0x00 ; 0 + 7eb8: c8 16 cp r12, r24 + 7eba: 80 e7 ldi r24, 0x70 ; 112 + 7ebc: d8 06 cpc r13, r24 + 7ebe: 20 f4 brcc .+8 ; 0x7ec8 + 7ec0: 83 e0 ldi r24, 0x03 ; 3 + 7ec2: f6 01 movw r30, r12 + 7ec4: 87 bf out 0x37, r24 ; 55 + 7ec6: e8 95 spm + 7ec8: c0 e0 ldi r28, 0x00 ; 0 + 7eca: d1 e0 ldi r29, 0x01 ; 1 // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); - cc: 63 d0 rcall .+198 ; 0x194 - ce: 89 93 st Y+, r24 + 7ecc: 63 d0 rcall .+198 ; 0x7f94 + 7ece: 89 93 st Y+, r24 while (--length); - d0: 0c 17 cp r16, r28 - d2: e1 f7 brne .-8 ; 0xcc <__SREG__+0x8d> + 7ed0: 0c 17 cp r16, r28 + 7ed2: e1 f7 brne .-8 ; 0x7ecc // If we are in NRWW section, page erase has to be delayed until now. // Todo: Take RAMPZ into account if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - d4: f0 e0 ldi r31, 0x00 ; 0 - d6: cf 16 cp r12, r31 - d8: f0 e7 ldi r31, 0x70 ; 112 - da: df 06 cpc r13, r31 - dc: 20 f0 brcs .+8 ; 0xe6 <__SREG__+0xa7> - de: 83 e0 ldi r24, 0x03 ; 3 - e0: f6 01 movw r30, r12 - e2: 87 bf out 0x37, r24 ; 55 - e4: e8 95 spm + 7ed4: f0 e0 ldi r31, 0x00 ; 0 + 7ed6: cf 16 cp r12, r31 + 7ed8: f0 e7 ldi r31, 0x70 ; 112 + 7eda: df 06 cpc r13, r31 + 7edc: 20 f0 brcs .+8 ; 0x7ee6 + 7ede: 83 e0 ldi r24, 0x03 ; 3 + 7ee0: f6 01 movw r30, r12 + 7ee2: 87 bf out 0x37, r24 ; 55 + 7ee4: e8 95 spm // Read command terminator, start reply verifySpace(); - e6: 64 d0 rcall .+200 ; 0x1b0 + 7ee6: 64 d0 rcall .+200 ; 0x7fb0 // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); - e8: 07 b6 in r0, 0x37 ; 55 - ea: 00 fc sbrc r0, 0 - ec: fd cf rjmp .-6 ; 0xe8 <__SREG__+0xa9> - ee: a6 01 movw r20, r12 - f0: a0 e0 ldi r26, 0x00 ; 0 - f2: b1 e0 ldi r27, 0x01 ; 1 + 7ee8: 07 b6 in r0, 0x37 ; 55 + 7eea: 00 fc sbrc r0, 0 + 7eec: fd cf rjmp .-6 ; 0x7ee8 + 7eee: a6 01 movw r20, r12 + 7ef0: a0 e0 ldi r26, 0x00 ; 0 + 7ef2: b1 e0 ldi r27, 0x01 ; 1 bufPtr = buff; addrPtr = (uint16_t)(void*)address; ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; - f4: 2c 91 ld r18, X - f6: 30 e0 ldi r19, 0x00 ; 0 + 7ef4: 2c 91 ld r18, X + 7ef6: 30 e0 ldi r19, 0x00 ; 0 a |= (*bufPtr++) << 8; - f8: 11 96 adiw r26, 0x01 ; 1 - fa: 8c 91 ld r24, X - fc: 11 97 sbiw r26, 0x01 ; 1 - fe: 90 e0 ldi r25, 0x00 ; 0 - 100: 98 2f mov r25, r24 - 102: 88 27 eor r24, r24 - 104: 82 2b or r24, r18 - 106: 93 2b or r25, r19 + 7ef8: 11 96 adiw r26, 0x01 ; 1 + 7efa: 8c 91 ld r24, X + 7efc: 11 97 sbiw r26, 0x01 ; 1 + 7efe: 90 e0 ldi r25, 0x00 ; 0 + 7f00: 98 2f mov r25, r24 + 7f02: 88 27 eor r24, r24 + 7f04: 82 2b or r24, r18 + 7f06: 93 2b or r25, r19 #define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) #define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif /* main program starts here */ int main(void) { - 108: 12 96 adiw r26, 0x02 ; 2 + 7f08: 12 96 adiw r26, 0x02 ; 2 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; a |= (*bufPtr++) << 8; __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - 10a: fa 01 movw r30, r20 - 10c: 0c 01 movw r0, r24 - 10e: 97 be out 0x37, r9 ; 55 - 110: e8 95 spm - 112: 11 24 eor r1, r1 + 7f0a: fa 01 movw r30, r20 + 7f0c: 0c 01 movw r0, r24 + 7f0e: 97 be out 0x37, r9 ; 55 + 7f10: e8 95 spm + 7f12: 11 24 eor r1, r1 addrPtr += 2; - 114: 4e 5f subi r20, 0xFE ; 254 - 116: 5f 4f sbci r21, 0xFF ; 255 + 7f14: 4e 5f subi r20, 0xFE ; 254 + 7f16: 5f 4f sbci r21, 0xFF ; 255 } while (--ch); - 118: f1 e0 ldi r31, 0x01 ; 1 - 11a: a0 38 cpi r26, 0x80 ; 128 - 11c: bf 07 cpc r27, r31 - 11e: 51 f7 brne .-44 ; 0xf4 <__SREG__+0xb5> + 7f18: f1 e0 ldi r31, 0x01 ; 1 + 7f1a: a0 38 cpi r26, 0x80 ; 128 + 7f1c: bf 07 cpc r27, r31 + 7f1e: 51 f7 brne .-44 ; 0x7ef4 // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); - 120: f6 01 movw r30, r12 - 122: a7 be out 0x37, r10 ; 55 - 124: e8 95 spm + 7f20: f6 01 movw r30, r12 + 7f22: a7 be out 0x37, r10 ; 55 + 7f24: e8 95 spm boot_spm_busy_wait(); - 126: 07 b6 in r0, 0x37 ; 55 - 128: 00 fc sbrc r0, 0 - 12a: fd cf rjmp .-6 ; 0x126 <__SREG__+0xe7> + 7f26: 07 b6 in r0, 0x37 ; 55 + 7f28: 00 fc sbrc r0, 0 + 7f2a: fd cf rjmp .-6 ; 0x7f26 #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 12c: b7 be out 0x37, r11 ; 55 - 12e: e8 95 spm - 130: 26 c0 rjmp .+76 ; 0x17e <__SREG__+0x13f> + 7f2c: b7 be out 0x37, r11 ; 55 + 7f2e: e8 95 spm + 7f30: 26 c0 rjmp .+76 ; 0x7f7e #endif } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { - 132: 84 37 cpi r24, 0x74 ; 116 - 134: b1 f4 brne .+44 ; 0x162 <__SREG__+0x123> + 7f32: 84 37 cpi r24, 0x74 ; 116 + 7f34: b1 f4 brne .+44 ; 0x7f62 // READ PAGE - we only read flash getch(); /* getlen() */ - 136: 2e d0 rcall .+92 ; 0x194 + 7f36: 2e d0 rcall .+92 ; 0x7f94 length = getch(); - 138: 2d d0 rcall .+90 ; 0x194 - 13a: f8 2e mov r15, r24 + 7f38: 2d d0 rcall .+90 ; 0x7f94 + 7f3a: f8 2e mov r15, r24 getch(); - 13c: 2b d0 rcall .+86 ; 0x194 + 7f3c: 2b d0 rcall .+86 ; 0x7f94 verifySpace(); - 13e: 38 d0 rcall .+112 ; 0x1b0 - 140: f6 01 movw r30, r12 - 142: ef 2c mov r14, r15 + 7f3e: 38 d0 rcall .+112 ; 0x7fb0 + 7f40: f6 01 movw r30, r12 + 7f42: ef 2c mov r14, r15 putch(result); address++; } while (--length); #else do putch(pgm_read_byte_near(address++)); - 144: 8f 01 movw r16, r30 - 146: 0f 5f subi r16, 0xFF ; 255 - 148: 1f 4f sbci r17, 0xFF ; 255 - 14a: 84 91 lpm r24, Z+ - 14c: 1b d0 rcall .+54 ; 0x184 + 7f44: 8f 01 movw r16, r30 + 7f46: 0f 5f subi r16, 0xFF ; 255 + 7f48: 1f 4f sbci r17, 0xFF ; 255 + 7f4a: 84 91 lpm r24, Z+ + 7f4c: 1b d0 rcall .+54 ; 0x7f84 while (--length); - 14e: ea 94 dec r14 - 150: f8 01 movw r30, r16 - 152: c1 f7 brne .-16 ; 0x144 <__SREG__+0x105> + 7f4e: ea 94 dec r14 + 7f50: f8 01 movw r30, r16 + 7f52: c1 f7 brne .-16 ; 0x7f44 #define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) #define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif /* main program starts here */ int main(void) { - 154: 08 94 sec - 156: c1 1c adc r12, r1 - 158: d1 1c adc r13, r1 - 15a: fa 94 dec r15 - 15c: cf 0c add r12, r15 - 15e: d1 1c adc r13, r1 - 160: 0e c0 rjmp .+28 ; 0x17e <__SREG__+0x13f> + 7f54: 08 94 sec + 7f56: c1 1c adc r12, r1 + 7f58: d1 1c adc r13, r1 + 7f5a: fa 94 dec r15 + 7f5c: cf 0c add r12, r15 + 7f5e: d1 1c adc r13, r1 + 7f60: 0e c0 rjmp .+28 ; 0x7f7e #endif #endif } /* Get device signature bytes */ else if(ch == STK_READ_SIGN) { - 162: 85 37 cpi r24, 0x75 ; 117 - 164: 39 f4 brne .+14 ; 0x174 <__SREG__+0x135> + 7f62: 85 37 cpi r24, 0x75 ; 117 + 7f64: 39 f4 brne .+14 ; 0x7f74 // READ SIGN - return what Avrdude wants to hear verifySpace(); - 166: 24 d0 rcall .+72 ; 0x1b0 + 7f66: 24 d0 rcall .+72 ; 0x7fb0 putch(SIGNATURE_0); - 168: 8e e1 ldi r24, 0x1E ; 30 - 16a: 0c d0 rcall .+24 ; 0x184 + 7f68: 8e e1 ldi r24, 0x1E ; 30 + 7f6a: 0c d0 rcall .+24 ; 0x7f84 putch(SIGNATURE_1); - 16c: 85 e9 ldi r24, 0x95 ; 149 - 16e: 0a d0 rcall .+20 ; 0x184 + 7f6c: 85 e9 ldi r24, 0x95 ; 149 + 7f6e: 0a d0 rcall .+20 ; 0x7f84 putch(SIGNATURE_2); - 170: 8f e0 ldi r24, 0x0F ; 15 - 172: 98 cf rjmp .-208 ; 0xa4 <__SREG__+0x65> + 7f70: 8f e0 ldi r24, 0x0F ; 15 + 7f72: 98 cf rjmp .-208 ; 0x7ea4 } else if (ch == 'Q') { - 174: 81 35 cpi r24, 0x51 ; 81 - 176: 11 f4 brne .+4 ; 0x17c <__SREG__+0x13d> + 7f74: 81 35 cpi r24, 0x51 ; 81 + 7f76: 11 f4 brne .+4 ; 0x7f7c // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); - 178: 88 e0 ldi r24, 0x08 ; 8 - 17a: 14 d0 rcall .+40 ; 0x1a4 + 7f78: 88 e0 ldi r24, 0x08 ; 8 + 7f7a: 14 d0 rcall .+40 ; 0x7fa4 verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 17c: 19 d0 rcall .+50 ; 0x1b0 + 7f7c: 19 d0 rcall .+50 ; 0x7fb0 } putch(STK_OK); - 17e: 80 e1 ldi r24, 0x10 ; 16 - 180: 01 d0 rcall .+2 ; 0x184 - 182: 6a cf rjmp .-300 ; 0x58 <__SREG__+0x19> + 7f7e: 80 e1 ldi r24, 0x10 ; 16 + 7f80: 01 d0 rcall .+2 ; 0x7f84 + 7f82: 6a cf rjmp .-300 ; 0x7e58 -00000184 : +00007f84 : } } void putch(char ch) { - 184: 98 2f mov r25, r24 + 7f84: 98 2f mov r25, r24 #ifndef SOFT_UART while (!(UCSR0A & _BV(UDRE0))); - 186: 80 91 c0 00 lds r24, 0x00C0 - 18a: 85 ff sbrs r24, 5 - 18c: fc cf rjmp .-8 ; 0x186 + 7f86: 80 91 c0 00 lds r24, 0x00C0 + 7f8a: 85 ff sbrs r24, 5 + 7f8c: fc cf rjmp .-8 ; 0x7f86 UDR0 = ch; - 18e: 90 93 c6 00 sts 0x00C6, r25 + 7f8e: 90 93 c6 00 sts 0x00C6, r25 [uartBit] "I" (UART_TX_BIT) : "r25" ); #endif } - 192: 08 95 ret + 7f92: 08 95 ret -00000194 : +00007f94 : } #endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 194: a8 95 wdr + 7f94: a8 95 wdr [uartBit] "I" (UART_RX_BIT) : "r25" ); #else while(!(UCSR0A & _BV(RXC0))); - 196: 80 91 c0 00 lds r24, 0x00C0 - 19a: 87 ff sbrs r24, 7 - 19c: fc cf rjmp .-8 ; 0x196 + 7f96: 80 91 c0 00 lds r24, 0x00C0 + 7f9a: 87 ff sbrs r24, 7 + 7f9c: fc cf rjmp .-8 ; 0x7f96 ch = UDR0; - 19e: 80 91 c6 00 lds r24, 0x00C6 + 7f9e: 80 91 c6 00 lds r24, 0x00C6 LED_PIN |= _BV(LED); #endif #endif return ch; } - 1a2: 08 95 ret + 7fa2: 08 95 ret -000001a4 : +00007fa4 : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 1a4: e0 e6 ldi r30, 0x60 ; 96 - 1a6: f0 e0 ldi r31, 0x00 ; 0 - 1a8: 98 e1 ldi r25, 0x18 ; 24 - 1aa: 90 83 st Z, r25 + 7fa4: e0 e6 ldi r30, 0x60 ; 96 + 7fa6: f0 e0 ldi r31, 0x00 ; 0 + 7fa8: 98 e1 ldi r25, 0x18 ; 24 + 7faa: 90 83 st Z, r25 WDTCSR = x; - 1ac: 80 83 st Z, r24 + 7fac: 80 83 st Z, r24 } - 1ae: 08 95 ret + 7fae: 08 95 ret -000001b0 : +00007fb0 : do getch(); while (--count); verifySpace(); } void verifySpace() { if (getch() != CRC_EOP) { - 1b0: f1 df rcall .-30 ; 0x194 - 1b2: 80 32 cpi r24, 0x20 ; 32 - 1b4: 19 f0 breq .+6 ; 0x1bc + 7fb0: f1 df rcall .-30 ; 0x7f94 + 7fb2: 80 32 cpi r24, 0x20 ; 32 + 7fb4: 19 f0 breq .+6 ; 0x7fbc watchdogConfig(WATCHDOG_16MS); // shorten WD timeout - 1b6: 88 e0 ldi r24, 0x08 ; 8 - 1b8: f5 df rcall .-22 ; 0x1a4 - 1ba: ff cf rjmp .-2 ; 0x1ba + 7fb6: 88 e0 ldi r24, 0x08 ; 8 + 7fb8: f5 df rcall .-22 ; 0x7fa4 + 7fba: ff cf rjmp .-2 ; 0x7fba while (1) // and busy-loop so that WD causes ; // a reset and app start. } putch(STK_INSYNC); - 1bc: 84 e1 ldi r24, 0x14 ; 20 + 7fbc: 84 e1 ldi r24, 0x14 ; 20 } - 1be: e2 cf rjmp .-60 ; 0x184 + 7fbe: e2 cf rjmp .-60 ; 0x7f84 -000001c0 : +00007fc0 : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 1c0: 1f 93 push r17 - 1c2: 18 2f mov r17, r24 + 7fc0: 1f 93 push r17 + 7fc2: 18 2f mov r17, r24 do getch(); while (--count); - 1c4: e7 df rcall .-50 ; 0x194 - 1c6: 11 50 subi r17, 0x01 ; 1 - 1c8: e9 f7 brne .-6 ; 0x1c4 + 7fc4: e7 df rcall .-50 ; 0x7f94 + 7fc6: 11 50 subi r17, 0x01 ; 1 + 7fc8: e9 f7 brne .-6 ; 0x7fc4 verifySpace(); - 1ca: f2 df rcall .-28 ; 0x1b0 + 7fca: f2 df rcall .-28 ; 0x7fb0 } - 1cc: 1f 91 pop r17 - 1ce: 08 95 ret + 7fcc: 1f 91 pop r17 + 7fce: 08 95 ret -000001d0 : +00007fd0 : WDTCSR = _BV(WDCE) | _BV(WDE); WDTCSR = x; } void appStart() { watchdogConfig(WATCHDOG_OFF); - 1d0: 80 e0 ldi r24, 0x00 ; 0 - 1d2: e8 df rcall .-48 ; 0x1a4 + 7fd0: 80 e0 ldi r24, 0x00 ; 0 + 7fd2: e8 df rcall .-48 ; 0x7fa4 __asm__ __volatile__ ( - 1d4: ee 27 eor r30, r30 - 1d6: ff 27 eor r31, r31 - 1d8: 09 94 ijmp + 7fd4: ee 27 eor r30, r30 + 7fd6: ff 27 eor r31, r31 + 7fd8: 09 94 ijmp diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.hex b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.hex index dcdbbb44f..00f7a3827 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.hex @@ -28,6 +28,6 @@ :103FB000F1DF803219F088E0F5DFFFCF84E1E2CF56 :103FC0001F93182FE7DF1150E9F7F2DF1F910895D3 :0A3FD00080E0E8DFEE27FF270994E8 -:023FFE000104BC +:023FFE000204BB :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.lst b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.lst index a70713ab5..4cebc2e32 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.lst @@ -11,19 +11,19 @@ Idx Name Size VMA LMA File off Algn CONTENTS, READONLY, DEBUGGING 3 .debug_pubnames 0000005f 00000000 00000000 00000258 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_info 0000028c 00000000 00000000 000002b7 2**0 + 4 .debug_info 0000028d 00000000 00000000 000002b7 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 00000199 00000000 00000000 00000543 2**0 + 5 .debug_abbrev 0000018a 00000000 00000000 00000544 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_line 00000456 00000000 00000000 000006dc 2**0 + 6 .debug_line 00000456 00000000 00000000 000006ce 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000080 00000000 00000000 00000b34 2**2 + 7 .debug_frame 00000080 00000000 00000000 00000b24 2**2 CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000149 00000000 00000000 00000bb4 2**0 + 8 .debug_str 00000149 00000000 00000000 00000ba4 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 0000027e 00000000 00000000 00000cfd 2**0 + 9 .debug_loc 0000027e 00000000 00000000 00000ced 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000060 00000000 00000000 00000f7b 2**0 + 10 .debug_ranges 00000060 00000000 00000000 00000f6b 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.hex b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.hex index dcdbbb44f..00f7a3827 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.hex @@ -28,6 +28,6 @@ :103FB000F1DF803219F088E0F5DFFFCF84E1E2CF56 :103FC0001F93182FE7DF1150E9F7F2DF1F910895D3 :0A3FD00080E0E8DFEE27FF270994E8 -:023FFE000104BC +:023FFE000204BB :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.lst b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.lst index 267683838..c8d07431c 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.lst @@ -11,19 +11,19 @@ Idx Name Size VMA LMA File off Algn CONTENTS, READONLY, DEBUGGING 3 .debug_pubnames 0000005f 00000000 00000000 00000258 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_info 0000028c 00000000 00000000 000002b7 2**0 + 4 .debug_info 0000028d 00000000 00000000 000002b7 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 00000199 00000000 00000000 00000543 2**0 + 5 .debug_abbrev 0000018a 00000000 00000000 00000544 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_line 00000456 00000000 00000000 000006dc 2**0 + 6 .debug_line 00000456 00000000 00000000 000006ce 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000080 00000000 00000000 00000b34 2**2 + 7 .debug_frame 00000080 00000000 00000000 00000b24 2**2 CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000149 00000000 00000000 00000bb4 2**0 + 8 .debug_str 00000149 00000000 00000000 00000ba4 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 0000027e 00000000 00000000 00000cfd 2**0 + 9 .debug_loc 0000027e 00000000 00000000 00000ced 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000060 00000000 00000000 00000f7b 2**0 + 10 .debug_ranges 00000060 00000000 00000000 00000f6b 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_luminet.hex b/hardware/arduino/bootloaders/optiboot/optiboot_luminet.hex index 843b2ef81..78fdc7030 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_luminet.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_luminet.hex @@ -1,39 +1,40 @@ -:10000000112484B714BE81FF18D185E08EBD8EE027 -:1000100000D1D49AD29A86E023EC3FEF91E03DBD27 -:100020002CBD9BB9589BFECFCC9AA8958150B9F7AF -:10003000BB24B39425E0A22E9FE7D92E8EECC82EC8 -:10004000D4D0813421F481E0F0D083E0B5C0823493 -:1000500011F484E103C0853419F485E0E6D0B3C01F -:10006000853569F4C2D0E82EFF24BFD0082F10E0F8 -:10007000102F00270E291F29000F111FA3C086353E -:1000800021F484E0D2D080E097C0843609F060C0CB -:10009000ACD0ABD0F82EA9D0C0E0D1E0A6D08993E7 -:1000A000FC16E1F783E0F80187BFE895B6D007B604 -:1000B00000FCFDCF0115110511F0A8012AC08091A7 -:1000C00000012091010130E0322F222790E0282BFF -:1000D000392B309385012093840140910801809150 -:1000E000090190E0982F882750E0842B952B90935E -:1000F0008701809386012450304020930801232FEC -:10010000332720930901D0920001C092010140E001 -:1001100050E0A0E0B1E02C9130E011968C91119765 -:1001200090E0982F8827822B932B1296FA010C01CE -:10013000B7BEE89511244E5F5F4FF1E0A034BF07D2 -:1001400051F7F801A7BEE89507B600FCFDCF3BC00C -:10015000843751F54AD049D0F82E47D05ED0E80117 -:10016000EF2C209719F48091840114C0C130D1057F -:1001700019F4809185010EC0C830D10519F4809121 -:10018000860108C0C930D10519F48091870102C0E9 -:10019000FE01849121961AD0EA9419F70F5F1F4F40 -:1001A000FA940F0D111D0FC0853741F436D08EE142 -:1001B0000DD083E90BD08CE009D005C0813511F456 -:1001C00088E027D02AD080E101D03ACF2AE030E081 -:1001D0008095089410F4DA9802C0DA9A000015D0DD -:1001E00014D086952A95B1F70895A89529E030E0B6 -:1001F000CB99FECF0AD009D008D08894CB99089427 -:100200002A9511F08795F7CF08959EE09A95F1F71A -:10021000089598E191BD81BD0895E7DF803219F01E -:1002200088E0F7DFFFCF84E1D1CF1F93182FDDDF08 -:100230001150E9F7F2DF1F91089580E0EADFE4E072 -:04024000FF270994F7 -:021EFE000104DD +:101D0000112484B714BE81FF18D185E08EBD8EE00A +:101D100000D1D49AD29A86E023EC3FEF91E03DBD0A +:101D20002CBD9BB9589BFECFCC9AA8958150B9F792 +:101D3000BB24B39425E0A22E9FE7D92E8EECC82EAB +:101D4000D4D0813421F481E0F0D083E0B5C0823476 +:101D500011F484E103C0853419F485E0E6D0B3C002 +:101D6000853569F4C2D0E82EFF24BFD0082F10E0DB +:101D7000102F00270E291F29000F111FA3C0863521 +:101D800021F484E0D2D080E097C0843609F060C0AE +:101D9000ACD0ABD0F82EA9D0C0E0D1E0A6D08993CA +:101DA000FC16E1F783E0F80187BFE895B6D007B6E7 +:101DB00000FCFDCF0115110511F0A8012AC080918A +:101DC00000012091010130E0322F222790E0282BE2 +:101DD000392B309385012093840140910801809133 +:101DE000090190E0982F882750E0842B952B909341 +:101DF0008701809386012450304020930801232FCF +:101E0000332720930901D0920001C092010140E0E4 +:101E100050E0A0E0B1E02C9130E011968C91119748 +:101E200090E0982F8827822B932B1296FA010C01B1 +:101E3000B7BEE89511244E5F5F4FF1E0A034BF07B5 +:101E400051F7F801A7BEE89507B600FCFDCF3BC0EF +:101E5000843751F54AD049D0F82E47D05ED0E801FA +:101E6000EF2C209719F48091840114C0C130D10562 +:101E700019F4809185010EC0C830D10519F4809104 +:101E8000860108C0C930D10519F48091870102C0CC +:101E9000FE01849121961AD0EA9419F70F5F1F4F23 +:101EA000FA940F0D111D0FC0853741F436D08EE125 +:101EB0000DD083E90BD08CE009D005C0813511F439 +:101EC00088E027D02AD080E101D03ACF2AE030E064 +:101ED0008095089410F4DA9802C0DA9A000015D0C0 +:101EE00014D086952A95B1F70895A89529E030E099 +:101EF000CB99FECF0AD009D008D08894CB9908940A +:101F00002A9511F08795F7CF08959EE09A95F1F7FD +:101F1000089598E191BD81BD0895E7DF803219F001 +:101F200088E0F7DFFFCF84E1D1CF1F93182FDDDFEB +:101F30001150E9F7F2DF1F91089580E0EADFE4E055 +:041F4000FF270994DA +:021EFE000204DC +:0400000300001D00DC :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_luminet.lst b/hardware/arduino/bootloaders/optiboot/optiboot_luminet.lst index 83336701c..447349df2 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_luminet.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_luminet.lst @@ -3,622 +3,622 @@ optiboot_luminet.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .version 00000002 00001efe 00001efe 00000298 2**0 - CONTENTS, READONLY - 1 .text 00000244 00000000 00000000 00000054 2**1 + 0 .text 00000244 00001d00 00001d00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 .version 00000002 00001efe 00001efe 00000298 2**0 + CONTENTS, READONLY 2 .debug_aranges 00000028 00000000 00000000 0000029a 2**0 CONTENTS, READONLY, DEBUGGING 3 .debug_pubnames 0000006d 00000000 00000000 000002c2 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_info 000002b0 00000000 00000000 0000032f 2**0 + 4 .debug_info 000002b1 00000000 00000000 0000032f 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 00000197 00000000 00000000 000005df 2**0 + 5 .debug_abbrev 00000188 00000000 00000000 000005e0 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_line 000004a7 00000000 00000000 00000776 2**0 + 6 .debug_line 000004a7 00000000 00000000 00000768 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000090 00000000 00000000 00000c20 2**2 + 7 .debug_frame 00000090 00000000 00000000 00000c10 2**2 CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000158 00000000 00000000 00000cb0 2**0 + 8 .debug_str 00000158 00000000 00000000 00000ca0 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 00000268 00000000 00000000 00000e08 2**0 + 9 .debug_loc 00000268 00000000 00000000 00000df8 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000080 00000000 00000000 00001070 2**0 + 10 .debug_ranges 00000080 00000000 00000000 00001060 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: -00000000
    : +00001d00
    : #define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) #define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif /* main program starts here */ int main(void) { - 0: 11 24 eor r1, r1 + 1d00: 11 24 eor r1, r1 #ifdef __AVR_ATmega8__ SP=RAMEND; // This is done by hardware reset #endif // Adaboot no-wait mod ch = MCUSR; - 2: 84 b7 in r24, 0x34 ; 52 + 1d02: 84 b7 in r24, 0x34 ; 52 MCUSR = 0; - 4: 14 be out 0x34, r1 ; 52 + 1d04: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); - 6: 81 ff sbrs r24, 1 - 8: 18 d1 rcall .+560 ; 0x23a + 1d06: 81 ff sbrs r24, 1 + 1d08: 18 d1 rcall .+560 ; 0x1f3a #if LED_START_FLASHES > 0 // Set up Timer 1 for timeout counter TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 - a: 85 e0 ldi r24, 0x05 ; 5 - c: 8e bd out 0x2e, r24 ; 46 + 1d0a: 85 e0 ldi r24, 0x05 ; 5 + 1d0c: 8e bd out 0x2e, r24 ; 46 UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); #endif #endif // Set up watchdog to trigger after 500ms watchdogConfig(WATCHDOG_1S); - e: 8e e0 ldi r24, 0x0E ; 14 - 10: 00 d1 rcall .+512 ; 0x212 + 1d0e: 8e e0 ldi r24, 0x0E ; 14 + 1d10: 00 d1 rcall .+512 ; 0x1f12 /* Set LED pin as output */ LED_DDR |= _BV(LED); - 12: d4 9a sbi 0x1a, 4 ; 26 + 1d12: d4 9a sbi 0x1a, 4 ; 26 #ifdef SOFT_UART /* Set TX pin as output */ UART_DDR |= _BV(UART_TX_BIT); - 14: d2 9a sbi 0x1a, 2 ; 26 - 16: 86 e0 ldi r24, 0x06 ; 6 + 1d14: d2 9a sbi 0x1a, 2 ; 26 + 1d16: 86 e0 ldi r24, 0x06 ; 6 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - 18: 23 ec ldi r18, 0xC3 ; 195 - 1a: 3f ef ldi r19, 0xFF ; 255 + 1d18: 23 ec ldi r18, 0xC3 ; 195 + 1d1a: 3f ef ldi r19, 0xFF ; 255 TIFR1 = _BV(TOV1); - 1c: 91 e0 ldi r25, 0x01 ; 1 + 1d1c: 91 e0 ldi r25, 0x01 ; 1 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - 1e: 3d bd out 0x2d, r19 ; 45 - 20: 2c bd out 0x2c, r18 ; 44 + 1d1e: 3d bd out 0x2d, r19 ; 45 + 1d20: 2c bd out 0x2c, r18 ; 44 TIFR1 = _BV(TOV1); - 22: 9b b9 out 0x0b, r25 ; 11 + 1d22: 9b b9 out 0x0b, r25 ; 11 while(!(TIFR1 & _BV(TOV1))); - 24: 58 9b sbis 0x0b, 0 ; 11 - 26: fe cf rjmp .-4 ; 0x24 <__zero_reg__+0x23> + 1d24: 58 9b sbis 0x0b, 0 ; 11 + 1d26: fe cf rjmp .-4 ; 0x1d24 #ifdef __AVR_ATmega8__ LED_PORT ^= _BV(LED); #else LED_PIN |= _BV(LED); - 28: cc 9a sbi 0x19, 4 ; 25 + 1d28: cc 9a sbi 0x19, 4 ; 25 } #endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 2a: a8 95 wdr + 1d2a: a8 95 wdr LED_PORT ^= _BV(LED); #else LED_PIN |= _BV(LED); #endif watchdogReset(); } while (--count); - 2c: 81 50 subi r24, 0x01 ; 1 - 2e: b9 f7 brne .-18 ; 0x1e <__zero_reg__+0x1d> + 1d2c: 81 50 subi r24, 0x01 ; 1 + 1d2e: b9 f7 brne .-18 ; 0x1d1e /* get character from UART */ ch = getch(); if(ch == STK_GET_PARAMETER) { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 30: bb 24 eor r11, r11 - 32: b3 94 inc r11 + 1d30: bb 24 eor r11, r11 + 1d32: b3 94 inc r11 __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); - 34: 25 e0 ldi r18, 0x05 ; 5 - 36: a2 2e mov r10, r18 + 1d34: 25 e0 ldi r18, 0x05 ; 5 + 1d36: a2 2e mov r10, r18 vect -= 4; // Instruction is a relative jump (rjmp), so recalculate. buff[8] = vect & 0xff; buff[9] = vect >> 8; // Add jump to bootloader at RESET vector buff[0] = 0x7f; - 38: 9f e7 ldi r25, 0x7F ; 127 - 3a: d9 2e mov r13, r25 + 1d38: 9f e7 ldi r25, 0x7F ; 127 + 1d3a: d9 2e mov r13, r25 buff[1] = 0xce; // rjmp 0x1d00 instruction - 3c: 8e ec ldi r24, 0xCE ; 206 - 3e: c8 2e mov r12, r24 + 1d3c: 8e ec ldi r24, 0xCE ; 206 + 1d3e: c8 2e mov r12, r24 #endif /* Forever loop */ for (;;) { /* get character from UART */ ch = getch(); - 40: d4 d0 rcall .+424 ; 0x1ea + 1d40: d4 d0 rcall .+424 ; 0x1eea if(ch == STK_GET_PARAMETER) { - 42: 81 34 cpi r24, 0x41 ; 65 - 44: 21 f4 brne .+8 ; 0x4e <__SREG__+0xf> + 1d42: 81 34 cpi r24, 0x41 ; 65 + 1d44: 21 f4 brne .+8 ; 0x1d4e // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); - 46: 81 e0 ldi r24, 0x01 ; 1 - 48: f0 d0 rcall .+480 ; 0x22a + 1d46: 81 e0 ldi r24, 0x01 ; 1 + 1d48: f0 d0 rcall .+480 ; 0x1f2a putch(0x03); - 4a: 83 e0 ldi r24, 0x03 ; 3 - 4c: b5 c0 rjmp .+362 ; 0x1b8 <__SREG__+0x179> + 1d4a: 83 e0 ldi r24, 0x03 ; 3 + 1d4c: b5 c0 rjmp .+362 ; 0x1eb8 } else if(ch == STK_SET_DEVICE) { - 4e: 82 34 cpi r24, 0x42 ; 66 - 50: 11 f4 brne .+4 ; 0x56 <__SREG__+0x17> + 1d4e: 82 34 cpi r24, 0x42 ; 66 + 1d50: 11 f4 brne .+4 ; 0x1d56 // SET DEVICE is ignored getNch(20); - 52: 84 e1 ldi r24, 0x14 ; 20 - 54: 03 c0 rjmp .+6 ; 0x5c <__SREG__+0x1d> + 1d52: 84 e1 ldi r24, 0x14 ; 20 + 1d54: 03 c0 rjmp .+6 ; 0x1d5c } else if(ch == STK_SET_DEVICE_EXT) { - 56: 85 34 cpi r24, 0x45 ; 69 - 58: 19 f4 brne .+6 ; 0x60 <__SREG__+0x21> + 1d56: 85 34 cpi r24, 0x45 ; 69 + 1d58: 19 f4 brne .+6 ; 0x1d60 // SET DEVICE EXT is ignored getNch(5); - 5a: 85 e0 ldi r24, 0x05 ; 5 - 5c: e6 d0 rcall .+460 ; 0x22a - 5e: b3 c0 rjmp .+358 ; 0x1c6 <__SREG__+0x187> + 1d5a: 85 e0 ldi r24, 0x05 ; 5 + 1d5c: e6 d0 rcall .+460 ; 0x1f2a + 1d5e: b3 c0 rjmp .+358 ; 0x1ec6 } else if(ch == STK_LOAD_ADDRESS) { - 60: 85 35 cpi r24, 0x55 ; 85 - 62: 69 f4 brne .+26 ; 0x7e <__SREG__+0x3f> + 1d60: 85 35 cpi r24, 0x55 ; 85 + 1d62: 69 f4 brne .+26 ; 0x1d7e // LOAD ADDRESS uint16_t newAddress; newAddress = getch(); - 64: c2 d0 rcall .+388 ; 0x1ea + 1d64: c2 d0 rcall .+388 ; 0x1eea newAddress = (newAddress & 0xff) | (getch() << 8); - 66: e8 2e mov r14, r24 - 68: ff 24 eor r15, r15 - 6a: bf d0 rcall .+382 ; 0x1ea - 6c: 08 2f mov r16, r24 - 6e: 10 e0 ldi r17, 0x00 ; 0 - 70: 10 2f mov r17, r16 - 72: 00 27 eor r16, r16 - 74: 0e 29 or r16, r14 - 76: 1f 29 or r17, r15 + 1d66: e8 2e mov r14, r24 + 1d68: ff 24 eor r15, r15 + 1d6a: bf d0 rcall .+382 ; 0x1eea + 1d6c: 08 2f mov r16, r24 + 1d6e: 10 e0 ldi r17, 0x00 ; 0 + 1d70: 10 2f mov r17, r16 + 1d72: 00 27 eor r16, r16 + 1d74: 0e 29 or r16, r14 + 1d76: 1f 29 or r17, r15 #ifdef RAMPZ // Transfer top bit to RAMPZ RAMPZ = (newAddress & 0x8000) ? 1 : 0; #endif newAddress += newAddress; // Convert from word address to byte address - 78: 00 0f add r16, r16 - 7a: 11 1f adc r17, r17 - 7c: a3 c0 rjmp .+326 ; 0x1c4 <__SREG__+0x185> + 1d78: 00 0f add r16, r16 + 1d7a: 11 1f adc r17, r17 + 1d7c: a3 c0 rjmp .+326 ; 0x1ec4 address = newAddress; verifySpace(); } else if(ch == STK_UNIVERSAL) { - 7e: 86 35 cpi r24, 0x56 ; 86 - 80: 21 f4 brne .+8 ; 0x8a <__SREG__+0x4b> + 1d7e: 86 35 cpi r24, 0x56 ; 86 + 1d80: 21 f4 brne .+8 ; 0x1d8a // UNIVERSAL command is ignored getNch(4); - 82: 84 e0 ldi r24, 0x04 ; 4 - 84: d2 d0 rcall .+420 ; 0x22a + 1d82: 84 e0 ldi r24, 0x04 ; 4 + 1d84: d2 d0 rcall .+420 ; 0x1f2a putch(0x00); - 86: 80 e0 ldi r24, 0x00 ; 0 - 88: 97 c0 rjmp .+302 ; 0x1b8 <__SREG__+0x179> + 1d86: 80 e0 ldi r24, 0x00 ; 0 + 1d88: 97 c0 rjmp .+302 ; 0x1eb8 } /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { - 8a: 84 36 cpi r24, 0x64 ; 100 - 8c: 09 f0 breq .+2 ; 0x90 <__SREG__+0x51> - 8e: 60 c0 rjmp .+192 ; 0x150 <__SREG__+0x111> + 1d8a: 84 36 cpi r24, 0x64 ; 100 + 1d8c: 09 f0 breq .+2 ; 0x1d90 + 1d8e: 60 c0 rjmp .+192 ; 0x1e50 // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t *bufPtr; uint16_t addrPtr; getch(); /* getlen() */ - 90: ac d0 rcall .+344 ; 0x1ea + 1d90: ac d0 rcall .+344 ; 0x1eea length = getch(); - 92: ab d0 rcall .+342 ; 0x1ea - 94: f8 2e mov r15, r24 + 1d92: ab d0 rcall .+342 ; 0x1eea + 1d94: f8 2e mov r15, r24 getch(); - 96: a9 d0 rcall .+338 ; 0x1ea - 98: c0 e0 ldi r28, 0x00 ; 0 - 9a: d1 e0 ldi r29, 0x01 ; 1 + 1d96: a9 d0 rcall .+338 ; 0x1eea + 1d98: c0 e0 ldi r28, 0x00 ; 0 + 1d9a: d1 e0 ldi r29, 0x01 ; 1 // If we are in RWW section, immediately start page erase if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); - 9c: a6 d0 rcall .+332 ; 0x1ea - 9e: 89 93 st Y+, r24 + 1d9c: a6 d0 rcall .+332 ; 0x1eea + 1d9e: 89 93 st Y+, r24 while (--length); - a0: fc 16 cp r15, r28 - a2: e1 f7 brne .-8 ; 0x9c <__SREG__+0x5d> + 1da0: fc 16 cp r15, r28 + 1da2: e1 f7 brne .-8 ; 0x1d9c // If we are in NRWW section, page erase has to be delayed until now. // Todo: Take RAMPZ into account if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - a4: 83 e0 ldi r24, 0x03 ; 3 - a6: f8 01 movw r30, r16 - a8: 87 bf out 0x37, r24 ; 55 - aa: e8 95 spm + 1da4: 83 e0 ldi r24, 0x03 ; 3 + 1da6: f8 01 movw r30, r16 + 1da8: 87 bf out 0x37, r24 ; 55 + 1daa: e8 95 spm // Read command terminator, start reply verifySpace(); - ac: b6 d0 rcall .+364 ; 0x21a + 1dac: b6 d0 rcall .+364 ; 0x1f1a // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); - ae: 07 b6 in r0, 0x37 ; 55 - b0: 00 fc sbrc r0, 0 - b2: fd cf rjmp .-6 ; 0xae <__SREG__+0x6f> + 1dae: 07 b6 in r0, 0x37 ; 55 + 1db0: 00 fc sbrc r0, 0 + 1db2: fd cf rjmp .-6 ; 0x1dae #ifdef VIRTUAL_BOOT_PARTITION if ((uint16_t)(void*)address == 0) { - b4: 01 15 cp r16, r1 - b6: 11 05 cpc r17, r1 - b8: 11 f0 breq .+4 ; 0xbe <__SREG__+0x7f> - ba: a8 01 movw r20, r16 - bc: 2a c0 rjmp .+84 ; 0x112 <__SREG__+0xd3> + 1db4: 01 15 cp r16, r1 + 1db6: 11 05 cpc r17, r1 + 1db8: 11 f0 breq .+4 ; 0x1dbe + 1dba: a8 01 movw r20, r16 + 1dbc: 2a c0 rjmp .+84 ; 0x1e12 // This is the reset vector page. We need to live-patch the code so the // bootloader runs. // // Move RESET vector to WDT vector uint16_t vect = buff[0] | (buff[1]<<8); - be: 80 91 00 01 lds r24, 0x0100 - c2: 20 91 01 01 lds r18, 0x0101 - c6: 30 e0 ldi r19, 0x00 ; 0 - c8: 32 2f mov r19, r18 - ca: 22 27 eor r18, r18 - cc: 90 e0 ldi r25, 0x00 ; 0 - ce: 28 2b or r18, r24 - d0: 39 2b or r19, r25 + 1dbe: 80 91 00 01 lds r24, 0x0100 + 1dc2: 20 91 01 01 lds r18, 0x0101 + 1dc6: 30 e0 ldi r19, 0x00 ; 0 + 1dc8: 32 2f mov r19, r18 + 1dca: 22 27 eor r18, r18 + 1dcc: 90 e0 ldi r25, 0x00 ; 0 + 1dce: 28 2b or r18, r24 + 1dd0: 39 2b or r19, r25 rstVect = vect; - d2: 30 93 85 01 sts 0x0185, r19 - d6: 20 93 84 01 sts 0x0184, r18 + 1dd2: 30 93 85 01 sts 0x0185, r19 + 1dd6: 20 93 84 01 sts 0x0184, r18 wdtVect = buff[8] | (buff[9]<<8); - da: 40 91 08 01 lds r20, 0x0108 - de: 80 91 09 01 lds r24, 0x0109 - e2: 90 e0 ldi r25, 0x00 ; 0 - e4: 98 2f mov r25, r24 - e6: 88 27 eor r24, r24 - e8: 50 e0 ldi r21, 0x00 ; 0 - ea: 84 2b or r24, r20 - ec: 95 2b or r25, r21 - ee: 90 93 87 01 sts 0x0187, r25 - f2: 80 93 86 01 sts 0x0186, r24 + 1dda: 40 91 08 01 lds r20, 0x0108 + 1dde: 80 91 09 01 lds r24, 0x0109 + 1de2: 90 e0 ldi r25, 0x00 ; 0 + 1de4: 98 2f mov r25, r24 + 1de6: 88 27 eor r24, r24 + 1de8: 50 e0 ldi r21, 0x00 ; 0 + 1dea: 84 2b or r24, r20 + 1dec: 95 2b or r25, r21 + 1dee: 90 93 87 01 sts 0x0187, r25 + 1df2: 80 93 86 01 sts 0x0186, r24 vect -= 4; // Instruction is a relative jump (rjmp), so recalculate. - f6: 24 50 subi r18, 0x04 ; 4 - f8: 30 40 sbci r19, 0x00 ; 0 + 1df6: 24 50 subi r18, 0x04 ; 4 + 1df8: 30 40 sbci r19, 0x00 ; 0 buff[8] = vect & 0xff; - fa: 20 93 08 01 sts 0x0108, r18 + 1dfa: 20 93 08 01 sts 0x0108, r18 buff[9] = vect >> 8; - fe: 23 2f mov r18, r19 - 100: 33 27 eor r19, r19 - 102: 20 93 09 01 sts 0x0109, r18 + 1dfe: 23 2f mov r18, r19 + 1e00: 33 27 eor r19, r19 + 1e02: 20 93 09 01 sts 0x0109, r18 // Add jump to bootloader at RESET vector buff[0] = 0x7f; - 106: d0 92 00 01 sts 0x0100, r13 + 1e06: d0 92 00 01 sts 0x0100, r13 buff[1] = 0xce; // rjmp 0x1d00 instruction - 10a: c0 92 01 01 sts 0x0101, r12 - 10e: 40 e0 ldi r20, 0x00 ; 0 - 110: 50 e0 ldi r21, 0x00 ; 0 - 112: a0 e0 ldi r26, 0x00 ; 0 - 114: b1 e0 ldi r27, 0x01 ; 1 + 1e0a: c0 92 01 01 sts 0x0101, r12 + 1e0e: 40 e0 ldi r20, 0x00 ; 0 + 1e10: 50 e0 ldi r21, 0x00 ; 0 + 1e12: a0 e0 ldi r26, 0x00 ; 0 + 1e14: b1 e0 ldi r27, 0x01 ; 1 bufPtr = buff; addrPtr = (uint16_t)(void*)address; ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; - 116: 2c 91 ld r18, X - 118: 30 e0 ldi r19, 0x00 ; 0 + 1e16: 2c 91 ld r18, X + 1e18: 30 e0 ldi r19, 0x00 ; 0 a |= (*bufPtr++) << 8; - 11a: 11 96 adiw r26, 0x01 ; 1 - 11c: 8c 91 ld r24, X - 11e: 11 97 sbiw r26, 0x01 ; 1 - 120: 90 e0 ldi r25, 0x00 ; 0 - 122: 98 2f mov r25, r24 - 124: 88 27 eor r24, r24 - 126: 82 2b or r24, r18 - 128: 93 2b or r25, r19 + 1e1a: 11 96 adiw r26, 0x01 ; 1 + 1e1c: 8c 91 ld r24, X + 1e1e: 11 97 sbiw r26, 0x01 ; 1 + 1e20: 90 e0 ldi r25, 0x00 ; 0 + 1e22: 98 2f mov r25, r24 + 1e24: 88 27 eor r24, r24 + 1e26: 82 2b or r24, r18 + 1e28: 93 2b or r25, r19 #define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) #define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif /* main program starts here */ int main(void) { - 12a: 12 96 adiw r26, 0x02 ; 2 + 1e2a: 12 96 adiw r26, 0x02 ; 2 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; a |= (*bufPtr++) << 8; __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - 12c: fa 01 movw r30, r20 - 12e: 0c 01 movw r0, r24 - 130: b7 be out 0x37, r11 ; 55 - 132: e8 95 spm - 134: 11 24 eor r1, r1 + 1e2c: fa 01 movw r30, r20 + 1e2e: 0c 01 movw r0, r24 + 1e30: b7 be out 0x37, r11 ; 55 + 1e32: e8 95 spm + 1e34: 11 24 eor r1, r1 addrPtr += 2; - 136: 4e 5f subi r20, 0xFE ; 254 - 138: 5f 4f sbci r21, 0xFF ; 255 + 1e36: 4e 5f subi r20, 0xFE ; 254 + 1e38: 5f 4f sbci r21, 0xFF ; 255 } while (--ch); - 13a: f1 e0 ldi r31, 0x01 ; 1 - 13c: a0 34 cpi r26, 0x40 ; 64 - 13e: bf 07 cpc r27, r31 - 140: 51 f7 brne .-44 ; 0x116 <__SREG__+0xd7> + 1e3a: f1 e0 ldi r31, 0x01 ; 1 + 1e3c: a0 34 cpi r26, 0x40 ; 64 + 1e3e: bf 07 cpc r27, r31 + 1e40: 51 f7 brne .-44 ; 0x1e16 // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); - 142: f8 01 movw r30, r16 - 144: a7 be out 0x37, r10 ; 55 - 146: e8 95 spm + 1e42: f8 01 movw r30, r16 + 1e44: a7 be out 0x37, r10 ; 55 + 1e46: e8 95 spm boot_spm_busy_wait(); - 148: 07 b6 in r0, 0x37 ; 55 - 14a: 00 fc sbrc r0, 0 - 14c: fd cf rjmp .-6 ; 0x148 <__SREG__+0x109> - 14e: 3b c0 rjmp .+118 ; 0x1c6 <__SREG__+0x187> + 1e48: 07 b6 in r0, 0x37 ; 55 + 1e4a: 00 fc sbrc r0, 0 + 1e4c: fd cf rjmp .-6 ; 0x1e48 + 1e4e: 3b c0 rjmp .+118 ; 0x1ec6 boot_rww_enable(); #endif } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { - 150: 84 37 cpi r24, 0x74 ; 116 - 152: 51 f5 brne .+84 ; 0x1a8 <__SREG__+0x169> + 1e50: 84 37 cpi r24, 0x74 ; 116 + 1e52: 51 f5 brne .+84 ; 0x1ea8 // READ PAGE - we only read flash getch(); /* getlen() */ - 154: 4a d0 rcall .+148 ; 0x1ea + 1e54: 4a d0 rcall .+148 ; 0x1eea length = getch(); - 156: 49 d0 rcall .+146 ; 0x1ea - 158: f8 2e mov r15, r24 + 1e56: 49 d0 rcall .+146 ; 0x1eea + 1e58: f8 2e mov r15, r24 getch(); - 15a: 47 d0 rcall .+142 ; 0x1ea + 1e5a: 47 d0 rcall .+142 ; 0x1eea verifySpace(); - 15c: 5e d0 rcall .+188 ; 0x21a - 15e: e8 01 movw r28, r16 - 160: ef 2c mov r14, r15 + 1e5c: 5e d0 rcall .+188 ; 0x1f1a + 1e5e: e8 01 movw r28, r16 + 1e60: ef 2c mov r14, r15 #ifdef VIRTUAL_BOOT_PARTITION do { // Undo vector patch in bottom page so verify passes if (address == 0) ch=rstVect & 0xff; - 162: 20 97 sbiw r28, 0x00 ; 0 - 164: 19 f4 brne .+6 ; 0x16c <__SREG__+0x12d> - 166: 80 91 84 01 lds r24, 0x0184 - 16a: 14 c0 rjmp .+40 ; 0x194 <__SREG__+0x155> + 1e62: 20 97 sbiw r28, 0x00 ; 0 + 1e64: 19 f4 brne .+6 ; 0x1e6c + 1e66: 80 91 84 01 lds r24, 0x0184 + 1e6a: 14 c0 rjmp .+40 ; 0x1e94 else if (address == 1) ch=rstVect >> 8; - 16c: c1 30 cpi r28, 0x01 ; 1 - 16e: d1 05 cpc r29, r1 - 170: 19 f4 brne .+6 ; 0x178 <__SREG__+0x139> - 172: 80 91 85 01 lds r24, 0x0185 - 176: 0e c0 rjmp .+28 ; 0x194 <__SREG__+0x155> + 1e6c: c1 30 cpi r28, 0x01 ; 1 + 1e6e: d1 05 cpc r29, r1 + 1e70: 19 f4 brne .+6 ; 0x1e78 + 1e72: 80 91 85 01 lds r24, 0x0185 + 1e76: 0e c0 rjmp .+28 ; 0x1e94 else if (address == 8) ch=wdtVect & 0xff; - 178: c8 30 cpi r28, 0x08 ; 8 - 17a: d1 05 cpc r29, r1 - 17c: 19 f4 brne .+6 ; 0x184 <__SREG__+0x145> - 17e: 80 91 86 01 lds r24, 0x0186 - 182: 08 c0 rjmp .+16 ; 0x194 <__SREG__+0x155> + 1e78: c8 30 cpi r28, 0x08 ; 8 + 1e7a: d1 05 cpc r29, r1 + 1e7c: 19 f4 brne .+6 ; 0x1e84 + 1e7e: 80 91 86 01 lds r24, 0x0186 + 1e82: 08 c0 rjmp .+16 ; 0x1e94 else if (address == 9) ch=wdtVect >> 8; - 184: c9 30 cpi r28, 0x09 ; 9 - 186: d1 05 cpc r29, r1 - 188: 19 f4 brne .+6 ; 0x190 <__SREG__+0x151> - 18a: 80 91 87 01 lds r24, 0x0187 - 18e: 02 c0 rjmp .+4 ; 0x194 <__SREG__+0x155> + 1e84: c9 30 cpi r28, 0x09 ; 9 + 1e86: d1 05 cpc r29, r1 + 1e88: 19 f4 brne .+6 ; 0x1e90 + 1e8a: 80 91 87 01 lds r24, 0x0187 + 1e8e: 02 c0 rjmp .+4 ; 0x1e94 else ch = pgm_read_byte_near(address); - 190: fe 01 movw r30, r28 - 192: 84 91 lpm r24, Z+ + 1e90: fe 01 movw r30, r28 + 1e92: 84 91 lpm r24, Z+ address++; - 194: 21 96 adiw r28, 0x01 ; 1 + 1e94: 21 96 adiw r28, 0x01 ; 1 putch(ch); - 196: 1a d0 rcall .+52 ; 0x1cc + 1e96: 1a d0 rcall .+52 ; 0x1ecc } while (--length); - 198: ea 94 dec r14 - 19a: 19 f7 brne .-58 ; 0x162 <__SREG__+0x123> + 1e98: ea 94 dec r14 + 1e9a: 19 f7 brne .-58 ; 0x1e62 #define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) #define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif /* main program starts here */ int main(void) { - 19c: 0f 5f subi r16, 0xFF ; 255 - 19e: 1f 4f sbci r17, 0xFF ; 255 - 1a0: fa 94 dec r15 - 1a2: 0f 0d add r16, r15 - 1a4: 11 1d adc r17, r1 - 1a6: 0f c0 rjmp .+30 ; 0x1c6 <__SREG__+0x187> + 1e9c: 0f 5f subi r16, 0xFF ; 255 + 1e9e: 1f 4f sbci r17, 0xFF ; 255 + 1ea0: fa 94 dec r15 + 1ea2: 0f 0d add r16, r15 + 1ea4: 11 1d adc r17, r1 + 1ea6: 0f c0 rjmp .+30 ; 0x1ec6 #endif #endif } /* Get device signature bytes */ else if(ch == STK_READ_SIGN) { - 1a8: 85 37 cpi r24, 0x75 ; 117 - 1aa: 41 f4 brne .+16 ; 0x1bc <__SREG__+0x17d> + 1ea8: 85 37 cpi r24, 0x75 ; 117 + 1eaa: 41 f4 brne .+16 ; 0x1ebc // READ SIGN - return what Avrdude wants to hear verifySpace(); - 1ac: 36 d0 rcall .+108 ; 0x21a + 1eac: 36 d0 rcall .+108 ; 0x1f1a putch(SIGNATURE_0); - 1ae: 8e e1 ldi r24, 0x1E ; 30 - 1b0: 0d d0 rcall .+26 ; 0x1cc + 1eae: 8e e1 ldi r24, 0x1E ; 30 + 1eb0: 0d d0 rcall .+26 ; 0x1ecc putch(SIGNATURE_1); - 1b2: 83 e9 ldi r24, 0x93 ; 147 - 1b4: 0b d0 rcall .+22 ; 0x1cc + 1eb2: 83 e9 ldi r24, 0x93 ; 147 + 1eb4: 0b d0 rcall .+22 ; 0x1ecc putch(SIGNATURE_2); - 1b6: 8c e0 ldi r24, 0x0C ; 12 - 1b8: 09 d0 rcall .+18 ; 0x1cc - 1ba: 05 c0 rjmp .+10 ; 0x1c6 <__SREG__+0x187> + 1eb6: 8c e0 ldi r24, 0x0C ; 12 + 1eb8: 09 d0 rcall .+18 ; 0x1ecc + 1eba: 05 c0 rjmp .+10 ; 0x1ec6 } else if (ch == 'Q') { - 1bc: 81 35 cpi r24, 0x51 ; 81 - 1be: 11 f4 brne .+4 ; 0x1c4 <__SREG__+0x185> + 1ebc: 81 35 cpi r24, 0x51 ; 81 + 1ebe: 11 f4 brne .+4 ; 0x1ec4 // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); - 1c0: 88 e0 ldi r24, 0x08 ; 8 - 1c2: 27 d0 rcall .+78 ; 0x212 + 1ec0: 88 e0 ldi r24, 0x08 ; 8 + 1ec2: 27 d0 rcall .+78 ; 0x1f12 verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 1c4: 2a d0 rcall .+84 ; 0x21a + 1ec4: 2a d0 rcall .+84 ; 0x1f1a } putch(STK_OK); - 1c6: 80 e1 ldi r24, 0x10 ; 16 - 1c8: 01 d0 rcall .+2 ; 0x1cc - 1ca: 3a cf rjmp .-396 ; 0x40 <__SREG__+0x1> + 1ec6: 80 e1 ldi r24, 0x10 ; 16 + 1ec8: 01 d0 rcall .+2 ; 0x1ecc + 1eca: 3a cf rjmp .-396 ; 0x1d40 -000001cc : +00001ecc : void putch(char ch) { #ifndef SOFT_UART while (!(UCSR0A & _BV(UDRE0))); UDR0 = ch; #else __asm__ __volatile__ ( - 1cc: 2a e0 ldi r18, 0x0A ; 10 - 1ce: 30 e0 ldi r19, 0x00 ; 0 - 1d0: 80 95 com r24 - 1d2: 08 94 sec - 1d4: 10 f4 brcc .+4 ; 0x1da - 1d6: da 98 cbi 0x1b, 2 ; 27 - 1d8: 02 c0 rjmp .+4 ; 0x1de - 1da: da 9a sbi 0x1b, 2 ; 27 - 1dc: 00 00 nop - 1de: 15 d0 rcall .+42 ; 0x20a - 1e0: 14 d0 rcall .+40 ; 0x20a - 1e2: 86 95 lsr r24 - 1e4: 2a 95 dec r18 - 1e6: b1 f7 brne .-20 ; 0x1d4 + 1ecc: 2a e0 ldi r18, 0x0A ; 10 + 1ece: 30 e0 ldi r19, 0x00 ; 0 + 1ed0: 80 95 com r24 + 1ed2: 08 94 sec + 1ed4: 10 f4 brcc .+4 ; 0x1eda + 1ed6: da 98 cbi 0x1b, 2 ; 27 + 1ed8: 02 c0 rjmp .+4 ; 0x1ede + 1eda: da 9a sbi 0x1b, 2 ; 27 + 1edc: 00 00 nop + 1ede: 15 d0 rcall .+42 ; 0x1f0a + 1ee0: 14 d0 rcall .+40 ; 0x1f0a + 1ee2: 86 95 lsr r24 + 1ee4: 2a 95 dec r18 + 1ee6: b1 f7 brne .-20 ; 0x1ed4 [uartBit] "I" (UART_TX_BIT) : "r25" ); #endif } - 1e8: 08 95 ret + 1ee8: 08 95 ret -000001ea : +00001eea : } #endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 1ea: a8 95 wdr + 1eea: a8 95 wdr LED_PIN |= _BV(LED); #endif #endif return ch; } - 1ec: 29 e0 ldi r18, 0x09 ; 9 - 1ee: 30 e0 ldi r19, 0x00 ; 0 - 1f0: cb 99 sbic 0x19, 3 ; 25 - 1f2: fe cf rjmp .-4 ; 0x1f0 - 1f4: 0a d0 rcall .+20 ; 0x20a - 1f6: 09 d0 rcall .+18 ; 0x20a - 1f8: 08 d0 rcall .+16 ; 0x20a - 1fa: 88 94 clc - 1fc: cb 99 sbic 0x19, 3 ; 25 - 1fe: 08 94 sec - 200: 2a 95 dec r18 - 202: 11 f0 breq .+4 ; 0x208 - 204: 87 95 ror r24 - 206: f7 cf rjmp .-18 ; 0x1f6 - 208: 08 95 ret + 1eec: 29 e0 ldi r18, 0x09 ; 9 + 1eee: 30 e0 ldi r19, 0x00 ; 0 + 1ef0: cb 99 sbic 0x19, 3 ; 25 + 1ef2: fe cf rjmp .-4 ; 0x1ef0 + 1ef4: 0a d0 rcall .+20 ; 0x1f0a + 1ef6: 09 d0 rcall .+18 ; 0x1f0a + 1ef8: 08 d0 rcall .+16 ; 0x1f0a + 1efa: 88 94 clc + 1efc: cb 99 sbic 0x19, 3 ; 25 + 1efe: 08 94 sec + 1f00: 2a 95 dec r18 + 1f02: 11 f0 breq .+4 ; 0x1f08 + 1f04: 87 95 ror r24 + 1f06: f7 cf rjmp .-18 ; 0x1ef6 + 1f08: 08 95 ret -0000020a : +00001f0a : #if UART_B_VALUE > 255 #error Baud rate too slow for soft UART #endif void uartDelay() { __asm__ __volatile__ ( - 20a: 9e e0 ldi r25, 0x0E ; 14 - 20c: 9a 95 dec r25 - 20e: f1 f7 brne .-4 ; 0x20c - 210: 08 95 ret + 1f0a: 9e e0 ldi r25, 0x0E ; 14 + 1f0c: 9a 95 dec r25 + 1f0e: f1 f7 brne .-4 ; 0x1f0c + 1f10: 08 95 ret -00000212 : +00001f12 : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 212: 98 e1 ldi r25, 0x18 ; 24 - 214: 91 bd out 0x21, r25 ; 33 + 1f12: 98 e1 ldi r25, 0x18 ; 24 + 1f14: 91 bd out 0x21, r25 ; 33 WDTCSR = x; - 216: 81 bd out 0x21, r24 ; 33 + 1f16: 81 bd out 0x21, r24 ; 33 } - 218: 08 95 ret + 1f18: 08 95 ret -0000021a : +00001f1a : do getch(); while (--count); verifySpace(); } void verifySpace() { if (getch() != CRC_EOP) { - 21a: e7 df rcall .-50 ; 0x1ea - 21c: 80 32 cpi r24, 0x20 ; 32 - 21e: 19 f0 breq .+6 ; 0x226 + 1f1a: e7 df rcall .-50 ; 0x1eea + 1f1c: 80 32 cpi r24, 0x20 ; 32 + 1f1e: 19 f0 breq .+6 ; 0x1f26 watchdogConfig(WATCHDOG_16MS); // shorten WD timeout - 220: 88 e0 ldi r24, 0x08 ; 8 - 222: f7 df rcall .-18 ; 0x212 - 224: ff cf rjmp .-2 ; 0x224 + 1f20: 88 e0 ldi r24, 0x08 ; 8 + 1f22: f7 df rcall .-18 ; 0x1f12 + 1f24: ff cf rjmp .-2 ; 0x1f24 while (1) // and busy-loop so that WD causes ; // a reset and app start. } putch(STK_INSYNC); - 226: 84 e1 ldi r24, 0x14 ; 20 + 1f26: 84 e1 ldi r24, 0x14 ; 20 } - 228: d1 cf rjmp .-94 ; 0x1cc + 1f28: d1 cf rjmp .-94 ; 0x1ecc -0000022a : +00001f2a : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 22a: 1f 93 push r17 - 22c: 18 2f mov r17, r24 + 1f2a: 1f 93 push r17 + 1f2c: 18 2f mov r17, r24 do getch(); while (--count); - 22e: dd df rcall .-70 ; 0x1ea - 230: 11 50 subi r17, 0x01 ; 1 - 232: e9 f7 brne .-6 ; 0x22e + 1f2e: dd df rcall .-70 ; 0x1eea + 1f30: 11 50 subi r17, 0x01 ; 1 + 1f32: e9 f7 brne .-6 ; 0x1f2e verifySpace(); - 234: f2 df rcall .-28 ; 0x21a + 1f34: f2 df rcall .-28 ; 0x1f1a } - 236: 1f 91 pop r17 - 238: 08 95 ret + 1f36: 1f 91 pop r17 + 1f38: 08 95 ret -0000023a : +00001f3a : WDTCSR = _BV(WDCE) | _BV(WDE); WDTCSR = x; } void appStart() { watchdogConfig(WATCHDOG_OFF); - 23a: 80 e0 ldi r24, 0x00 ; 0 - 23c: ea df rcall .-44 ; 0x212 + 1f3a: 80 e0 ldi r24, 0x00 ; 0 + 1f3c: ea df rcall .-44 ; 0x1f12 __asm__ __volatile__ ( - 23e: e4 e0 ldi r30, 0x04 ; 4 - 240: ff 27 eor r31, r31 - 242: 09 94 ijmp + 1f3e: e4 e0 ldi r30, 0x04 ; 4 + 1f40: ff 27 eor r31, r31 + 1f42: 09 94 ijmp diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.hex b/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.hex index 733a1397e..26bbd4cdf 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.hex @@ -28,6 +28,6 @@ :103FB000F1DF803219F088E0F5DFFFCF84E1E2CF56 :103FC0001F93182FE7DF1150E9F7F2DF1F910895D3 :0A3FD00080E0E8DFEE27FF270994E8 -:023FFE000104BC +:023FFE000204BB :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.lst b/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.lst index b1d8c1b69..e615a8e21 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.lst @@ -11,19 +11,19 @@ Idx Name Size VMA LMA File off Algn CONTENTS, READONLY, DEBUGGING 3 .debug_pubnames 0000005f 00000000 00000000 00000258 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_info 0000028c 00000000 00000000 000002b7 2**0 + 4 .debug_info 0000028d 00000000 00000000 000002b7 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 00000199 00000000 00000000 00000543 2**0 + 5 .debug_abbrev 0000018a 00000000 00000000 00000544 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_line 00000456 00000000 00000000 000006dc 2**0 + 6 .debug_line 00000456 00000000 00000000 000006ce 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000080 00000000 00000000 00000b34 2**2 + 7 .debug_frame 00000080 00000000 00000000 00000b24 2**2 CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000149 00000000 00000000 00000bb4 2**0 + 8 .debug_str 00000149 00000000 00000000 00000ba4 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 0000027e 00000000 00000000 00000cfd 2**0 + 9 .debug_loc 0000027e 00000000 00000000 00000ced 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000060 00000000 00000000 00000f7b 2**0 + 10 .debug_ranges 00000060 00000000 00000000 00000f6b 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.hex b/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.hex index 58ed1dcc4..dbd29c1c7 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.hex @@ -28,6 +28,6 @@ :103FB000F1DF803219F088E0F5DFFFCF84E1E2CF56 :103FC0001F93182FE7DF1150E9F7F2DF1F910895D3 :0A3FD00080E0E8DFEE27FF270994E8 -:023FFE000104BC +:023FFE000204BB :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.lst b/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.lst index cd2d66a64..20d4db6fa 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.lst @@ -11,19 +11,19 @@ Idx Name Size VMA LMA File off Algn CONTENTS, READONLY, DEBUGGING 3 .debug_pubnames 0000005f 00000000 00000000 00000258 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_info 0000028c 00000000 00000000 000002b7 2**0 + 4 .debug_info 0000028d 00000000 00000000 000002b7 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 00000199 00000000 00000000 00000543 2**0 + 5 .debug_abbrev 0000018a 00000000 00000000 00000544 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_line 00000456 00000000 00000000 000006dc 2**0 + 6 .debug_line 00000456 00000000 00000000 000006ce 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000080 00000000 00000000 00000b34 2**2 + 7 .debug_frame 00000080 00000000 00000000 00000b24 2**2 CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000149 00000000 00000000 00000bb4 2**0 + 8 .debug_str 00000149 00000000 00000000 00000ba4 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 0000027e 00000000 00000000 00000cfd 2**0 + 9 .debug_loc 0000027e 00000000 00000000 00000ced 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000060 00000000 00000000 00000f7b 2**0 + 10 .debug_ranges 00000060 00000000 00000000 00000f6b 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.hex b/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.hex index dcdbbb44f..00f7a3827 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.hex @@ -28,6 +28,6 @@ :103FB000F1DF803219F088E0F5DFFFCF84E1E2CF56 :103FC0001F93182FE7DF1150E9F7F2DF1F910895D3 :0A3FD00080E0E8DFEE27FF270994E8 -:023FFE000104BC +:023FFE000204BB :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.lst b/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.lst index d3d760e5c..6c117ca63 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.lst @@ -11,19 +11,19 @@ Idx Name Size VMA LMA File off Algn CONTENTS, READONLY, DEBUGGING 3 .debug_pubnames 0000005f 00000000 00000000 00000258 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_info 0000028c 00000000 00000000 000002b7 2**0 + 4 .debug_info 0000028d 00000000 00000000 000002b7 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 00000199 00000000 00000000 00000543 2**0 + 5 .debug_abbrev 0000018a 00000000 00000000 00000544 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_line 00000456 00000000 00000000 000006dc 2**0 + 6 .debug_line 00000456 00000000 00000000 000006ce 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000080 00000000 00000000 00000b34 2**2 + 7 .debug_frame 00000080 00000000 00000000 00000b24 2**2 CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000149 00000000 00000000 00000bb4 2**0 + 8 .debug_str 00000149 00000000 00000000 00000ba4 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 0000027e 00000000 00000000 00000cfd 2**0 + 9 .debug_loc 0000027e 00000000 00000000 00000ced 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000060 00000000 00000000 00000f7b 2**0 + 10 .debug_ranges 00000060 00000000 00000000 00000f6b 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: From e81c1123b624b6cac7da018c9c786700f3152bc9 Mon Sep 17 00:00:00 2001 From: WestfW Date: Mon, 13 Jun 2011 19:07:07 -0700 Subject: [PATCH 28/33] http://code.google.com/p/arduino/issues/detail?id=368 Optiboot does not support ArduinoasISP programmer. When avrdude runs and talks to an arduino running ArduinoISP, it needs the optiboot (entered due to auto-reset) to abort and start the ArduinoISP "application" when it sees communications at the wrong serial speed. Unfortunately, optiboot treats all unrecognized command characters as "no-ops" and responds/loops for more commands, leading to a nice loop that never gets to the sketch. This patch causes characters received with Framing errors (the most likely error for speed mis-matches) to NOT reset the watchdog timer (normally done in getch()), which will cause the application to start if it continues for "a while." (tested. Works! Running ArduinoISP at speeds as high as 57600 still causes the bootloader to start the sketch (although it fails later on for other reasons.)) --- .../arduino/bootloaders/optiboot/README.TXT | 19 ++- .../arduino/bootloaders/optiboot/optiboot.c | 22 ++- .../optiboot/optiboot_atmega328.hex | 33 ++-- .../optiboot/optiboot_atmega328.lst | 140 ++++++++-------- .../optiboot/optiboot_atmega328_pro_8MHz.hex | 33 ++-- .../optiboot/optiboot_atmega328_pro_8MHz.lst | 140 ++++++++-------- .../optiboot/optiboot_diecimila.hex | 33 ++-- .../optiboot/optiboot_diecimila.lst | 140 ++++++++-------- .../bootloaders/optiboot/optiboot_lilypad.hex | 33 ++-- .../bootloaders/optiboot/optiboot_lilypad.lst | 140 ++++++++-------- .../optiboot/optiboot_lilypad_resonator.hex | 33 ++-- .../optiboot/optiboot_lilypad_resonator.lst | 140 ++++++++-------- .../bootloaders/optiboot/optiboot_luminet.hex | 36 ++--- .../bootloaders/optiboot/optiboot_luminet.lst | 151 +++++++++--------- .../optiboot/optiboot_pro_16MHz.hex | 33 ++-- .../optiboot/optiboot_pro_16MHz.lst | 140 ++++++++-------- .../optiboot/optiboot_pro_20mhz.hex | 33 ++-- .../optiboot/optiboot_pro_20mhz.lst | 140 ++++++++-------- .../optiboot/optiboot_pro_8MHz.hex | 33 ++-- .../optiboot/optiboot_pro_8MHz.lst | 140 ++++++++-------- .../arduino/bootloaders/optiboot/pin_defs.h | 1 + 21 files changed, 862 insertions(+), 751 deletions(-) diff --git a/hardware/arduino/bootloaders/optiboot/README.TXT b/hardware/arduino/bootloaders/optiboot/README.TXT index 9a68e2343..7e2f46df1 100644 --- a/hardware/arduino/bootloaders/optiboot/README.TXT +++ b/hardware/arduino/bootloaders/optiboot/README.TXT @@ -27,7 +27,7 @@ this may change if compiler versions drift apart between CrossPack and the Arduino IDE.) -Building optiboot in the arduino IDE install. +Building Optiboot in the Arduino IDE Install. Work in the .../hardware/arduino/bootloaders/optiboot/ and use the "omake " command, which just generates a command that uses @@ -44,7 +44,7 @@ the programs it needs, so you need to work in the existing optiboot directory (or something created at the same "level") for it to work. -Building optiboot in the arduino source development install. +Building Optiboot in the Arduino Source Development Install. In this case, there is no special shell script, and you're assumed to have "make" installed somewhere in your path. @@ -53,3 +53,18 @@ expected directory. Work in Arduino/hardware/arduino/bootloaders/optiboot and use make OS=windows ENV=arduinodev or make OS=macosx ENV=arduinodev + + +Programming Chips Using the _isp Targets + +The CPU targets have corresponding ISP targets that will actuall +program the bootloader into a chip. "atmega328_isp" for the atmega328, +for example. These will set the fuses and lock bits as appropriate as +well as uploading the bootloader code. + +The makefiles default to using a USB programmer, but you can use +a serial programmer like ArduinoISP by changing the appropriate +variables when you invoke make: + + make ISPTOOL=stk500v1 ISPPORT=/dev/tty.usbserial-A20e1eAN \ + ISPSPEED=-b19200 atmega328_isp diff --git a/hardware/arduino/bootloaders/optiboot/optiboot.c b/hardware/arduino/bootloaders/optiboot/optiboot.c index 8dbe1bfbb..3f4404d0e 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot.c +++ b/hardware/arduino/bootloaders/optiboot/optiboot.c @@ -132,13 +132,16 @@ /**********************************************************/ /* Edit History: */ /* */ +/* 4.3 WestfW: catch framing errors in getch(), so that */ +/* AVRISP works without HW kludges. */ +/* http://code.google.com/p/arduino/issues/detail?id=368n*/ /* 4.2 WestfW: reduce code size, fix timeouts, change */ /* verifySpace to use WDT instead of appstart */ /* 4.1 WestfW: put version number in binary. */ /**********************************************************/ #define OPTIBOOT_MAJVER 4 -#define OPTIBOOT_MINVER 2 +#define OPTIBOOT_MINVER 3 #define MAKESTR(a) #a #define MAKEVER(a, b) MAKESTR(a*256+b) @@ -512,8 +515,6 @@ void putch(char ch) { uint8_t getch(void) { uint8_t ch; - watchdogReset(); - #ifdef LED_DATA_FLASH #ifdef __AVR_ATmega8__ LED_PORT ^= _BV(LED); @@ -547,7 +548,20 @@ uint8_t getch(void) { "r25" ); #else - while(!(UCSR0A & _BV(RXC0))); + while(!(UCSR0A & _BV(RXC0))) + ; + if (!(UCSR0A & _BV(FE0))) { + /* + * A Framing Error indicates (probably) that something is talking + * to us at the wrong bit rate. Assume that this is because it + * expects to be talking to the application, and DON'T reset the + * watchdog. This should cause the bootloader to abort and run + * the application "soon", if it keeps happening. (Note that we + * don't care that an invalid char is returned...) + */ + watchdogReset(); + } + ch = UDR0; #endif diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.hex b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.hex index 10dcd6c80..f147e816c 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.hex @@ -1,33 +1,34 @@ -:107E0000112484B714BE81FFE3D085E08093810004 +:107E0000112484B714BE81FFE7D085E08093810000 :107E100082E08093C00088E18093C10086E0809377 -:107E2000C20080E18093C4008EE0BCD0259A86E039 +:107E2000C20080E18093C4008EE0C0D0259A86E035 :107E300020E33CEF91E0309385002093840096BBD3 :107E4000B09BFECF1D9AA8958150A9F799249394D1 :107E5000A5E0AA2EF1E1BF2E9DD0813421F481E06E -:107E6000AFD083E01FC0823411F484E103C08534B5 -:107E700019F485E0A5D083C0853579F48BD0E82E40 +:107E6000B3D083E01FC0823411F484E103C08534B1 +:107E700019F485E0A9D083C0853579F48BD0E82E3C :107E8000FF2488D0082F10E0102F00270E291F296B -:107E9000000F111F8DD0680172C0863529F484E06F -:107EA0008FD080E06FD06BC0843609F042C072D0B2 +:107E9000000F111F91D0680172C0863529F484E06B +:107EA00093D080E06FD06BC0843609F042C072D0AE :107EB00071D0082F6FD080E0C81680E7D80620F474 :107EC00083E0F60187BFE895C0E0D1E063D08993F5 :107ED0000C17E1F7F0E0CF16F0E7DF0620F083E0C3 -:107EE000F60187BFE89564D007B600FCFDCFA60178 +:107EE000F60187BFE89568D007B600FCFDCFA60174 :107EF000A0E0B1E02C9130E011968C91119790E0C8 :107F0000982F8827822B932B1296FA010C0197BE8B :107F1000E89511244E5F5F4FF1E0A038BF0751F79D :107F2000F601A7BEE89507B600FCFDCFB7BEE89501 -:107F300026C08437B1F42ED02DD0F82E2BD038D0D7 +:107F300026C08437B1F42ED02DD0F82E2BD03CD0D3 :107F4000F601EF2C8F010F5F1F4F84911BD0EA9435 :107F5000F801C1F70894C11CD11CFA94CF0CD11CB4 -:107F60000EC0853739F424D08EE10CD085E90AD0D3 -:107F70008FE098CF813511F488E014D019D080E1DA +:107F60000EC0853739F428D08EE10CD085E90AD0CF +:107F70008FE098CF813511F488E018D01DD080E1D2 :107F800001D06ACF982F8091C00085FFFCCF9093DD -:107F9000C6000895A8958091C00087FFFCCF80910E -:107FA000C6000895E0E6F0E098E1908380830895AC -:107FB000F1DF803219F088E0F5DFFFCF84E1E2CF16 -:107FC0001F93182FE7DF1150E9F7F2DF1F91089593 -:0A7FD00080E0E8DFEE27FF270994A8 -:027FFE0002047B +:107F9000C60008958091C00087FFFCCF8091C0008B +:107FA00084FD01C0A8958091C6000895E0E6F0E048 +:107FB00098E1908380830895EDDF803219F088E0A6 +:107FC000F5DFFFCF84E1DECF1F93182FE3DF1150E1 +:107FD000E9F7F2DF1F91089580E0E8DFEE27FF2741 +:027FE000099402 +:027FFE0003047A :0400000300007E007B :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.lst b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.lst index 89577f685..db4546250 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.lst @@ -3,27 +3,27 @@ optiboot_atmega328.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .text 000001da 00007e00 00007e00 00000054 2**1 + 0 .text 000001e2 00007e00 00007e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .version 00000002 00007ffe 00007ffe 0000022e 2**0 + 1 .version 00000002 00007ffe 00007ffe 00000236 2**0 CONTENTS, READONLY - 2 .debug_aranges 00000028 00000000 00000000 00000230 2**0 + 2 .debug_aranges 00000028 00000000 00000000 00000238 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_pubnames 0000005f 00000000 00000000 00000258 2**0 + 3 .debug_pubnames 0000005f 00000000 00000000 00000260 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_info 0000028d 00000000 00000000 000002b7 2**0 + 4 .debug_info 0000028e 00000000 00000000 000002bf 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 0000018a 00000000 00000000 00000544 2**0 + 5 .debug_abbrev 00000171 00000000 00000000 0000054d 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_line 00000456 00000000 00000000 000006ce 2**0 + 6 .debug_line 0000045e 00000000 00000000 000006be 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000080 00000000 00000000 00000b24 2**2 + 7 .debug_frame 00000080 00000000 00000000 00000b1c 2**2 CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000149 00000000 00000000 00000ba4 2**0 + 8 .debug_str 00000149 00000000 00000000 00000b9c 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 0000027e 00000000 00000000 00000ced 2**0 + 9 .debug_loc 0000027e 00000000 00000000 00000ce5 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000060 00000000 00000000 00000f6b 2**0 + 10 .debug_ranges 00000060 00000000 00000000 00000f63 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: @@ -47,7 +47,7 @@ int main(void) { 7e04: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); 7e06: 81 ff sbrs r24, 1 - 7e08: e3 d0 rcall .+454 ; 0x7fd0 + 7e08: e7 d0 rcall .+462 ; 0x7fd8 #if LED_START_FLASHES > 0 // Set up Timer 1 for timeout counter @@ -77,7 +77,7 @@ int main(void) { // Set up watchdog to trigger after 500ms watchdogConfig(WATCHDOG_1S); 7e28: 8e e0 ldi r24, 0x0E ; 14 - 7e2a: bc d0 rcall .+376 ; 0x7fa4 + 7e2a: c0 d0 rcall .+384 ; 0x7fac /* Set LED pin as output */ LED_DDR |= _BV(LED); @@ -163,7 +163,7 @@ void watchdogReset() { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); 7e5e: 81 e0 ldi r24, 0x01 ; 1 - 7e60: af d0 rcall .+350 ; 0x7fc0 + 7e60: b3 d0 rcall .+358 ; 0x7fc8 putch(0x03); 7e62: 83 e0 ldi r24, 0x03 ; 3 7e64: 1f c0 rjmp .+62 ; 0x7ea4 @@ -182,7 +182,7 @@ void watchdogReset() { // SET DEVICE EXT is ignored getNch(5); 7e72: 85 e0 ldi r24, 0x05 ; 5 - 7e74: a5 d0 rcall .+330 ; 0x7fc0 + 7e74: a9 d0 rcall .+338 ; 0x7fc8 7e76: 83 c0 rjmp .+262 ; 0x7f7e } else if(ch == STK_LOAD_ADDRESS) { @@ -211,7 +211,7 @@ void watchdogReset() { 7e92: 11 1f adc r17, r17 address = newAddress; verifySpace(); - 7e94: 8d d0 rcall .+282 ; 0x7fb0 + 7e94: 91 d0 rcall .+290 ; 0x7fb8 7e96: 68 01 movw r12, r16 7e98: 72 c0 rjmp .+228 ; 0x7f7e } @@ -221,7 +221,7 @@ void watchdogReset() { // UNIVERSAL command is ignored getNch(4); 7e9e: 84 e0 ldi r24, 0x04 ; 4 - 7ea0: 8f d0 rcall .+286 ; 0x7fc0 + 7ea0: 93 d0 rcall .+294 ; 0x7fc8 putch(0x00); 7ea2: 80 e0 ldi r24, 0x00 ; 0 7ea4: 6f d0 rcall .+222 ; 0x7f84 @@ -282,7 +282,7 @@ void watchdogReset() { // Read command terminator, start reply verifySpace(); - 7ee6: 64 d0 rcall .+200 ; 0x7fb0 + 7ee6: 68 d0 rcall .+208 ; 0x7fb8 // If only a partial page is to be programmed, the erase might not be complete. // So check that here @@ -370,7 +370,7 @@ int main(void) { 7f3c: 2b d0 rcall .+86 ; 0x7f94 verifySpace(); - 7f3e: 38 d0 rcall .+112 ; 0x7fb0 + 7f3e: 3c d0 rcall .+120 ; 0x7fb8 7f40: f6 01 movw r30, r12 7f42: ef 2c mov r14, r15 putch(result); @@ -411,7 +411,7 @@ int main(void) { 7f64: 39 f4 brne .+14 ; 0x7f74 // READ SIGN - return what Avrdude wants to hear verifySpace(); - 7f66: 24 d0 rcall .+72 ; 0x7fb0 + 7f66: 28 d0 rcall .+80 ; 0x7fb8 putch(SIGNATURE_0); 7f68: 8e e1 ldi r24, 0x1E ; 30 7f6a: 0c d0 rcall .+24 ; 0x7f84 @@ -428,13 +428,13 @@ int main(void) { // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); 7f78: 88 e0 ldi r24, 0x08 ; 8 - 7f7a: 14 d0 rcall .+40 ; 0x7fa4 + 7f7a: 18 d0 rcall .+48 ; 0x7fac verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 7f7c: 19 d0 rcall .+50 ; 0x7fb0 + 7f7c: 1d d0 rcall .+58 ; 0x7fb8 } putch(STK_OK); 7f7e: 80 e1 ldi r24, 0x10 ; 16 @@ -463,99 +463,109 @@ void putch(char ch) { 7f92: 08 95 ret 00007f94 : + [uartBit] "I" (UART_RX_BIT) + : + "r25" +); +#else + while(!(UCSR0A & _BV(RXC0))) + 7f94: 80 91 c0 00 lds r24, 0x00C0 + 7f98: 87 ff sbrs r24, 7 + 7f9a: fc cf rjmp .-8 ; 0x7f94 + ; + if (!(UCSR0A & _BV(FE0))) { + 7f9c: 80 91 c0 00 lds r24, 0x00C0 + 7fa0: 84 fd sbrc r24, 4 + 7fa2: 01 c0 rjmp .+2 ; 0x7fa6 } #endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 7f94: a8 95 wdr - [uartBit] "I" (UART_RX_BIT) - : - "r25" -); -#else - while(!(UCSR0A & _BV(RXC0))); - 7f96: 80 91 c0 00 lds r24, 0x00C0 - 7f9a: 87 ff sbrs r24, 7 - 7f9c: fc cf rjmp .-8 ; 0x7f96 + 7fa4: a8 95 wdr + * don't care that an invalid char is returned...) + */ + watchdogReset(); + } + ch = UDR0; - 7f9e: 80 91 c6 00 lds r24, 0x00C6 + 7fa6: 80 91 c6 00 lds r24, 0x00C6 LED_PIN |= _BV(LED); #endif #endif return ch; } - 7fa2: 08 95 ret + 7faa: 08 95 ret -00007fa4 : +00007fac : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 7fa4: e0 e6 ldi r30, 0x60 ; 96 - 7fa6: f0 e0 ldi r31, 0x00 ; 0 - 7fa8: 98 e1 ldi r25, 0x18 ; 24 - 7faa: 90 83 st Z, r25 + 7fac: e0 e6 ldi r30, 0x60 ; 96 + 7fae: f0 e0 ldi r31, 0x00 ; 0 + 7fb0: 98 e1 ldi r25, 0x18 ; 24 + 7fb2: 90 83 st Z, r25 WDTCSR = x; - 7fac: 80 83 st Z, r24 + 7fb4: 80 83 st Z, r24 } - 7fae: 08 95 ret + 7fb6: 08 95 ret -00007fb0 : +00007fb8 : do getch(); while (--count); verifySpace(); } void verifySpace() { if (getch() != CRC_EOP) { - 7fb0: f1 df rcall .-30 ; 0x7f94 - 7fb2: 80 32 cpi r24, 0x20 ; 32 - 7fb4: 19 f0 breq .+6 ; 0x7fbc + 7fb8: ed df rcall .-38 ; 0x7f94 + 7fba: 80 32 cpi r24, 0x20 ; 32 + 7fbc: 19 f0 breq .+6 ; 0x7fc4 watchdogConfig(WATCHDOG_16MS); // shorten WD timeout - 7fb6: 88 e0 ldi r24, 0x08 ; 8 - 7fb8: f5 df rcall .-22 ; 0x7fa4 - 7fba: ff cf rjmp .-2 ; 0x7fba + 7fbe: 88 e0 ldi r24, 0x08 ; 8 + 7fc0: f5 df rcall .-22 ; 0x7fac + 7fc2: ff cf rjmp .-2 ; 0x7fc2 while (1) // and busy-loop so that WD causes ; // a reset and app start. } putch(STK_INSYNC); - 7fbc: 84 e1 ldi r24, 0x14 ; 20 + 7fc4: 84 e1 ldi r24, 0x14 ; 20 } - 7fbe: e2 cf rjmp .-60 ; 0x7f84 + 7fc6: de cf rjmp .-68 ; 0x7f84 -00007fc0 : +00007fc8 : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 7fc0: 1f 93 push r17 - 7fc2: 18 2f mov r17, r24 + 7fc8: 1f 93 push r17 + 7fca: 18 2f mov r17, r24 do getch(); while (--count); - 7fc4: e7 df rcall .-50 ; 0x7f94 - 7fc6: 11 50 subi r17, 0x01 ; 1 - 7fc8: e9 f7 brne .-6 ; 0x7fc4 + 7fcc: e3 df rcall .-58 ; 0x7f94 + 7fce: 11 50 subi r17, 0x01 ; 1 + 7fd0: e9 f7 brne .-6 ; 0x7fcc verifySpace(); - 7fca: f2 df rcall .-28 ; 0x7fb0 + 7fd2: f2 df rcall .-28 ; 0x7fb8 } - 7fcc: 1f 91 pop r17 - 7fce: 08 95 ret + 7fd4: 1f 91 pop r17 + 7fd6: 08 95 ret -00007fd0 : +00007fd8 : WDTCSR = _BV(WDCE) | _BV(WDE); WDTCSR = x; } void appStart() { watchdogConfig(WATCHDOG_OFF); - 7fd0: 80 e0 ldi r24, 0x00 ; 0 - 7fd2: e8 df rcall .-48 ; 0x7fa4 + 7fd8: 80 e0 ldi r24, 0x00 ; 0 + 7fda: e8 df rcall .-48 ; 0x7fac __asm__ __volatile__ ( - 7fd4: ee 27 eor r30, r30 - 7fd6: ff 27 eor r31, r31 - 7fd8: 09 94 ijmp + 7fdc: ee 27 eor r30, r30 + 7fde: ff 27 eor r31, r31 + 7fe0: 09 94 ijmp diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.hex b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.hex index 3b543c1a3..499c631e3 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.hex @@ -1,33 +1,34 @@ -:107E0000112484B714BE81FFE3D085E08093810004 +:107E0000112484B714BE81FFE7D085E08093810000 :107E100082E08093C00088E18093C10086E0809377 -:107E2000C20088E08093C4008EE0BCD0259A86E032 +:107E2000C20088E08093C4008EE0C0D0259A86E02E :107E300028E13EEF91E0309385002093840096BBCB :107E4000B09BFECF1D9AA8958150A9F799249394D1 :107E5000A5E0AA2EF1E1BF2E9DD0813421F481E06E -:107E6000AFD083E01FC0823411F484E103C08534B5 -:107E700019F485E0A5D083C0853579F48BD0E82E40 +:107E6000B3D083E01FC0823411F484E103C08534B1 +:107E700019F485E0A9D083C0853579F48BD0E82E3C :107E8000FF2488D0082F10E0102F00270E291F296B -:107E9000000F111F8DD0680172C0863529F484E06F -:107EA0008FD080E06FD06BC0843609F042C072D0B2 +:107E9000000F111F91D0680172C0863529F484E06B +:107EA00093D080E06FD06BC0843609F042C072D0AE :107EB00071D0082F6FD080E0C81680E7D80620F474 :107EC00083E0F60187BFE895C0E0D1E063D08993F5 :107ED0000C17E1F7F0E0CF16F0E7DF0620F083E0C3 -:107EE000F60187BFE89564D007B600FCFDCFA60178 +:107EE000F60187BFE89568D007B600FCFDCFA60174 :107EF000A0E0B1E02C9130E011968C91119790E0C8 :107F0000982F8827822B932B1296FA010C0197BE8B :107F1000E89511244E5F5F4FF1E0A038BF0751F79D :107F2000F601A7BEE89507B600FCFDCFB7BEE89501 -:107F300026C08437B1F42ED02DD0F82E2BD038D0D7 +:107F300026C08437B1F42ED02DD0F82E2BD03CD0D3 :107F4000F601EF2C8F010F5F1F4F84911BD0EA9435 :107F5000F801C1F70894C11CD11CFA94CF0CD11CB4 -:107F60000EC0853739F424D08EE10CD085E90AD0D3 -:107F70008FE098CF813511F488E014D019D080E1DA +:107F60000EC0853739F428D08EE10CD085E90AD0CF +:107F70008FE098CF813511F488E018D01DD080E1D2 :107F800001D06ACF982F8091C00085FFFCCF9093DD -:107F9000C6000895A8958091C00087FFFCCF80910E -:107FA000C6000895E0E6F0E098E1908380830895AC -:107FB000F1DF803219F088E0F5DFFFCF84E1E2CF16 -:107FC0001F93182FE7DF1150E9F7F2DF1F91089593 -:0A7FD00080E0E8DFEE27FF270994A8 -:027FFE0002047B +:107F9000C60008958091C00087FFFCCF8091C0008B +:107FA00084FD01C0A8958091C6000895E0E6F0E048 +:107FB00098E1908380830895EDDF803219F088E0A6 +:107FC000F5DFFFCF84E1DECF1F93182FE3DF1150E1 +:107FD000E9F7F2DF1F91089580E0E8DFEE27FF2741 +:027FE000099402 +:027FFE0003047A :0400000300007E007B :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.lst b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.lst index 002f9a3dc..0577bdc2f 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.lst @@ -3,27 +3,27 @@ optiboot_atmega328_pro_8MHz.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .text 000001da 00007e00 00007e00 00000054 2**1 + 0 .text 000001e2 00007e00 00007e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .version 00000002 00007ffe 00007ffe 0000022e 2**0 + 1 .version 00000002 00007ffe 00007ffe 00000236 2**0 CONTENTS, READONLY - 2 .debug_aranges 00000028 00000000 00000000 00000230 2**0 + 2 .debug_aranges 00000028 00000000 00000000 00000238 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_pubnames 0000005f 00000000 00000000 00000258 2**0 + 3 .debug_pubnames 0000005f 00000000 00000000 00000260 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_info 0000028d 00000000 00000000 000002b7 2**0 + 4 .debug_info 0000028e 00000000 00000000 000002bf 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 0000018a 00000000 00000000 00000544 2**0 + 5 .debug_abbrev 00000171 00000000 00000000 0000054d 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_line 00000456 00000000 00000000 000006ce 2**0 + 6 .debug_line 0000045e 00000000 00000000 000006be 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000080 00000000 00000000 00000b24 2**2 + 7 .debug_frame 00000080 00000000 00000000 00000b1c 2**2 CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000149 00000000 00000000 00000ba4 2**0 + 8 .debug_str 00000149 00000000 00000000 00000b9c 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 0000027e 00000000 00000000 00000ced 2**0 + 9 .debug_loc 0000027e 00000000 00000000 00000ce5 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000060 00000000 00000000 00000f6b 2**0 + 10 .debug_ranges 00000060 00000000 00000000 00000f63 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: @@ -47,7 +47,7 @@ int main(void) { 7e04: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); 7e06: 81 ff sbrs r24, 1 - 7e08: e3 d0 rcall .+454 ; 0x7fd0 + 7e08: e7 d0 rcall .+462 ; 0x7fd8 #if LED_START_FLASHES > 0 // Set up Timer 1 for timeout counter @@ -77,7 +77,7 @@ int main(void) { // Set up watchdog to trigger after 500ms watchdogConfig(WATCHDOG_1S); 7e28: 8e e0 ldi r24, 0x0E ; 14 - 7e2a: bc d0 rcall .+376 ; 0x7fa4 + 7e2a: c0 d0 rcall .+384 ; 0x7fac /* Set LED pin as output */ LED_DDR |= _BV(LED); @@ -163,7 +163,7 @@ void watchdogReset() { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); 7e5e: 81 e0 ldi r24, 0x01 ; 1 - 7e60: af d0 rcall .+350 ; 0x7fc0 + 7e60: b3 d0 rcall .+358 ; 0x7fc8 putch(0x03); 7e62: 83 e0 ldi r24, 0x03 ; 3 7e64: 1f c0 rjmp .+62 ; 0x7ea4 @@ -182,7 +182,7 @@ void watchdogReset() { // SET DEVICE EXT is ignored getNch(5); 7e72: 85 e0 ldi r24, 0x05 ; 5 - 7e74: a5 d0 rcall .+330 ; 0x7fc0 + 7e74: a9 d0 rcall .+338 ; 0x7fc8 7e76: 83 c0 rjmp .+262 ; 0x7f7e } else if(ch == STK_LOAD_ADDRESS) { @@ -211,7 +211,7 @@ void watchdogReset() { 7e92: 11 1f adc r17, r17 address = newAddress; verifySpace(); - 7e94: 8d d0 rcall .+282 ; 0x7fb0 + 7e94: 91 d0 rcall .+290 ; 0x7fb8 7e96: 68 01 movw r12, r16 7e98: 72 c0 rjmp .+228 ; 0x7f7e } @@ -221,7 +221,7 @@ void watchdogReset() { // UNIVERSAL command is ignored getNch(4); 7e9e: 84 e0 ldi r24, 0x04 ; 4 - 7ea0: 8f d0 rcall .+286 ; 0x7fc0 + 7ea0: 93 d0 rcall .+294 ; 0x7fc8 putch(0x00); 7ea2: 80 e0 ldi r24, 0x00 ; 0 7ea4: 6f d0 rcall .+222 ; 0x7f84 @@ -282,7 +282,7 @@ void watchdogReset() { // Read command terminator, start reply verifySpace(); - 7ee6: 64 d0 rcall .+200 ; 0x7fb0 + 7ee6: 68 d0 rcall .+208 ; 0x7fb8 // If only a partial page is to be programmed, the erase might not be complete. // So check that here @@ -370,7 +370,7 @@ int main(void) { 7f3c: 2b d0 rcall .+86 ; 0x7f94 verifySpace(); - 7f3e: 38 d0 rcall .+112 ; 0x7fb0 + 7f3e: 3c d0 rcall .+120 ; 0x7fb8 7f40: f6 01 movw r30, r12 7f42: ef 2c mov r14, r15 putch(result); @@ -411,7 +411,7 @@ int main(void) { 7f64: 39 f4 brne .+14 ; 0x7f74 // READ SIGN - return what Avrdude wants to hear verifySpace(); - 7f66: 24 d0 rcall .+72 ; 0x7fb0 + 7f66: 28 d0 rcall .+80 ; 0x7fb8 putch(SIGNATURE_0); 7f68: 8e e1 ldi r24, 0x1E ; 30 7f6a: 0c d0 rcall .+24 ; 0x7f84 @@ -428,13 +428,13 @@ int main(void) { // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); 7f78: 88 e0 ldi r24, 0x08 ; 8 - 7f7a: 14 d0 rcall .+40 ; 0x7fa4 + 7f7a: 18 d0 rcall .+48 ; 0x7fac verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 7f7c: 19 d0 rcall .+50 ; 0x7fb0 + 7f7c: 1d d0 rcall .+58 ; 0x7fb8 } putch(STK_OK); 7f7e: 80 e1 ldi r24, 0x10 ; 16 @@ -463,99 +463,109 @@ void putch(char ch) { 7f92: 08 95 ret 00007f94 : + [uartBit] "I" (UART_RX_BIT) + : + "r25" +); +#else + while(!(UCSR0A & _BV(RXC0))) + 7f94: 80 91 c0 00 lds r24, 0x00C0 + 7f98: 87 ff sbrs r24, 7 + 7f9a: fc cf rjmp .-8 ; 0x7f94 + ; + if (!(UCSR0A & _BV(FE0))) { + 7f9c: 80 91 c0 00 lds r24, 0x00C0 + 7fa0: 84 fd sbrc r24, 4 + 7fa2: 01 c0 rjmp .+2 ; 0x7fa6 } #endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 7f94: a8 95 wdr - [uartBit] "I" (UART_RX_BIT) - : - "r25" -); -#else - while(!(UCSR0A & _BV(RXC0))); - 7f96: 80 91 c0 00 lds r24, 0x00C0 - 7f9a: 87 ff sbrs r24, 7 - 7f9c: fc cf rjmp .-8 ; 0x7f96 + 7fa4: a8 95 wdr + * don't care that an invalid char is returned...) + */ + watchdogReset(); + } + ch = UDR0; - 7f9e: 80 91 c6 00 lds r24, 0x00C6 + 7fa6: 80 91 c6 00 lds r24, 0x00C6 LED_PIN |= _BV(LED); #endif #endif return ch; } - 7fa2: 08 95 ret + 7faa: 08 95 ret -00007fa4 : +00007fac : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 7fa4: e0 e6 ldi r30, 0x60 ; 96 - 7fa6: f0 e0 ldi r31, 0x00 ; 0 - 7fa8: 98 e1 ldi r25, 0x18 ; 24 - 7faa: 90 83 st Z, r25 + 7fac: e0 e6 ldi r30, 0x60 ; 96 + 7fae: f0 e0 ldi r31, 0x00 ; 0 + 7fb0: 98 e1 ldi r25, 0x18 ; 24 + 7fb2: 90 83 st Z, r25 WDTCSR = x; - 7fac: 80 83 st Z, r24 + 7fb4: 80 83 st Z, r24 } - 7fae: 08 95 ret + 7fb6: 08 95 ret -00007fb0 : +00007fb8 : do getch(); while (--count); verifySpace(); } void verifySpace() { if (getch() != CRC_EOP) { - 7fb0: f1 df rcall .-30 ; 0x7f94 - 7fb2: 80 32 cpi r24, 0x20 ; 32 - 7fb4: 19 f0 breq .+6 ; 0x7fbc + 7fb8: ed df rcall .-38 ; 0x7f94 + 7fba: 80 32 cpi r24, 0x20 ; 32 + 7fbc: 19 f0 breq .+6 ; 0x7fc4 watchdogConfig(WATCHDOG_16MS); // shorten WD timeout - 7fb6: 88 e0 ldi r24, 0x08 ; 8 - 7fb8: f5 df rcall .-22 ; 0x7fa4 - 7fba: ff cf rjmp .-2 ; 0x7fba + 7fbe: 88 e0 ldi r24, 0x08 ; 8 + 7fc0: f5 df rcall .-22 ; 0x7fac + 7fc2: ff cf rjmp .-2 ; 0x7fc2 while (1) // and busy-loop so that WD causes ; // a reset and app start. } putch(STK_INSYNC); - 7fbc: 84 e1 ldi r24, 0x14 ; 20 + 7fc4: 84 e1 ldi r24, 0x14 ; 20 } - 7fbe: e2 cf rjmp .-60 ; 0x7f84 + 7fc6: de cf rjmp .-68 ; 0x7f84 -00007fc0 : +00007fc8 : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 7fc0: 1f 93 push r17 - 7fc2: 18 2f mov r17, r24 + 7fc8: 1f 93 push r17 + 7fca: 18 2f mov r17, r24 do getch(); while (--count); - 7fc4: e7 df rcall .-50 ; 0x7f94 - 7fc6: 11 50 subi r17, 0x01 ; 1 - 7fc8: e9 f7 brne .-6 ; 0x7fc4 + 7fcc: e3 df rcall .-58 ; 0x7f94 + 7fce: 11 50 subi r17, 0x01 ; 1 + 7fd0: e9 f7 brne .-6 ; 0x7fcc verifySpace(); - 7fca: f2 df rcall .-28 ; 0x7fb0 + 7fd2: f2 df rcall .-28 ; 0x7fb8 } - 7fcc: 1f 91 pop r17 - 7fce: 08 95 ret + 7fd4: 1f 91 pop r17 + 7fd6: 08 95 ret -00007fd0 : +00007fd8 : WDTCSR = _BV(WDCE) | _BV(WDE); WDTCSR = x; } void appStart() { watchdogConfig(WATCHDOG_OFF); - 7fd0: 80 e0 ldi r24, 0x00 ; 0 - 7fd2: e8 df rcall .-48 ; 0x7fa4 + 7fd8: 80 e0 ldi r24, 0x00 ; 0 + 7fda: e8 df rcall .-48 ; 0x7fac __asm__ __volatile__ ( - 7fd4: ee 27 eor r30, r30 - 7fd6: ff 27 eor r31, r31 - 7fd8: 09 94 ijmp + 7fdc: ee 27 eor r30, r30 + 7fde: ff 27 eor r31, r31 + 7fe0: 09 94 ijmp diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.hex b/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.hex index 26bbd4cdf..b685a4e9a 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.hex @@ -1,33 +1,34 @@ -:103E0000112484B714BE81FFE3D085E08093810044 +:103E0000112484B714BE81FFE7D085E08093810040 :103E100082E08093C00088E18093C10086E08093B7 -:103E2000C20080E18093C4008EE0BCD0259A86E079 +:103E2000C20080E18093C4008EE0C0D0259A86E075 :103E300020E33CEF91E0309385002093840096BB13 :103E4000B09BFECF1D9AA8958150A9F79924939411 :103E5000A5E0AA2EF1E1BF2E9DD0813421F481E0AE -:103E6000AFD083E01FC0823411F484E103C08534F5 -:103E700019F485E0A5D083C0853579F48BD0E82E80 +:103E6000B3D083E01FC0823411F484E103C08534F1 +:103E700019F485E0A9D083C0853579F48BD0E82E7C :103E8000FF2488D0082F10E0102F00270E291F29AB -:103E9000000F111F8DD0680172C0863529F484E0AF -:103EA0008FD080E06FD06BC0843609F042C072D0F2 +:103E9000000F111F91D0680172C0863529F484E0AB +:103EA00093D080E06FD06BC0843609F042C072D0EE :103EB00071D0082F6FD080E0C81688E3D80620F4B0 :103EC00083E0F60187BFE895C0E0D1E063D0899335 :103ED0000C17E1F7F0E0CF16F8E3DF0620F083E0FF -:103EE000F60187BFE89564D007B600FCFDCFA601B8 +:103EE000F60187BFE89568D007B600FCFDCFA601B4 :103EF000A0E0B1E02C9130E011968C91119790E008 :103F0000982F8827822B932B1296FA010C0197BECB :103F1000E89511244E5F5F4FF1E0A038BF0751F7DD :103F2000F601A7BEE89507B600FCFDCFB7BEE89541 -:103F300026C08437B1F42ED02DD0F82E2BD038D017 +:103F300026C08437B1F42ED02DD0F82E2BD03CD013 :103F4000F601EF2C8F010F5F1F4F84911BD0EA9475 :103F5000F801C1F70894C11CD11CFA94CF0CD11CF4 -:103F60000EC0853739F424D08EE10CD084E90AD014 -:103F700086E098CF813511F488E014D019D080E123 +:103F60000EC0853739F428D08EE10CD084E90AD010 +:103F700086E098CF813511F488E018D01DD080E11B :103F800001D06ACF982F8091C00085FFFCCF90931D -:103F9000C6000895A8958091C00087FFFCCF80914E -:103FA000C6000895E0E6F0E098E1908380830895EC -:103FB000F1DF803219F088E0F5DFFFCF84E1E2CF56 -:103FC0001F93182FE7DF1150E9F7F2DF1F910895D3 -:0A3FD00080E0E8DFEE27FF270994E8 -:023FFE000204BB +:103F9000C60008958091C00087FFFCCF8091C000CB +:103FA00084FD01C0A8958091C6000895E0E6F0E088 +:103FB00098E1908380830895EDDF803219F088E0E6 +:103FC000F5DFFFCF84E1DECF1F93182FE3DF115021 +:103FD000E9F7F2DF1F91089580E0E8DFEE27FF2781 +:023FE000099442 +:023FFE000304BA :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.lst b/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.lst index 6e0843d6d..357dc11c4 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.lst @@ -3,27 +3,27 @@ optiboot_diecimila.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .text 000001da 00003e00 00003e00 00000054 2**1 + 0 .text 000001e2 00003e00 00003e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .version 00000002 00003ffe 00003ffe 0000022e 2**0 + 1 .version 00000002 00003ffe 00003ffe 00000236 2**0 CONTENTS, READONLY - 2 .debug_aranges 00000028 00000000 00000000 00000230 2**0 + 2 .debug_aranges 00000028 00000000 00000000 00000238 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_pubnames 0000005f 00000000 00000000 00000258 2**0 + 3 .debug_pubnames 0000005f 00000000 00000000 00000260 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_info 0000028d 00000000 00000000 000002b7 2**0 + 4 .debug_info 0000028e 00000000 00000000 000002bf 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 0000018a 00000000 00000000 00000544 2**0 + 5 .debug_abbrev 00000171 00000000 00000000 0000054d 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_line 00000456 00000000 00000000 000006ce 2**0 + 6 .debug_line 0000045e 00000000 00000000 000006be 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000080 00000000 00000000 00000b24 2**2 + 7 .debug_frame 00000080 00000000 00000000 00000b1c 2**2 CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000149 00000000 00000000 00000ba4 2**0 + 8 .debug_str 00000149 00000000 00000000 00000b9c 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 0000027e 00000000 00000000 00000ced 2**0 + 9 .debug_loc 0000027e 00000000 00000000 00000ce5 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000060 00000000 00000000 00000f6b 2**0 + 10 .debug_ranges 00000060 00000000 00000000 00000f63 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: @@ -47,7 +47,7 @@ int main(void) { 3e04: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); 3e06: 81 ff sbrs r24, 1 - 3e08: e3 d0 rcall .+454 ; 0x3fd0 + 3e08: e7 d0 rcall .+462 ; 0x3fd8 #if LED_START_FLASHES > 0 // Set up Timer 1 for timeout counter @@ -77,7 +77,7 @@ int main(void) { // Set up watchdog to trigger after 500ms watchdogConfig(WATCHDOG_1S); 3e28: 8e e0 ldi r24, 0x0E ; 14 - 3e2a: bc d0 rcall .+376 ; 0x3fa4 + 3e2a: c0 d0 rcall .+384 ; 0x3fac /* Set LED pin as output */ LED_DDR |= _BV(LED); @@ -163,7 +163,7 @@ void watchdogReset() { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); 3e5e: 81 e0 ldi r24, 0x01 ; 1 - 3e60: af d0 rcall .+350 ; 0x3fc0 + 3e60: b3 d0 rcall .+358 ; 0x3fc8 putch(0x03); 3e62: 83 e0 ldi r24, 0x03 ; 3 3e64: 1f c0 rjmp .+62 ; 0x3ea4 @@ -182,7 +182,7 @@ void watchdogReset() { // SET DEVICE EXT is ignored getNch(5); 3e72: 85 e0 ldi r24, 0x05 ; 5 - 3e74: a5 d0 rcall .+330 ; 0x3fc0 + 3e74: a9 d0 rcall .+338 ; 0x3fc8 3e76: 83 c0 rjmp .+262 ; 0x3f7e } else if(ch == STK_LOAD_ADDRESS) { @@ -211,7 +211,7 @@ void watchdogReset() { 3e92: 11 1f adc r17, r17 address = newAddress; verifySpace(); - 3e94: 8d d0 rcall .+282 ; 0x3fb0 + 3e94: 91 d0 rcall .+290 ; 0x3fb8 3e96: 68 01 movw r12, r16 3e98: 72 c0 rjmp .+228 ; 0x3f7e } @@ -221,7 +221,7 @@ void watchdogReset() { // UNIVERSAL command is ignored getNch(4); 3e9e: 84 e0 ldi r24, 0x04 ; 4 - 3ea0: 8f d0 rcall .+286 ; 0x3fc0 + 3ea0: 93 d0 rcall .+294 ; 0x3fc8 putch(0x00); 3ea2: 80 e0 ldi r24, 0x00 ; 0 3ea4: 6f d0 rcall .+222 ; 0x3f84 @@ -282,7 +282,7 @@ void watchdogReset() { // Read command terminator, start reply verifySpace(); - 3ee6: 64 d0 rcall .+200 ; 0x3fb0 + 3ee6: 68 d0 rcall .+208 ; 0x3fb8 // If only a partial page is to be programmed, the erase might not be complete. // So check that here @@ -370,7 +370,7 @@ int main(void) { 3f3c: 2b d0 rcall .+86 ; 0x3f94 verifySpace(); - 3f3e: 38 d0 rcall .+112 ; 0x3fb0 + 3f3e: 3c d0 rcall .+120 ; 0x3fb8 3f40: f6 01 movw r30, r12 3f42: ef 2c mov r14, r15 putch(result); @@ -411,7 +411,7 @@ int main(void) { 3f64: 39 f4 brne .+14 ; 0x3f74 // READ SIGN - return what Avrdude wants to hear verifySpace(); - 3f66: 24 d0 rcall .+72 ; 0x3fb0 + 3f66: 28 d0 rcall .+80 ; 0x3fb8 putch(SIGNATURE_0); 3f68: 8e e1 ldi r24, 0x1E ; 30 3f6a: 0c d0 rcall .+24 ; 0x3f84 @@ -428,13 +428,13 @@ int main(void) { // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); 3f78: 88 e0 ldi r24, 0x08 ; 8 - 3f7a: 14 d0 rcall .+40 ; 0x3fa4 + 3f7a: 18 d0 rcall .+48 ; 0x3fac verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 3f7c: 19 d0 rcall .+50 ; 0x3fb0 + 3f7c: 1d d0 rcall .+58 ; 0x3fb8 } putch(STK_OK); 3f7e: 80 e1 ldi r24, 0x10 ; 16 @@ -463,99 +463,109 @@ void putch(char ch) { 3f92: 08 95 ret 00003f94 : + [uartBit] "I" (UART_RX_BIT) + : + "r25" +); +#else + while(!(UCSR0A & _BV(RXC0))) + 3f94: 80 91 c0 00 lds r24, 0x00C0 + 3f98: 87 ff sbrs r24, 7 + 3f9a: fc cf rjmp .-8 ; 0x3f94 + ; + if (!(UCSR0A & _BV(FE0))) { + 3f9c: 80 91 c0 00 lds r24, 0x00C0 + 3fa0: 84 fd sbrc r24, 4 + 3fa2: 01 c0 rjmp .+2 ; 0x3fa6 } #endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 3f94: a8 95 wdr - [uartBit] "I" (UART_RX_BIT) - : - "r25" -); -#else - while(!(UCSR0A & _BV(RXC0))); - 3f96: 80 91 c0 00 lds r24, 0x00C0 - 3f9a: 87 ff sbrs r24, 7 - 3f9c: fc cf rjmp .-8 ; 0x3f96 + 3fa4: a8 95 wdr + * don't care that an invalid char is returned...) + */ + watchdogReset(); + } + ch = UDR0; - 3f9e: 80 91 c6 00 lds r24, 0x00C6 + 3fa6: 80 91 c6 00 lds r24, 0x00C6 LED_PIN |= _BV(LED); #endif #endif return ch; } - 3fa2: 08 95 ret + 3faa: 08 95 ret -00003fa4 : +00003fac : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 3fa4: e0 e6 ldi r30, 0x60 ; 96 - 3fa6: f0 e0 ldi r31, 0x00 ; 0 - 3fa8: 98 e1 ldi r25, 0x18 ; 24 - 3faa: 90 83 st Z, r25 + 3fac: e0 e6 ldi r30, 0x60 ; 96 + 3fae: f0 e0 ldi r31, 0x00 ; 0 + 3fb0: 98 e1 ldi r25, 0x18 ; 24 + 3fb2: 90 83 st Z, r25 WDTCSR = x; - 3fac: 80 83 st Z, r24 + 3fb4: 80 83 st Z, r24 } - 3fae: 08 95 ret + 3fb6: 08 95 ret -00003fb0 : +00003fb8 : do getch(); while (--count); verifySpace(); } void verifySpace() { if (getch() != CRC_EOP) { - 3fb0: f1 df rcall .-30 ; 0x3f94 - 3fb2: 80 32 cpi r24, 0x20 ; 32 - 3fb4: 19 f0 breq .+6 ; 0x3fbc + 3fb8: ed df rcall .-38 ; 0x3f94 + 3fba: 80 32 cpi r24, 0x20 ; 32 + 3fbc: 19 f0 breq .+6 ; 0x3fc4 watchdogConfig(WATCHDOG_16MS); // shorten WD timeout - 3fb6: 88 e0 ldi r24, 0x08 ; 8 - 3fb8: f5 df rcall .-22 ; 0x3fa4 - 3fba: ff cf rjmp .-2 ; 0x3fba + 3fbe: 88 e0 ldi r24, 0x08 ; 8 + 3fc0: f5 df rcall .-22 ; 0x3fac + 3fc2: ff cf rjmp .-2 ; 0x3fc2 while (1) // and busy-loop so that WD causes ; // a reset and app start. } putch(STK_INSYNC); - 3fbc: 84 e1 ldi r24, 0x14 ; 20 + 3fc4: 84 e1 ldi r24, 0x14 ; 20 } - 3fbe: e2 cf rjmp .-60 ; 0x3f84 + 3fc6: de cf rjmp .-68 ; 0x3f84 -00003fc0 : +00003fc8 : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 3fc0: 1f 93 push r17 - 3fc2: 18 2f mov r17, r24 + 3fc8: 1f 93 push r17 + 3fca: 18 2f mov r17, r24 do getch(); while (--count); - 3fc4: e7 df rcall .-50 ; 0x3f94 - 3fc6: 11 50 subi r17, 0x01 ; 1 - 3fc8: e9 f7 brne .-6 ; 0x3fc4 + 3fcc: e3 df rcall .-58 ; 0x3f94 + 3fce: 11 50 subi r17, 0x01 ; 1 + 3fd0: e9 f7 brne .-6 ; 0x3fcc verifySpace(); - 3fca: f2 df rcall .-28 ; 0x3fb0 + 3fd2: f2 df rcall .-28 ; 0x3fb8 } - 3fcc: 1f 91 pop r17 - 3fce: 08 95 ret + 3fd4: 1f 91 pop r17 + 3fd6: 08 95 ret -00003fd0 : +00003fd8 : WDTCSR = _BV(WDCE) | _BV(WDE); WDTCSR = x; } void appStart() { watchdogConfig(WATCHDOG_OFF); - 3fd0: 80 e0 ldi r24, 0x00 ; 0 - 3fd2: e8 df rcall .-48 ; 0x3fa4 + 3fd8: 80 e0 ldi r24, 0x00 ; 0 + 3fda: e8 df rcall .-48 ; 0x3fac __asm__ __volatile__ ( - 3fd4: ee 27 eor r30, r30 - 3fd6: ff 27 eor r31, r31 - 3fd8: 09 94 ijmp + 3fdc: ee 27 eor r30, r30 + 3fde: ff 27 eor r31, r31 + 3fe0: 09 94 ijmp diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.hex b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.hex index 00f7a3827..2c6339554 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.hex @@ -1,33 +1,34 @@ -:103E0000112484B714BE81FFE3D085E08093810044 +:103E0000112484B714BE81FFE7D085E08093810040 :103E100082E08093C00088E18093C10086E08093B7 -:103E2000C20088E08093C4008EE0BCD0259A86E072 +:103E2000C20088E08093C4008EE0C0D0259A86E06E :103E300028E13EEF91E0309385002093840096BB0B :103E4000B09BFECF1D9AA8958150A9F79924939411 :103E5000A5E0AA2EF1E1BF2E9DD0813421F481E0AE -:103E6000AFD083E01FC0823411F484E103C08534F5 -:103E700019F485E0A5D083C0853579F48BD0E82E80 +:103E6000B3D083E01FC0823411F484E103C08534F1 +:103E700019F485E0A9D083C0853579F48BD0E82E7C :103E8000FF2488D0082F10E0102F00270E291F29AB -:103E9000000F111F8DD0680172C0863529F484E0AF -:103EA0008FD080E06FD06BC0843609F042C072D0F2 +:103E9000000F111F91D0680172C0863529F484E0AB +:103EA00093D080E06FD06BC0843609F042C072D0EE :103EB00071D0082F6FD080E0C81688E3D80620F4B0 :103EC00083E0F60187BFE895C0E0D1E063D0899335 :103ED0000C17E1F7F0E0CF16F8E3DF0620F083E0FF -:103EE000F60187BFE89564D007B600FCFDCFA601B8 +:103EE000F60187BFE89568D007B600FCFDCFA601B4 :103EF000A0E0B1E02C9130E011968C91119790E008 :103F0000982F8827822B932B1296FA010C0197BECB :103F1000E89511244E5F5F4FF1E0A038BF0751F7DD :103F2000F601A7BEE89507B600FCFDCFB7BEE89541 -:103F300026C08437B1F42ED02DD0F82E2BD038D017 +:103F300026C08437B1F42ED02DD0F82E2BD03CD013 :103F4000F601EF2C8F010F5F1F4F84911BD0EA9475 :103F5000F801C1F70894C11CD11CFA94CF0CD11CF4 -:103F60000EC0853739F424D08EE10CD084E90AD014 -:103F700086E098CF813511F488E014D019D080E123 +:103F60000EC0853739F428D08EE10CD084E90AD010 +:103F700086E098CF813511F488E018D01DD080E11B :103F800001D06ACF982F8091C00085FFFCCF90931D -:103F9000C6000895A8958091C00087FFFCCF80914E -:103FA000C6000895E0E6F0E098E1908380830895EC -:103FB000F1DF803219F088E0F5DFFFCF84E1E2CF56 -:103FC0001F93182FE7DF1150E9F7F2DF1F910895D3 -:0A3FD00080E0E8DFEE27FF270994E8 -:023FFE000204BB +:103F9000C60008958091C00087FFFCCF8091C000CB +:103FA00084FD01C0A8958091C6000895E0E6F0E088 +:103FB00098E1908380830895EDDF803219F088E0E6 +:103FC000F5DFFFCF84E1DECF1F93182FE3DF115021 +:103FD000E9F7F2DF1F91089580E0E8DFEE27FF2781 +:023FE000099442 +:023FFE000304BA :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.lst b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.lst index 4cebc2e32..425cbf4a8 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.lst @@ -3,27 +3,27 @@ optiboot_lilypad.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .text 000001da 00003e00 00003e00 00000054 2**1 + 0 .text 000001e2 00003e00 00003e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .version 00000002 00003ffe 00003ffe 0000022e 2**0 + 1 .version 00000002 00003ffe 00003ffe 00000236 2**0 CONTENTS, READONLY - 2 .debug_aranges 00000028 00000000 00000000 00000230 2**0 + 2 .debug_aranges 00000028 00000000 00000000 00000238 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_pubnames 0000005f 00000000 00000000 00000258 2**0 + 3 .debug_pubnames 0000005f 00000000 00000000 00000260 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_info 0000028d 00000000 00000000 000002b7 2**0 + 4 .debug_info 0000028e 00000000 00000000 000002bf 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 0000018a 00000000 00000000 00000544 2**0 + 5 .debug_abbrev 00000171 00000000 00000000 0000054d 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_line 00000456 00000000 00000000 000006ce 2**0 + 6 .debug_line 0000045e 00000000 00000000 000006be 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000080 00000000 00000000 00000b24 2**2 + 7 .debug_frame 00000080 00000000 00000000 00000b1c 2**2 CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000149 00000000 00000000 00000ba4 2**0 + 8 .debug_str 00000149 00000000 00000000 00000b9c 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 0000027e 00000000 00000000 00000ced 2**0 + 9 .debug_loc 0000027e 00000000 00000000 00000ce5 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000060 00000000 00000000 00000f6b 2**0 + 10 .debug_ranges 00000060 00000000 00000000 00000f63 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: @@ -47,7 +47,7 @@ int main(void) { 3e04: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); 3e06: 81 ff sbrs r24, 1 - 3e08: e3 d0 rcall .+454 ; 0x3fd0 + 3e08: e7 d0 rcall .+462 ; 0x3fd8 #if LED_START_FLASHES > 0 // Set up Timer 1 for timeout counter @@ -77,7 +77,7 @@ int main(void) { // Set up watchdog to trigger after 500ms watchdogConfig(WATCHDOG_1S); 3e28: 8e e0 ldi r24, 0x0E ; 14 - 3e2a: bc d0 rcall .+376 ; 0x3fa4 + 3e2a: c0 d0 rcall .+384 ; 0x3fac /* Set LED pin as output */ LED_DDR |= _BV(LED); @@ -163,7 +163,7 @@ void watchdogReset() { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); 3e5e: 81 e0 ldi r24, 0x01 ; 1 - 3e60: af d0 rcall .+350 ; 0x3fc0 + 3e60: b3 d0 rcall .+358 ; 0x3fc8 putch(0x03); 3e62: 83 e0 ldi r24, 0x03 ; 3 3e64: 1f c0 rjmp .+62 ; 0x3ea4 @@ -182,7 +182,7 @@ void watchdogReset() { // SET DEVICE EXT is ignored getNch(5); 3e72: 85 e0 ldi r24, 0x05 ; 5 - 3e74: a5 d0 rcall .+330 ; 0x3fc0 + 3e74: a9 d0 rcall .+338 ; 0x3fc8 3e76: 83 c0 rjmp .+262 ; 0x3f7e } else if(ch == STK_LOAD_ADDRESS) { @@ -211,7 +211,7 @@ void watchdogReset() { 3e92: 11 1f adc r17, r17 address = newAddress; verifySpace(); - 3e94: 8d d0 rcall .+282 ; 0x3fb0 + 3e94: 91 d0 rcall .+290 ; 0x3fb8 3e96: 68 01 movw r12, r16 3e98: 72 c0 rjmp .+228 ; 0x3f7e } @@ -221,7 +221,7 @@ void watchdogReset() { // UNIVERSAL command is ignored getNch(4); 3e9e: 84 e0 ldi r24, 0x04 ; 4 - 3ea0: 8f d0 rcall .+286 ; 0x3fc0 + 3ea0: 93 d0 rcall .+294 ; 0x3fc8 putch(0x00); 3ea2: 80 e0 ldi r24, 0x00 ; 0 3ea4: 6f d0 rcall .+222 ; 0x3f84 @@ -282,7 +282,7 @@ void watchdogReset() { // Read command terminator, start reply verifySpace(); - 3ee6: 64 d0 rcall .+200 ; 0x3fb0 + 3ee6: 68 d0 rcall .+208 ; 0x3fb8 // If only a partial page is to be programmed, the erase might not be complete. // So check that here @@ -370,7 +370,7 @@ int main(void) { 3f3c: 2b d0 rcall .+86 ; 0x3f94 verifySpace(); - 3f3e: 38 d0 rcall .+112 ; 0x3fb0 + 3f3e: 3c d0 rcall .+120 ; 0x3fb8 3f40: f6 01 movw r30, r12 3f42: ef 2c mov r14, r15 putch(result); @@ -411,7 +411,7 @@ int main(void) { 3f64: 39 f4 brne .+14 ; 0x3f74 // READ SIGN - return what Avrdude wants to hear verifySpace(); - 3f66: 24 d0 rcall .+72 ; 0x3fb0 + 3f66: 28 d0 rcall .+80 ; 0x3fb8 putch(SIGNATURE_0); 3f68: 8e e1 ldi r24, 0x1E ; 30 3f6a: 0c d0 rcall .+24 ; 0x3f84 @@ -428,13 +428,13 @@ int main(void) { // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); 3f78: 88 e0 ldi r24, 0x08 ; 8 - 3f7a: 14 d0 rcall .+40 ; 0x3fa4 + 3f7a: 18 d0 rcall .+48 ; 0x3fac verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 3f7c: 19 d0 rcall .+50 ; 0x3fb0 + 3f7c: 1d d0 rcall .+58 ; 0x3fb8 } putch(STK_OK); 3f7e: 80 e1 ldi r24, 0x10 ; 16 @@ -463,99 +463,109 @@ void putch(char ch) { 3f92: 08 95 ret 00003f94 : + [uartBit] "I" (UART_RX_BIT) + : + "r25" +); +#else + while(!(UCSR0A & _BV(RXC0))) + 3f94: 80 91 c0 00 lds r24, 0x00C0 + 3f98: 87 ff sbrs r24, 7 + 3f9a: fc cf rjmp .-8 ; 0x3f94 + ; + if (!(UCSR0A & _BV(FE0))) { + 3f9c: 80 91 c0 00 lds r24, 0x00C0 + 3fa0: 84 fd sbrc r24, 4 + 3fa2: 01 c0 rjmp .+2 ; 0x3fa6 } #endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 3f94: a8 95 wdr - [uartBit] "I" (UART_RX_BIT) - : - "r25" -); -#else - while(!(UCSR0A & _BV(RXC0))); - 3f96: 80 91 c0 00 lds r24, 0x00C0 - 3f9a: 87 ff sbrs r24, 7 - 3f9c: fc cf rjmp .-8 ; 0x3f96 + 3fa4: a8 95 wdr + * don't care that an invalid char is returned...) + */ + watchdogReset(); + } + ch = UDR0; - 3f9e: 80 91 c6 00 lds r24, 0x00C6 + 3fa6: 80 91 c6 00 lds r24, 0x00C6 LED_PIN |= _BV(LED); #endif #endif return ch; } - 3fa2: 08 95 ret + 3faa: 08 95 ret -00003fa4 : +00003fac : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 3fa4: e0 e6 ldi r30, 0x60 ; 96 - 3fa6: f0 e0 ldi r31, 0x00 ; 0 - 3fa8: 98 e1 ldi r25, 0x18 ; 24 - 3faa: 90 83 st Z, r25 + 3fac: e0 e6 ldi r30, 0x60 ; 96 + 3fae: f0 e0 ldi r31, 0x00 ; 0 + 3fb0: 98 e1 ldi r25, 0x18 ; 24 + 3fb2: 90 83 st Z, r25 WDTCSR = x; - 3fac: 80 83 st Z, r24 + 3fb4: 80 83 st Z, r24 } - 3fae: 08 95 ret + 3fb6: 08 95 ret -00003fb0 : +00003fb8 : do getch(); while (--count); verifySpace(); } void verifySpace() { if (getch() != CRC_EOP) { - 3fb0: f1 df rcall .-30 ; 0x3f94 - 3fb2: 80 32 cpi r24, 0x20 ; 32 - 3fb4: 19 f0 breq .+6 ; 0x3fbc + 3fb8: ed df rcall .-38 ; 0x3f94 + 3fba: 80 32 cpi r24, 0x20 ; 32 + 3fbc: 19 f0 breq .+6 ; 0x3fc4 watchdogConfig(WATCHDOG_16MS); // shorten WD timeout - 3fb6: 88 e0 ldi r24, 0x08 ; 8 - 3fb8: f5 df rcall .-22 ; 0x3fa4 - 3fba: ff cf rjmp .-2 ; 0x3fba + 3fbe: 88 e0 ldi r24, 0x08 ; 8 + 3fc0: f5 df rcall .-22 ; 0x3fac + 3fc2: ff cf rjmp .-2 ; 0x3fc2 while (1) // and busy-loop so that WD causes ; // a reset and app start. } putch(STK_INSYNC); - 3fbc: 84 e1 ldi r24, 0x14 ; 20 + 3fc4: 84 e1 ldi r24, 0x14 ; 20 } - 3fbe: e2 cf rjmp .-60 ; 0x3f84 + 3fc6: de cf rjmp .-68 ; 0x3f84 -00003fc0 : +00003fc8 : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 3fc0: 1f 93 push r17 - 3fc2: 18 2f mov r17, r24 + 3fc8: 1f 93 push r17 + 3fca: 18 2f mov r17, r24 do getch(); while (--count); - 3fc4: e7 df rcall .-50 ; 0x3f94 - 3fc6: 11 50 subi r17, 0x01 ; 1 - 3fc8: e9 f7 brne .-6 ; 0x3fc4 + 3fcc: e3 df rcall .-58 ; 0x3f94 + 3fce: 11 50 subi r17, 0x01 ; 1 + 3fd0: e9 f7 brne .-6 ; 0x3fcc verifySpace(); - 3fca: f2 df rcall .-28 ; 0x3fb0 + 3fd2: f2 df rcall .-28 ; 0x3fb8 } - 3fcc: 1f 91 pop r17 - 3fce: 08 95 ret + 3fd4: 1f 91 pop r17 + 3fd6: 08 95 ret -00003fd0 : +00003fd8 : WDTCSR = _BV(WDCE) | _BV(WDE); WDTCSR = x; } void appStart() { watchdogConfig(WATCHDOG_OFF); - 3fd0: 80 e0 ldi r24, 0x00 ; 0 - 3fd2: e8 df rcall .-48 ; 0x3fa4 + 3fd8: 80 e0 ldi r24, 0x00 ; 0 + 3fda: e8 df rcall .-48 ; 0x3fac __asm__ __volatile__ ( - 3fd4: ee 27 eor r30, r30 - 3fd6: ff 27 eor r31, r31 - 3fd8: 09 94 ijmp + 3fdc: ee 27 eor r30, r30 + 3fde: ff 27 eor r31, r31 + 3fe0: 09 94 ijmp diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.hex b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.hex index 00f7a3827..2c6339554 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.hex @@ -1,33 +1,34 @@ -:103E0000112484B714BE81FFE3D085E08093810044 +:103E0000112484B714BE81FFE7D085E08093810040 :103E100082E08093C00088E18093C10086E08093B7 -:103E2000C20088E08093C4008EE0BCD0259A86E072 +:103E2000C20088E08093C4008EE0C0D0259A86E06E :103E300028E13EEF91E0309385002093840096BB0B :103E4000B09BFECF1D9AA8958150A9F79924939411 :103E5000A5E0AA2EF1E1BF2E9DD0813421F481E0AE -:103E6000AFD083E01FC0823411F484E103C08534F5 -:103E700019F485E0A5D083C0853579F48BD0E82E80 +:103E6000B3D083E01FC0823411F484E103C08534F1 +:103E700019F485E0A9D083C0853579F48BD0E82E7C :103E8000FF2488D0082F10E0102F00270E291F29AB -:103E9000000F111F8DD0680172C0863529F484E0AF -:103EA0008FD080E06FD06BC0843609F042C072D0F2 +:103E9000000F111F91D0680172C0863529F484E0AB +:103EA00093D080E06FD06BC0843609F042C072D0EE :103EB00071D0082F6FD080E0C81688E3D80620F4B0 :103EC00083E0F60187BFE895C0E0D1E063D0899335 :103ED0000C17E1F7F0E0CF16F8E3DF0620F083E0FF -:103EE000F60187BFE89564D007B600FCFDCFA601B8 +:103EE000F60187BFE89568D007B600FCFDCFA601B4 :103EF000A0E0B1E02C9130E011968C91119790E008 :103F0000982F8827822B932B1296FA010C0197BECB :103F1000E89511244E5F5F4FF1E0A038BF0751F7DD :103F2000F601A7BEE89507B600FCFDCFB7BEE89541 -:103F300026C08437B1F42ED02DD0F82E2BD038D017 +:103F300026C08437B1F42ED02DD0F82E2BD03CD013 :103F4000F601EF2C8F010F5F1F4F84911BD0EA9475 :103F5000F801C1F70894C11CD11CFA94CF0CD11CF4 -:103F60000EC0853739F424D08EE10CD084E90AD014 -:103F700086E098CF813511F488E014D019D080E123 +:103F60000EC0853739F428D08EE10CD084E90AD010 +:103F700086E098CF813511F488E018D01DD080E11B :103F800001D06ACF982F8091C00085FFFCCF90931D -:103F9000C6000895A8958091C00087FFFCCF80914E -:103FA000C6000895E0E6F0E098E1908380830895EC -:103FB000F1DF803219F088E0F5DFFFCF84E1E2CF56 -:103FC0001F93182FE7DF1150E9F7F2DF1F910895D3 -:0A3FD00080E0E8DFEE27FF270994E8 -:023FFE000204BB +:103F9000C60008958091C00087FFFCCF8091C000CB +:103FA00084FD01C0A8958091C6000895E0E6F0E088 +:103FB00098E1908380830895EDDF803219F088E0E6 +:103FC000F5DFFFCF84E1DECF1F93182FE3DF115021 +:103FD000E9F7F2DF1F91089580E0E8DFEE27FF2781 +:023FE000099442 +:023FFE000304BA :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.lst b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.lst index c8d07431c..cb0ea83cd 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.lst @@ -3,27 +3,27 @@ optiboot_lilypad_resonator.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .text 000001da 00003e00 00003e00 00000054 2**1 + 0 .text 000001e2 00003e00 00003e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .version 00000002 00003ffe 00003ffe 0000022e 2**0 + 1 .version 00000002 00003ffe 00003ffe 00000236 2**0 CONTENTS, READONLY - 2 .debug_aranges 00000028 00000000 00000000 00000230 2**0 + 2 .debug_aranges 00000028 00000000 00000000 00000238 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_pubnames 0000005f 00000000 00000000 00000258 2**0 + 3 .debug_pubnames 0000005f 00000000 00000000 00000260 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_info 0000028d 00000000 00000000 000002b7 2**0 + 4 .debug_info 0000028e 00000000 00000000 000002bf 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 0000018a 00000000 00000000 00000544 2**0 + 5 .debug_abbrev 00000171 00000000 00000000 0000054d 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_line 00000456 00000000 00000000 000006ce 2**0 + 6 .debug_line 0000045e 00000000 00000000 000006be 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000080 00000000 00000000 00000b24 2**2 + 7 .debug_frame 00000080 00000000 00000000 00000b1c 2**2 CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000149 00000000 00000000 00000ba4 2**0 + 8 .debug_str 00000149 00000000 00000000 00000b9c 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 0000027e 00000000 00000000 00000ced 2**0 + 9 .debug_loc 0000027e 00000000 00000000 00000ce5 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000060 00000000 00000000 00000f6b 2**0 + 10 .debug_ranges 00000060 00000000 00000000 00000f63 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: @@ -47,7 +47,7 @@ int main(void) { 3e04: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); 3e06: 81 ff sbrs r24, 1 - 3e08: e3 d0 rcall .+454 ; 0x3fd0 + 3e08: e7 d0 rcall .+462 ; 0x3fd8 #if LED_START_FLASHES > 0 // Set up Timer 1 for timeout counter @@ -77,7 +77,7 @@ int main(void) { // Set up watchdog to trigger after 500ms watchdogConfig(WATCHDOG_1S); 3e28: 8e e0 ldi r24, 0x0E ; 14 - 3e2a: bc d0 rcall .+376 ; 0x3fa4 + 3e2a: c0 d0 rcall .+384 ; 0x3fac /* Set LED pin as output */ LED_DDR |= _BV(LED); @@ -163,7 +163,7 @@ void watchdogReset() { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); 3e5e: 81 e0 ldi r24, 0x01 ; 1 - 3e60: af d0 rcall .+350 ; 0x3fc0 + 3e60: b3 d0 rcall .+358 ; 0x3fc8 putch(0x03); 3e62: 83 e0 ldi r24, 0x03 ; 3 3e64: 1f c0 rjmp .+62 ; 0x3ea4 @@ -182,7 +182,7 @@ void watchdogReset() { // SET DEVICE EXT is ignored getNch(5); 3e72: 85 e0 ldi r24, 0x05 ; 5 - 3e74: a5 d0 rcall .+330 ; 0x3fc0 + 3e74: a9 d0 rcall .+338 ; 0x3fc8 3e76: 83 c0 rjmp .+262 ; 0x3f7e } else if(ch == STK_LOAD_ADDRESS) { @@ -211,7 +211,7 @@ void watchdogReset() { 3e92: 11 1f adc r17, r17 address = newAddress; verifySpace(); - 3e94: 8d d0 rcall .+282 ; 0x3fb0 + 3e94: 91 d0 rcall .+290 ; 0x3fb8 3e96: 68 01 movw r12, r16 3e98: 72 c0 rjmp .+228 ; 0x3f7e } @@ -221,7 +221,7 @@ void watchdogReset() { // UNIVERSAL command is ignored getNch(4); 3e9e: 84 e0 ldi r24, 0x04 ; 4 - 3ea0: 8f d0 rcall .+286 ; 0x3fc0 + 3ea0: 93 d0 rcall .+294 ; 0x3fc8 putch(0x00); 3ea2: 80 e0 ldi r24, 0x00 ; 0 3ea4: 6f d0 rcall .+222 ; 0x3f84 @@ -282,7 +282,7 @@ void watchdogReset() { // Read command terminator, start reply verifySpace(); - 3ee6: 64 d0 rcall .+200 ; 0x3fb0 + 3ee6: 68 d0 rcall .+208 ; 0x3fb8 // If only a partial page is to be programmed, the erase might not be complete. // So check that here @@ -370,7 +370,7 @@ int main(void) { 3f3c: 2b d0 rcall .+86 ; 0x3f94 verifySpace(); - 3f3e: 38 d0 rcall .+112 ; 0x3fb0 + 3f3e: 3c d0 rcall .+120 ; 0x3fb8 3f40: f6 01 movw r30, r12 3f42: ef 2c mov r14, r15 putch(result); @@ -411,7 +411,7 @@ int main(void) { 3f64: 39 f4 brne .+14 ; 0x3f74 // READ SIGN - return what Avrdude wants to hear verifySpace(); - 3f66: 24 d0 rcall .+72 ; 0x3fb0 + 3f66: 28 d0 rcall .+80 ; 0x3fb8 putch(SIGNATURE_0); 3f68: 8e e1 ldi r24, 0x1E ; 30 3f6a: 0c d0 rcall .+24 ; 0x3f84 @@ -428,13 +428,13 @@ int main(void) { // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); 3f78: 88 e0 ldi r24, 0x08 ; 8 - 3f7a: 14 d0 rcall .+40 ; 0x3fa4 + 3f7a: 18 d0 rcall .+48 ; 0x3fac verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 3f7c: 19 d0 rcall .+50 ; 0x3fb0 + 3f7c: 1d d0 rcall .+58 ; 0x3fb8 } putch(STK_OK); 3f7e: 80 e1 ldi r24, 0x10 ; 16 @@ -463,99 +463,109 @@ void putch(char ch) { 3f92: 08 95 ret 00003f94 : + [uartBit] "I" (UART_RX_BIT) + : + "r25" +); +#else + while(!(UCSR0A & _BV(RXC0))) + 3f94: 80 91 c0 00 lds r24, 0x00C0 + 3f98: 87 ff sbrs r24, 7 + 3f9a: fc cf rjmp .-8 ; 0x3f94 + ; + if (!(UCSR0A & _BV(FE0))) { + 3f9c: 80 91 c0 00 lds r24, 0x00C0 + 3fa0: 84 fd sbrc r24, 4 + 3fa2: 01 c0 rjmp .+2 ; 0x3fa6 } #endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 3f94: a8 95 wdr - [uartBit] "I" (UART_RX_BIT) - : - "r25" -); -#else - while(!(UCSR0A & _BV(RXC0))); - 3f96: 80 91 c0 00 lds r24, 0x00C0 - 3f9a: 87 ff sbrs r24, 7 - 3f9c: fc cf rjmp .-8 ; 0x3f96 + 3fa4: a8 95 wdr + * don't care that an invalid char is returned...) + */ + watchdogReset(); + } + ch = UDR0; - 3f9e: 80 91 c6 00 lds r24, 0x00C6 + 3fa6: 80 91 c6 00 lds r24, 0x00C6 LED_PIN |= _BV(LED); #endif #endif return ch; } - 3fa2: 08 95 ret + 3faa: 08 95 ret -00003fa4 : +00003fac : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 3fa4: e0 e6 ldi r30, 0x60 ; 96 - 3fa6: f0 e0 ldi r31, 0x00 ; 0 - 3fa8: 98 e1 ldi r25, 0x18 ; 24 - 3faa: 90 83 st Z, r25 + 3fac: e0 e6 ldi r30, 0x60 ; 96 + 3fae: f0 e0 ldi r31, 0x00 ; 0 + 3fb0: 98 e1 ldi r25, 0x18 ; 24 + 3fb2: 90 83 st Z, r25 WDTCSR = x; - 3fac: 80 83 st Z, r24 + 3fb4: 80 83 st Z, r24 } - 3fae: 08 95 ret + 3fb6: 08 95 ret -00003fb0 : +00003fb8 : do getch(); while (--count); verifySpace(); } void verifySpace() { if (getch() != CRC_EOP) { - 3fb0: f1 df rcall .-30 ; 0x3f94 - 3fb2: 80 32 cpi r24, 0x20 ; 32 - 3fb4: 19 f0 breq .+6 ; 0x3fbc + 3fb8: ed df rcall .-38 ; 0x3f94 + 3fba: 80 32 cpi r24, 0x20 ; 32 + 3fbc: 19 f0 breq .+6 ; 0x3fc4 watchdogConfig(WATCHDOG_16MS); // shorten WD timeout - 3fb6: 88 e0 ldi r24, 0x08 ; 8 - 3fb8: f5 df rcall .-22 ; 0x3fa4 - 3fba: ff cf rjmp .-2 ; 0x3fba + 3fbe: 88 e0 ldi r24, 0x08 ; 8 + 3fc0: f5 df rcall .-22 ; 0x3fac + 3fc2: ff cf rjmp .-2 ; 0x3fc2 while (1) // and busy-loop so that WD causes ; // a reset and app start. } putch(STK_INSYNC); - 3fbc: 84 e1 ldi r24, 0x14 ; 20 + 3fc4: 84 e1 ldi r24, 0x14 ; 20 } - 3fbe: e2 cf rjmp .-60 ; 0x3f84 + 3fc6: de cf rjmp .-68 ; 0x3f84 -00003fc0 : +00003fc8 : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 3fc0: 1f 93 push r17 - 3fc2: 18 2f mov r17, r24 + 3fc8: 1f 93 push r17 + 3fca: 18 2f mov r17, r24 do getch(); while (--count); - 3fc4: e7 df rcall .-50 ; 0x3f94 - 3fc6: 11 50 subi r17, 0x01 ; 1 - 3fc8: e9 f7 brne .-6 ; 0x3fc4 + 3fcc: e3 df rcall .-58 ; 0x3f94 + 3fce: 11 50 subi r17, 0x01 ; 1 + 3fd0: e9 f7 brne .-6 ; 0x3fcc verifySpace(); - 3fca: f2 df rcall .-28 ; 0x3fb0 + 3fd2: f2 df rcall .-28 ; 0x3fb8 } - 3fcc: 1f 91 pop r17 - 3fce: 08 95 ret + 3fd4: 1f 91 pop r17 + 3fd6: 08 95 ret -00003fd0 : +00003fd8 : WDTCSR = _BV(WDCE) | _BV(WDE); WDTCSR = x; } void appStart() { watchdogConfig(WATCHDOG_OFF); - 3fd0: 80 e0 ldi r24, 0x00 ; 0 - 3fd2: e8 df rcall .-48 ; 0x3fa4 + 3fd8: 80 e0 ldi r24, 0x00 ; 0 + 3fda: e8 df rcall .-48 ; 0x3fac __asm__ __volatile__ ( - 3fd4: ee 27 eor r30, r30 - 3fd6: ff 27 eor r31, r31 - 3fd8: 09 94 ijmp + 3fdc: ee 27 eor r30, r30 + 3fde: ff 27 eor r31, r31 + 3fe0: 09 94 ijmp diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_luminet.hex b/hardware/arduino/bootloaders/optiboot/optiboot_luminet.hex index 78fdc7030..45b4dcd34 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_luminet.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_luminet.hex @@ -1,14 +1,14 @@ -:101D0000112484B714BE81FF18D185E08EBD8EE00A -:101D100000D1D49AD29A86E023EC3FEF91E03DBD0A +:101D0000112484B714BE81FF17D185E08EBD8EE00B +:101D1000FFD0D49AD29A86E023EC3FEF91E03DBD0C :101D20002CBD9BB9589BFECFCC9AA8958150B9F792 :101D3000BB24B39425E0A22E9FE7D92E8EECC82EAB -:101D4000D4D0813421F481E0F0D083E0B5C0823476 -:101D500011F484E103C0853419F485E0E6D0B3C002 +:101D4000D4D0813421F481E0EFD083E0B5C0823477 +:101D500011F484E103C0853419F485E0E5D0B3C003 :101D6000853569F4C2D0E82EFF24BFD0082F10E0DB :101D7000102F00270E291F29000F111FA3C0863521 -:101D800021F484E0D2D080E097C0843609F060C0AE +:101D800021F484E0D1D080E097C0843609F060C0AF :101D9000ACD0ABD0F82EA9D0C0E0D1E0A6D08993CA -:101DA000FC16E1F783E0F80187BFE895B6D007B6E7 +:101DA000FC16E1F783E0F80187BFE895B5D007B6E8 :101DB00000FCFDCF0115110511F0A8012AC080918A :101DC00000012091010130E0322F222790E0282BE2 :101DD000392B309385012093840140910801809133 @@ -19,22 +19,22 @@ :101E200090E0982F8827822B932B1296FA010C01B1 :101E3000B7BEE89511244E5F5F4FF1E0A034BF07B5 :101E400051F7F801A7BEE89507B600FCFDCF3BC0EF -:101E5000843751F54AD049D0F82E47D05ED0E801FA +:101E5000843751F54AD049D0F82E47D05DD0E801FB :101E6000EF2C209719F48091840114C0C130D10562 :101E700019F4809185010EC0C830D10519F4809104 :101E8000860108C0C930D10519F48091870102C0CC :101E9000FE01849121961AD0EA9419F70F5F1F4F23 -:101EA000FA940F0D111D0FC0853741F436D08EE125 +:101EA000FA940F0D111D0FC0853741F435D08EE126 :101EB0000DD083E90BD08CE009D005C0813511F439 -:101EC00088E027D02AD080E101D03ACF2AE030E064 -:101ED0008095089410F4DA9802C0DA9A000015D0C0 -:101EE00014D086952A95B1F70895A89529E030E099 -:101EF000CB99FECF0AD009D008D08894CB9908940A -:101F00002A9511F08795F7CF08959EE09A95F1F7FD -:101F1000089598E191BD81BD0895E7DF803219F001 -:101F200088E0F7DFFFCF84E1D1CF1F93182FDDDFEB -:101F30001150E9F7F2DF1F91089580E0EADFE4E055 -:041F4000FF270994DA -:021EFE000204DC +:101EC00088E026D029D080E101D03ACF2AE030E066 +:101ED0008095089410F4DA9802C0DA9A000014D0C1 +:101EE00013D086952A95B1F7089529E030E0CB9973 +:101EF000FECF0AD009D008D08894CB9908942A95AF +:101F000011F08795F7CF08959EE09A95F1F708951F +:101F100098E191BD81BD0895E8DF803219F088E035 +:101F2000F7DFFFCF84E1D2CF1F93182FDEDF1150F0 +:101F3000E9F7F2DF1F91089580E0EADFE4E0FF2790 +:021F4000099402 +:021EFE000304DB :0400000300001D00DC :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_luminet.lst b/hardware/arduino/bootloaders/optiboot/optiboot_luminet.lst index 447349df2..e40e0ef26 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_luminet.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_luminet.lst @@ -3,27 +3,27 @@ optiboot_luminet.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .text 00000244 00001d00 00001d00 00000054 2**1 + 0 .text 00000242 00001d00 00001d00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .version 00000002 00001efe 00001efe 00000298 2**0 + 1 .version 00000002 00001efe 00001efe 00000296 2**0 CONTENTS, READONLY - 2 .debug_aranges 00000028 00000000 00000000 0000029a 2**0 + 2 .debug_aranges 00000028 00000000 00000000 00000298 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_pubnames 0000006d 00000000 00000000 000002c2 2**0 + 3 .debug_pubnames 0000006d 00000000 00000000 000002c0 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_info 000002b1 00000000 00000000 0000032f 2**0 + 4 .debug_info 000002a2 00000000 00000000 0000032d 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 00000188 00000000 00000000 000005e0 2**0 + 5 .debug_abbrev 0000016f 00000000 00000000 000005cf 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_line 000004a7 00000000 00000000 00000768 2**0 + 6 .debug_line 0000049d 00000000 00000000 0000073e 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000090 00000000 00000000 00000c10 2**2 + 7 .debug_frame 00000090 00000000 00000000 00000bdc 2**2 CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000158 00000000 00000000 00000ca0 2**0 + 8 .debug_str 00000158 00000000 00000000 00000c6c 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 00000268 00000000 00000000 00000df8 2**0 + 9 .debug_loc 00000268 00000000 00000000 00000dc4 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000080 00000000 00000000 00001060 2**0 + 10 .debug_ranges 00000080 00000000 00000000 0000102c 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: @@ -47,7 +47,7 @@ int main(void) { 1d04: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); 1d06: 81 ff sbrs r24, 1 - 1d08: 18 d1 rcall .+560 ; 0x1f3a + 1d08: 17 d1 rcall .+558 ; 0x1f38 #if LED_START_FLASHES > 0 // Set up Timer 1 for timeout counter @@ -61,7 +61,7 @@ int main(void) { // Set up watchdog to trigger after 500ms watchdogConfig(WATCHDOG_1S); 1d0e: 8e e0 ldi r24, 0x0E ; 14 - 1d10: 00 d1 rcall .+512 ; 0x1f12 + 1d10: ff d0 rcall .+510 ; 0x1f10 /* Set LED pin as output */ LED_DDR |= _BV(LED); @@ -156,7 +156,7 @@ void watchdogReset() { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); 1d46: 81 e0 ldi r24, 0x01 ; 1 - 1d48: f0 d0 rcall .+480 ; 0x1f2a + 1d48: ef d0 rcall .+478 ; 0x1f28 putch(0x03); 1d4a: 83 e0 ldi r24, 0x03 ; 3 1d4c: b5 c0 rjmp .+362 ; 0x1eb8 @@ -175,7 +175,7 @@ void watchdogReset() { // SET DEVICE EXT is ignored getNch(5); 1d5a: 85 e0 ldi r24, 0x05 ; 5 - 1d5c: e6 d0 rcall .+460 ; 0x1f2a + 1d5c: e5 d0 rcall .+458 ; 0x1f28 1d5e: b3 c0 rjmp .+358 ; 0x1ec6 } else if(ch == STK_LOAD_ADDRESS) { @@ -212,7 +212,7 @@ void watchdogReset() { // UNIVERSAL command is ignored getNch(4); 1d82: 84 e0 ldi r24, 0x04 ; 4 - 1d84: d2 d0 rcall .+420 ; 0x1f2a + 1d84: d1 d0 rcall .+418 ; 0x1f28 putch(0x00); 1d86: 80 e0 ldi r24, 0x00 ; 0 1d88: 97 c0 rjmp .+302 ; 0x1eb8 @@ -257,7 +257,7 @@ void watchdogReset() { // Read command terminator, start reply verifySpace(); - 1dac: b6 d0 rcall .+364 ; 0x1f1a + 1dac: b5 d0 rcall .+362 ; 0x1f18 // If only a partial page is to be programmed, the erase might not be complete. // So check that here @@ -391,7 +391,7 @@ int main(void) { 1e5a: 47 d0 rcall .+142 ; 0x1eea verifySpace(); - 1e5c: 5e d0 rcall .+188 ; 0x1f1a + 1e5c: 5d d0 rcall .+186 ; 0x1f18 1e5e: e8 01 movw r28, r16 1e60: ef 2c mov r14, r15 #ifdef VIRTUAL_BOOT_PARTITION @@ -452,7 +452,7 @@ int main(void) { 1eaa: 41 f4 brne .+16 ; 0x1ebc // READ SIGN - return what Avrdude wants to hear verifySpace(); - 1eac: 36 d0 rcall .+108 ; 0x1f1a + 1eac: 35 d0 rcall .+106 ; 0x1f18 putch(SIGNATURE_0); 1eae: 8e e1 ldi r24, 0x1E ; 30 1eb0: 0d d0 rcall .+26 ; 0x1ecc @@ -470,13 +470,13 @@ int main(void) { // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); 1ec0: 88 e0 ldi r24, 0x08 ; 8 - 1ec2: 27 d0 rcall .+78 ; 0x1f12 + 1ec2: 26 d0 rcall .+76 ; 0x1f10 verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 1ec4: 2a d0 rcall .+84 ; 0x1f1a + 1ec4: 29 d0 rcall .+82 ; 0x1f18 } putch(STK_OK); 1ec6: 80 e1 ldi r24, 0x10 ; 16 @@ -499,8 +499,8 @@ void putch(char ch) { 1ed8: 02 c0 rjmp .+4 ; 0x1ede 1eda: da 9a sbi 0x1b, 2 ; 27 1edc: 00 00 nop - 1ede: 15 d0 rcall .+42 ; 0x1f0a - 1ee0: 14 d0 rcall .+40 ; 0x1f0a + 1ede: 14 d0 rcall .+40 ; 0x1f08 + 1ee0: 13 d0 rcall .+38 ; 0x1f08 1ee2: 86 95 lsr r24 1ee4: 2a 95 dec r18 1ee6: b1 f7 brne .-20 ; 0x1ed4 @@ -513,112 +513,105 @@ void putch(char ch) { 1ee8: 08 95 ret 00001eea : -} -#endif - -// Watchdog functions. These are only safe with interrupts turned off. -void watchdogReset() { - __asm__ __volatile__ ( - 1eea: a8 95 wdr LED_PIN |= _BV(LED); #endif #endif return ch; } - 1eec: 29 e0 ldi r18, 0x09 ; 9 - 1eee: 30 e0 ldi r19, 0x00 ; 0 - 1ef0: cb 99 sbic 0x19, 3 ; 25 - 1ef2: fe cf rjmp .-4 ; 0x1ef0 - 1ef4: 0a d0 rcall .+20 ; 0x1f0a - 1ef6: 09 d0 rcall .+18 ; 0x1f0a - 1ef8: 08 d0 rcall .+16 ; 0x1f0a - 1efa: 88 94 clc - 1efc: cb 99 sbic 0x19, 3 ; 25 - 1efe: 08 94 sec - 1f00: 2a 95 dec r18 - 1f02: 11 f0 breq .+4 ; 0x1f08 - 1f04: 87 95 ror r24 - 1f06: f7 cf rjmp .-18 ; 0x1ef6 - 1f08: 08 95 ret + 1eea: 29 e0 ldi r18, 0x09 ; 9 + 1eec: 30 e0 ldi r19, 0x00 ; 0 + 1eee: cb 99 sbic 0x19, 3 ; 25 + 1ef0: fe cf rjmp .-4 ; 0x1eee + 1ef2: 0a d0 rcall .+20 ; 0x1f08 + 1ef4: 09 d0 rcall .+18 ; 0x1f08 + 1ef6: 08 d0 rcall .+16 ; 0x1f08 + 1ef8: 88 94 clc + 1efa: cb 99 sbic 0x19, 3 ; 25 + 1efc: 08 94 sec + 1efe: 2a 95 dec r18 + 1f00: 11 f0 breq .+4 ; 0x1f06 + 1f02: 87 95 ror r24 + 1f04: f7 cf rjmp .-18 ; 0x1ef4 + 1f06: 08 95 ret -00001f0a : +00001f08 : #if UART_B_VALUE > 255 #error Baud rate too slow for soft UART #endif void uartDelay() { __asm__ __volatile__ ( - 1f0a: 9e e0 ldi r25, 0x0E ; 14 - 1f0c: 9a 95 dec r25 - 1f0e: f1 f7 brne .-4 ; 0x1f0c - 1f10: 08 95 ret + 1f08: 9e e0 ldi r25, 0x0E ; 14 + 1f0a: 9a 95 dec r25 + 1f0c: f1 f7 brne .-4 ; 0x1f0a + 1f0e: 08 95 ret -00001f12 : +00001f10 : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 1f12: 98 e1 ldi r25, 0x18 ; 24 - 1f14: 91 bd out 0x21, r25 ; 33 + 1f10: 98 e1 ldi r25, 0x18 ; 24 + 1f12: 91 bd out 0x21, r25 ; 33 WDTCSR = x; - 1f16: 81 bd out 0x21, r24 ; 33 + 1f14: 81 bd out 0x21, r24 ; 33 } - 1f18: 08 95 ret + 1f16: 08 95 ret -00001f1a : +00001f18 : do getch(); while (--count); verifySpace(); } void verifySpace() { if (getch() != CRC_EOP) { - 1f1a: e7 df rcall .-50 ; 0x1eea - 1f1c: 80 32 cpi r24, 0x20 ; 32 - 1f1e: 19 f0 breq .+6 ; 0x1f26 + 1f18: e8 df rcall .-48 ; 0x1eea + 1f1a: 80 32 cpi r24, 0x20 ; 32 + 1f1c: 19 f0 breq .+6 ; 0x1f24 watchdogConfig(WATCHDOG_16MS); // shorten WD timeout - 1f20: 88 e0 ldi r24, 0x08 ; 8 - 1f22: f7 df rcall .-18 ; 0x1f12 - 1f24: ff cf rjmp .-2 ; 0x1f24 + 1f1e: 88 e0 ldi r24, 0x08 ; 8 + 1f20: f7 df rcall .-18 ; 0x1f10 + 1f22: ff cf rjmp .-2 ; 0x1f22 while (1) // and busy-loop so that WD causes ; // a reset and app start. } putch(STK_INSYNC); - 1f26: 84 e1 ldi r24, 0x14 ; 20 + 1f24: 84 e1 ldi r24, 0x14 ; 20 } - 1f28: d1 cf rjmp .-94 ; 0x1ecc + 1f26: d2 cf rjmp .-92 ; 0x1ecc -00001f2a : +00001f28 : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 1f2a: 1f 93 push r17 - 1f2c: 18 2f mov r17, r24 + 1f28: 1f 93 push r17 + 1f2a: 18 2f mov r17, r24 do getch(); while (--count); - 1f2e: dd df rcall .-70 ; 0x1eea - 1f30: 11 50 subi r17, 0x01 ; 1 - 1f32: e9 f7 brne .-6 ; 0x1f2e + 1f2c: de df rcall .-68 ; 0x1eea + 1f2e: 11 50 subi r17, 0x01 ; 1 + 1f30: e9 f7 brne .-6 ; 0x1f2c verifySpace(); - 1f34: f2 df rcall .-28 ; 0x1f1a + 1f32: f2 df rcall .-28 ; 0x1f18 } - 1f36: 1f 91 pop r17 - 1f38: 08 95 ret + 1f34: 1f 91 pop r17 + 1f36: 08 95 ret -00001f3a : +00001f38 : WDTCSR = _BV(WDCE) | _BV(WDE); WDTCSR = x; } void appStart() { watchdogConfig(WATCHDOG_OFF); - 1f3a: 80 e0 ldi r24, 0x00 ; 0 - 1f3c: ea df rcall .-44 ; 0x1f12 + 1f38: 80 e0 ldi r24, 0x00 ; 0 + 1f3a: ea df rcall .-44 ; 0x1f10 __asm__ __volatile__ ( - 1f3e: e4 e0 ldi r30, 0x04 ; 4 - 1f40: ff 27 eor r31, r31 - 1f42: 09 94 ijmp + 1f3c: e4 e0 ldi r30, 0x04 ; 4 + 1f3e: ff 27 eor r31, r31 + 1f40: 09 94 ijmp diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.hex b/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.hex index 26bbd4cdf..b685a4e9a 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.hex @@ -1,33 +1,34 @@ -:103E0000112484B714BE81FFE3D085E08093810044 +:103E0000112484B714BE81FFE7D085E08093810040 :103E100082E08093C00088E18093C10086E08093B7 -:103E2000C20080E18093C4008EE0BCD0259A86E079 +:103E2000C20080E18093C4008EE0C0D0259A86E075 :103E300020E33CEF91E0309385002093840096BB13 :103E4000B09BFECF1D9AA8958150A9F79924939411 :103E5000A5E0AA2EF1E1BF2E9DD0813421F481E0AE -:103E6000AFD083E01FC0823411F484E103C08534F5 -:103E700019F485E0A5D083C0853579F48BD0E82E80 +:103E6000B3D083E01FC0823411F484E103C08534F1 +:103E700019F485E0A9D083C0853579F48BD0E82E7C :103E8000FF2488D0082F10E0102F00270E291F29AB -:103E9000000F111F8DD0680172C0863529F484E0AF -:103EA0008FD080E06FD06BC0843609F042C072D0F2 +:103E9000000F111F91D0680172C0863529F484E0AB +:103EA00093D080E06FD06BC0843609F042C072D0EE :103EB00071D0082F6FD080E0C81688E3D80620F4B0 :103EC00083E0F60187BFE895C0E0D1E063D0899335 :103ED0000C17E1F7F0E0CF16F8E3DF0620F083E0FF -:103EE000F60187BFE89564D007B600FCFDCFA601B8 +:103EE000F60187BFE89568D007B600FCFDCFA601B4 :103EF000A0E0B1E02C9130E011968C91119790E008 :103F0000982F8827822B932B1296FA010C0197BECB :103F1000E89511244E5F5F4FF1E0A038BF0751F7DD :103F2000F601A7BEE89507B600FCFDCFB7BEE89541 -:103F300026C08437B1F42ED02DD0F82E2BD038D017 +:103F300026C08437B1F42ED02DD0F82E2BD03CD013 :103F4000F601EF2C8F010F5F1F4F84911BD0EA9475 :103F5000F801C1F70894C11CD11CFA94CF0CD11CF4 -:103F60000EC0853739F424D08EE10CD084E90AD014 -:103F700086E098CF813511F488E014D019D080E123 +:103F60000EC0853739F428D08EE10CD084E90AD010 +:103F700086E098CF813511F488E018D01DD080E11B :103F800001D06ACF982F8091C00085FFFCCF90931D -:103F9000C6000895A8958091C00087FFFCCF80914E -:103FA000C6000895E0E6F0E098E1908380830895EC -:103FB000F1DF803219F088E0F5DFFFCF84E1E2CF56 -:103FC0001F93182FE7DF1150E9F7F2DF1F910895D3 -:0A3FD00080E0E8DFEE27FF270994E8 -:023FFE000204BB +:103F9000C60008958091C00087FFFCCF8091C000CB +:103FA00084FD01C0A8958091C6000895E0E6F0E088 +:103FB00098E1908380830895EDDF803219F088E0E6 +:103FC000F5DFFFCF84E1DECF1F93182FE3DF115021 +:103FD000E9F7F2DF1F91089580E0E8DFEE27FF2781 +:023FE000099442 +:023FFE000304BA :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.lst b/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.lst index e615a8e21..2c6bea1eb 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.lst @@ -3,27 +3,27 @@ optiboot_pro_16MHz.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .text 000001da 00003e00 00003e00 00000054 2**1 + 0 .text 000001e2 00003e00 00003e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .version 00000002 00003ffe 00003ffe 0000022e 2**0 + 1 .version 00000002 00003ffe 00003ffe 00000236 2**0 CONTENTS, READONLY - 2 .debug_aranges 00000028 00000000 00000000 00000230 2**0 + 2 .debug_aranges 00000028 00000000 00000000 00000238 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_pubnames 0000005f 00000000 00000000 00000258 2**0 + 3 .debug_pubnames 0000005f 00000000 00000000 00000260 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_info 0000028d 00000000 00000000 000002b7 2**0 + 4 .debug_info 0000028e 00000000 00000000 000002bf 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 0000018a 00000000 00000000 00000544 2**0 + 5 .debug_abbrev 00000171 00000000 00000000 0000054d 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_line 00000456 00000000 00000000 000006ce 2**0 + 6 .debug_line 0000045e 00000000 00000000 000006be 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000080 00000000 00000000 00000b24 2**2 + 7 .debug_frame 00000080 00000000 00000000 00000b1c 2**2 CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000149 00000000 00000000 00000ba4 2**0 + 8 .debug_str 00000149 00000000 00000000 00000b9c 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 0000027e 00000000 00000000 00000ced 2**0 + 9 .debug_loc 0000027e 00000000 00000000 00000ce5 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000060 00000000 00000000 00000f6b 2**0 + 10 .debug_ranges 00000060 00000000 00000000 00000f63 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: @@ -47,7 +47,7 @@ int main(void) { 3e04: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); 3e06: 81 ff sbrs r24, 1 - 3e08: e3 d0 rcall .+454 ; 0x3fd0 + 3e08: e7 d0 rcall .+462 ; 0x3fd8 #if LED_START_FLASHES > 0 // Set up Timer 1 for timeout counter @@ -77,7 +77,7 @@ int main(void) { // Set up watchdog to trigger after 500ms watchdogConfig(WATCHDOG_1S); 3e28: 8e e0 ldi r24, 0x0E ; 14 - 3e2a: bc d0 rcall .+376 ; 0x3fa4 + 3e2a: c0 d0 rcall .+384 ; 0x3fac /* Set LED pin as output */ LED_DDR |= _BV(LED); @@ -163,7 +163,7 @@ void watchdogReset() { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); 3e5e: 81 e0 ldi r24, 0x01 ; 1 - 3e60: af d0 rcall .+350 ; 0x3fc0 + 3e60: b3 d0 rcall .+358 ; 0x3fc8 putch(0x03); 3e62: 83 e0 ldi r24, 0x03 ; 3 3e64: 1f c0 rjmp .+62 ; 0x3ea4 @@ -182,7 +182,7 @@ void watchdogReset() { // SET DEVICE EXT is ignored getNch(5); 3e72: 85 e0 ldi r24, 0x05 ; 5 - 3e74: a5 d0 rcall .+330 ; 0x3fc0 + 3e74: a9 d0 rcall .+338 ; 0x3fc8 3e76: 83 c0 rjmp .+262 ; 0x3f7e } else if(ch == STK_LOAD_ADDRESS) { @@ -211,7 +211,7 @@ void watchdogReset() { 3e92: 11 1f adc r17, r17 address = newAddress; verifySpace(); - 3e94: 8d d0 rcall .+282 ; 0x3fb0 + 3e94: 91 d0 rcall .+290 ; 0x3fb8 3e96: 68 01 movw r12, r16 3e98: 72 c0 rjmp .+228 ; 0x3f7e } @@ -221,7 +221,7 @@ void watchdogReset() { // UNIVERSAL command is ignored getNch(4); 3e9e: 84 e0 ldi r24, 0x04 ; 4 - 3ea0: 8f d0 rcall .+286 ; 0x3fc0 + 3ea0: 93 d0 rcall .+294 ; 0x3fc8 putch(0x00); 3ea2: 80 e0 ldi r24, 0x00 ; 0 3ea4: 6f d0 rcall .+222 ; 0x3f84 @@ -282,7 +282,7 @@ void watchdogReset() { // Read command terminator, start reply verifySpace(); - 3ee6: 64 d0 rcall .+200 ; 0x3fb0 + 3ee6: 68 d0 rcall .+208 ; 0x3fb8 // If only a partial page is to be programmed, the erase might not be complete. // So check that here @@ -370,7 +370,7 @@ int main(void) { 3f3c: 2b d0 rcall .+86 ; 0x3f94 verifySpace(); - 3f3e: 38 d0 rcall .+112 ; 0x3fb0 + 3f3e: 3c d0 rcall .+120 ; 0x3fb8 3f40: f6 01 movw r30, r12 3f42: ef 2c mov r14, r15 putch(result); @@ -411,7 +411,7 @@ int main(void) { 3f64: 39 f4 brne .+14 ; 0x3f74 // READ SIGN - return what Avrdude wants to hear verifySpace(); - 3f66: 24 d0 rcall .+72 ; 0x3fb0 + 3f66: 28 d0 rcall .+80 ; 0x3fb8 putch(SIGNATURE_0); 3f68: 8e e1 ldi r24, 0x1E ; 30 3f6a: 0c d0 rcall .+24 ; 0x3f84 @@ -428,13 +428,13 @@ int main(void) { // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); 3f78: 88 e0 ldi r24, 0x08 ; 8 - 3f7a: 14 d0 rcall .+40 ; 0x3fa4 + 3f7a: 18 d0 rcall .+48 ; 0x3fac verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 3f7c: 19 d0 rcall .+50 ; 0x3fb0 + 3f7c: 1d d0 rcall .+58 ; 0x3fb8 } putch(STK_OK); 3f7e: 80 e1 ldi r24, 0x10 ; 16 @@ -463,99 +463,109 @@ void putch(char ch) { 3f92: 08 95 ret 00003f94 : + [uartBit] "I" (UART_RX_BIT) + : + "r25" +); +#else + while(!(UCSR0A & _BV(RXC0))) + 3f94: 80 91 c0 00 lds r24, 0x00C0 + 3f98: 87 ff sbrs r24, 7 + 3f9a: fc cf rjmp .-8 ; 0x3f94 + ; + if (!(UCSR0A & _BV(FE0))) { + 3f9c: 80 91 c0 00 lds r24, 0x00C0 + 3fa0: 84 fd sbrc r24, 4 + 3fa2: 01 c0 rjmp .+2 ; 0x3fa6 } #endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 3f94: a8 95 wdr - [uartBit] "I" (UART_RX_BIT) - : - "r25" -); -#else - while(!(UCSR0A & _BV(RXC0))); - 3f96: 80 91 c0 00 lds r24, 0x00C0 - 3f9a: 87 ff sbrs r24, 7 - 3f9c: fc cf rjmp .-8 ; 0x3f96 + 3fa4: a8 95 wdr + * don't care that an invalid char is returned...) + */ + watchdogReset(); + } + ch = UDR0; - 3f9e: 80 91 c6 00 lds r24, 0x00C6 + 3fa6: 80 91 c6 00 lds r24, 0x00C6 LED_PIN |= _BV(LED); #endif #endif return ch; } - 3fa2: 08 95 ret + 3faa: 08 95 ret -00003fa4 : +00003fac : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 3fa4: e0 e6 ldi r30, 0x60 ; 96 - 3fa6: f0 e0 ldi r31, 0x00 ; 0 - 3fa8: 98 e1 ldi r25, 0x18 ; 24 - 3faa: 90 83 st Z, r25 + 3fac: e0 e6 ldi r30, 0x60 ; 96 + 3fae: f0 e0 ldi r31, 0x00 ; 0 + 3fb0: 98 e1 ldi r25, 0x18 ; 24 + 3fb2: 90 83 st Z, r25 WDTCSR = x; - 3fac: 80 83 st Z, r24 + 3fb4: 80 83 st Z, r24 } - 3fae: 08 95 ret + 3fb6: 08 95 ret -00003fb0 : +00003fb8 : do getch(); while (--count); verifySpace(); } void verifySpace() { if (getch() != CRC_EOP) { - 3fb0: f1 df rcall .-30 ; 0x3f94 - 3fb2: 80 32 cpi r24, 0x20 ; 32 - 3fb4: 19 f0 breq .+6 ; 0x3fbc + 3fb8: ed df rcall .-38 ; 0x3f94 + 3fba: 80 32 cpi r24, 0x20 ; 32 + 3fbc: 19 f0 breq .+6 ; 0x3fc4 watchdogConfig(WATCHDOG_16MS); // shorten WD timeout - 3fb6: 88 e0 ldi r24, 0x08 ; 8 - 3fb8: f5 df rcall .-22 ; 0x3fa4 - 3fba: ff cf rjmp .-2 ; 0x3fba + 3fbe: 88 e0 ldi r24, 0x08 ; 8 + 3fc0: f5 df rcall .-22 ; 0x3fac + 3fc2: ff cf rjmp .-2 ; 0x3fc2 while (1) // and busy-loop so that WD causes ; // a reset and app start. } putch(STK_INSYNC); - 3fbc: 84 e1 ldi r24, 0x14 ; 20 + 3fc4: 84 e1 ldi r24, 0x14 ; 20 } - 3fbe: e2 cf rjmp .-60 ; 0x3f84 + 3fc6: de cf rjmp .-68 ; 0x3f84 -00003fc0 : +00003fc8 : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 3fc0: 1f 93 push r17 - 3fc2: 18 2f mov r17, r24 + 3fc8: 1f 93 push r17 + 3fca: 18 2f mov r17, r24 do getch(); while (--count); - 3fc4: e7 df rcall .-50 ; 0x3f94 - 3fc6: 11 50 subi r17, 0x01 ; 1 - 3fc8: e9 f7 brne .-6 ; 0x3fc4 + 3fcc: e3 df rcall .-58 ; 0x3f94 + 3fce: 11 50 subi r17, 0x01 ; 1 + 3fd0: e9 f7 brne .-6 ; 0x3fcc verifySpace(); - 3fca: f2 df rcall .-28 ; 0x3fb0 + 3fd2: f2 df rcall .-28 ; 0x3fb8 } - 3fcc: 1f 91 pop r17 - 3fce: 08 95 ret + 3fd4: 1f 91 pop r17 + 3fd6: 08 95 ret -00003fd0 : +00003fd8 : WDTCSR = _BV(WDCE) | _BV(WDE); WDTCSR = x; } void appStart() { watchdogConfig(WATCHDOG_OFF); - 3fd0: 80 e0 ldi r24, 0x00 ; 0 - 3fd2: e8 df rcall .-48 ; 0x3fa4 + 3fd8: 80 e0 ldi r24, 0x00 ; 0 + 3fda: e8 df rcall .-48 ; 0x3fac __asm__ __volatile__ ( - 3fd4: ee 27 eor r30, r30 - 3fd6: ff 27 eor r31, r31 - 3fd8: 09 94 ijmp + 3fdc: ee 27 eor r30, r30 + 3fde: ff 27 eor r31, r31 + 3fe0: 09 94 ijmp diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.hex b/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.hex index dbd29c1c7..451a99c63 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.hex @@ -1,33 +1,34 @@ -:103E0000112484B714BE81FFE3D085E08093810044 +:103E0000112484B714BE81FFE7D085E08093810040 :103E100082E08093C00088E18093C10086E08093B7 -:103E2000C20085E18093C4008EE0BCD0259A86E074 +:103E2000C20085E18093C4008EE0C0D0259A86E070 :103E30002CE33BEF91E0309385002093840096BB08 :103E4000B09BFECF1D9AA8958150A9F79924939411 :103E5000A5E0AA2EF1E1BF2E9DD0813421F481E0AE -:103E6000AFD083E01FC0823411F484E103C08534F5 -:103E700019F485E0A5D083C0853579F48BD0E82E80 +:103E6000B3D083E01FC0823411F484E103C08534F1 +:103E700019F485E0A9D083C0853579F48BD0E82E7C :103E8000FF2488D0082F10E0102F00270E291F29AB -:103E9000000F111F8DD0680172C0863529F484E0AF -:103EA0008FD080E06FD06BC0843609F042C072D0F2 +:103E9000000F111F91D0680172C0863529F484E0AB +:103EA00093D080E06FD06BC0843609F042C072D0EE :103EB00071D0082F6FD080E0C81688E3D80620F4B0 :103EC00083E0F60187BFE895C0E0D1E063D0899335 :103ED0000C17E1F7F0E0CF16F8E3DF0620F083E0FF -:103EE000F60187BFE89564D007B600FCFDCFA601B8 +:103EE000F60187BFE89568D007B600FCFDCFA601B4 :103EF000A0E0B1E02C9130E011968C91119790E008 :103F0000982F8827822B932B1296FA010C0197BECB :103F1000E89511244E5F5F4FF1E0A038BF0751F7DD :103F2000F601A7BEE89507B600FCFDCFB7BEE89541 -:103F300026C08437B1F42ED02DD0F82E2BD038D017 +:103F300026C08437B1F42ED02DD0F82E2BD03CD013 :103F4000F601EF2C8F010F5F1F4F84911BD0EA9475 :103F5000F801C1F70894C11CD11CFA94CF0CD11CF4 -:103F60000EC0853739F424D08EE10CD084E90AD014 -:103F700086E098CF813511F488E014D019D080E123 +:103F60000EC0853739F428D08EE10CD084E90AD010 +:103F700086E098CF813511F488E018D01DD080E11B :103F800001D06ACF982F8091C00085FFFCCF90931D -:103F9000C6000895A8958091C00087FFFCCF80914E -:103FA000C6000895E0E6F0E098E1908380830895EC -:103FB000F1DF803219F088E0F5DFFFCF84E1E2CF56 -:103FC0001F93182FE7DF1150E9F7F2DF1F910895D3 -:0A3FD00080E0E8DFEE27FF270994E8 -:023FFE000204BB +:103F9000C60008958091C00087FFFCCF8091C000CB +:103FA00084FD01C0A8958091C6000895E0E6F0E088 +:103FB00098E1908380830895EDDF803219F088E0E6 +:103FC000F5DFFFCF84E1DECF1F93182FE3DF115021 +:103FD000E9F7F2DF1F91089580E0E8DFEE27FF2781 +:023FE000099442 +:023FFE000304BA :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.lst b/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.lst index 20d4db6fa..83146479e 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.lst @@ -3,27 +3,27 @@ optiboot_pro_20mhz.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .text 000001da 00003e00 00003e00 00000054 2**1 + 0 .text 000001e2 00003e00 00003e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .version 00000002 00003ffe 00003ffe 0000022e 2**0 + 1 .version 00000002 00003ffe 00003ffe 00000236 2**0 CONTENTS, READONLY - 2 .debug_aranges 00000028 00000000 00000000 00000230 2**0 + 2 .debug_aranges 00000028 00000000 00000000 00000238 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_pubnames 0000005f 00000000 00000000 00000258 2**0 + 3 .debug_pubnames 0000005f 00000000 00000000 00000260 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_info 0000028d 00000000 00000000 000002b7 2**0 + 4 .debug_info 0000028e 00000000 00000000 000002bf 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 0000018a 00000000 00000000 00000544 2**0 + 5 .debug_abbrev 00000171 00000000 00000000 0000054d 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_line 00000456 00000000 00000000 000006ce 2**0 + 6 .debug_line 0000045e 00000000 00000000 000006be 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000080 00000000 00000000 00000b24 2**2 + 7 .debug_frame 00000080 00000000 00000000 00000b1c 2**2 CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000149 00000000 00000000 00000ba4 2**0 + 8 .debug_str 00000149 00000000 00000000 00000b9c 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 0000027e 00000000 00000000 00000ced 2**0 + 9 .debug_loc 0000027e 00000000 00000000 00000ce5 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000060 00000000 00000000 00000f6b 2**0 + 10 .debug_ranges 00000060 00000000 00000000 00000f63 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: @@ -47,7 +47,7 @@ int main(void) { 3e04: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); 3e06: 81 ff sbrs r24, 1 - 3e08: e3 d0 rcall .+454 ; 0x3fd0 + 3e08: e7 d0 rcall .+462 ; 0x3fd8 #if LED_START_FLASHES > 0 // Set up Timer 1 for timeout counter @@ -77,7 +77,7 @@ int main(void) { // Set up watchdog to trigger after 500ms watchdogConfig(WATCHDOG_1S); 3e28: 8e e0 ldi r24, 0x0E ; 14 - 3e2a: bc d0 rcall .+376 ; 0x3fa4 + 3e2a: c0 d0 rcall .+384 ; 0x3fac /* Set LED pin as output */ LED_DDR |= _BV(LED); @@ -163,7 +163,7 @@ void watchdogReset() { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); 3e5e: 81 e0 ldi r24, 0x01 ; 1 - 3e60: af d0 rcall .+350 ; 0x3fc0 + 3e60: b3 d0 rcall .+358 ; 0x3fc8 putch(0x03); 3e62: 83 e0 ldi r24, 0x03 ; 3 3e64: 1f c0 rjmp .+62 ; 0x3ea4 @@ -182,7 +182,7 @@ void watchdogReset() { // SET DEVICE EXT is ignored getNch(5); 3e72: 85 e0 ldi r24, 0x05 ; 5 - 3e74: a5 d0 rcall .+330 ; 0x3fc0 + 3e74: a9 d0 rcall .+338 ; 0x3fc8 3e76: 83 c0 rjmp .+262 ; 0x3f7e } else if(ch == STK_LOAD_ADDRESS) { @@ -211,7 +211,7 @@ void watchdogReset() { 3e92: 11 1f adc r17, r17 address = newAddress; verifySpace(); - 3e94: 8d d0 rcall .+282 ; 0x3fb0 + 3e94: 91 d0 rcall .+290 ; 0x3fb8 3e96: 68 01 movw r12, r16 3e98: 72 c0 rjmp .+228 ; 0x3f7e } @@ -221,7 +221,7 @@ void watchdogReset() { // UNIVERSAL command is ignored getNch(4); 3e9e: 84 e0 ldi r24, 0x04 ; 4 - 3ea0: 8f d0 rcall .+286 ; 0x3fc0 + 3ea0: 93 d0 rcall .+294 ; 0x3fc8 putch(0x00); 3ea2: 80 e0 ldi r24, 0x00 ; 0 3ea4: 6f d0 rcall .+222 ; 0x3f84 @@ -282,7 +282,7 @@ void watchdogReset() { // Read command terminator, start reply verifySpace(); - 3ee6: 64 d0 rcall .+200 ; 0x3fb0 + 3ee6: 68 d0 rcall .+208 ; 0x3fb8 // If only a partial page is to be programmed, the erase might not be complete. // So check that here @@ -370,7 +370,7 @@ int main(void) { 3f3c: 2b d0 rcall .+86 ; 0x3f94 verifySpace(); - 3f3e: 38 d0 rcall .+112 ; 0x3fb0 + 3f3e: 3c d0 rcall .+120 ; 0x3fb8 3f40: f6 01 movw r30, r12 3f42: ef 2c mov r14, r15 putch(result); @@ -411,7 +411,7 @@ int main(void) { 3f64: 39 f4 brne .+14 ; 0x3f74 // READ SIGN - return what Avrdude wants to hear verifySpace(); - 3f66: 24 d0 rcall .+72 ; 0x3fb0 + 3f66: 28 d0 rcall .+80 ; 0x3fb8 putch(SIGNATURE_0); 3f68: 8e e1 ldi r24, 0x1E ; 30 3f6a: 0c d0 rcall .+24 ; 0x3f84 @@ -428,13 +428,13 @@ int main(void) { // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); 3f78: 88 e0 ldi r24, 0x08 ; 8 - 3f7a: 14 d0 rcall .+40 ; 0x3fa4 + 3f7a: 18 d0 rcall .+48 ; 0x3fac verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 3f7c: 19 d0 rcall .+50 ; 0x3fb0 + 3f7c: 1d d0 rcall .+58 ; 0x3fb8 } putch(STK_OK); 3f7e: 80 e1 ldi r24, 0x10 ; 16 @@ -463,99 +463,109 @@ void putch(char ch) { 3f92: 08 95 ret 00003f94 : + [uartBit] "I" (UART_RX_BIT) + : + "r25" +); +#else + while(!(UCSR0A & _BV(RXC0))) + 3f94: 80 91 c0 00 lds r24, 0x00C0 + 3f98: 87 ff sbrs r24, 7 + 3f9a: fc cf rjmp .-8 ; 0x3f94 + ; + if (!(UCSR0A & _BV(FE0))) { + 3f9c: 80 91 c0 00 lds r24, 0x00C0 + 3fa0: 84 fd sbrc r24, 4 + 3fa2: 01 c0 rjmp .+2 ; 0x3fa6 } #endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 3f94: a8 95 wdr - [uartBit] "I" (UART_RX_BIT) - : - "r25" -); -#else - while(!(UCSR0A & _BV(RXC0))); - 3f96: 80 91 c0 00 lds r24, 0x00C0 - 3f9a: 87 ff sbrs r24, 7 - 3f9c: fc cf rjmp .-8 ; 0x3f96 + 3fa4: a8 95 wdr + * don't care that an invalid char is returned...) + */ + watchdogReset(); + } + ch = UDR0; - 3f9e: 80 91 c6 00 lds r24, 0x00C6 + 3fa6: 80 91 c6 00 lds r24, 0x00C6 LED_PIN |= _BV(LED); #endif #endif return ch; } - 3fa2: 08 95 ret + 3faa: 08 95 ret -00003fa4 : +00003fac : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 3fa4: e0 e6 ldi r30, 0x60 ; 96 - 3fa6: f0 e0 ldi r31, 0x00 ; 0 - 3fa8: 98 e1 ldi r25, 0x18 ; 24 - 3faa: 90 83 st Z, r25 + 3fac: e0 e6 ldi r30, 0x60 ; 96 + 3fae: f0 e0 ldi r31, 0x00 ; 0 + 3fb0: 98 e1 ldi r25, 0x18 ; 24 + 3fb2: 90 83 st Z, r25 WDTCSR = x; - 3fac: 80 83 st Z, r24 + 3fb4: 80 83 st Z, r24 } - 3fae: 08 95 ret + 3fb6: 08 95 ret -00003fb0 : +00003fb8 : do getch(); while (--count); verifySpace(); } void verifySpace() { if (getch() != CRC_EOP) { - 3fb0: f1 df rcall .-30 ; 0x3f94 - 3fb2: 80 32 cpi r24, 0x20 ; 32 - 3fb4: 19 f0 breq .+6 ; 0x3fbc + 3fb8: ed df rcall .-38 ; 0x3f94 + 3fba: 80 32 cpi r24, 0x20 ; 32 + 3fbc: 19 f0 breq .+6 ; 0x3fc4 watchdogConfig(WATCHDOG_16MS); // shorten WD timeout - 3fb6: 88 e0 ldi r24, 0x08 ; 8 - 3fb8: f5 df rcall .-22 ; 0x3fa4 - 3fba: ff cf rjmp .-2 ; 0x3fba + 3fbe: 88 e0 ldi r24, 0x08 ; 8 + 3fc0: f5 df rcall .-22 ; 0x3fac + 3fc2: ff cf rjmp .-2 ; 0x3fc2 while (1) // and busy-loop so that WD causes ; // a reset and app start. } putch(STK_INSYNC); - 3fbc: 84 e1 ldi r24, 0x14 ; 20 + 3fc4: 84 e1 ldi r24, 0x14 ; 20 } - 3fbe: e2 cf rjmp .-60 ; 0x3f84 + 3fc6: de cf rjmp .-68 ; 0x3f84 -00003fc0 : +00003fc8 : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 3fc0: 1f 93 push r17 - 3fc2: 18 2f mov r17, r24 + 3fc8: 1f 93 push r17 + 3fca: 18 2f mov r17, r24 do getch(); while (--count); - 3fc4: e7 df rcall .-50 ; 0x3f94 - 3fc6: 11 50 subi r17, 0x01 ; 1 - 3fc8: e9 f7 brne .-6 ; 0x3fc4 + 3fcc: e3 df rcall .-58 ; 0x3f94 + 3fce: 11 50 subi r17, 0x01 ; 1 + 3fd0: e9 f7 brne .-6 ; 0x3fcc verifySpace(); - 3fca: f2 df rcall .-28 ; 0x3fb0 + 3fd2: f2 df rcall .-28 ; 0x3fb8 } - 3fcc: 1f 91 pop r17 - 3fce: 08 95 ret + 3fd4: 1f 91 pop r17 + 3fd6: 08 95 ret -00003fd0 : +00003fd8 : WDTCSR = _BV(WDCE) | _BV(WDE); WDTCSR = x; } void appStart() { watchdogConfig(WATCHDOG_OFF); - 3fd0: 80 e0 ldi r24, 0x00 ; 0 - 3fd2: e8 df rcall .-48 ; 0x3fa4 + 3fd8: 80 e0 ldi r24, 0x00 ; 0 + 3fda: e8 df rcall .-48 ; 0x3fac __asm__ __volatile__ ( - 3fd4: ee 27 eor r30, r30 - 3fd6: ff 27 eor r31, r31 - 3fd8: 09 94 ijmp + 3fdc: ee 27 eor r30, r30 + 3fde: ff 27 eor r31, r31 + 3fe0: 09 94 ijmp diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.hex b/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.hex index 00f7a3827..2c6339554 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.hex @@ -1,33 +1,34 @@ -:103E0000112484B714BE81FFE3D085E08093810044 +:103E0000112484B714BE81FFE7D085E08093810040 :103E100082E08093C00088E18093C10086E08093B7 -:103E2000C20088E08093C4008EE0BCD0259A86E072 +:103E2000C20088E08093C4008EE0C0D0259A86E06E :103E300028E13EEF91E0309385002093840096BB0B :103E4000B09BFECF1D9AA8958150A9F79924939411 :103E5000A5E0AA2EF1E1BF2E9DD0813421F481E0AE -:103E6000AFD083E01FC0823411F484E103C08534F5 -:103E700019F485E0A5D083C0853579F48BD0E82E80 +:103E6000B3D083E01FC0823411F484E103C08534F1 +:103E700019F485E0A9D083C0853579F48BD0E82E7C :103E8000FF2488D0082F10E0102F00270E291F29AB -:103E9000000F111F8DD0680172C0863529F484E0AF -:103EA0008FD080E06FD06BC0843609F042C072D0F2 +:103E9000000F111F91D0680172C0863529F484E0AB +:103EA00093D080E06FD06BC0843609F042C072D0EE :103EB00071D0082F6FD080E0C81688E3D80620F4B0 :103EC00083E0F60187BFE895C0E0D1E063D0899335 :103ED0000C17E1F7F0E0CF16F8E3DF0620F083E0FF -:103EE000F60187BFE89564D007B600FCFDCFA601B8 +:103EE000F60187BFE89568D007B600FCFDCFA601B4 :103EF000A0E0B1E02C9130E011968C91119790E008 :103F0000982F8827822B932B1296FA010C0197BECB :103F1000E89511244E5F5F4FF1E0A038BF0751F7DD :103F2000F601A7BEE89507B600FCFDCFB7BEE89541 -:103F300026C08437B1F42ED02DD0F82E2BD038D017 +:103F300026C08437B1F42ED02DD0F82E2BD03CD013 :103F4000F601EF2C8F010F5F1F4F84911BD0EA9475 :103F5000F801C1F70894C11CD11CFA94CF0CD11CF4 -:103F60000EC0853739F424D08EE10CD084E90AD014 -:103F700086E098CF813511F488E014D019D080E123 +:103F60000EC0853739F428D08EE10CD084E90AD010 +:103F700086E098CF813511F488E018D01DD080E11B :103F800001D06ACF982F8091C00085FFFCCF90931D -:103F9000C6000895A8958091C00087FFFCCF80914E -:103FA000C6000895E0E6F0E098E1908380830895EC -:103FB000F1DF803219F088E0F5DFFFCF84E1E2CF56 -:103FC0001F93182FE7DF1150E9F7F2DF1F910895D3 -:0A3FD00080E0E8DFEE27FF270994E8 -:023FFE000204BB +:103F9000C60008958091C00087FFFCCF8091C000CB +:103FA00084FD01C0A8958091C6000895E0E6F0E088 +:103FB00098E1908380830895EDDF803219F088E0E6 +:103FC000F5DFFFCF84E1DECF1F93182FE3DF115021 +:103FD000E9F7F2DF1F91089580E0E8DFEE27FF2781 +:023FE000099442 +:023FFE000304BA :0400000300003E00BB :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.lst b/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.lst index 6c117ca63..1fb903ca1 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.lst @@ -3,27 +3,27 @@ optiboot_pro_8MHz.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .text 000001da 00003e00 00003e00 00000054 2**1 + 0 .text 000001e2 00003e00 00003e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .version 00000002 00003ffe 00003ffe 0000022e 2**0 + 1 .version 00000002 00003ffe 00003ffe 00000236 2**0 CONTENTS, READONLY - 2 .debug_aranges 00000028 00000000 00000000 00000230 2**0 + 2 .debug_aranges 00000028 00000000 00000000 00000238 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_pubnames 0000005f 00000000 00000000 00000258 2**0 + 3 .debug_pubnames 0000005f 00000000 00000000 00000260 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_info 0000028d 00000000 00000000 000002b7 2**0 + 4 .debug_info 0000028e 00000000 00000000 000002bf 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 0000018a 00000000 00000000 00000544 2**0 + 5 .debug_abbrev 00000171 00000000 00000000 0000054d 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_line 00000456 00000000 00000000 000006ce 2**0 + 6 .debug_line 0000045e 00000000 00000000 000006be 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000080 00000000 00000000 00000b24 2**2 + 7 .debug_frame 00000080 00000000 00000000 00000b1c 2**2 CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000149 00000000 00000000 00000ba4 2**0 + 8 .debug_str 00000149 00000000 00000000 00000b9c 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 0000027e 00000000 00000000 00000ced 2**0 + 9 .debug_loc 0000027e 00000000 00000000 00000ce5 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000060 00000000 00000000 00000f6b 2**0 + 10 .debug_ranges 00000060 00000000 00000000 00000f63 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: @@ -47,7 +47,7 @@ int main(void) { 3e04: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); 3e06: 81 ff sbrs r24, 1 - 3e08: e3 d0 rcall .+454 ; 0x3fd0 + 3e08: e7 d0 rcall .+462 ; 0x3fd8 #if LED_START_FLASHES > 0 // Set up Timer 1 for timeout counter @@ -77,7 +77,7 @@ int main(void) { // Set up watchdog to trigger after 500ms watchdogConfig(WATCHDOG_1S); 3e28: 8e e0 ldi r24, 0x0E ; 14 - 3e2a: bc d0 rcall .+376 ; 0x3fa4 + 3e2a: c0 d0 rcall .+384 ; 0x3fac /* Set LED pin as output */ LED_DDR |= _BV(LED); @@ -163,7 +163,7 @@ void watchdogReset() { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); 3e5e: 81 e0 ldi r24, 0x01 ; 1 - 3e60: af d0 rcall .+350 ; 0x3fc0 + 3e60: b3 d0 rcall .+358 ; 0x3fc8 putch(0x03); 3e62: 83 e0 ldi r24, 0x03 ; 3 3e64: 1f c0 rjmp .+62 ; 0x3ea4 @@ -182,7 +182,7 @@ void watchdogReset() { // SET DEVICE EXT is ignored getNch(5); 3e72: 85 e0 ldi r24, 0x05 ; 5 - 3e74: a5 d0 rcall .+330 ; 0x3fc0 + 3e74: a9 d0 rcall .+338 ; 0x3fc8 3e76: 83 c0 rjmp .+262 ; 0x3f7e } else if(ch == STK_LOAD_ADDRESS) { @@ -211,7 +211,7 @@ void watchdogReset() { 3e92: 11 1f adc r17, r17 address = newAddress; verifySpace(); - 3e94: 8d d0 rcall .+282 ; 0x3fb0 + 3e94: 91 d0 rcall .+290 ; 0x3fb8 3e96: 68 01 movw r12, r16 3e98: 72 c0 rjmp .+228 ; 0x3f7e } @@ -221,7 +221,7 @@ void watchdogReset() { // UNIVERSAL command is ignored getNch(4); 3e9e: 84 e0 ldi r24, 0x04 ; 4 - 3ea0: 8f d0 rcall .+286 ; 0x3fc0 + 3ea0: 93 d0 rcall .+294 ; 0x3fc8 putch(0x00); 3ea2: 80 e0 ldi r24, 0x00 ; 0 3ea4: 6f d0 rcall .+222 ; 0x3f84 @@ -282,7 +282,7 @@ void watchdogReset() { // Read command terminator, start reply verifySpace(); - 3ee6: 64 d0 rcall .+200 ; 0x3fb0 + 3ee6: 68 d0 rcall .+208 ; 0x3fb8 // If only a partial page is to be programmed, the erase might not be complete. // So check that here @@ -370,7 +370,7 @@ int main(void) { 3f3c: 2b d0 rcall .+86 ; 0x3f94 verifySpace(); - 3f3e: 38 d0 rcall .+112 ; 0x3fb0 + 3f3e: 3c d0 rcall .+120 ; 0x3fb8 3f40: f6 01 movw r30, r12 3f42: ef 2c mov r14, r15 putch(result); @@ -411,7 +411,7 @@ int main(void) { 3f64: 39 f4 brne .+14 ; 0x3f74 // READ SIGN - return what Avrdude wants to hear verifySpace(); - 3f66: 24 d0 rcall .+72 ; 0x3fb0 + 3f66: 28 d0 rcall .+80 ; 0x3fb8 putch(SIGNATURE_0); 3f68: 8e e1 ldi r24, 0x1E ; 30 3f6a: 0c d0 rcall .+24 ; 0x3f84 @@ -428,13 +428,13 @@ int main(void) { // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); 3f78: 88 e0 ldi r24, 0x08 ; 8 - 3f7a: 14 d0 rcall .+40 ; 0x3fa4 + 3f7a: 18 d0 rcall .+48 ; 0x3fac verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 3f7c: 19 d0 rcall .+50 ; 0x3fb0 + 3f7c: 1d d0 rcall .+58 ; 0x3fb8 } putch(STK_OK); 3f7e: 80 e1 ldi r24, 0x10 ; 16 @@ -463,99 +463,109 @@ void putch(char ch) { 3f92: 08 95 ret 00003f94 : + [uartBit] "I" (UART_RX_BIT) + : + "r25" +); +#else + while(!(UCSR0A & _BV(RXC0))) + 3f94: 80 91 c0 00 lds r24, 0x00C0 + 3f98: 87 ff sbrs r24, 7 + 3f9a: fc cf rjmp .-8 ; 0x3f94 + ; + if (!(UCSR0A & _BV(FE0))) { + 3f9c: 80 91 c0 00 lds r24, 0x00C0 + 3fa0: 84 fd sbrc r24, 4 + 3fa2: 01 c0 rjmp .+2 ; 0x3fa6 } #endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 3f94: a8 95 wdr - [uartBit] "I" (UART_RX_BIT) - : - "r25" -); -#else - while(!(UCSR0A & _BV(RXC0))); - 3f96: 80 91 c0 00 lds r24, 0x00C0 - 3f9a: 87 ff sbrs r24, 7 - 3f9c: fc cf rjmp .-8 ; 0x3f96 + 3fa4: a8 95 wdr + * don't care that an invalid char is returned...) + */ + watchdogReset(); + } + ch = UDR0; - 3f9e: 80 91 c6 00 lds r24, 0x00C6 + 3fa6: 80 91 c6 00 lds r24, 0x00C6 LED_PIN |= _BV(LED); #endif #endif return ch; } - 3fa2: 08 95 ret + 3faa: 08 95 ret -00003fa4 : +00003fac : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 3fa4: e0 e6 ldi r30, 0x60 ; 96 - 3fa6: f0 e0 ldi r31, 0x00 ; 0 - 3fa8: 98 e1 ldi r25, 0x18 ; 24 - 3faa: 90 83 st Z, r25 + 3fac: e0 e6 ldi r30, 0x60 ; 96 + 3fae: f0 e0 ldi r31, 0x00 ; 0 + 3fb0: 98 e1 ldi r25, 0x18 ; 24 + 3fb2: 90 83 st Z, r25 WDTCSR = x; - 3fac: 80 83 st Z, r24 + 3fb4: 80 83 st Z, r24 } - 3fae: 08 95 ret + 3fb6: 08 95 ret -00003fb0 : +00003fb8 : do getch(); while (--count); verifySpace(); } void verifySpace() { if (getch() != CRC_EOP) { - 3fb0: f1 df rcall .-30 ; 0x3f94 - 3fb2: 80 32 cpi r24, 0x20 ; 32 - 3fb4: 19 f0 breq .+6 ; 0x3fbc + 3fb8: ed df rcall .-38 ; 0x3f94 + 3fba: 80 32 cpi r24, 0x20 ; 32 + 3fbc: 19 f0 breq .+6 ; 0x3fc4 watchdogConfig(WATCHDOG_16MS); // shorten WD timeout - 3fb6: 88 e0 ldi r24, 0x08 ; 8 - 3fb8: f5 df rcall .-22 ; 0x3fa4 - 3fba: ff cf rjmp .-2 ; 0x3fba + 3fbe: 88 e0 ldi r24, 0x08 ; 8 + 3fc0: f5 df rcall .-22 ; 0x3fac + 3fc2: ff cf rjmp .-2 ; 0x3fc2 while (1) // and busy-loop so that WD causes ; // a reset and app start. } putch(STK_INSYNC); - 3fbc: 84 e1 ldi r24, 0x14 ; 20 + 3fc4: 84 e1 ldi r24, 0x14 ; 20 } - 3fbe: e2 cf rjmp .-60 ; 0x3f84 + 3fc6: de cf rjmp .-68 ; 0x3f84 -00003fc0 : +00003fc8 : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 3fc0: 1f 93 push r17 - 3fc2: 18 2f mov r17, r24 + 3fc8: 1f 93 push r17 + 3fca: 18 2f mov r17, r24 do getch(); while (--count); - 3fc4: e7 df rcall .-50 ; 0x3f94 - 3fc6: 11 50 subi r17, 0x01 ; 1 - 3fc8: e9 f7 brne .-6 ; 0x3fc4 + 3fcc: e3 df rcall .-58 ; 0x3f94 + 3fce: 11 50 subi r17, 0x01 ; 1 + 3fd0: e9 f7 brne .-6 ; 0x3fcc verifySpace(); - 3fca: f2 df rcall .-28 ; 0x3fb0 + 3fd2: f2 df rcall .-28 ; 0x3fb8 } - 3fcc: 1f 91 pop r17 - 3fce: 08 95 ret + 3fd4: 1f 91 pop r17 + 3fd6: 08 95 ret -00003fd0 : +00003fd8 : WDTCSR = _BV(WDCE) | _BV(WDE); WDTCSR = x; } void appStart() { watchdogConfig(WATCHDOG_OFF); - 3fd0: 80 e0 ldi r24, 0x00 ; 0 - 3fd2: e8 df rcall .-48 ; 0x3fa4 + 3fd8: 80 e0 ldi r24, 0x00 ; 0 + 3fda: e8 df rcall .-48 ; 0x3fac __asm__ __volatile__ ( - 3fd4: ee 27 eor r30, r30 - 3fd6: ff 27 eor r31, r31 - 3fd8: 09 94 ijmp + 3fdc: ee 27 eor r30, r30 + 3fde: ff 27 eor r31, r31 + 3fe0: 09 94 ijmp diff --git a/hardware/arduino/bootloaders/optiboot/pin_defs.h b/hardware/arduino/bootloaders/optiboot/pin_defs.h index 313e45385..27d777244 100644 --- a/hardware/arduino/bootloaders/optiboot/pin_defs.h +++ b/hardware/arduino/bootloaders/optiboot/pin_defs.h @@ -21,6 +21,7 @@ #define UDR0 UDR #define UDRE0 UDRE #define RXC0 RXC + #define FE0 FE #define TIFR1 TIFR #define WDTCSR WDTCR #endif From 39a496616f241a3908d7821dcb15520f16ecd871 Mon Sep 17 00:00:00 2001 From: WestfW Date: Tue, 14 Jun 2011 01:13:41 -0700 Subject: [PATCH 29/33] Modify Uno "lock" bits in boards.txt to make bootloader readable by sketches. Part of http://code.google.com/p/arduino/issues/detail?id=554 --- hardware/arduino/boards.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hardware/arduino/boards.txt b/hardware/arduino/boards.txt index 0ae40d3b6..c252a758d 100644 --- a/hardware/arduino/boards.txt +++ b/hardware/arduino/boards.txt @@ -10,7 +10,7 @@ uno.bootloader.extended_fuses=0x05 uno.bootloader.path=optiboot uno.bootloader.file=optiboot_atmega328.hex uno.bootloader.unlock_bits=0x3F -uno.bootloader.lock_bits=0x0F +uno.bootloader.lock_bits=0x2F uno.build.mcu=atmega328p uno.build.f_cpu=16000000L uno.build.core=arduino From 7b1ee0f1b0192143fffbbed66dc046b6568f4386 Mon Sep 17 00:00:00 2001 From: WestfW Date: Tue, 14 Jun 2011 10:24:27 -0700 Subject: [PATCH 30/33] Allow the READ PARAMETER command to return our version number. (significant size impact: 14 bytes!) Initialized "address" to eliminate compiler warning (4 bytes!) Add "atmega168" as a more accurate target name than "diecimila" (keep diecimila as well for backward compatibility) Reduce the .hex and .lst targets that are stored in source control to the three basics: atmega8, atmega168, atmega328. The other targets remain in the makefile and makeall, but will need to be built from source if wanted. Which should be less of a problem now that the source is buildable without installing crosspack. --- .../arduino/bootloaders/optiboot/Makefile | 21 +- .../arduino/bootloaders/optiboot/README.TXT | 11 + hardware/arduino/bootloaders/optiboot/makeall | 11 +- .../arduino/bootloaders/optiboot/optiboot.c | 28 +- .../optiboot/optiboot_atmega328.hex | 61 +- .../optiboot/optiboot_atmega328.lst | 479 +++++++------- .../optiboot/optiboot_atmega328_pro_8MHz.hex | 34 - .../optiboot/optiboot_atmega328_pro_8MHz.lst | 571 ---------------- .../optiboot/optiboot_diecimila.hex | 34 - .../optiboot/optiboot_diecimila.lst | 571 ---------------- .../bootloaders/optiboot/optiboot_lilypad.hex | 34 - .../bootloaders/optiboot/optiboot_lilypad.lst | 571 ---------------- .../optiboot/optiboot_lilypad_resonator.hex | 34 - .../optiboot/optiboot_lilypad_resonator.lst | 571 ---------------- .../bootloaders/optiboot/optiboot_luminet.hex | 40 -- .../bootloaders/optiboot/optiboot_luminet.lst | 617 ------------------ .../optiboot/optiboot_pro_16MHz.hex | 34 - .../optiboot/optiboot_pro_16MHz.lst | 571 ---------------- .../optiboot/optiboot_pro_20mhz.hex | 34 - .../optiboot/optiboot_pro_20mhz.lst | 571 ---------------- .../optiboot/optiboot_pro_8MHz.hex | 34 - .../optiboot/optiboot_pro_8MHz.lst | 571 ---------------- 22 files changed, 346 insertions(+), 5157 deletions(-) delete mode 100644 hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.hex delete mode 100644 hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.lst delete mode 100644 hardware/arduino/bootloaders/optiboot/optiboot_diecimila.hex delete mode 100644 hardware/arduino/bootloaders/optiboot/optiboot_diecimila.lst delete mode 100644 hardware/arduino/bootloaders/optiboot/optiboot_lilypad.hex delete mode 100644 hardware/arduino/bootloaders/optiboot/optiboot_lilypad.lst delete mode 100644 hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.hex delete mode 100644 hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.lst delete mode 100644 hardware/arduino/bootloaders/optiboot/optiboot_luminet.hex delete mode 100644 hardware/arduino/bootloaders/optiboot/optiboot_luminet.lst delete mode 100644 hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.hex delete mode 100644 hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.lst delete mode 100644 hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.hex delete mode 100644 hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.lst delete mode 100644 hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.hex delete mode 100644 hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.lst diff --git a/hardware/arduino/bootloaders/optiboot/Makefile b/hardware/arduino/bootloaders/optiboot/Makefile index f6ba3747f..c2e03e3a6 100644 --- a/hardware/arduino/bootloaders/optiboot/Makefile +++ b/hardware/arduino/bootloaders/optiboot/Makefile @@ -177,8 +177,27 @@ pro16_isp: LFUSE = C6 pro16_isp: EFUSE = 04 pro16_isp: isp -# Diecimila and NG use identical bootloaders +# Diecimila, Duemilanove with m168, and NG use identical bootloaders +# Call it "atmega168" for generality and clarity, keep "diecimila" for +# backward compatibility of makefile # +atmega168: TARGET = atmega168 +atmega168: MCU_TARGET = atmega168 +atmega168: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' +atmega168: AVR_FREQ = 16000000L +atmega168: $(PROGRAM)_atmega168.hex +atmega168: $(PROGRAM)_atmega168.lst + +atmega168_isp: atmega168 +atmega168_isp: TARGET = atmega168 +# 2.7V brownout +atmega168_isp: HFUSE = DD +# Low power xtal (16MHz) 16KCK/14CK+65ms +atmega168_isp: LFUSE = FF +# 512 byte boot +atmega168_isp: EFUSE = 04 +atmega168_isp: isp + diecimila: TARGET = diecimila diecimila: MCU_TARGET = atmega168 diecimila: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' diff --git a/hardware/arduino/bootloaders/optiboot/README.TXT b/hardware/arduino/bootloaders/optiboot/README.TXT index 7e2f46df1..cd79cd953 100644 --- a/hardware/arduino/bootloaders/optiboot/README.TXT +++ b/hardware/arduino/bootloaders/optiboot/README.TXT @@ -68,3 +68,14 @@ variables when you invoke make: make ISPTOOL=stk500v1 ISPPORT=/dev/tty.usbserial-A20e1eAN \ ISPSPEED=-b19200 atmega328_isp + +The "atmega8_isp" target does not currently work, because the mega8 +doesn't have the "extended" fuse that the generic ISP target wants to +pass on to avrdude. You'll need to run avrdude manually. + + +Standard Targets + +I've reduced the pre-built and source-version-controlled targets +(.hex and .lst files included in the git repository) to just the +three basic 16MHz targets: atmega8, atmega16, atmega328. diff --git a/hardware/arduino/bootloaders/optiboot/makeall b/hardware/arduino/bootloaders/optiboot/makeall index b92c56e35..f076bc7f5 100755 --- a/hardware/arduino/bootloaders/optiboot/makeall +++ b/hardware/arduino/bootloaders/optiboot/makeall @@ -1,15 +1,20 @@ #!/bin/bash make clean +# +# The "big three" standard bootloaders. +make atmega8 +make atmega168 +make atmega328 +# +# additional buildable platforms of +# somewhat questionable support level make lilypad make lilypad_resonator make pro8 make pro16 make pro20 -make diecimila -make atmega328 make atmega328_pro8 make sanguino make mega -make atmega8 make atmega88 make luminet diff --git a/hardware/arduino/bootloaders/optiboot/optiboot.c b/hardware/arduino/bootloaders/optiboot/optiboot.c index 3f4404d0e..d499d85e8 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot.c +++ b/hardware/arduino/bootloaders/optiboot/optiboot.c @@ -132,6 +132,9 @@ /**********************************************************/ /* Edit History: */ /* */ +/* 4.4 WestfW: add initialization of address to keep */ +/* the compiler happy. Change SC'ed targets. */ +/* Return the SW version via READ PARAM */ /* 4.3 WestfW: catch framing errors in getch(), so that */ /* AVRISP works without HW kludges. */ /* http://code.google.com/p/arduino/issues/detail?id=368n*/ @@ -141,7 +144,7 @@ /**********************************************************/ #define OPTIBOOT_MAJVER 4 -#define OPTIBOOT_MINVER 3 +#define OPTIBOOT_MINVER 4 #define MAKESTR(a) #a #define MAKEVER(a, b) MAKESTR(a*256+b) @@ -261,8 +264,10 @@ int main(void) { /* * Making these local and in registers prevents the need for initializing * them, and also saves space because code no longer stores to memory. + * (initializing address keeps the compiler happy, but isn't really + * necessary, and uses 4 bytes of flash.) */ - register uint16_t address; + register uint16_t address = 0; register uint8_t length; // After the zero init loop, this is the first code to run. @@ -324,9 +329,22 @@ int main(void) { ch = getch(); if(ch == STK_GET_PARAMETER) { - // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy - getNch(1); - putch(0x03); + unsigned char which = getch(); + verifySpace(); + if (which == 0x82) { + /* + * Send optiboot version as "minor SW version" + */ + putch(OPTIBOOT_MINVER); + } else if (which == 0x81) { + putch(OPTIBOOT_MAJVER); + } else { + /* + * GET PARAMETER returns a generic 0x03 reply for + * other parameters - enough to keep Avrdude happy + */ + putch(0x03); + } } else if(ch == STK_SET_DEVICE) { // SET DEVICE is ignored diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.hex b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.hex index f147e816c..a219f0833 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.hex +++ b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.hex @@ -1,34 +1,35 @@ -:107E0000112484B714BE81FFE7D085E08093810000 +:107E0000112484B714BE81FFF0D085E080938100F7 :107E100082E08093C00088E18093C10086E0809377 -:107E2000C20080E18093C4008EE0C0D0259A86E035 +:107E2000C20080E18093C4008EE0C9D0259A86E02C :107E300020E33CEF91E0309385002093840096BBD3 -:107E4000B09BFECF1D9AA8958150A9F799249394D1 -:107E5000A5E0AA2EF1E1BF2E9DD0813421F481E06E -:107E6000B3D083E01FC0823411F484E103C08534B1 -:107E700019F485E0A9D083C0853579F48BD0E82E3C -:107E8000FF2488D0082F10E0102F00270E291F296B -:107E9000000F111F91D0680172C0863529F484E06B -:107EA00093D080E06FD06BC0843609F042C072D0AE -:107EB00071D0082F6FD080E0C81680E7D80620F474 -:107EC00083E0F60187BFE895C0E0D1E063D08993F5 -:107ED0000C17E1F7F0E0CF16F0E7DF0620F083E0C3 -:107EE000F60187BFE89568D007B600FCFDCFA60174 -:107EF000A0E0B1E02C9130E011968C91119790E0C8 -:107F0000982F8827822B932B1296FA010C0197BE8B -:107F1000E89511244E5F5F4FF1E0A038BF0751F79D -:107F2000F601A7BEE89507B600FCFDCFB7BEE89501 -:107F300026C08437B1F42ED02DD0F82E2BD03CD0D3 -:107F4000F601EF2C8F010F5F1F4F84911BD0EA9435 -:107F5000F801C1F70894C11CD11CFA94CF0CD11CB4 -:107F60000EC0853739F428D08EE10CD085E90AD0CF -:107F70008FE098CF813511F488E018D01DD080E1D2 -:107F800001D06ACF982F8091C00085FFFCCF9093DD -:107F9000C60008958091C00087FFFCCF8091C0008B -:107FA00084FD01C0A8958091C6000895E0E6F0E048 -:107FB00098E1908380830895EDDF803219F088E0A6 -:107FC000F5DFFFCF84E1DECF1F93182FE3DF1150E1 -:107FD000E9F7F2DF1F91089580E0E8DFEE27FF2741 -:027FE000099402 -:027FFE0003047A +:107E4000B09BFECF1D9AA8958150A9F7CC24DD24C4 +:107E500088248394B5E0AB2EA1E19A2EF3E0BF2EE7 +:107E6000A2D0813461F49FD0082FAFD0023811F036 +:107E7000013811F484E001C083E08DD089C08234E0 +:107E800011F484E103C0853419F485E0A6D080C0E4 +:107E9000853579F488D0E82EFF2485D0082F10E0AE +:107EA000102F00270E291F29000F111F8ED06801E7 +:107EB0006FC0863521F484E090D080E0DECF843638 +:107EC00009F040C070D06FD0082F6DD080E0C81688 +:107ED00080E7D80618F4F601B7BEE895C0E0D1E017 +:107EE00062D089930C17E1F7F0E0CF16F0E7DF06D8 +:107EF00018F0F601B7BEE89568D007B600FCFDCFD4 +:107F0000A601A0E0B1E02C9130E011968C91119780 +:107F100090E0982F8827822B932B1296FA010C0160 +:107F200087BEE89511244E5F5F4FF1E0A038BF0790 +:107F300051F7F601A7BEE89507B600FCFDCF97BE46 +:107F4000E89526C08437B1F42ED02DD0F82E2BD052 +:107F50003CD0F601EF2C8F010F5F1F4F84911BD097 +:107F6000EA94F801C1F70894C11CD11CFA94CF0C13 +:107F7000D11C0EC0853739F428D08EE10CD085E9AC +:107F80000AD08FE07ACF813511F488E018D01DD067 +:107F900080E101D065CF982F8091C00085FFFCCF94 +:107FA0009093C60008958091C00087FFFCCF809118 +:107FB000C00084FD01C0A8958091C6000895E0E648 +:107FC000F0E098E1908380830895EDDF803219F02E +:107FD00088E0F5DFFFCF84E1DECF1F93182FE3DFCA +:107FE0001150E9F7F2DF1F91089580E0E8DFEE27F6 +:047FF000FF270994CA +:027FFE00040479 :0400000300007E007B :00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.lst b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.lst index db4546250..d9dd4cc20 100644 --- a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.lst +++ b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328.lst @@ -3,27 +3,27 @@ optiboot_atmega328.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .text 000001e2 00007e00 00007e00 00000054 2**1 + 0 .text 000001f4 00007e00 00007e00 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .version 00000002 00007ffe 00007ffe 00000236 2**0 + 1 .version 00000002 00007ffe 00007ffe 00000248 2**0 CONTENTS, READONLY - 2 .debug_aranges 00000028 00000000 00000000 00000238 2**0 + 2 .debug_aranges 00000028 00000000 00000000 0000024a 2**0 CONTENTS, READONLY, DEBUGGING - 3 .debug_pubnames 0000005f 00000000 00000000 00000260 2**0 + 3 .debug_pubnames 0000005f 00000000 00000000 00000272 2**0 CONTENTS, READONLY, DEBUGGING - 4 .debug_info 0000028e 00000000 00000000 000002bf 2**0 + 4 .debug_info 000002a8 00000000 00000000 000002d1 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 00000171 00000000 00000000 0000054d 2**0 + 5 .debug_abbrev 00000178 00000000 00000000 00000579 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_line 0000045e 00000000 00000000 000006be 2**0 + 6 .debug_line 00000488 00000000 00000000 000006f1 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000080 00000000 00000000 00000b1c 2**2 + 7 .debug_frame 00000080 00000000 00000000 00000b7c 2**2 CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000149 00000000 00000000 00000b9c 2**0 + 8 .debug_str 0000014f 00000000 00000000 00000bfc 2**0 CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 0000027e 00000000 00000000 00000ce5 2**0 + 9 .debug_loc 000002d8 00000000 00000000 00000d4b 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000060 00000000 00000000 00000f63 2**0 + 10 .debug_ranges 00000078 00000000 00000000 00001023 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: @@ -47,7 +47,7 @@ int main(void) { 7e04: 14 be out 0x34, r1 ; 52 if (!(ch & _BV(EXTRF))) appStart(); 7e06: 81 ff sbrs r24, 1 - 7e08: e7 d0 rcall .+462 ; 0x7fd8 + 7e08: f0 d0 rcall .+480 ; 0x7fea #if LED_START_FLASHES > 0 // Set up Timer 1 for timeout counter @@ -77,7 +77,7 @@ int main(void) { // Set up watchdog to trigger after 500ms watchdogConfig(WATCHDOG_1S); 7e28: 8e e0 ldi r24, 0x0E ; 14 - 7e2a: c0 d0 rcall .+384 ; 0x7fac + 7e2a: c9 d0 rcall .+402 ; 0x7fbe /* Set LED pin as output */ LED_DDR |= _BV(LED); @@ -126,446 +126,473 @@ void watchdogReset() { } while (--count); 7e48: 81 50 subi r24, 0x01 ; 1 7e4a: a9 f7 brne .-22 ; 0x7e36 - /* get character from UART */ - ch = getch(); - - if(ch == STK_GET_PARAMETER) { - // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy - getNch(1); - 7e4c: 99 24 eor r9, r9 - 7e4e: 93 94 inc r9 + 7e4c: cc 24 eor r12, r12 + 7e4e: dd 24 eor r13, r13 + ch = SPM_PAGESIZE / 2; + do { + uint16_t a; + a = *bufPtr++; + a |= (*bufPtr++) << 8; __boot_page_fill_short((uint16_t)(void*)addrPtr,a); + 7e50: 88 24 eor r8, r8 + 7e52: 83 94 inc r8 addrPtr += 2; } while (--ch); // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); - 7e50: a5 e0 ldi r26, 0x05 ; 5 - 7e52: aa 2e mov r10, r26 + 7e54: b5 e0 ldi r27, 0x05 ; 5 + 7e56: ab 2e mov r10, r27 boot_spm_busy_wait(); #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 7e54: f1 e1 ldi r31, 0x11 ; 17 - 7e56: bf 2e mov r11, r31 + 7e58: a1 e1 ldi r26, 0x11 ; 17 + 7e5a: 9a 2e mov r9, r26 + do *bufPtr++ = getch(); + while (--length); + + // If we are in NRWW section, page erase has to be delayed until now. + // Todo: Take RAMPZ into account + if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + 7e5c: f3 e0 ldi r31, 0x03 ; 3 + 7e5e: bf 2e mov r11, r31 #endif /* Forever loop */ for (;;) { /* get character from UART */ ch = getch(); - 7e58: 9d d0 rcall .+314 ; 0x7f94 + 7e60: a2 d0 rcall .+324 ; 0x7fa6 if(ch == STK_GET_PARAMETER) { - 7e5a: 81 34 cpi r24, 0x41 ; 65 - 7e5c: 21 f4 brne .+8 ; 0x7e66 - // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy - getNch(1); - 7e5e: 81 e0 ldi r24, 0x01 ; 1 - 7e60: b3 d0 rcall .+358 ; 0x7fc8 - putch(0x03); - 7e62: 83 e0 ldi r24, 0x03 ; 3 - 7e64: 1f c0 rjmp .+62 ; 0x7ea4 + 7e62: 81 34 cpi r24, 0x41 ; 65 + 7e64: 61 f4 brne .+24 ; 0x7e7e + unsigned char which = getch(); + 7e66: 9f d0 rcall .+318 ; 0x7fa6 + 7e68: 08 2f mov r16, r24 + verifySpace(); + 7e6a: af d0 rcall .+350 ; 0x7fca + if (which == 0x82) { + 7e6c: 02 38 cpi r16, 0x82 ; 130 + 7e6e: 11 f0 breq .+4 ; 0x7e74 + /* + * Send optiboot version as "minor SW version" + */ + putch(OPTIBOOT_MINVER); + } else if (which == 0x81) { + 7e70: 01 38 cpi r16, 0x81 ; 129 + 7e72: 11 f4 brne .+4 ; 0x7e78 + putch(OPTIBOOT_MAJVER); + 7e74: 84 e0 ldi r24, 0x04 ; 4 + 7e76: 01 c0 rjmp .+2 ; 0x7e7a + } else { + /* + * GET PARAMETER returns a generic 0x03 reply for + * other parameters - enough to keep Avrdude happy + */ + putch(0x03); + 7e78: 83 e0 ldi r24, 0x03 ; 3 + 7e7a: 8d d0 rcall .+282 ; 0x7f96 + 7e7c: 89 c0 rjmp .+274 ; 0x7f90 + } } else if(ch == STK_SET_DEVICE) { - 7e66: 82 34 cpi r24, 0x42 ; 66 - 7e68: 11 f4 brne .+4 ; 0x7e6e + 7e7e: 82 34 cpi r24, 0x42 ; 66 + 7e80: 11 f4 brne .+4 ; 0x7e86 // SET DEVICE is ignored getNch(20); - 7e6a: 84 e1 ldi r24, 0x14 ; 20 - 7e6c: 03 c0 rjmp .+6 ; 0x7e74 + 7e82: 84 e1 ldi r24, 0x14 ; 20 + 7e84: 03 c0 rjmp .+6 ; 0x7e8c } else if(ch == STK_SET_DEVICE_EXT) { - 7e6e: 85 34 cpi r24, 0x45 ; 69 - 7e70: 19 f4 brne .+6 ; 0x7e78 + 7e86: 85 34 cpi r24, 0x45 ; 69 + 7e88: 19 f4 brne .+6 ; 0x7e90 // SET DEVICE EXT is ignored getNch(5); - 7e72: 85 e0 ldi r24, 0x05 ; 5 - 7e74: a9 d0 rcall .+338 ; 0x7fc8 - 7e76: 83 c0 rjmp .+262 ; 0x7f7e + 7e8a: 85 e0 ldi r24, 0x05 ; 5 + 7e8c: a6 d0 rcall .+332 ; 0x7fda + 7e8e: 80 c0 rjmp .+256 ; 0x7f90 } else if(ch == STK_LOAD_ADDRESS) { - 7e78: 85 35 cpi r24, 0x55 ; 85 - 7e7a: 79 f4 brne .+30 ; 0x7e9a + 7e90: 85 35 cpi r24, 0x55 ; 85 + 7e92: 79 f4 brne .+30 ; 0x7eb2 // LOAD ADDRESS uint16_t newAddress; newAddress = getch(); - 7e7c: 8b d0 rcall .+278 ; 0x7f94 + 7e94: 88 d0 rcall .+272 ; 0x7fa6 newAddress = (newAddress & 0xff) | (getch() << 8); - 7e7e: e8 2e mov r14, r24 - 7e80: ff 24 eor r15, r15 - 7e82: 88 d0 rcall .+272 ; 0x7f94 - 7e84: 08 2f mov r16, r24 - 7e86: 10 e0 ldi r17, 0x00 ; 0 - 7e88: 10 2f mov r17, r16 - 7e8a: 00 27 eor r16, r16 - 7e8c: 0e 29 or r16, r14 - 7e8e: 1f 29 or r17, r15 + 7e96: e8 2e mov r14, r24 + 7e98: ff 24 eor r15, r15 + 7e9a: 85 d0 rcall .+266 ; 0x7fa6 + 7e9c: 08 2f mov r16, r24 + 7e9e: 10 e0 ldi r17, 0x00 ; 0 + 7ea0: 10 2f mov r17, r16 + 7ea2: 00 27 eor r16, r16 + 7ea4: 0e 29 or r16, r14 + 7ea6: 1f 29 or r17, r15 #ifdef RAMPZ // Transfer top bit to RAMPZ RAMPZ = (newAddress & 0x8000) ? 1 : 0; #endif newAddress += newAddress; // Convert from word address to byte address - 7e90: 00 0f add r16, r16 - 7e92: 11 1f adc r17, r17 + 7ea8: 00 0f add r16, r16 + 7eaa: 11 1f adc r17, r17 address = newAddress; verifySpace(); - 7e94: 91 d0 rcall .+290 ; 0x7fb8 - 7e96: 68 01 movw r12, r16 - 7e98: 72 c0 rjmp .+228 ; 0x7f7e + 7eac: 8e d0 rcall .+284 ; 0x7fca + 7eae: 68 01 movw r12, r16 + 7eb0: 6f c0 rjmp .+222 ; 0x7f90 } else if(ch == STK_UNIVERSAL) { - 7e9a: 86 35 cpi r24, 0x56 ; 86 - 7e9c: 29 f4 brne .+10 ; 0x7ea8 + 7eb2: 86 35 cpi r24, 0x56 ; 86 + 7eb4: 21 f4 brne .+8 ; 0x7ebe // UNIVERSAL command is ignored getNch(4); - 7e9e: 84 e0 ldi r24, 0x04 ; 4 - 7ea0: 93 d0 rcall .+294 ; 0x7fc8 + 7eb6: 84 e0 ldi r24, 0x04 ; 4 + 7eb8: 90 d0 rcall .+288 ; 0x7fda putch(0x00); - 7ea2: 80 e0 ldi r24, 0x00 ; 0 - 7ea4: 6f d0 rcall .+222 ; 0x7f84 - 7ea6: 6b c0 rjmp .+214 ; 0x7f7e + 7eba: 80 e0 ldi r24, 0x00 ; 0 + 7ebc: de cf rjmp .-68 ; 0x7e7a } /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { - 7ea8: 84 36 cpi r24, 0x64 ; 100 - 7eaa: 09 f0 breq .+2 ; 0x7eae - 7eac: 42 c0 rjmp .+132 ; 0x7f32 + 7ebe: 84 36 cpi r24, 0x64 ; 100 + 7ec0: 09 f0 breq .+2 ; 0x7ec4 + 7ec2: 40 c0 rjmp .+128 ; 0x7f44 // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t *bufPtr; uint16_t addrPtr; getch(); /* getlen() */ - 7eae: 72 d0 rcall .+228 ; 0x7f94 + 7ec4: 70 d0 rcall .+224 ; 0x7fa6 length = getch(); - 7eb0: 71 d0 rcall .+226 ; 0x7f94 - 7eb2: 08 2f mov r16, r24 + 7ec6: 6f d0 rcall .+222 ; 0x7fa6 + 7ec8: 08 2f mov r16, r24 getch(); - 7eb4: 6f d0 rcall .+222 ; 0x7f94 + 7eca: 6d d0 rcall .+218 ; 0x7fa6 // If we are in RWW section, immediately start page erase if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 7eb6: 80 e0 ldi r24, 0x00 ; 0 - 7eb8: c8 16 cp r12, r24 - 7eba: 80 e7 ldi r24, 0x70 ; 112 - 7ebc: d8 06 cpc r13, r24 - 7ebe: 20 f4 brcc .+8 ; 0x7ec8 - 7ec0: 83 e0 ldi r24, 0x03 ; 3 - 7ec2: f6 01 movw r30, r12 - 7ec4: 87 bf out 0x37, r24 ; 55 - 7ec6: e8 95 spm - 7ec8: c0 e0 ldi r28, 0x00 ; 0 - 7eca: d1 e0 ldi r29, 0x01 ; 1 + 7ecc: 80 e0 ldi r24, 0x00 ; 0 + 7ece: c8 16 cp r12, r24 + 7ed0: 80 e7 ldi r24, 0x70 ; 112 + 7ed2: d8 06 cpc r13, r24 + 7ed4: 18 f4 brcc .+6 ; 0x7edc + 7ed6: f6 01 movw r30, r12 + 7ed8: b7 be out 0x37, r11 ; 55 + 7eda: e8 95 spm + 7edc: c0 e0 ldi r28, 0x00 ; 0 + 7ede: d1 e0 ldi r29, 0x01 ; 1 // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); - 7ecc: 63 d0 rcall .+198 ; 0x7f94 - 7ece: 89 93 st Y+, r24 + 7ee0: 62 d0 rcall .+196 ; 0x7fa6 + 7ee2: 89 93 st Y+, r24 while (--length); - 7ed0: 0c 17 cp r16, r28 - 7ed2: e1 f7 brne .-8 ; 0x7ecc + 7ee4: 0c 17 cp r16, r28 + 7ee6: e1 f7 brne .-8 ; 0x7ee0 // If we are in NRWW section, page erase has to be delayed until now. // Todo: Take RAMPZ into account if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 7ed4: f0 e0 ldi r31, 0x00 ; 0 - 7ed6: cf 16 cp r12, r31 - 7ed8: f0 e7 ldi r31, 0x70 ; 112 - 7eda: df 06 cpc r13, r31 - 7edc: 20 f0 brcs .+8 ; 0x7ee6 - 7ede: 83 e0 ldi r24, 0x03 ; 3 - 7ee0: f6 01 movw r30, r12 - 7ee2: 87 bf out 0x37, r24 ; 55 - 7ee4: e8 95 spm + 7ee8: f0 e0 ldi r31, 0x00 ; 0 + 7eea: cf 16 cp r12, r31 + 7eec: f0 e7 ldi r31, 0x70 ; 112 + 7eee: df 06 cpc r13, r31 + 7ef0: 18 f0 brcs .+6 ; 0x7ef8 + 7ef2: f6 01 movw r30, r12 + 7ef4: b7 be out 0x37, r11 ; 55 + 7ef6: e8 95 spm // Read command terminator, start reply verifySpace(); - 7ee6: 68 d0 rcall .+208 ; 0x7fb8 + 7ef8: 68 d0 rcall .+208 ; 0x7fca // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); - 7ee8: 07 b6 in r0, 0x37 ; 55 - 7eea: 00 fc sbrc r0, 0 - 7eec: fd cf rjmp .-6 ; 0x7ee8 - 7eee: a6 01 movw r20, r12 - 7ef0: a0 e0 ldi r26, 0x00 ; 0 - 7ef2: b1 e0 ldi r27, 0x01 ; 1 + 7efa: 07 b6 in r0, 0x37 ; 55 + 7efc: 00 fc sbrc r0, 0 + 7efe: fd cf rjmp .-6 ; 0x7efa + 7f00: a6 01 movw r20, r12 + 7f02: a0 e0 ldi r26, 0x00 ; 0 + 7f04: b1 e0 ldi r27, 0x01 ; 1 bufPtr = buff; addrPtr = (uint16_t)(void*)address; ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; - 7ef4: 2c 91 ld r18, X - 7ef6: 30 e0 ldi r19, 0x00 ; 0 + 7f06: 2c 91 ld r18, X + 7f08: 30 e0 ldi r19, 0x00 ; 0 a |= (*bufPtr++) << 8; - 7ef8: 11 96 adiw r26, 0x01 ; 1 - 7efa: 8c 91 ld r24, X - 7efc: 11 97 sbiw r26, 0x01 ; 1 - 7efe: 90 e0 ldi r25, 0x00 ; 0 - 7f00: 98 2f mov r25, r24 - 7f02: 88 27 eor r24, r24 - 7f04: 82 2b or r24, r18 - 7f06: 93 2b or r25, r19 + 7f0a: 11 96 adiw r26, 0x01 ; 1 + 7f0c: 8c 91 ld r24, X + 7f0e: 11 97 sbiw r26, 0x01 ; 1 + 7f10: 90 e0 ldi r25, 0x00 ; 0 + 7f12: 98 2f mov r25, r24 + 7f14: 88 27 eor r24, r24 + 7f16: 82 2b or r24, r18 + 7f18: 93 2b or r25, r19 #define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) #define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif /* main program starts here */ int main(void) { - 7f08: 12 96 adiw r26, 0x02 ; 2 + 7f1a: 12 96 adiw r26, 0x02 ; 2 ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; a |= (*bufPtr++) << 8; __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - 7f0a: fa 01 movw r30, r20 - 7f0c: 0c 01 movw r0, r24 - 7f0e: 97 be out 0x37, r9 ; 55 - 7f10: e8 95 spm - 7f12: 11 24 eor r1, r1 + 7f1c: fa 01 movw r30, r20 + 7f1e: 0c 01 movw r0, r24 + 7f20: 87 be out 0x37, r8 ; 55 + 7f22: e8 95 spm + 7f24: 11 24 eor r1, r1 addrPtr += 2; - 7f14: 4e 5f subi r20, 0xFE ; 254 - 7f16: 5f 4f sbci r21, 0xFF ; 255 + 7f26: 4e 5f subi r20, 0xFE ; 254 + 7f28: 5f 4f sbci r21, 0xFF ; 255 } while (--ch); - 7f18: f1 e0 ldi r31, 0x01 ; 1 - 7f1a: a0 38 cpi r26, 0x80 ; 128 - 7f1c: bf 07 cpc r27, r31 - 7f1e: 51 f7 brne .-44 ; 0x7ef4 + 7f2a: f1 e0 ldi r31, 0x01 ; 1 + 7f2c: a0 38 cpi r26, 0x80 ; 128 + 7f2e: bf 07 cpc r27, r31 + 7f30: 51 f7 brne .-44 ; 0x7f06 // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); - 7f20: f6 01 movw r30, r12 - 7f22: a7 be out 0x37, r10 ; 55 - 7f24: e8 95 spm + 7f32: f6 01 movw r30, r12 + 7f34: a7 be out 0x37, r10 ; 55 + 7f36: e8 95 spm boot_spm_busy_wait(); - 7f26: 07 b6 in r0, 0x37 ; 55 - 7f28: 00 fc sbrc r0, 0 - 7f2a: fd cf rjmp .-6 ; 0x7f26 + 7f38: 07 b6 in r0, 0x37 ; 55 + 7f3a: 00 fc sbrc r0, 0 + 7f3c: fd cf rjmp .-6 ; 0x7f38 #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); - 7f2c: b7 be out 0x37, r11 ; 55 - 7f2e: e8 95 spm - 7f30: 26 c0 rjmp .+76 ; 0x7f7e + 7f3e: 97 be out 0x37, r9 ; 55 + 7f40: e8 95 spm + 7f42: 26 c0 rjmp .+76 ; 0x7f90 #endif } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { - 7f32: 84 37 cpi r24, 0x74 ; 116 - 7f34: b1 f4 brne .+44 ; 0x7f62 + 7f44: 84 37 cpi r24, 0x74 ; 116 + 7f46: b1 f4 brne .+44 ; 0x7f74 // READ PAGE - we only read flash getch(); /* getlen() */ - 7f36: 2e d0 rcall .+92 ; 0x7f94 + 7f48: 2e d0 rcall .+92 ; 0x7fa6 length = getch(); - 7f38: 2d d0 rcall .+90 ; 0x7f94 - 7f3a: f8 2e mov r15, r24 + 7f4a: 2d d0 rcall .+90 ; 0x7fa6 + 7f4c: f8 2e mov r15, r24 getch(); - 7f3c: 2b d0 rcall .+86 ; 0x7f94 + 7f4e: 2b d0 rcall .+86 ; 0x7fa6 verifySpace(); - 7f3e: 3c d0 rcall .+120 ; 0x7fb8 - 7f40: f6 01 movw r30, r12 - 7f42: ef 2c mov r14, r15 + 7f50: 3c d0 rcall .+120 ; 0x7fca + 7f52: f6 01 movw r30, r12 + 7f54: ef 2c mov r14, r15 putch(result); address++; } while (--length); #else do putch(pgm_read_byte_near(address++)); - 7f44: 8f 01 movw r16, r30 - 7f46: 0f 5f subi r16, 0xFF ; 255 - 7f48: 1f 4f sbci r17, 0xFF ; 255 - 7f4a: 84 91 lpm r24, Z+ - 7f4c: 1b d0 rcall .+54 ; 0x7f84 + 7f56: 8f 01 movw r16, r30 + 7f58: 0f 5f subi r16, 0xFF ; 255 + 7f5a: 1f 4f sbci r17, 0xFF ; 255 + 7f5c: 84 91 lpm r24, Z+ + 7f5e: 1b d0 rcall .+54 ; 0x7f96 while (--length); - 7f4e: ea 94 dec r14 - 7f50: f8 01 movw r30, r16 - 7f52: c1 f7 brne .-16 ; 0x7f44 + 7f60: ea 94 dec r14 + 7f62: f8 01 movw r30, r16 + 7f64: c1 f7 brne .-16 ; 0x7f56 #define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) #define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #endif /* main program starts here */ int main(void) { - 7f54: 08 94 sec - 7f56: c1 1c adc r12, r1 - 7f58: d1 1c adc r13, r1 - 7f5a: fa 94 dec r15 - 7f5c: cf 0c add r12, r15 - 7f5e: d1 1c adc r13, r1 - 7f60: 0e c0 rjmp .+28 ; 0x7f7e + 7f66: 08 94 sec + 7f68: c1 1c adc r12, r1 + 7f6a: d1 1c adc r13, r1 + 7f6c: fa 94 dec r15 + 7f6e: cf 0c add r12, r15 + 7f70: d1 1c adc r13, r1 + 7f72: 0e c0 rjmp .+28 ; 0x7f90 #endif #endif } /* Get device signature bytes */ else if(ch == STK_READ_SIGN) { - 7f62: 85 37 cpi r24, 0x75 ; 117 - 7f64: 39 f4 brne .+14 ; 0x7f74 + 7f74: 85 37 cpi r24, 0x75 ; 117 + 7f76: 39 f4 brne .+14 ; 0x7f86 // READ SIGN - return what Avrdude wants to hear verifySpace(); - 7f66: 28 d0 rcall .+80 ; 0x7fb8 + 7f78: 28 d0 rcall .+80 ; 0x7fca putch(SIGNATURE_0); - 7f68: 8e e1 ldi r24, 0x1E ; 30 - 7f6a: 0c d0 rcall .+24 ; 0x7f84 + 7f7a: 8e e1 ldi r24, 0x1E ; 30 + 7f7c: 0c d0 rcall .+24 ; 0x7f96 putch(SIGNATURE_1); - 7f6c: 85 e9 ldi r24, 0x95 ; 149 - 7f6e: 0a d0 rcall .+20 ; 0x7f84 + 7f7e: 85 e9 ldi r24, 0x95 ; 149 + 7f80: 0a d0 rcall .+20 ; 0x7f96 putch(SIGNATURE_2); - 7f70: 8f e0 ldi r24, 0x0F ; 15 - 7f72: 98 cf rjmp .-208 ; 0x7ea4 + 7f82: 8f e0 ldi r24, 0x0F ; 15 + 7f84: 7a cf rjmp .-268 ; 0x7e7a } else if (ch == 'Q') { - 7f74: 81 35 cpi r24, 0x51 ; 81 - 7f76: 11 f4 brne .+4 ; 0x7f7c + 7f86: 81 35 cpi r24, 0x51 ; 81 + 7f88: 11 f4 brne .+4 ; 0x7f8e // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); - 7f78: 88 e0 ldi r24, 0x08 ; 8 - 7f7a: 18 d0 rcall .+48 ; 0x7fac + 7f8a: 88 e0 ldi r24, 0x08 ; 8 + 7f8c: 18 d0 rcall .+48 ; 0x7fbe verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 7f7c: 1d d0 rcall .+58 ; 0x7fb8 + 7f8e: 1d d0 rcall .+58 ; 0x7fca } putch(STK_OK); - 7f7e: 80 e1 ldi r24, 0x10 ; 16 - 7f80: 01 d0 rcall .+2 ; 0x7f84 - 7f82: 6a cf rjmp .-300 ; 0x7e58 + 7f90: 80 e1 ldi r24, 0x10 ; 16 + 7f92: 01 d0 rcall .+2 ; 0x7f96 + 7f94: 65 cf rjmp .-310 ; 0x7e60 -00007f84 : +00007f96 : } } void putch(char ch) { - 7f84: 98 2f mov r25, r24 + 7f96: 98 2f mov r25, r24 #ifndef SOFT_UART while (!(UCSR0A & _BV(UDRE0))); - 7f86: 80 91 c0 00 lds r24, 0x00C0 - 7f8a: 85 ff sbrs r24, 5 - 7f8c: fc cf rjmp .-8 ; 0x7f86 + 7f98: 80 91 c0 00 lds r24, 0x00C0 + 7f9c: 85 ff sbrs r24, 5 + 7f9e: fc cf rjmp .-8 ; 0x7f98 UDR0 = ch; - 7f8e: 90 93 c6 00 sts 0x00C6, r25 + 7fa0: 90 93 c6 00 sts 0x00C6, r25 [uartBit] "I" (UART_TX_BIT) : "r25" ); #endif } - 7f92: 08 95 ret + 7fa4: 08 95 ret -00007f94 : +00007fa6 : [uartBit] "I" (UART_RX_BIT) : "r25" ); #else while(!(UCSR0A & _BV(RXC0))) - 7f94: 80 91 c0 00 lds r24, 0x00C0 - 7f98: 87 ff sbrs r24, 7 - 7f9a: fc cf rjmp .-8 ; 0x7f94 + 7fa6: 80 91 c0 00 lds r24, 0x00C0 + 7faa: 87 ff sbrs r24, 7 + 7fac: fc cf rjmp .-8 ; 0x7fa6 ; if (!(UCSR0A & _BV(FE0))) { - 7f9c: 80 91 c0 00 lds r24, 0x00C0 - 7fa0: 84 fd sbrc r24, 4 - 7fa2: 01 c0 rjmp .+2 ; 0x7fa6 + 7fae: 80 91 c0 00 lds r24, 0x00C0 + 7fb2: 84 fd sbrc r24, 4 + 7fb4: 01 c0 rjmp .+2 ; 0x7fb8 } #endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 7fa4: a8 95 wdr + 7fb6: a8 95 wdr * don't care that an invalid char is returned...) */ watchdogReset(); } ch = UDR0; - 7fa6: 80 91 c6 00 lds r24, 0x00C6 + 7fb8: 80 91 c6 00 lds r24, 0x00C6 LED_PIN |= _BV(LED); #endif #endif return ch; } - 7faa: 08 95 ret + 7fbc: 08 95 ret -00007fac : +00007fbe : "wdr\n" ); } void watchdogConfig(uint8_t x) { WDTCSR = _BV(WDCE) | _BV(WDE); - 7fac: e0 e6 ldi r30, 0x60 ; 96 - 7fae: f0 e0 ldi r31, 0x00 ; 0 - 7fb0: 98 e1 ldi r25, 0x18 ; 24 - 7fb2: 90 83 st Z, r25 + 7fbe: e0 e6 ldi r30, 0x60 ; 96 + 7fc0: f0 e0 ldi r31, 0x00 ; 0 + 7fc2: 98 e1 ldi r25, 0x18 ; 24 + 7fc4: 90 83 st Z, r25 WDTCSR = x; - 7fb4: 80 83 st Z, r24 + 7fc6: 80 83 st Z, r24 } - 7fb6: 08 95 ret + 7fc8: 08 95 ret -00007fb8 : +00007fca : do getch(); while (--count); verifySpace(); } void verifySpace() { if (getch() != CRC_EOP) { - 7fb8: ed df rcall .-38 ; 0x7f94 - 7fba: 80 32 cpi r24, 0x20 ; 32 - 7fbc: 19 f0 breq .+6 ; 0x7fc4 + 7fca: ed df rcall .-38 ; 0x7fa6 + 7fcc: 80 32 cpi r24, 0x20 ; 32 + 7fce: 19 f0 breq .+6 ; 0x7fd6 watchdogConfig(WATCHDOG_16MS); // shorten WD timeout - 7fbe: 88 e0 ldi r24, 0x08 ; 8 - 7fc0: f5 df rcall .-22 ; 0x7fac - 7fc2: ff cf rjmp .-2 ; 0x7fc2 + 7fd0: 88 e0 ldi r24, 0x08 ; 8 + 7fd2: f5 df rcall .-22 ; 0x7fbe + 7fd4: ff cf rjmp .-2 ; 0x7fd4 while (1) // and busy-loop so that WD causes ; // a reset and app start. } putch(STK_INSYNC); - 7fc4: 84 e1 ldi r24, 0x14 ; 20 + 7fd6: 84 e1 ldi r24, 0x14 ; 20 } - 7fc6: de cf rjmp .-68 ; 0x7f84 + 7fd8: de cf rjmp .-68 ; 0x7f96 -00007fc8 : +00007fda : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 7fc8: 1f 93 push r17 - 7fca: 18 2f mov r17, r24 + 7fda: 1f 93 push r17 + 7fdc: 18 2f mov r17, r24 do getch(); while (--count); - 7fcc: e3 df rcall .-58 ; 0x7f94 - 7fce: 11 50 subi r17, 0x01 ; 1 - 7fd0: e9 f7 brne .-6 ; 0x7fcc + 7fde: e3 df rcall .-58 ; 0x7fa6 + 7fe0: 11 50 subi r17, 0x01 ; 1 + 7fe2: e9 f7 brne .-6 ; 0x7fde verifySpace(); - 7fd2: f2 df rcall .-28 ; 0x7fb8 + 7fe4: f2 df rcall .-28 ; 0x7fca } - 7fd4: 1f 91 pop r17 - 7fd6: 08 95 ret + 7fe6: 1f 91 pop r17 + 7fe8: 08 95 ret -00007fd8 : +00007fea : WDTCSR = _BV(WDCE) | _BV(WDE); WDTCSR = x; } void appStart() { watchdogConfig(WATCHDOG_OFF); - 7fd8: 80 e0 ldi r24, 0x00 ; 0 - 7fda: e8 df rcall .-48 ; 0x7fac + 7fea: 80 e0 ldi r24, 0x00 ; 0 + 7fec: e8 df rcall .-48 ; 0x7fbe __asm__ __volatile__ ( - 7fdc: ee 27 eor r30, r30 - 7fde: ff 27 eor r31, r31 - 7fe0: 09 94 ijmp + 7fee: ee 27 eor r30, r30 + 7ff0: ff 27 eor r31, r31 + 7ff2: 09 94 ijmp diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.hex b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.hex deleted file mode 100644 index 499c631e3..000000000 --- a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.hex +++ /dev/null @@ -1,34 +0,0 @@ -:107E0000112484B714BE81FFE7D085E08093810000 -:107E100082E08093C00088E18093C10086E0809377 -:107E2000C20088E08093C4008EE0C0D0259A86E02E -:107E300028E13EEF91E0309385002093840096BBCB -:107E4000B09BFECF1D9AA8958150A9F799249394D1 -:107E5000A5E0AA2EF1E1BF2E9DD0813421F481E06E -:107E6000B3D083E01FC0823411F484E103C08534B1 -:107E700019F485E0A9D083C0853579F48BD0E82E3C -:107E8000FF2488D0082F10E0102F00270E291F296B -:107E9000000F111F91D0680172C0863529F484E06B -:107EA00093D080E06FD06BC0843609F042C072D0AE -:107EB00071D0082F6FD080E0C81680E7D80620F474 -:107EC00083E0F60187BFE895C0E0D1E063D08993F5 -:107ED0000C17E1F7F0E0CF16F0E7DF0620F083E0C3 -:107EE000F60187BFE89568D007B600FCFDCFA60174 -:107EF000A0E0B1E02C9130E011968C91119790E0C8 -:107F0000982F8827822B932B1296FA010C0197BE8B -:107F1000E89511244E5F5F4FF1E0A038BF0751F79D -:107F2000F601A7BEE89507B600FCFDCFB7BEE89501 -:107F300026C08437B1F42ED02DD0F82E2BD03CD0D3 -:107F4000F601EF2C8F010F5F1F4F84911BD0EA9435 -:107F5000F801C1F70894C11CD11CFA94CF0CD11CB4 -:107F60000EC0853739F428D08EE10CD085E90AD0CF -:107F70008FE098CF813511F488E018D01DD080E1D2 -:107F800001D06ACF982F8091C00085FFFCCF9093DD -:107F9000C60008958091C00087FFFCCF8091C0008B -:107FA00084FD01C0A8958091C6000895E0E6F0E048 -:107FB00098E1908380830895EDDF803219F088E0A6 -:107FC000F5DFFFCF84E1DECF1F93182FE3DF1150E1 -:107FD000E9F7F2DF1F91089580E0E8DFEE27FF2741 -:027FE000099402 -:027FFE0003047A -:0400000300007E007B -:00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.lst b/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.lst deleted file mode 100644 index 0577bdc2f..000000000 --- a/hardware/arduino/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.lst +++ /dev/null @@ -1,571 +0,0 @@ - -optiboot_atmega328_pro_8MHz.elf: file format elf32-avr - -Sections: -Idx Name Size VMA LMA File off Algn - 0 .text 000001e2 00007e00 00007e00 00000054 2**1 - CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .version 00000002 00007ffe 00007ffe 00000236 2**0 - CONTENTS, READONLY - 2 .debug_aranges 00000028 00000000 00000000 00000238 2**0 - CONTENTS, READONLY, DEBUGGING - 3 .debug_pubnames 0000005f 00000000 00000000 00000260 2**0 - CONTENTS, READONLY, DEBUGGING - 4 .debug_info 0000028e 00000000 00000000 000002bf 2**0 - CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 00000171 00000000 00000000 0000054d 2**0 - CONTENTS, READONLY, DEBUGGING - 6 .debug_line 0000045e 00000000 00000000 000006be 2**0 - CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000080 00000000 00000000 00000b1c 2**2 - CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000149 00000000 00000000 00000b9c 2**0 - CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 0000027e 00000000 00000000 00000ce5 2**0 - CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000060 00000000 00000000 00000f63 2**0 - CONTENTS, READONLY, DEBUGGING - -Disassembly of section .text: - -00007e00
    : -#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) -#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) -#endif - -/* main program starts here */ -int main(void) { - 7e00: 11 24 eor r1, r1 -#ifdef __AVR_ATmega8__ - SP=RAMEND; // This is done by hardware reset -#endif - - // Adaboot no-wait mod - ch = MCUSR; - 7e02: 84 b7 in r24, 0x34 ; 52 - MCUSR = 0; - 7e04: 14 be out 0x34, r1 ; 52 - if (!(ch & _BV(EXTRF))) appStart(); - 7e06: 81 ff sbrs r24, 1 - 7e08: e7 d0 rcall .+462 ; 0x7fd8 - -#if LED_START_FLASHES > 0 - // Set up Timer 1 for timeout counter - TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 - 7e0a: 85 e0 ldi r24, 0x05 ; 5 - 7e0c: 80 93 81 00 sts 0x0081, r24 - UCSRA = _BV(U2X); //Double speed mode USART - UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx - UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 - UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); -#else - UCSR0A = _BV(U2X0); //Double speed mode USART0 - 7e10: 82 e0 ldi r24, 0x02 ; 2 - 7e12: 80 93 c0 00 sts 0x00C0, r24 - UCSR0B = _BV(RXEN0) | _BV(TXEN0); - 7e16: 88 e1 ldi r24, 0x18 ; 24 - 7e18: 80 93 c1 00 sts 0x00C1, r24 - UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); - 7e1c: 86 e0 ldi r24, 0x06 ; 6 - 7e1e: 80 93 c2 00 sts 0x00C2, r24 - UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); - 7e22: 88 e0 ldi r24, 0x08 ; 8 - 7e24: 80 93 c4 00 sts 0x00C4, r24 -#endif -#endif - - // Set up watchdog to trigger after 500ms - watchdogConfig(WATCHDOG_1S); - 7e28: 8e e0 ldi r24, 0x0E ; 14 - 7e2a: c0 d0 rcall .+384 ; 0x7fac - - /* Set LED pin as output */ - LED_DDR |= _BV(LED); - 7e2c: 25 9a sbi 0x04, 5 ; 4 - 7e2e: 86 e0 ldi r24, 0x06 ; 6 -} - -#if LED_START_FLASHES > 0 -void flash_led(uint8_t count) { - do { - TCNT1 = -(F_CPU/(1024*16)); - 7e30: 28 e1 ldi r18, 0x18 ; 24 - 7e32: 3e ef ldi r19, 0xFE ; 254 - TIFR1 = _BV(TOV1); - 7e34: 91 e0 ldi r25, 0x01 ; 1 -} - -#if LED_START_FLASHES > 0 -void flash_led(uint8_t count) { - do { - TCNT1 = -(F_CPU/(1024*16)); - 7e36: 30 93 85 00 sts 0x0085, r19 - 7e3a: 20 93 84 00 sts 0x0084, r18 - TIFR1 = _BV(TOV1); - 7e3e: 96 bb out 0x16, r25 ; 22 - while(!(TIFR1 & _BV(TOV1))); - 7e40: b0 9b sbis 0x16, 0 ; 22 - 7e42: fe cf rjmp .-4 ; 0x7e40 -#ifdef __AVR_ATmega8__ - LED_PORT ^= _BV(LED); -#else - LED_PIN |= _BV(LED); - 7e44: 1d 9a sbi 0x03, 5 ; 3 -} -#endif - -// Watchdog functions. These are only safe with interrupts turned off. -void watchdogReset() { - __asm__ __volatile__ ( - 7e46: a8 95 wdr - LED_PORT ^= _BV(LED); -#else - LED_PIN |= _BV(LED); -#endif - watchdogReset(); - } while (--count); - 7e48: 81 50 subi r24, 0x01 ; 1 - 7e4a: a9 f7 brne .-22 ; 0x7e36 - /* get character from UART */ - ch = getch(); - - if(ch == STK_GET_PARAMETER) { - // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy - getNch(1); - 7e4c: 99 24 eor r9, r9 - 7e4e: 93 94 inc r9 - __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - addrPtr += 2; - } while (--ch); - - // Write from programming buffer - __boot_page_write_short((uint16_t)(void*)address); - 7e50: a5 e0 ldi r26, 0x05 ; 5 - 7e52: aa 2e mov r10, r26 - boot_spm_busy_wait(); - -#if defined(RWWSRE) - // Reenable read access to flash - boot_rww_enable(); - 7e54: f1 e1 ldi r31, 0x11 ; 17 - 7e56: bf 2e mov r11, r31 -#endif - - /* Forever loop */ - for (;;) { - /* get character from UART */ - ch = getch(); - 7e58: 9d d0 rcall .+314 ; 0x7f94 - - if(ch == STK_GET_PARAMETER) { - 7e5a: 81 34 cpi r24, 0x41 ; 65 - 7e5c: 21 f4 brne .+8 ; 0x7e66 - // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy - getNch(1); - 7e5e: 81 e0 ldi r24, 0x01 ; 1 - 7e60: b3 d0 rcall .+358 ; 0x7fc8 - putch(0x03); - 7e62: 83 e0 ldi r24, 0x03 ; 3 - 7e64: 1f c0 rjmp .+62 ; 0x7ea4 - } - else if(ch == STK_SET_DEVICE) { - 7e66: 82 34 cpi r24, 0x42 ; 66 - 7e68: 11 f4 brne .+4 ; 0x7e6e - // SET DEVICE is ignored - getNch(20); - 7e6a: 84 e1 ldi r24, 0x14 ; 20 - 7e6c: 03 c0 rjmp .+6 ; 0x7e74 - } - else if(ch == STK_SET_DEVICE_EXT) { - 7e6e: 85 34 cpi r24, 0x45 ; 69 - 7e70: 19 f4 brne .+6 ; 0x7e78 - // SET DEVICE EXT is ignored - getNch(5); - 7e72: 85 e0 ldi r24, 0x05 ; 5 - 7e74: a9 d0 rcall .+338 ; 0x7fc8 - 7e76: 83 c0 rjmp .+262 ; 0x7f7e - } - else if(ch == STK_LOAD_ADDRESS) { - 7e78: 85 35 cpi r24, 0x55 ; 85 - 7e7a: 79 f4 brne .+30 ; 0x7e9a - // LOAD ADDRESS - uint16_t newAddress; - newAddress = getch(); - 7e7c: 8b d0 rcall .+278 ; 0x7f94 - newAddress = (newAddress & 0xff) | (getch() << 8); - 7e7e: e8 2e mov r14, r24 - 7e80: ff 24 eor r15, r15 - 7e82: 88 d0 rcall .+272 ; 0x7f94 - 7e84: 08 2f mov r16, r24 - 7e86: 10 e0 ldi r17, 0x00 ; 0 - 7e88: 10 2f mov r17, r16 - 7e8a: 00 27 eor r16, r16 - 7e8c: 0e 29 or r16, r14 - 7e8e: 1f 29 or r17, r15 -#ifdef RAMPZ - // Transfer top bit to RAMPZ - RAMPZ = (newAddress & 0x8000) ? 1 : 0; -#endif - newAddress += newAddress; // Convert from word address to byte address - 7e90: 00 0f add r16, r16 - 7e92: 11 1f adc r17, r17 - address = newAddress; - verifySpace(); - 7e94: 91 d0 rcall .+290 ; 0x7fb8 - 7e96: 68 01 movw r12, r16 - 7e98: 72 c0 rjmp .+228 ; 0x7f7e - } - else if(ch == STK_UNIVERSAL) { - 7e9a: 86 35 cpi r24, 0x56 ; 86 - 7e9c: 29 f4 brne .+10 ; 0x7ea8 - // UNIVERSAL command is ignored - getNch(4); - 7e9e: 84 e0 ldi r24, 0x04 ; 4 - 7ea0: 93 d0 rcall .+294 ; 0x7fc8 - putch(0x00); - 7ea2: 80 e0 ldi r24, 0x00 ; 0 - 7ea4: 6f d0 rcall .+222 ; 0x7f84 - 7ea6: 6b c0 rjmp .+214 ; 0x7f7e - } - /* Write memory, length is big endian and is in bytes */ - else if(ch == STK_PROG_PAGE) { - 7ea8: 84 36 cpi r24, 0x64 ; 100 - 7eaa: 09 f0 breq .+2 ; 0x7eae - 7eac: 42 c0 rjmp .+132 ; 0x7f32 - // PROGRAM PAGE - we support flash programming only, not EEPROM - uint8_t *bufPtr; - uint16_t addrPtr; - - getch(); /* getlen() */ - 7eae: 72 d0 rcall .+228 ; 0x7f94 - length = getch(); - 7eb0: 71 d0 rcall .+226 ; 0x7f94 - 7eb2: 08 2f mov r16, r24 - getch(); - 7eb4: 6f d0 rcall .+222 ; 0x7f94 - - // If we are in RWW section, immediately start page erase - if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 7eb6: 80 e0 ldi r24, 0x00 ; 0 - 7eb8: c8 16 cp r12, r24 - 7eba: 80 e7 ldi r24, 0x70 ; 112 - 7ebc: d8 06 cpc r13, r24 - 7ebe: 20 f4 brcc .+8 ; 0x7ec8 - 7ec0: 83 e0 ldi r24, 0x03 ; 3 - 7ec2: f6 01 movw r30, r12 - 7ec4: 87 bf out 0x37, r24 ; 55 - 7ec6: e8 95 spm - 7ec8: c0 e0 ldi r28, 0x00 ; 0 - 7eca: d1 e0 ldi r29, 0x01 ; 1 - - // While that is going on, read in page contents - bufPtr = buff; - do *bufPtr++ = getch(); - 7ecc: 63 d0 rcall .+198 ; 0x7f94 - 7ece: 89 93 st Y+, r24 - while (--length); - 7ed0: 0c 17 cp r16, r28 - 7ed2: e1 f7 brne .-8 ; 0x7ecc - - // If we are in NRWW section, page erase has to be delayed until now. - // Todo: Take RAMPZ into account - if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 7ed4: f0 e0 ldi r31, 0x00 ; 0 - 7ed6: cf 16 cp r12, r31 - 7ed8: f0 e7 ldi r31, 0x70 ; 112 - 7eda: df 06 cpc r13, r31 - 7edc: 20 f0 brcs .+8 ; 0x7ee6 - 7ede: 83 e0 ldi r24, 0x03 ; 3 - 7ee0: f6 01 movw r30, r12 - 7ee2: 87 bf out 0x37, r24 ; 55 - 7ee4: e8 95 spm - - // Read command terminator, start reply - verifySpace(); - 7ee6: 68 d0 rcall .+208 ; 0x7fb8 - - // If only a partial page is to be programmed, the erase might not be complete. - // So check that here - boot_spm_busy_wait(); - 7ee8: 07 b6 in r0, 0x37 ; 55 - 7eea: 00 fc sbrc r0, 0 - 7eec: fd cf rjmp .-6 ; 0x7ee8 - 7eee: a6 01 movw r20, r12 - 7ef0: a0 e0 ldi r26, 0x00 ; 0 - 7ef2: b1 e0 ldi r27, 0x01 ; 1 - bufPtr = buff; - addrPtr = (uint16_t)(void*)address; - ch = SPM_PAGESIZE / 2; - do { - uint16_t a; - a = *bufPtr++; - 7ef4: 2c 91 ld r18, X - 7ef6: 30 e0 ldi r19, 0x00 ; 0 - a |= (*bufPtr++) << 8; - 7ef8: 11 96 adiw r26, 0x01 ; 1 - 7efa: 8c 91 ld r24, X - 7efc: 11 97 sbiw r26, 0x01 ; 1 - 7efe: 90 e0 ldi r25, 0x00 ; 0 - 7f00: 98 2f mov r25, r24 - 7f02: 88 27 eor r24, r24 - 7f04: 82 2b or r24, r18 - 7f06: 93 2b or r25, r19 -#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) -#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) -#endif - -/* main program starts here */ -int main(void) { - 7f08: 12 96 adiw r26, 0x02 ; 2 - ch = SPM_PAGESIZE / 2; - do { - uint16_t a; - a = *bufPtr++; - a |= (*bufPtr++) << 8; - __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - 7f0a: fa 01 movw r30, r20 - 7f0c: 0c 01 movw r0, r24 - 7f0e: 97 be out 0x37, r9 ; 55 - 7f10: e8 95 spm - 7f12: 11 24 eor r1, r1 - addrPtr += 2; - 7f14: 4e 5f subi r20, 0xFE ; 254 - 7f16: 5f 4f sbci r21, 0xFF ; 255 - } while (--ch); - 7f18: f1 e0 ldi r31, 0x01 ; 1 - 7f1a: a0 38 cpi r26, 0x80 ; 128 - 7f1c: bf 07 cpc r27, r31 - 7f1e: 51 f7 brne .-44 ; 0x7ef4 - - // Write from programming buffer - __boot_page_write_short((uint16_t)(void*)address); - 7f20: f6 01 movw r30, r12 - 7f22: a7 be out 0x37, r10 ; 55 - 7f24: e8 95 spm - boot_spm_busy_wait(); - 7f26: 07 b6 in r0, 0x37 ; 55 - 7f28: 00 fc sbrc r0, 0 - 7f2a: fd cf rjmp .-6 ; 0x7f26 - -#if defined(RWWSRE) - // Reenable read access to flash - boot_rww_enable(); - 7f2c: b7 be out 0x37, r11 ; 55 - 7f2e: e8 95 spm - 7f30: 26 c0 rjmp .+76 ; 0x7f7e -#endif - - } - /* Read memory block mode, length is big endian. */ - else if(ch == STK_READ_PAGE) { - 7f32: 84 37 cpi r24, 0x74 ; 116 - 7f34: b1 f4 brne .+44 ; 0x7f62 - // READ PAGE - we only read flash - getch(); /* getlen() */ - 7f36: 2e d0 rcall .+92 ; 0x7f94 - length = getch(); - 7f38: 2d d0 rcall .+90 ; 0x7f94 - 7f3a: f8 2e mov r15, r24 - getch(); - 7f3c: 2b d0 rcall .+86 ; 0x7f94 - - verifySpace(); - 7f3e: 3c d0 rcall .+120 ; 0x7fb8 - 7f40: f6 01 movw r30, r12 - 7f42: ef 2c mov r14, r15 - putch(result); - address++; - } - while (--length); -#else - do putch(pgm_read_byte_near(address++)); - 7f44: 8f 01 movw r16, r30 - 7f46: 0f 5f subi r16, 0xFF ; 255 - 7f48: 1f 4f sbci r17, 0xFF ; 255 - 7f4a: 84 91 lpm r24, Z+ - 7f4c: 1b d0 rcall .+54 ; 0x7f84 - while (--length); - 7f4e: ea 94 dec r14 - 7f50: f8 01 movw r30, r16 - 7f52: c1 f7 brne .-16 ; 0x7f44 -#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) -#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) -#endif - -/* main program starts here */ -int main(void) { - 7f54: 08 94 sec - 7f56: c1 1c adc r12, r1 - 7f58: d1 1c adc r13, r1 - 7f5a: fa 94 dec r15 - 7f5c: cf 0c add r12, r15 - 7f5e: d1 1c adc r13, r1 - 7f60: 0e c0 rjmp .+28 ; 0x7f7e -#endif -#endif - } - - /* Get device signature bytes */ - else if(ch == STK_READ_SIGN) { - 7f62: 85 37 cpi r24, 0x75 ; 117 - 7f64: 39 f4 brne .+14 ; 0x7f74 - // READ SIGN - return what Avrdude wants to hear - verifySpace(); - 7f66: 28 d0 rcall .+80 ; 0x7fb8 - putch(SIGNATURE_0); - 7f68: 8e e1 ldi r24, 0x1E ; 30 - 7f6a: 0c d0 rcall .+24 ; 0x7f84 - putch(SIGNATURE_1); - 7f6c: 85 e9 ldi r24, 0x95 ; 149 - 7f6e: 0a d0 rcall .+20 ; 0x7f84 - putch(SIGNATURE_2); - 7f70: 8f e0 ldi r24, 0x0F ; 15 - 7f72: 98 cf rjmp .-208 ; 0x7ea4 - } - else if (ch == 'Q') { - 7f74: 81 35 cpi r24, 0x51 ; 81 - 7f76: 11 f4 brne .+4 ; 0x7f7c - // Adaboot no-wait mod - watchdogConfig(WATCHDOG_16MS); - 7f78: 88 e0 ldi r24, 0x08 ; 8 - 7f7a: 18 d0 rcall .+48 ; 0x7fac - verifySpace(); - } - else { - // This covers the response to commands like STK_ENTER_PROGMODE - verifySpace(); - 7f7c: 1d d0 rcall .+58 ; 0x7fb8 - } - putch(STK_OK); - 7f7e: 80 e1 ldi r24, 0x10 ; 16 - 7f80: 01 d0 rcall .+2 ; 0x7f84 - 7f82: 6a cf rjmp .-300 ; 0x7e58 - -00007f84 : - } -} - -void putch(char ch) { - 7f84: 98 2f mov r25, r24 -#ifndef SOFT_UART - while (!(UCSR0A & _BV(UDRE0))); - 7f86: 80 91 c0 00 lds r24, 0x00C0 - 7f8a: 85 ff sbrs r24, 5 - 7f8c: fc cf rjmp .-8 ; 0x7f86 - UDR0 = ch; - 7f8e: 90 93 c6 00 sts 0x00C6, r25 - [uartBit] "I" (UART_TX_BIT) - : - "r25" - ); -#endif -} - 7f92: 08 95 ret - -00007f94 : - [uartBit] "I" (UART_RX_BIT) - : - "r25" -); -#else - while(!(UCSR0A & _BV(RXC0))) - 7f94: 80 91 c0 00 lds r24, 0x00C0 - 7f98: 87 ff sbrs r24, 7 - 7f9a: fc cf rjmp .-8 ; 0x7f94 - ; - if (!(UCSR0A & _BV(FE0))) { - 7f9c: 80 91 c0 00 lds r24, 0x00C0 - 7fa0: 84 fd sbrc r24, 4 - 7fa2: 01 c0 rjmp .+2 ; 0x7fa6 -} -#endif - -// Watchdog functions. These are only safe with interrupts turned off. -void watchdogReset() { - __asm__ __volatile__ ( - 7fa4: a8 95 wdr - * don't care that an invalid char is returned...) - */ - watchdogReset(); - } - - ch = UDR0; - 7fa6: 80 91 c6 00 lds r24, 0x00C6 - LED_PIN |= _BV(LED); -#endif -#endif - - return ch; -} - 7faa: 08 95 ret - -00007fac : - "wdr\n" - ); -} - -void watchdogConfig(uint8_t x) { - WDTCSR = _BV(WDCE) | _BV(WDE); - 7fac: e0 e6 ldi r30, 0x60 ; 96 - 7fae: f0 e0 ldi r31, 0x00 ; 0 - 7fb0: 98 e1 ldi r25, 0x18 ; 24 - 7fb2: 90 83 st Z, r25 - WDTCSR = x; - 7fb4: 80 83 st Z, r24 -} - 7fb6: 08 95 ret - -00007fb8 : - do getch(); while (--count); - verifySpace(); -} - -void verifySpace() { - if (getch() != CRC_EOP) { - 7fb8: ed df rcall .-38 ; 0x7f94 - 7fba: 80 32 cpi r24, 0x20 ; 32 - 7fbc: 19 f0 breq .+6 ; 0x7fc4 - watchdogConfig(WATCHDOG_16MS); // shorten WD timeout - 7fbe: 88 e0 ldi r24, 0x08 ; 8 - 7fc0: f5 df rcall .-22 ; 0x7fac - 7fc2: ff cf rjmp .-2 ; 0x7fc2 - while (1) // and busy-loop so that WD causes - ; // a reset and app start. - } - putch(STK_INSYNC); - 7fc4: 84 e1 ldi r24, 0x14 ; 20 -} - 7fc6: de cf rjmp .-68 ; 0x7f84 - -00007fc8 : - ::[count] "M" (UART_B_VALUE) - ); -} -#endif - -void getNch(uint8_t count) { - 7fc8: 1f 93 push r17 - 7fca: 18 2f mov r17, r24 - do getch(); while (--count); - 7fcc: e3 df rcall .-58 ; 0x7f94 - 7fce: 11 50 subi r17, 0x01 ; 1 - 7fd0: e9 f7 brne .-6 ; 0x7fcc - verifySpace(); - 7fd2: f2 df rcall .-28 ; 0x7fb8 -} - 7fd4: 1f 91 pop r17 - 7fd6: 08 95 ret - -00007fd8 : - WDTCSR = _BV(WDCE) | _BV(WDE); - WDTCSR = x; -} - -void appStart() { - watchdogConfig(WATCHDOG_OFF); - 7fd8: 80 e0 ldi r24, 0x00 ; 0 - 7fda: e8 df rcall .-48 ; 0x7fac - __asm__ __volatile__ ( - 7fdc: ee 27 eor r30, r30 - 7fde: ff 27 eor r31, r31 - 7fe0: 09 94 ijmp diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.hex b/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.hex deleted file mode 100644 index b685a4e9a..000000000 --- a/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.hex +++ /dev/null @@ -1,34 +0,0 @@ -:103E0000112484B714BE81FFE7D085E08093810040 -:103E100082E08093C00088E18093C10086E08093B7 -:103E2000C20080E18093C4008EE0C0D0259A86E075 -:103E300020E33CEF91E0309385002093840096BB13 -:103E4000B09BFECF1D9AA8958150A9F79924939411 -:103E5000A5E0AA2EF1E1BF2E9DD0813421F481E0AE -:103E6000B3D083E01FC0823411F484E103C08534F1 -:103E700019F485E0A9D083C0853579F48BD0E82E7C -:103E8000FF2488D0082F10E0102F00270E291F29AB -:103E9000000F111F91D0680172C0863529F484E0AB -:103EA00093D080E06FD06BC0843609F042C072D0EE -:103EB00071D0082F6FD080E0C81688E3D80620F4B0 -:103EC00083E0F60187BFE895C0E0D1E063D0899335 -:103ED0000C17E1F7F0E0CF16F8E3DF0620F083E0FF -:103EE000F60187BFE89568D007B600FCFDCFA601B4 -:103EF000A0E0B1E02C9130E011968C91119790E008 -:103F0000982F8827822B932B1296FA010C0197BECB -:103F1000E89511244E5F5F4FF1E0A038BF0751F7DD -:103F2000F601A7BEE89507B600FCFDCFB7BEE89541 -:103F300026C08437B1F42ED02DD0F82E2BD03CD013 -:103F4000F601EF2C8F010F5F1F4F84911BD0EA9475 -:103F5000F801C1F70894C11CD11CFA94CF0CD11CF4 -:103F60000EC0853739F428D08EE10CD084E90AD010 -:103F700086E098CF813511F488E018D01DD080E11B -:103F800001D06ACF982F8091C00085FFFCCF90931D -:103F9000C60008958091C00087FFFCCF8091C000CB -:103FA00084FD01C0A8958091C6000895E0E6F0E088 -:103FB00098E1908380830895EDDF803219F088E0E6 -:103FC000F5DFFFCF84E1DECF1F93182FE3DF115021 -:103FD000E9F7F2DF1F91089580E0E8DFEE27FF2781 -:023FE000099442 -:023FFE000304BA -:0400000300003E00BB -:00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.lst b/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.lst deleted file mode 100644 index 357dc11c4..000000000 --- a/hardware/arduino/bootloaders/optiboot/optiboot_diecimila.lst +++ /dev/null @@ -1,571 +0,0 @@ - -optiboot_diecimila.elf: file format elf32-avr - -Sections: -Idx Name Size VMA LMA File off Algn - 0 .text 000001e2 00003e00 00003e00 00000054 2**1 - CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .version 00000002 00003ffe 00003ffe 00000236 2**0 - CONTENTS, READONLY - 2 .debug_aranges 00000028 00000000 00000000 00000238 2**0 - CONTENTS, READONLY, DEBUGGING - 3 .debug_pubnames 0000005f 00000000 00000000 00000260 2**0 - CONTENTS, READONLY, DEBUGGING - 4 .debug_info 0000028e 00000000 00000000 000002bf 2**0 - CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 00000171 00000000 00000000 0000054d 2**0 - CONTENTS, READONLY, DEBUGGING - 6 .debug_line 0000045e 00000000 00000000 000006be 2**0 - CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000080 00000000 00000000 00000b1c 2**2 - CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000149 00000000 00000000 00000b9c 2**0 - CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 0000027e 00000000 00000000 00000ce5 2**0 - CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000060 00000000 00000000 00000f63 2**0 - CONTENTS, READONLY, DEBUGGING - -Disassembly of section .text: - -00003e00
    : -#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) -#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) -#endif - -/* main program starts here */ -int main(void) { - 3e00: 11 24 eor r1, r1 -#ifdef __AVR_ATmega8__ - SP=RAMEND; // This is done by hardware reset -#endif - - // Adaboot no-wait mod - ch = MCUSR; - 3e02: 84 b7 in r24, 0x34 ; 52 - MCUSR = 0; - 3e04: 14 be out 0x34, r1 ; 52 - if (!(ch & _BV(EXTRF))) appStart(); - 3e06: 81 ff sbrs r24, 1 - 3e08: e7 d0 rcall .+462 ; 0x3fd8 - -#if LED_START_FLASHES > 0 - // Set up Timer 1 for timeout counter - TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 - 3e0a: 85 e0 ldi r24, 0x05 ; 5 - 3e0c: 80 93 81 00 sts 0x0081, r24 - UCSRA = _BV(U2X); //Double speed mode USART - UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx - UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 - UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); -#else - UCSR0A = _BV(U2X0); //Double speed mode USART0 - 3e10: 82 e0 ldi r24, 0x02 ; 2 - 3e12: 80 93 c0 00 sts 0x00C0, r24 - UCSR0B = _BV(RXEN0) | _BV(TXEN0); - 3e16: 88 e1 ldi r24, 0x18 ; 24 - 3e18: 80 93 c1 00 sts 0x00C1, r24 - UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); - 3e1c: 86 e0 ldi r24, 0x06 ; 6 - 3e1e: 80 93 c2 00 sts 0x00C2, r24 - UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); - 3e22: 80 e1 ldi r24, 0x10 ; 16 - 3e24: 80 93 c4 00 sts 0x00C4, r24 -#endif -#endif - - // Set up watchdog to trigger after 500ms - watchdogConfig(WATCHDOG_1S); - 3e28: 8e e0 ldi r24, 0x0E ; 14 - 3e2a: c0 d0 rcall .+384 ; 0x3fac - - /* Set LED pin as output */ - LED_DDR |= _BV(LED); - 3e2c: 25 9a sbi 0x04, 5 ; 4 - 3e2e: 86 e0 ldi r24, 0x06 ; 6 -} - -#if LED_START_FLASHES > 0 -void flash_led(uint8_t count) { - do { - TCNT1 = -(F_CPU/(1024*16)); - 3e30: 20 e3 ldi r18, 0x30 ; 48 - 3e32: 3c ef ldi r19, 0xFC ; 252 - TIFR1 = _BV(TOV1); - 3e34: 91 e0 ldi r25, 0x01 ; 1 -} - -#if LED_START_FLASHES > 0 -void flash_led(uint8_t count) { - do { - TCNT1 = -(F_CPU/(1024*16)); - 3e36: 30 93 85 00 sts 0x0085, r19 - 3e3a: 20 93 84 00 sts 0x0084, r18 - TIFR1 = _BV(TOV1); - 3e3e: 96 bb out 0x16, r25 ; 22 - while(!(TIFR1 & _BV(TOV1))); - 3e40: b0 9b sbis 0x16, 0 ; 22 - 3e42: fe cf rjmp .-4 ; 0x3e40 -#ifdef __AVR_ATmega8__ - LED_PORT ^= _BV(LED); -#else - LED_PIN |= _BV(LED); - 3e44: 1d 9a sbi 0x03, 5 ; 3 -} -#endif - -// Watchdog functions. These are only safe with interrupts turned off. -void watchdogReset() { - __asm__ __volatile__ ( - 3e46: a8 95 wdr - LED_PORT ^= _BV(LED); -#else - LED_PIN |= _BV(LED); -#endif - watchdogReset(); - } while (--count); - 3e48: 81 50 subi r24, 0x01 ; 1 - 3e4a: a9 f7 brne .-22 ; 0x3e36 - /* get character from UART */ - ch = getch(); - - if(ch == STK_GET_PARAMETER) { - // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy - getNch(1); - 3e4c: 99 24 eor r9, r9 - 3e4e: 93 94 inc r9 - __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - addrPtr += 2; - } while (--ch); - - // Write from programming buffer - __boot_page_write_short((uint16_t)(void*)address); - 3e50: a5 e0 ldi r26, 0x05 ; 5 - 3e52: aa 2e mov r10, r26 - boot_spm_busy_wait(); - -#if defined(RWWSRE) - // Reenable read access to flash - boot_rww_enable(); - 3e54: f1 e1 ldi r31, 0x11 ; 17 - 3e56: bf 2e mov r11, r31 -#endif - - /* Forever loop */ - for (;;) { - /* get character from UART */ - ch = getch(); - 3e58: 9d d0 rcall .+314 ; 0x3f94 - - if(ch == STK_GET_PARAMETER) { - 3e5a: 81 34 cpi r24, 0x41 ; 65 - 3e5c: 21 f4 brne .+8 ; 0x3e66 - // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy - getNch(1); - 3e5e: 81 e0 ldi r24, 0x01 ; 1 - 3e60: b3 d0 rcall .+358 ; 0x3fc8 - putch(0x03); - 3e62: 83 e0 ldi r24, 0x03 ; 3 - 3e64: 1f c0 rjmp .+62 ; 0x3ea4 - } - else if(ch == STK_SET_DEVICE) { - 3e66: 82 34 cpi r24, 0x42 ; 66 - 3e68: 11 f4 brne .+4 ; 0x3e6e - // SET DEVICE is ignored - getNch(20); - 3e6a: 84 e1 ldi r24, 0x14 ; 20 - 3e6c: 03 c0 rjmp .+6 ; 0x3e74 - } - else if(ch == STK_SET_DEVICE_EXT) { - 3e6e: 85 34 cpi r24, 0x45 ; 69 - 3e70: 19 f4 brne .+6 ; 0x3e78 - // SET DEVICE EXT is ignored - getNch(5); - 3e72: 85 e0 ldi r24, 0x05 ; 5 - 3e74: a9 d0 rcall .+338 ; 0x3fc8 - 3e76: 83 c0 rjmp .+262 ; 0x3f7e - } - else if(ch == STK_LOAD_ADDRESS) { - 3e78: 85 35 cpi r24, 0x55 ; 85 - 3e7a: 79 f4 brne .+30 ; 0x3e9a - // LOAD ADDRESS - uint16_t newAddress; - newAddress = getch(); - 3e7c: 8b d0 rcall .+278 ; 0x3f94 - newAddress = (newAddress & 0xff) | (getch() << 8); - 3e7e: e8 2e mov r14, r24 - 3e80: ff 24 eor r15, r15 - 3e82: 88 d0 rcall .+272 ; 0x3f94 - 3e84: 08 2f mov r16, r24 - 3e86: 10 e0 ldi r17, 0x00 ; 0 - 3e88: 10 2f mov r17, r16 - 3e8a: 00 27 eor r16, r16 - 3e8c: 0e 29 or r16, r14 - 3e8e: 1f 29 or r17, r15 -#ifdef RAMPZ - // Transfer top bit to RAMPZ - RAMPZ = (newAddress & 0x8000) ? 1 : 0; -#endif - newAddress += newAddress; // Convert from word address to byte address - 3e90: 00 0f add r16, r16 - 3e92: 11 1f adc r17, r17 - address = newAddress; - verifySpace(); - 3e94: 91 d0 rcall .+290 ; 0x3fb8 - 3e96: 68 01 movw r12, r16 - 3e98: 72 c0 rjmp .+228 ; 0x3f7e - } - else if(ch == STK_UNIVERSAL) { - 3e9a: 86 35 cpi r24, 0x56 ; 86 - 3e9c: 29 f4 brne .+10 ; 0x3ea8 - // UNIVERSAL command is ignored - getNch(4); - 3e9e: 84 e0 ldi r24, 0x04 ; 4 - 3ea0: 93 d0 rcall .+294 ; 0x3fc8 - putch(0x00); - 3ea2: 80 e0 ldi r24, 0x00 ; 0 - 3ea4: 6f d0 rcall .+222 ; 0x3f84 - 3ea6: 6b c0 rjmp .+214 ; 0x3f7e - } - /* Write memory, length is big endian and is in bytes */ - else if(ch == STK_PROG_PAGE) { - 3ea8: 84 36 cpi r24, 0x64 ; 100 - 3eaa: 09 f0 breq .+2 ; 0x3eae - 3eac: 42 c0 rjmp .+132 ; 0x3f32 - // PROGRAM PAGE - we support flash programming only, not EEPROM - uint8_t *bufPtr; - uint16_t addrPtr; - - getch(); /* getlen() */ - 3eae: 72 d0 rcall .+228 ; 0x3f94 - length = getch(); - 3eb0: 71 d0 rcall .+226 ; 0x3f94 - 3eb2: 08 2f mov r16, r24 - getch(); - 3eb4: 6f d0 rcall .+222 ; 0x3f94 - - // If we are in RWW section, immediately start page erase - if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 3eb6: 80 e0 ldi r24, 0x00 ; 0 - 3eb8: c8 16 cp r12, r24 - 3eba: 88 e3 ldi r24, 0x38 ; 56 - 3ebc: d8 06 cpc r13, r24 - 3ebe: 20 f4 brcc .+8 ; 0x3ec8 - 3ec0: 83 e0 ldi r24, 0x03 ; 3 - 3ec2: f6 01 movw r30, r12 - 3ec4: 87 bf out 0x37, r24 ; 55 - 3ec6: e8 95 spm - 3ec8: c0 e0 ldi r28, 0x00 ; 0 - 3eca: d1 e0 ldi r29, 0x01 ; 1 - - // While that is going on, read in page contents - bufPtr = buff; - do *bufPtr++ = getch(); - 3ecc: 63 d0 rcall .+198 ; 0x3f94 - 3ece: 89 93 st Y+, r24 - while (--length); - 3ed0: 0c 17 cp r16, r28 - 3ed2: e1 f7 brne .-8 ; 0x3ecc - - // If we are in NRWW section, page erase has to be delayed until now. - // Todo: Take RAMPZ into account - if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 3ed4: f0 e0 ldi r31, 0x00 ; 0 - 3ed6: cf 16 cp r12, r31 - 3ed8: f8 e3 ldi r31, 0x38 ; 56 - 3eda: df 06 cpc r13, r31 - 3edc: 20 f0 brcs .+8 ; 0x3ee6 - 3ede: 83 e0 ldi r24, 0x03 ; 3 - 3ee0: f6 01 movw r30, r12 - 3ee2: 87 bf out 0x37, r24 ; 55 - 3ee4: e8 95 spm - - // Read command terminator, start reply - verifySpace(); - 3ee6: 68 d0 rcall .+208 ; 0x3fb8 - - // If only a partial page is to be programmed, the erase might not be complete. - // So check that here - boot_spm_busy_wait(); - 3ee8: 07 b6 in r0, 0x37 ; 55 - 3eea: 00 fc sbrc r0, 0 - 3eec: fd cf rjmp .-6 ; 0x3ee8 - 3eee: a6 01 movw r20, r12 - 3ef0: a0 e0 ldi r26, 0x00 ; 0 - 3ef2: b1 e0 ldi r27, 0x01 ; 1 - bufPtr = buff; - addrPtr = (uint16_t)(void*)address; - ch = SPM_PAGESIZE / 2; - do { - uint16_t a; - a = *bufPtr++; - 3ef4: 2c 91 ld r18, X - 3ef6: 30 e0 ldi r19, 0x00 ; 0 - a |= (*bufPtr++) << 8; - 3ef8: 11 96 adiw r26, 0x01 ; 1 - 3efa: 8c 91 ld r24, X - 3efc: 11 97 sbiw r26, 0x01 ; 1 - 3efe: 90 e0 ldi r25, 0x00 ; 0 - 3f00: 98 2f mov r25, r24 - 3f02: 88 27 eor r24, r24 - 3f04: 82 2b or r24, r18 - 3f06: 93 2b or r25, r19 -#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) -#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) -#endif - -/* main program starts here */ -int main(void) { - 3f08: 12 96 adiw r26, 0x02 ; 2 - ch = SPM_PAGESIZE / 2; - do { - uint16_t a; - a = *bufPtr++; - a |= (*bufPtr++) << 8; - __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - 3f0a: fa 01 movw r30, r20 - 3f0c: 0c 01 movw r0, r24 - 3f0e: 97 be out 0x37, r9 ; 55 - 3f10: e8 95 spm - 3f12: 11 24 eor r1, r1 - addrPtr += 2; - 3f14: 4e 5f subi r20, 0xFE ; 254 - 3f16: 5f 4f sbci r21, 0xFF ; 255 - } while (--ch); - 3f18: f1 e0 ldi r31, 0x01 ; 1 - 3f1a: a0 38 cpi r26, 0x80 ; 128 - 3f1c: bf 07 cpc r27, r31 - 3f1e: 51 f7 brne .-44 ; 0x3ef4 - - // Write from programming buffer - __boot_page_write_short((uint16_t)(void*)address); - 3f20: f6 01 movw r30, r12 - 3f22: a7 be out 0x37, r10 ; 55 - 3f24: e8 95 spm - boot_spm_busy_wait(); - 3f26: 07 b6 in r0, 0x37 ; 55 - 3f28: 00 fc sbrc r0, 0 - 3f2a: fd cf rjmp .-6 ; 0x3f26 - -#if defined(RWWSRE) - // Reenable read access to flash - boot_rww_enable(); - 3f2c: b7 be out 0x37, r11 ; 55 - 3f2e: e8 95 spm - 3f30: 26 c0 rjmp .+76 ; 0x3f7e -#endif - - } - /* Read memory block mode, length is big endian. */ - else if(ch == STK_READ_PAGE) { - 3f32: 84 37 cpi r24, 0x74 ; 116 - 3f34: b1 f4 brne .+44 ; 0x3f62 - // READ PAGE - we only read flash - getch(); /* getlen() */ - 3f36: 2e d0 rcall .+92 ; 0x3f94 - length = getch(); - 3f38: 2d d0 rcall .+90 ; 0x3f94 - 3f3a: f8 2e mov r15, r24 - getch(); - 3f3c: 2b d0 rcall .+86 ; 0x3f94 - - verifySpace(); - 3f3e: 3c d0 rcall .+120 ; 0x3fb8 - 3f40: f6 01 movw r30, r12 - 3f42: ef 2c mov r14, r15 - putch(result); - address++; - } - while (--length); -#else - do putch(pgm_read_byte_near(address++)); - 3f44: 8f 01 movw r16, r30 - 3f46: 0f 5f subi r16, 0xFF ; 255 - 3f48: 1f 4f sbci r17, 0xFF ; 255 - 3f4a: 84 91 lpm r24, Z+ - 3f4c: 1b d0 rcall .+54 ; 0x3f84 - while (--length); - 3f4e: ea 94 dec r14 - 3f50: f8 01 movw r30, r16 - 3f52: c1 f7 brne .-16 ; 0x3f44 -#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) -#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) -#endif - -/* main program starts here */ -int main(void) { - 3f54: 08 94 sec - 3f56: c1 1c adc r12, r1 - 3f58: d1 1c adc r13, r1 - 3f5a: fa 94 dec r15 - 3f5c: cf 0c add r12, r15 - 3f5e: d1 1c adc r13, r1 - 3f60: 0e c0 rjmp .+28 ; 0x3f7e -#endif -#endif - } - - /* Get device signature bytes */ - else if(ch == STK_READ_SIGN) { - 3f62: 85 37 cpi r24, 0x75 ; 117 - 3f64: 39 f4 brne .+14 ; 0x3f74 - // READ SIGN - return what Avrdude wants to hear - verifySpace(); - 3f66: 28 d0 rcall .+80 ; 0x3fb8 - putch(SIGNATURE_0); - 3f68: 8e e1 ldi r24, 0x1E ; 30 - 3f6a: 0c d0 rcall .+24 ; 0x3f84 - putch(SIGNATURE_1); - 3f6c: 84 e9 ldi r24, 0x94 ; 148 - 3f6e: 0a d0 rcall .+20 ; 0x3f84 - putch(SIGNATURE_2); - 3f70: 86 e0 ldi r24, 0x06 ; 6 - 3f72: 98 cf rjmp .-208 ; 0x3ea4 - } - else if (ch == 'Q') { - 3f74: 81 35 cpi r24, 0x51 ; 81 - 3f76: 11 f4 brne .+4 ; 0x3f7c - // Adaboot no-wait mod - watchdogConfig(WATCHDOG_16MS); - 3f78: 88 e0 ldi r24, 0x08 ; 8 - 3f7a: 18 d0 rcall .+48 ; 0x3fac - verifySpace(); - } - else { - // This covers the response to commands like STK_ENTER_PROGMODE - verifySpace(); - 3f7c: 1d d0 rcall .+58 ; 0x3fb8 - } - putch(STK_OK); - 3f7e: 80 e1 ldi r24, 0x10 ; 16 - 3f80: 01 d0 rcall .+2 ; 0x3f84 - 3f82: 6a cf rjmp .-300 ; 0x3e58 - -00003f84 : - } -} - -void putch(char ch) { - 3f84: 98 2f mov r25, r24 -#ifndef SOFT_UART - while (!(UCSR0A & _BV(UDRE0))); - 3f86: 80 91 c0 00 lds r24, 0x00C0 - 3f8a: 85 ff sbrs r24, 5 - 3f8c: fc cf rjmp .-8 ; 0x3f86 - UDR0 = ch; - 3f8e: 90 93 c6 00 sts 0x00C6, r25 - [uartBit] "I" (UART_TX_BIT) - : - "r25" - ); -#endif -} - 3f92: 08 95 ret - -00003f94 : - [uartBit] "I" (UART_RX_BIT) - : - "r25" -); -#else - while(!(UCSR0A & _BV(RXC0))) - 3f94: 80 91 c0 00 lds r24, 0x00C0 - 3f98: 87 ff sbrs r24, 7 - 3f9a: fc cf rjmp .-8 ; 0x3f94 - ; - if (!(UCSR0A & _BV(FE0))) { - 3f9c: 80 91 c0 00 lds r24, 0x00C0 - 3fa0: 84 fd sbrc r24, 4 - 3fa2: 01 c0 rjmp .+2 ; 0x3fa6 -} -#endif - -// Watchdog functions. These are only safe with interrupts turned off. -void watchdogReset() { - __asm__ __volatile__ ( - 3fa4: a8 95 wdr - * don't care that an invalid char is returned...) - */ - watchdogReset(); - } - - ch = UDR0; - 3fa6: 80 91 c6 00 lds r24, 0x00C6 - LED_PIN |= _BV(LED); -#endif -#endif - - return ch; -} - 3faa: 08 95 ret - -00003fac : - "wdr\n" - ); -} - -void watchdogConfig(uint8_t x) { - WDTCSR = _BV(WDCE) | _BV(WDE); - 3fac: e0 e6 ldi r30, 0x60 ; 96 - 3fae: f0 e0 ldi r31, 0x00 ; 0 - 3fb0: 98 e1 ldi r25, 0x18 ; 24 - 3fb2: 90 83 st Z, r25 - WDTCSR = x; - 3fb4: 80 83 st Z, r24 -} - 3fb6: 08 95 ret - -00003fb8 : - do getch(); while (--count); - verifySpace(); -} - -void verifySpace() { - if (getch() != CRC_EOP) { - 3fb8: ed df rcall .-38 ; 0x3f94 - 3fba: 80 32 cpi r24, 0x20 ; 32 - 3fbc: 19 f0 breq .+6 ; 0x3fc4 - watchdogConfig(WATCHDOG_16MS); // shorten WD timeout - 3fbe: 88 e0 ldi r24, 0x08 ; 8 - 3fc0: f5 df rcall .-22 ; 0x3fac - 3fc2: ff cf rjmp .-2 ; 0x3fc2 - while (1) // and busy-loop so that WD causes - ; // a reset and app start. - } - putch(STK_INSYNC); - 3fc4: 84 e1 ldi r24, 0x14 ; 20 -} - 3fc6: de cf rjmp .-68 ; 0x3f84 - -00003fc8 : - ::[count] "M" (UART_B_VALUE) - ); -} -#endif - -void getNch(uint8_t count) { - 3fc8: 1f 93 push r17 - 3fca: 18 2f mov r17, r24 - do getch(); while (--count); - 3fcc: e3 df rcall .-58 ; 0x3f94 - 3fce: 11 50 subi r17, 0x01 ; 1 - 3fd0: e9 f7 brne .-6 ; 0x3fcc - verifySpace(); - 3fd2: f2 df rcall .-28 ; 0x3fb8 -} - 3fd4: 1f 91 pop r17 - 3fd6: 08 95 ret - -00003fd8 : - WDTCSR = _BV(WDCE) | _BV(WDE); - WDTCSR = x; -} - -void appStart() { - watchdogConfig(WATCHDOG_OFF); - 3fd8: 80 e0 ldi r24, 0x00 ; 0 - 3fda: e8 df rcall .-48 ; 0x3fac - __asm__ __volatile__ ( - 3fdc: ee 27 eor r30, r30 - 3fde: ff 27 eor r31, r31 - 3fe0: 09 94 ijmp diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.hex b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.hex deleted file mode 100644 index 2c6339554..000000000 --- a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.hex +++ /dev/null @@ -1,34 +0,0 @@ -:103E0000112484B714BE81FFE7D085E08093810040 -:103E100082E08093C00088E18093C10086E08093B7 -:103E2000C20088E08093C4008EE0C0D0259A86E06E -:103E300028E13EEF91E0309385002093840096BB0B -:103E4000B09BFECF1D9AA8958150A9F79924939411 -:103E5000A5E0AA2EF1E1BF2E9DD0813421F481E0AE -:103E6000B3D083E01FC0823411F484E103C08534F1 -:103E700019F485E0A9D083C0853579F48BD0E82E7C -:103E8000FF2488D0082F10E0102F00270E291F29AB -:103E9000000F111F91D0680172C0863529F484E0AB -:103EA00093D080E06FD06BC0843609F042C072D0EE -:103EB00071D0082F6FD080E0C81688E3D80620F4B0 -:103EC00083E0F60187BFE895C0E0D1E063D0899335 -:103ED0000C17E1F7F0E0CF16F8E3DF0620F083E0FF -:103EE000F60187BFE89568D007B600FCFDCFA601B4 -:103EF000A0E0B1E02C9130E011968C91119790E008 -:103F0000982F8827822B932B1296FA010C0197BECB -:103F1000E89511244E5F5F4FF1E0A038BF0751F7DD -:103F2000F601A7BEE89507B600FCFDCFB7BEE89541 -:103F300026C08437B1F42ED02DD0F82E2BD03CD013 -:103F4000F601EF2C8F010F5F1F4F84911BD0EA9475 -:103F5000F801C1F70894C11CD11CFA94CF0CD11CF4 -:103F60000EC0853739F428D08EE10CD084E90AD010 -:103F700086E098CF813511F488E018D01DD080E11B -:103F800001D06ACF982F8091C00085FFFCCF90931D -:103F9000C60008958091C00087FFFCCF8091C000CB -:103FA00084FD01C0A8958091C6000895E0E6F0E088 -:103FB00098E1908380830895EDDF803219F088E0E6 -:103FC000F5DFFFCF84E1DECF1F93182FE3DF115021 -:103FD000E9F7F2DF1F91089580E0E8DFEE27FF2781 -:023FE000099442 -:023FFE000304BA -:0400000300003E00BB -:00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.lst b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.lst deleted file mode 100644 index 425cbf4a8..000000000 --- a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad.lst +++ /dev/null @@ -1,571 +0,0 @@ - -optiboot_lilypad.elf: file format elf32-avr - -Sections: -Idx Name Size VMA LMA File off Algn - 0 .text 000001e2 00003e00 00003e00 00000054 2**1 - CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .version 00000002 00003ffe 00003ffe 00000236 2**0 - CONTENTS, READONLY - 2 .debug_aranges 00000028 00000000 00000000 00000238 2**0 - CONTENTS, READONLY, DEBUGGING - 3 .debug_pubnames 0000005f 00000000 00000000 00000260 2**0 - CONTENTS, READONLY, DEBUGGING - 4 .debug_info 0000028e 00000000 00000000 000002bf 2**0 - CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 00000171 00000000 00000000 0000054d 2**0 - CONTENTS, READONLY, DEBUGGING - 6 .debug_line 0000045e 00000000 00000000 000006be 2**0 - CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000080 00000000 00000000 00000b1c 2**2 - CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000149 00000000 00000000 00000b9c 2**0 - CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 0000027e 00000000 00000000 00000ce5 2**0 - CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000060 00000000 00000000 00000f63 2**0 - CONTENTS, READONLY, DEBUGGING - -Disassembly of section .text: - -00003e00
    : -#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) -#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) -#endif - -/* main program starts here */ -int main(void) { - 3e00: 11 24 eor r1, r1 -#ifdef __AVR_ATmega8__ - SP=RAMEND; // This is done by hardware reset -#endif - - // Adaboot no-wait mod - ch = MCUSR; - 3e02: 84 b7 in r24, 0x34 ; 52 - MCUSR = 0; - 3e04: 14 be out 0x34, r1 ; 52 - if (!(ch & _BV(EXTRF))) appStart(); - 3e06: 81 ff sbrs r24, 1 - 3e08: e7 d0 rcall .+462 ; 0x3fd8 - -#if LED_START_FLASHES > 0 - // Set up Timer 1 for timeout counter - TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 - 3e0a: 85 e0 ldi r24, 0x05 ; 5 - 3e0c: 80 93 81 00 sts 0x0081, r24 - UCSRA = _BV(U2X); //Double speed mode USART - UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx - UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 - UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); -#else - UCSR0A = _BV(U2X0); //Double speed mode USART0 - 3e10: 82 e0 ldi r24, 0x02 ; 2 - 3e12: 80 93 c0 00 sts 0x00C0, r24 - UCSR0B = _BV(RXEN0) | _BV(TXEN0); - 3e16: 88 e1 ldi r24, 0x18 ; 24 - 3e18: 80 93 c1 00 sts 0x00C1, r24 - UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); - 3e1c: 86 e0 ldi r24, 0x06 ; 6 - 3e1e: 80 93 c2 00 sts 0x00C2, r24 - UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); - 3e22: 88 e0 ldi r24, 0x08 ; 8 - 3e24: 80 93 c4 00 sts 0x00C4, r24 -#endif -#endif - - // Set up watchdog to trigger after 500ms - watchdogConfig(WATCHDOG_1S); - 3e28: 8e e0 ldi r24, 0x0E ; 14 - 3e2a: c0 d0 rcall .+384 ; 0x3fac - - /* Set LED pin as output */ - LED_DDR |= _BV(LED); - 3e2c: 25 9a sbi 0x04, 5 ; 4 - 3e2e: 86 e0 ldi r24, 0x06 ; 6 -} - -#if LED_START_FLASHES > 0 -void flash_led(uint8_t count) { - do { - TCNT1 = -(F_CPU/(1024*16)); - 3e30: 28 e1 ldi r18, 0x18 ; 24 - 3e32: 3e ef ldi r19, 0xFE ; 254 - TIFR1 = _BV(TOV1); - 3e34: 91 e0 ldi r25, 0x01 ; 1 -} - -#if LED_START_FLASHES > 0 -void flash_led(uint8_t count) { - do { - TCNT1 = -(F_CPU/(1024*16)); - 3e36: 30 93 85 00 sts 0x0085, r19 - 3e3a: 20 93 84 00 sts 0x0084, r18 - TIFR1 = _BV(TOV1); - 3e3e: 96 bb out 0x16, r25 ; 22 - while(!(TIFR1 & _BV(TOV1))); - 3e40: b0 9b sbis 0x16, 0 ; 22 - 3e42: fe cf rjmp .-4 ; 0x3e40 -#ifdef __AVR_ATmega8__ - LED_PORT ^= _BV(LED); -#else - LED_PIN |= _BV(LED); - 3e44: 1d 9a sbi 0x03, 5 ; 3 -} -#endif - -// Watchdog functions. These are only safe with interrupts turned off. -void watchdogReset() { - __asm__ __volatile__ ( - 3e46: a8 95 wdr - LED_PORT ^= _BV(LED); -#else - LED_PIN |= _BV(LED); -#endif - watchdogReset(); - } while (--count); - 3e48: 81 50 subi r24, 0x01 ; 1 - 3e4a: a9 f7 brne .-22 ; 0x3e36 - /* get character from UART */ - ch = getch(); - - if(ch == STK_GET_PARAMETER) { - // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy - getNch(1); - 3e4c: 99 24 eor r9, r9 - 3e4e: 93 94 inc r9 - __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - addrPtr += 2; - } while (--ch); - - // Write from programming buffer - __boot_page_write_short((uint16_t)(void*)address); - 3e50: a5 e0 ldi r26, 0x05 ; 5 - 3e52: aa 2e mov r10, r26 - boot_spm_busy_wait(); - -#if defined(RWWSRE) - // Reenable read access to flash - boot_rww_enable(); - 3e54: f1 e1 ldi r31, 0x11 ; 17 - 3e56: bf 2e mov r11, r31 -#endif - - /* Forever loop */ - for (;;) { - /* get character from UART */ - ch = getch(); - 3e58: 9d d0 rcall .+314 ; 0x3f94 - - if(ch == STK_GET_PARAMETER) { - 3e5a: 81 34 cpi r24, 0x41 ; 65 - 3e5c: 21 f4 brne .+8 ; 0x3e66 - // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy - getNch(1); - 3e5e: 81 e0 ldi r24, 0x01 ; 1 - 3e60: b3 d0 rcall .+358 ; 0x3fc8 - putch(0x03); - 3e62: 83 e0 ldi r24, 0x03 ; 3 - 3e64: 1f c0 rjmp .+62 ; 0x3ea4 - } - else if(ch == STK_SET_DEVICE) { - 3e66: 82 34 cpi r24, 0x42 ; 66 - 3e68: 11 f4 brne .+4 ; 0x3e6e - // SET DEVICE is ignored - getNch(20); - 3e6a: 84 e1 ldi r24, 0x14 ; 20 - 3e6c: 03 c0 rjmp .+6 ; 0x3e74 - } - else if(ch == STK_SET_DEVICE_EXT) { - 3e6e: 85 34 cpi r24, 0x45 ; 69 - 3e70: 19 f4 brne .+6 ; 0x3e78 - // SET DEVICE EXT is ignored - getNch(5); - 3e72: 85 e0 ldi r24, 0x05 ; 5 - 3e74: a9 d0 rcall .+338 ; 0x3fc8 - 3e76: 83 c0 rjmp .+262 ; 0x3f7e - } - else if(ch == STK_LOAD_ADDRESS) { - 3e78: 85 35 cpi r24, 0x55 ; 85 - 3e7a: 79 f4 brne .+30 ; 0x3e9a - // LOAD ADDRESS - uint16_t newAddress; - newAddress = getch(); - 3e7c: 8b d0 rcall .+278 ; 0x3f94 - newAddress = (newAddress & 0xff) | (getch() << 8); - 3e7e: e8 2e mov r14, r24 - 3e80: ff 24 eor r15, r15 - 3e82: 88 d0 rcall .+272 ; 0x3f94 - 3e84: 08 2f mov r16, r24 - 3e86: 10 e0 ldi r17, 0x00 ; 0 - 3e88: 10 2f mov r17, r16 - 3e8a: 00 27 eor r16, r16 - 3e8c: 0e 29 or r16, r14 - 3e8e: 1f 29 or r17, r15 -#ifdef RAMPZ - // Transfer top bit to RAMPZ - RAMPZ = (newAddress & 0x8000) ? 1 : 0; -#endif - newAddress += newAddress; // Convert from word address to byte address - 3e90: 00 0f add r16, r16 - 3e92: 11 1f adc r17, r17 - address = newAddress; - verifySpace(); - 3e94: 91 d0 rcall .+290 ; 0x3fb8 - 3e96: 68 01 movw r12, r16 - 3e98: 72 c0 rjmp .+228 ; 0x3f7e - } - else if(ch == STK_UNIVERSAL) { - 3e9a: 86 35 cpi r24, 0x56 ; 86 - 3e9c: 29 f4 brne .+10 ; 0x3ea8 - // UNIVERSAL command is ignored - getNch(4); - 3e9e: 84 e0 ldi r24, 0x04 ; 4 - 3ea0: 93 d0 rcall .+294 ; 0x3fc8 - putch(0x00); - 3ea2: 80 e0 ldi r24, 0x00 ; 0 - 3ea4: 6f d0 rcall .+222 ; 0x3f84 - 3ea6: 6b c0 rjmp .+214 ; 0x3f7e - } - /* Write memory, length is big endian and is in bytes */ - else if(ch == STK_PROG_PAGE) { - 3ea8: 84 36 cpi r24, 0x64 ; 100 - 3eaa: 09 f0 breq .+2 ; 0x3eae - 3eac: 42 c0 rjmp .+132 ; 0x3f32 - // PROGRAM PAGE - we support flash programming only, not EEPROM - uint8_t *bufPtr; - uint16_t addrPtr; - - getch(); /* getlen() */ - 3eae: 72 d0 rcall .+228 ; 0x3f94 - length = getch(); - 3eb0: 71 d0 rcall .+226 ; 0x3f94 - 3eb2: 08 2f mov r16, r24 - getch(); - 3eb4: 6f d0 rcall .+222 ; 0x3f94 - - // If we are in RWW section, immediately start page erase - if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 3eb6: 80 e0 ldi r24, 0x00 ; 0 - 3eb8: c8 16 cp r12, r24 - 3eba: 88 e3 ldi r24, 0x38 ; 56 - 3ebc: d8 06 cpc r13, r24 - 3ebe: 20 f4 brcc .+8 ; 0x3ec8 - 3ec0: 83 e0 ldi r24, 0x03 ; 3 - 3ec2: f6 01 movw r30, r12 - 3ec4: 87 bf out 0x37, r24 ; 55 - 3ec6: e8 95 spm - 3ec8: c0 e0 ldi r28, 0x00 ; 0 - 3eca: d1 e0 ldi r29, 0x01 ; 1 - - // While that is going on, read in page contents - bufPtr = buff; - do *bufPtr++ = getch(); - 3ecc: 63 d0 rcall .+198 ; 0x3f94 - 3ece: 89 93 st Y+, r24 - while (--length); - 3ed0: 0c 17 cp r16, r28 - 3ed2: e1 f7 brne .-8 ; 0x3ecc - - // If we are in NRWW section, page erase has to be delayed until now. - // Todo: Take RAMPZ into account - if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 3ed4: f0 e0 ldi r31, 0x00 ; 0 - 3ed6: cf 16 cp r12, r31 - 3ed8: f8 e3 ldi r31, 0x38 ; 56 - 3eda: df 06 cpc r13, r31 - 3edc: 20 f0 brcs .+8 ; 0x3ee6 - 3ede: 83 e0 ldi r24, 0x03 ; 3 - 3ee0: f6 01 movw r30, r12 - 3ee2: 87 bf out 0x37, r24 ; 55 - 3ee4: e8 95 spm - - // Read command terminator, start reply - verifySpace(); - 3ee6: 68 d0 rcall .+208 ; 0x3fb8 - - // If only a partial page is to be programmed, the erase might not be complete. - // So check that here - boot_spm_busy_wait(); - 3ee8: 07 b6 in r0, 0x37 ; 55 - 3eea: 00 fc sbrc r0, 0 - 3eec: fd cf rjmp .-6 ; 0x3ee8 - 3eee: a6 01 movw r20, r12 - 3ef0: a0 e0 ldi r26, 0x00 ; 0 - 3ef2: b1 e0 ldi r27, 0x01 ; 1 - bufPtr = buff; - addrPtr = (uint16_t)(void*)address; - ch = SPM_PAGESIZE / 2; - do { - uint16_t a; - a = *bufPtr++; - 3ef4: 2c 91 ld r18, X - 3ef6: 30 e0 ldi r19, 0x00 ; 0 - a |= (*bufPtr++) << 8; - 3ef8: 11 96 adiw r26, 0x01 ; 1 - 3efa: 8c 91 ld r24, X - 3efc: 11 97 sbiw r26, 0x01 ; 1 - 3efe: 90 e0 ldi r25, 0x00 ; 0 - 3f00: 98 2f mov r25, r24 - 3f02: 88 27 eor r24, r24 - 3f04: 82 2b or r24, r18 - 3f06: 93 2b or r25, r19 -#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) -#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) -#endif - -/* main program starts here */ -int main(void) { - 3f08: 12 96 adiw r26, 0x02 ; 2 - ch = SPM_PAGESIZE / 2; - do { - uint16_t a; - a = *bufPtr++; - a |= (*bufPtr++) << 8; - __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - 3f0a: fa 01 movw r30, r20 - 3f0c: 0c 01 movw r0, r24 - 3f0e: 97 be out 0x37, r9 ; 55 - 3f10: e8 95 spm - 3f12: 11 24 eor r1, r1 - addrPtr += 2; - 3f14: 4e 5f subi r20, 0xFE ; 254 - 3f16: 5f 4f sbci r21, 0xFF ; 255 - } while (--ch); - 3f18: f1 e0 ldi r31, 0x01 ; 1 - 3f1a: a0 38 cpi r26, 0x80 ; 128 - 3f1c: bf 07 cpc r27, r31 - 3f1e: 51 f7 brne .-44 ; 0x3ef4 - - // Write from programming buffer - __boot_page_write_short((uint16_t)(void*)address); - 3f20: f6 01 movw r30, r12 - 3f22: a7 be out 0x37, r10 ; 55 - 3f24: e8 95 spm - boot_spm_busy_wait(); - 3f26: 07 b6 in r0, 0x37 ; 55 - 3f28: 00 fc sbrc r0, 0 - 3f2a: fd cf rjmp .-6 ; 0x3f26 - -#if defined(RWWSRE) - // Reenable read access to flash - boot_rww_enable(); - 3f2c: b7 be out 0x37, r11 ; 55 - 3f2e: e8 95 spm - 3f30: 26 c0 rjmp .+76 ; 0x3f7e -#endif - - } - /* Read memory block mode, length is big endian. */ - else if(ch == STK_READ_PAGE) { - 3f32: 84 37 cpi r24, 0x74 ; 116 - 3f34: b1 f4 brne .+44 ; 0x3f62 - // READ PAGE - we only read flash - getch(); /* getlen() */ - 3f36: 2e d0 rcall .+92 ; 0x3f94 - length = getch(); - 3f38: 2d d0 rcall .+90 ; 0x3f94 - 3f3a: f8 2e mov r15, r24 - getch(); - 3f3c: 2b d0 rcall .+86 ; 0x3f94 - - verifySpace(); - 3f3e: 3c d0 rcall .+120 ; 0x3fb8 - 3f40: f6 01 movw r30, r12 - 3f42: ef 2c mov r14, r15 - putch(result); - address++; - } - while (--length); -#else - do putch(pgm_read_byte_near(address++)); - 3f44: 8f 01 movw r16, r30 - 3f46: 0f 5f subi r16, 0xFF ; 255 - 3f48: 1f 4f sbci r17, 0xFF ; 255 - 3f4a: 84 91 lpm r24, Z+ - 3f4c: 1b d0 rcall .+54 ; 0x3f84 - while (--length); - 3f4e: ea 94 dec r14 - 3f50: f8 01 movw r30, r16 - 3f52: c1 f7 brne .-16 ; 0x3f44 -#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) -#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) -#endif - -/* main program starts here */ -int main(void) { - 3f54: 08 94 sec - 3f56: c1 1c adc r12, r1 - 3f58: d1 1c adc r13, r1 - 3f5a: fa 94 dec r15 - 3f5c: cf 0c add r12, r15 - 3f5e: d1 1c adc r13, r1 - 3f60: 0e c0 rjmp .+28 ; 0x3f7e -#endif -#endif - } - - /* Get device signature bytes */ - else if(ch == STK_READ_SIGN) { - 3f62: 85 37 cpi r24, 0x75 ; 117 - 3f64: 39 f4 brne .+14 ; 0x3f74 - // READ SIGN - return what Avrdude wants to hear - verifySpace(); - 3f66: 28 d0 rcall .+80 ; 0x3fb8 - putch(SIGNATURE_0); - 3f68: 8e e1 ldi r24, 0x1E ; 30 - 3f6a: 0c d0 rcall .+24 ; 0x3f84 - putch(SIGNATURE_1); - 3f6c: 84 e9 ldi r24, 0x94 ; 148 - 3f6e: 0a d0 rcall .+20 ; 0x3f84 - putch(SIGNATURE_2); - 3f70: 86 e0 ldi r24, 0x06 ; 6 - 3f72: 98 cf rjmp .-208 ; 0x3ea4 - } - else if (ch == 'Q') { - 3f74: 81 35 cpi r24, 0x51 ; 81 - 3f76: 11 f4 brne .+4 ; 0x3f7c - // Adaboot no-wait mod - watchdogConfig(WATCHDOG_16MS); - 3f78: 88 e0 ldi r24, 0x08 ; 8 - 3f7a: 18 d0 rcall .+48 ; 0x3fac - verifySpace(); - } - else { - // This covers the response to commands like STK_ENTER_PROGMODE - verifySpace(); - 3f7c: 1d d0 rcall .+58 ; 0x3fb8 - } - putch(STK_OK); - 3f7e: 80 e1 ldi r24, 0x10 ; 16 - 3f80: 01 d0 rcall .+2 ; 0x3f84 - 3f82: 6a cf rjmp .-300 ; 0x3e58 - -00003f84 : - } -} - -void putch(char ch) { - 3f84: 98 2f mov r25, r24 -#ifndef SOFT_UART - while (!(UCSR0A & _BV(UDRE0))); - 3f86: 80 91 c0 00 lds r24, 0x00C0 - 3f8a: 85 ff sbrs r24, 5 - 3f8c: fc cf rjmp .-8 ; 0x3f86 - UDR0 = ch; - 3f8e: 90 93 c6 00 sts 0x00C6, r25 - [uartBit] "I" (UART_TX_BIT) - : - "r25" - ); -#endif -} - 3f92: 08 95 ret - -00003f94 : - [uartBit] "I" (UART_RX_BIT) - : - "r25" -); -#else - while(!(UCSR0A & _BV(RXC0))) - 3f94: 80 91 c0 00 lds r24, 0x00C0 - 3f98: 87 ff sbrs r24, 7 - 3f9a: fc cf rjmp .-8 ; 0x3f94 - ; - if (!(UCSR0A & _BV(FE0))) { - 3f9c: 80 91 c0 00 lds r24, 0x00C0 - 3fa0: 84 fd sbrc r24, 4 - 3fa2: 01 c0 rjmp .+2 ; 0x3fa6 -} -#endif - -// Watchdog functions. These are only safe with interrupts turned off. -void watchdogReset() { - __asm__ __volatile__ ( - 3fa4: a8 95 wdr - * don't care that an invalid char is returned...) - */ - watchdogReset(); - } - - ch = UDR0; - 3fa6: 80 91 c6 00 lds r24, 0x00C6 - LED_PIN |= _BV(LED); -#endif -#endif - - return ch; -} - 3faa: 08 95 ret - -00003fac : - "wdr\n" - ); -} - -void watchdogConfig(uint8_t x) { - WDTCSR = _BV(WDCE) | _BV(WDE); - 3fac: e0 e6 ldi r30, 0x60 ; 96 - 3fae: f0 e0 ldi r31, 0x00 ; 0 - 3fb0: 98 e1 ldi r25, 0x18 ; 24 - 3fb2: 90 83 st Z, r25 - WDTCSR = x; - 3fb4: 80 83 st Z, r24 -} - 3fb6: 08 95 ret - -00003fb8 : - do getch(); while (--count); - verifySpace(); -} - -void verifySpace() { - if (getch() != CRC_EOP) { - 3fb8: ed df rcall .-38 ; 0x3f94 - 3fba: 80 32 cpi r24, 0x20 ; 32 - 3fbc: 19 f0 breq .+6 ; 0x3fc4 - watchdogConfig(WATCHDOG_16MS); // shorten WD timeout - 3fbe: 88 e0 ldi r24, 0x08 ; 8 - 3fc0: f5 df rcall .-22 ; 0x3fac - 3fc2: ff cf rjmp .-2 ; 0x3fc2 - while (1) // and busy-loop so that WD causes - ; // a reset and app start. - } - putch(STK_INSYNC); - 3fc4: 84 e1 ldi r24, 0x14 ; 20 -} - 3fc6: de cf rjmp .-68 ; 0x3f84 - -00003fc8 : - ::[count] "M" (UART_B_VALUE) - ); -} -#endif - -void getNch(uint8_t count) { - 3fc8: 1f 93 push r17 - 3fca: 18 2f mov r17, r24 - do getch(); while (--count); - 3fcc: e3 df rcall .-58 ; 0x3f94 - 3fce: 11 50 subi r17, 0x01 ; 1 - 3fd0: e9 f7 brne .-6 ; 0x3fcc - verifySpace(); - 3fd2: f2 df rcall .-28 ; 0x3fb8 -} - 3fd4: 1f 91 pop r17 - 3fd6: 08 95 ret - -00003fd8 : - WDTCSR = _BV(WDCE) | _BV(WDE); - WDTCSR = x; -} - -void appStart() { - watchdogConfig(WATCHDOG_OFF); - 3fd8: 80 e0 ldi r24, 0x00 ; 0 - 3fda: e8 df rcall .-48 ; 0x3fac - __asm__ __volatile__ ( - 3fdc: ee 27 eor r30, r30 - 3fde: ff 27 eor r31, r31 - 3fe0: 09 94 ijmp diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.hex b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.hex deleted file mode 100644 index 2c6339554..000000000 --- a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.hex +++ /dev/null @@ -1,34 +0,0 @@ -:103E0000112484B714BE81FFE7D085E08093810040 -:103E100082E08093C00088E18093C10086E08093B7 -:103E2000C20088E08093C4008EE0C0D0259A86E06E -:103E300028E13EEF91E0309385002093840096BB0B -:103E4000B09BFECF1D9AA8958150A9F79924939411 -:103E5000A5E0AA2EF1E1BF2E9DD0813421F481E0AE -:103E6000B3D083E01FC0823411F484E103C08534F1 -:103E700019F485E0A9D083C0853579F48BD0E82E7C -:103E8000FF2488D0082F10E0102F00270E291F29AB -:103E9000000F111F91D0680172C0863529F484E0AB -:103EA00093D080E06FD06BC0843609F042C072D0EE -:103EB00071D0082F6FD080E0C81688E3D80620F4B0 -:103EC00083E0F60187BFE895C0E0D1E063D0899335 -:103ED0000C17E1F7F0E0CF16F8E3DF0620F083E0FF -:103EE000F60187BFE89568D007B600FCFDCFA601B4 -:103EF000A0E0B1E02C9130E011968C91119790E008 -:103F0000982F8827822B932B1296FA010C0197BECB -:103F1000E89511244E5F5F4FF1E0A038BF0751F7DD -:103F2000F601A7BEE89507B600FCFDCFB7BEE89541 -:103F300026C08437B1F42ED02DD0F82E2BD03CD013 -:103F4000F601EF2C8F010F5F1F4F84911BD0EA9475 -:103F5000F801C1F70894C11CD11CFA94CF0CD11CF4 -:103F60000EC0853739F428D08EE10CD084E90AD010 -:103F700086E098CF813511F488E018D01DD080E11B -:103F800001D06ACF982F8091C00085FFFCCF90931D -:103F9000C60008958091C00087FFFCCF8091C000CB -:103FA00084FD01C0A8958091C6000895E0E6F0E088 -:103FB00098E1908380830895EDDF803219F088E0E6 -:103FC000F5DFFFCF84E1DECF1F93182FE3DF115021 -:103FD000E9F7F2DF1F91089580E0E8DFEE27FF2781 -:023FE000099442 -:023FFE000304BA -:0400000300003E00BB -:00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.lst b/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.lst deleted file mode 100644 index cb0ea83cd..000000000 --- a/hardware/arduino/bootloaders/optiboot/optiboot_lilypad_resonator.lst +++ /dev/null @@ -1,571 +0,0 @@ - -optiboot_lilypad_resonator.elf: file format elf32-avr - -Sections: -Idx Name Size VMA LMA File off Algn - 0 .text 000001e2 00003e00 00003e00 00000054 2**1 - CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .version 00000002 00003ffe 00003ffe 00000236 2**0 - CONTENTS, READONLY - 2 .debug_aranges 00000028 00000000 00000000 00000238 2**0 - CONTENTS, READONLY, DEBUGGING - 3 .debug_pubnames 0000005f 00000000 00000000 00000260 2**0 - CONTENTS, READONLY, DEBUGGING - 4 .debug_info 0000028e 00000000 00000000 000002bf 2**0 - CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 00000171 00000000 00000000 0000054d 2**0 - CONTENTS, READONLY, DEBUGGING - 6 .debug_line 0000045e 00000000 00000000 000006be 2**0 - CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000080 00000000 00000000 00000b1c 2**2 - CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000149 00000000 00000000 00000b9c 2**0 - CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 0000027e 00000000 00000000 00000ce5 2**0 - CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000060 00000000 00000000 00000f63 2**0 - CONTENTS, READONLY, DEBUGGING - -Disassembly of section .text: - -00003e00
    : -#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) -#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) -#endif - -/* main program starts here */ -int main(void) { - 3e00: 11 24 eor r1, r1 -#ifdef __AVR_ATmega8__ - SP=RAMEND; // This is done by hardware reset -#endif - - // Adaboot no-wait mod - ch = MCUSR; - 3e02: 84 b7 in r24, 0x34 ; 52 - MCUSR = 0; - 3e04: 14 be out 0x34, r1 ; 52 - if (!(ch & _BV(EXTRF))) appStart(); - 3e06: 81 ff sbrs r24, 1 - 3e08: e7 d0 rcall .+462 ; 0x3fd8 - -#if LED_START_FLASHES > 0 - // Set up Timer 1 for timeout counter - TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 - 3e0a: 85 e0 ldi r24, 0x05 ; 5 - 3e0c: 80 93 81 00 sts 0x0081, r24 - UCSRA = _BV(U2X); //Double speed mode USART - UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx - UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 - UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); -#else - UCSR0A = _BV(U2X0); //Double speed mode USART0 - 3e10: 82 e0 ldi r24, 0x02 ; 2 - 3e12: 80 93 c0 00 sts 0x00C0, r24 - UCSR0B = _BV(RXEN0) | _BV(TXEN0); - 3e16: 88 e1 ldi r24, 0x18 ; 24 - 3e18: 80 93 c1 00 sts 0x00C1, r24 - UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); - 3e1c: 86 e0 ldi r24, 0x06 ; 6 - 3e1e: 80 93 c2 00 sts 0x00C2, r24 - UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); - 3e22: 88 e0 ldi r24, 0x08 ; 8 - 3e24: 80 93 c4 00 sts 0x00C4, r24 -#endif -#endif - - // Set up watchdog to trigger after 500ms - watchdogConfig(WATCHDOG_1S); - 3e28: 8e e0 ldi r24, 0x0E ; 14 - 3e2a: c0 d0 rcall .+384 ; 0x3fac - - /* Set LED pin as output */ - LED_DDR |= _BV(LED); - 3e2c: 25 9a sbi 0x04, 5 ; 4 - 3e2e: 86 e0 ldi r24, 0x06 ; 6 -} - -#if LED_START_FLASHES > 0 -void flash_led(uint8_t count) { - do { - TCNT1 = -(F_CPU/(1024*16)); - 3e30: 28 e1 ldi r18, 0x18 ; 24 - 3e32: 3e ef ldi r19, 0xFE ; 254 - TIFR1 = _BV(TOV1); - 3e34: 91 e0 ldi r25, 0x01 ; 1 -} - -#if LED_START_FLASHES > 0 -void flash_led(uint8_t count) { - do { - TCNT1 = -(F_CPU/(1024*16)); - 3e36: 30 93 85 00 sts 0x0085, r19 - 3e3a: 20 93 84 00 sts 0x0084, r18 - TIFR1 = _BV(TOV1); - 3e3e: 96 bb out 0x16, r25 ; 22 - while(!(TIFR1 & _BV(TOV1))); - 3e40: b0 9b sbis 0x16, 0 ; 22 - 3e42: fe cf rjmp .-4 ; 0x3e40 -#ifdef __AVR_ATmega8__ - LED_PORT ^= _BV(LED); -#else - LED_PIN |= _BV(LED); - 3e44: 1d 9a sbi 0x03, 5 ; 3 -} -#endif - -// Watchdog functions. These are only safe with interrupts turned off. -void watchdogReset() { - __asm__ __volatile__ ( - 3e46: a8 95 wdr - LED_PORT ^= _BV(LED); -#else - LED_PIN |= _BV(LED); -#endif - watchdogReset(); - } while (--count); - 3e48: 81 50 subi r24, 0x01 ; 1 - 3e4a: a9 f7 brne .-22 ; 0x3e36 - /* get character from UART */ - ch = getch(); - - if(ch == STK_GET_PARAMETER) { - // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy - getNch(1); - 3e4c: 99 24 eor r9, r9 - 3e4e: 93 94 inc r9 - __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - addrPtr += 2; - } while (--ch); - - // Write from programming buffer - __boot_page_write_short((uint16_t)(void*)address); - 3e50: a5 e0 ldi r26, 0x05 ; 5 - 3e52: aa 2e mov r10, r26 - boot_spm_busy_wait(); - -#if defined(RWWSRE) - // Reenable read access to flash - boot_rww_enable(); - 3e54: f1 e1 ldi r31, 0x11 ; 17 - 3e56: bf 2e mov r11, r31 -#endif - - /* Forever loop */ - for (;;) { - /* get character from UART */ - ch = getch(); - 3e58: 9d d0 rcall .+314 ; 0x3f94 - - if(ch == STK_GET_PARAMETER) { - 3e5a: 81 34 cpi r24, 0x41 ; 65 - 3e5c: 21 f4 brne .+8 ; 0x3e66 - // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy - getNch(1); - 3e5e: 81 e0 ldi r24, 0x01 ; 1 - 3e60: b3 d0 rcall .+358 ; 0x3fc8 - putch(0x03); - 3e62: 83 e0 ldi r24, 0x03 ; 3 - 3e64: 1f c0 rjmp .+62 ; 0x3ea4 - } - else if(ch == STK_SET_DEVICE) { - 3e66: 82 34 cpi r24, 0x42 ; 66 - 3e68: 11 f4 brne .+4 ; 0x3e6e - // SET DEVICE is ignored - getNch(20); - 3e6a: 84 e1 ldi r24, 0x14 ; 20 - 3e6c: 03 c0 rjmp .+6 ; 0x3e74 - } - else if(ch == STK_SET_DEVICE_EXT) { - 3e6e: 85 34 cpi r24, 0x45 ; 69 - 3e70: 19 f4 brne .+6 ; 0x3e78 - // SET DEVICE EXT is ignored - getNch(5); - 3e72: 85 e0 ldi r24, 0x05 ; 5 - 3e74: a9 d0 rcall .+338 ; 0x3fc8 - 3e76: 83 c0 rjmp .+262 ; 0x3f7e - } - else if(ch == STK_LOAD_ADDRESS) { - 3e78: 85 35 cpi r24, 0x55 ; 85 - 3e7a: 79 f4 brne .+30 ; 0x3e9a - // LOAD ADDRESS - uint16_t newAddress; - newAddress = getch(); - 3e7c: 8b d0 rcall .+278 ; 0x3f94 - newAddress = (newAddress & 0xff) | (getch() << 8); - 3e7e: e8 2e mov r14, r24 - 3e80: ff 24 eor r15, r15 - 3e82: 88 d0 rcall .+272 ; 0x3f94 - 3e84: 08 2f mov r16, r24 - 3e86: 10 e0 ldi r17, 0x00 ; 0 - 3e88: 10 2f mov r17, r16 - 3e8a: 00 27 eor r16, r16 - 3e8c: 0e 29 or r16, r14 - 3e8e: 1f 29 or r17, r15 -#ifdef RAMPZ - // Transfer top bit to RAMPZ - RAMPZ = (newAddress & 0x8000) ? 1 : 0; -#endif - newAddress += newAddress; // Convert from word address to byte address - 3e90: 00 0f add r16, r16 - 3e92: 11 1f adc r17, r17 - address = newAddress; - verifySpace(); - 3e94: 91 d0 rcall .+290 ; 0x3fb8 - 3e96: 68 01 movw r12, r16 - 3e98: 72 c0 rjmp .+228 ; 0x3f7e - } - else if(ch == STK_UNIVERSAL) { - 3e9a: 86 35 cpi r24, 0x56 ; 86 - 3e9c: 29 f4 brne .+10 ; 0x3ea8 - // UNIVERSAL command is ignored - getNch(4); - 3e9e: 84 e0 ldi r24, 0x04 ; 4 - 3ea0: 93 d0 rcall .+294 ; 0x3fc8 - putch(0x00); - 3ea2: 80 e0 ldi r24, 0x00 ; 0 - 3ea4: 6f d0 rcall .+222 ; 0x3f84 - 3ea6: 6b c0 rjmp .+214 ; 0x3f7e - } - /* Write memory, length is big endian and is in bytes */ - else if(ch == STK_PROG_PAGE) { - 3ea8: 84 36 cpi r24, 0x64 ; 100 - 3eaa: 09 f0 breq .+2 ; 0x3eae - 3eac: 42 c0 rjmp .+132 ; 0x3f32 - // PROGRAM PAGE - we support flash programming only, not EEPROM - uint8_t *bufPtr; - uint16_t addrPtr; - - getch(); /* getlen() */ - 3eae: 72 d0 rcall .+228 ; 0x3f94 - length = getch(); - 3eb0: 71 d0 rcall .+226 ; 0x3f94 - 3eb2: 08 2f mov r16, r24 - getch(); - 3eb4: 6f d0 rcall .+222 ; 0x3f94 - - // If we are in RWW section, immediately start page erase - if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 3eb6: 80 e0 ldi r24, 0x00 ; 0 - 3eb8: c8 16 cp r12, r24 - 3eba: 88 e3 ldi r24, 0x38 ; 56 - 3ebc: d8 06 cpc r13, r24 - 3ebe: 20 f4 brcc .+8 ; 0x3ec8 - 3ec0: 83 e0 ldi r24, 0x03 ; 3 - 3ec2: f6 01 movw r30, r12 - 3ec4: 87 bf out 0x37, r24 ; 55 - 3ec6: e8 95 spm - 3ec8: c0 e0 ldi r28, 0x00 ; 0 - 3eca: d1 e0 ldi r29, 0x01 ; 1 - - // While that is going on, read in page contents - bufPtr = buff; - do *bufPtr++ = getch(); - 3ecc: 63 d0 rcall .+198 ; 0x3f94 - 3ece: 89 93 st Y+, r24 - while (--length); - 3ed0: 0c 17 cp r16, r28 - 3ed2: e1 f7 brne .-8 ; 0x3ecc - - // If we are in NRWW section, page erase has to be delayed until now. - // Todo: Take RAMPZ into account - if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 3ed4: f0 e0 ldi r31, 0x00 ; 0 - 3ed6: cf 16 cp r12, r31 - 3ed8: f8 e3 ldi r31, 0x38 ; 56 - 3eda: df 06 cpc r13, r31 - 3edc: 20 f0 brcs .+8 ; 0x3ee6 - 3ede: 83 e0 ldi r24, 0x03 ; 3 - 3ee0: f6 01 movw r30, r12 - 3ee2: 87 bf out 0x37, r24 ; 55 - 3ee4: e8 95 spm - - // Read command terminator, start reply - verifySpace(); - 3ee6: 68 d0 rcall .+208 ; 0x3fb8 - - // If only a partial page is to be programmed, the erase might not be complete. - // So check that here - boot_spm_busy_wait(); - 3ee8: 07 b6 in r0, 0x37 ; 55 - 3eea: 00 fc sbrc r0, 0 - 3eec: fd cf rjmp .-6 ; 0x3ee8 - 3eee: a6 01 movw r20, r12 - 3ef0: a0 e0 ldi r26, 0x00 ; 0 - 3ef2: b1 e0 ldi r27, 0x01 ; 1 - bufPtr = buff; - addrPtr = (uint16_t)(void*)address; - ch = SPM_PAGESIZE / 2; - do { - uint16_t a; - a = *bufPtr++; - 3ef4: 2c 91 ld r18, X - 3ef6: 30 e0 ldi r19, 0x00 ; 0 - a |= (*bufPtr++) << 8; - 3ef8: 11 96 adiw r26, 0x01 ; 1 - 3efa: 8c 91 ld r24, X - 3efc: 11 97 sbiw r26, 0x01 ; 1 - 3efe: 90 e0 ldi r25, 0x00 ; 0 - 3f00: 98 2f mov r25, r24 - 3f02: 88 27 eor r24, r24 - 3f04: 82 2b or r24, r18 - 3f06: 93 2b or r25, r19 -#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) -#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) -#endif - -/* main program starts here */ -int main(void) { - 3f08: 12 96 adiw r26, 0x02 ; 2 - ch = SPM_PAGESIZE / 2; - do { - uint16_t a; - a = *bufPtr++; - a |= (*bufPtr++) << 8; - __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - 3f0a: fa 01 movw r30, r20 - 3f0c: 0c 01 movw r0, r24 - 3f0e: 97 be out 0x37, r9 ; 55 - 3f10: e8 95 spm - 3f12: 11 24 eor r1, r1 - addrPtr += 2; - 3f14: 4e 5f subi r20, 0xFE ; 254 - 3f16: 5f 4f sbci r21, 0xFF ; 255 - } while (--ch); - 3f18: f1 e0 ldi r31, 0x01 ; 1 - 3f1a: a0 38 cpi r26, 0x80 ; 128 - 3f1c: bf 07 cpc r27, r31 - 3f1e: 51 f7 brne .-44 ; 0x3ef4 - - // Write from programming buffer - __boot_page_write_short((uint16_t)(void*)address); - 3f20: f6 01 movw r30, r12 - 3f22: a7 be out 0x37, r10 ; 55 - 3f24: e8 95 spm - boot_spm_busy_wait(); - 3f26: 07 b6 in r0, 0x37 ; 55 - 3f28: 00 fc sbrc r0, 0 - 3f2a: fd cf rjmp .-6 ; 0x3f26 - -#if defined(RWWSRE) - // Reenable read access to flash - boot_rww_enable(); - 3f2c: b7 be out 0x37, r11 ; 55 - 3f2e: e8 95 spm - 3f30: 26 c0 rjmp .+76 ; 0x3f7e -#endif - - } - /* Read memory block mode, length is big endian. */ - else if(ch == STK_READ_PAGE) { - 3f32: 84 37 cpi r24, 0x74 ; 116 - 3f34: b1 f4 brne .+44 ; 0x3f62 - // READ PAGE - we only read flash - getch(); /* getlen() */ - 3f36: 2e d0 rcall .+92 ; 0x3f94 - length = getch(); - 3f38: 2d d0 rcall .+90 ; 0x3f94 - 3f3a: f8 2e mov r15, r24 - getch(); - 3f3c: 2b d0 rcall .+86 ; 0x3f94 - - verifySpace(); - 3f3e: 3c d0 rcall .+120 ; 0x3fb8 - 3f40: f6 01 movw r30, r12 - 3f42: ef 2c mov r14, r15 - putch(result); - address++; - } - while (--length); -#else - do putch(pgm_read_byte_near(address++)); - 3f44: 8f 01 movw r16, r30 - 3f46: 0f 5f subi r16, 0xFF ; 255 - 3f48: 1f 4f sbci r17, 0xFF ; 255 - 3f4a: 84 91 lpm r24, Z+ - 3f4c: 1b d0 rcall .+54 ; 0x3f84 - while (--length); - 3f4e: ea 94 dec r14 - 3f50: f8 01 movw r30, r16 - 3f52: c1 f7 brne .-16 ; 0x3f44 -#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) -#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) -#endif - -/* main program starts here */ -int main(void) { - 3f54: 08 94 sec - 3f56: c1 1c adc r12, r1 - 3f58: d1 1c adc r13, r1 - 3f5a: fa 94 dec r15 - 3f5c: cf 0c add r12, r15 - 3f5e: d1 1c adc r13, r1 - 3f60: 0e c0 rjmp .+28 ; 0x3f7e -#endif -#endif - } - - /* Get device signature bytes */ - else if(ch == STK_READ_SIGN) { - 3f62: 85 37 cpi r24, 0x75 ; 117 - 3f64: 39 f4 brne .+14 ; 0x3f74 - // READ SIGN - return what Avrdude wants to hear - verifySpace(); - 3f66: 28 d0 rcall .+80 ; 0x3fb8 - putch(SIGNATURE_0); - 3f68: 8e e1 ldi r24, 0x1E ; 30 - 3f6a: 0c d0 rcall .+24 ; 0x3f84 - putch(SIGNATURE_1); - 3f6c: 84 e9 ldi r24, 0x94 ; 148 - 3f6e: 0a d0 rcall .+20 ; 0x3f84 - putch(SIGNATURE_2); - 3f70: 86 e0 ldi r24, 0x06 ; 6 - 3f72: 98 cf rjmp .-208 ; 0x3ea4 - } - else if (ch == 'Q') { - 3f74: 81 35 cpi r24, 0x51 ; 81 - 3f76: 11 f4 brne .+4 ; 0x3f7c - // Adaboot no-wait mod - watchdogConfig(WATCHDOG_16MS); - 3f78: 88 e0 ldi r24, 0x08 ; 8 - 3f7a: 18 d0 rcall .+48 ; 0x3fac - verifySpace(); - } - else { - // This covers the response to commands like STK_ENTER_PROGMODE - verifySpace(); - 3f7c: 1d d0 rcall .+58 ; 0x3fb8 - } - putch(STK_OK); - 3f7e: 80 e1 ldi r24, 0x10 ; 16 - 3f80: 01 d0 rcall .+2 ; 0x3f84 - 3f82: 6a cf rjmp .-300 ; 0x3e58 - -00003f84 : - } -} - -void putch(char ch) { - 3f84: 98 2f mov r25, r24 -#ifndef SOFT_UART - while (!(UCSR0A & _BV(UDRE0))); - 3f86: 80 91 c0 00 lds r24, 0x00C0 - 3f8a: 85 ff sbrs r24, 5 - 3f8c: fc cf rjmp .-8 ; 0x3f86 - UDR0 = ch; - 3f8e: 90 93 c6 00 sts 0x00C6, r25 - [uartBit] "I" (UART_TX_BIT) - : - "r25" - ); -#endif -} - 3f92: 08 95 ret - -00003f94 : - [uartBit] "I" (UART_RX_BIT) - : - "r25" -); -#else - while(!(UCSR0A & _BV(RXC0))) - 3f94: 80 91 c0 00 lds r24, 0x00C0 - 3f98: 87 ff sbrs r24, 7 - 3f9a: fc cf rjmp .-8 ; 0x3f94 - ; - if (!(UCSR0A & _BV(FE0))) { - 3f9c: 80 91 c0 00 lds r24, 0x00C0 - 3fa0: 84 fd sbrc r24, 4 - 3fa2: 01 c0 rjmp .+2 ; 0x3fa6 -} -#endif - -// Watchdog functions. These are only safe with interrupts turned off. -void watchdogReset() { - __asm__ __volatile__ ( - 3fa4: a8 95 wdr - * don't care that an invalid char is returned...) - */ - watchdogReset(); - } - - ch = UDR0; - 3fa6: 80 91 c6 00 lds r24, 0x00C6 - LED_PIN |= _BV(LED); -#endif -#endif - - return ch; -} - 3faa: 08 95 ret - -00003fac : - "wdr\n" - ); -} - -void watchdogConfig(uint8_t x) { - WDTCSR = _BV(WDCE) | _BV(WDE); - 3fac: e0 e6 ldi r30, 0x60 ; 96 - 3fae: f0 e0 ldi r31, 0x00 ; 0 - 3fb0: 98 e1 ldi r25, 0x18 ; 24 - 3fb2: 90 83 st Z, r25 - WDTCSR = x; - 3fb4: 80 83 st Z, r24 -} - 3fb6: 08 95 ret - -00003fb8 : - do getch(); while (--count); - verifySpace(); -} - -void verifySpace() { - if (getch() != CRC_EOP) { - 3fb8: ed df rcall .-38 ; 0x3f94 - 3fba: 80 32 cpi r24, 0x20 ; 32 - 3fbc: 19 f0 breq .+6 ; 0x3fc4 - watchdogConfig(WATCHDOG_16MS); // shorten WD timeout - 3fbe: 88 e0 ldi r24, 0x08 ; 8 - 3fc0: f5 df rcall .-22 ; 0x3fac - 3fc2: ff cf rjmp .-2 ; 0x3fc2 - while (1) // and busy-loop so that WD causes - ; // a reset and app start. - } - putch(STK_INSYNC); - 3fc4: 84 e1 ldi r24, 0x14 ; 20 -} - 3fc6: de cf rjmp .-68 ; 0x3f84 - -00003fc8 : - ::[count] "M" (UART_B_VALUE) - ); -} -#endif - -void getNch(uint8_t count) { - 3fc8: 1f 93 push r17 - 3fca: 18 2f mov r17, r24 - do getch(); while (--count); - 3fcc: e3 df rcall .-58 ; 0x3f94 - 3fce: 11 50 subi r17, 0x01 ; 1 - 3fd0: e9 f7 brne .-6 ; 0x3fcc - verifySpace(); - 3fd2: f2 df rcall .-28 ; 0x3fb8 -} - 3fd4: 1f 91 pop r17 - 3fd6: 08 95 ret - -00003fd8 : - WDTCSR = _BV(WDCE) | _BV(WDE); - WDTCSR = x; -} - -void appStart() { - watchdogConfig(WATCHDOG_OFF); - 3fd8: 80 e0 ldi r24, 0x00 ; 0 - 3fda: e8 df rcall .-48 ; 0x3fac - __asm__ __volatile__ ( - 3fdc: ee 27 eor r30, r30 - 3fde: ff 27 eor r31, r31 - 3fe0: 09 94 ijmp diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_luminet.hex b/hardware/arduino/bootloaders/optiboot/optiboot_luminet.hex deleted file mode 100644 index 45b4dcd34..000000000 --- a/hardware/arduino/bootloaders/optiboot/optiboot_luminet.hex +++ /dev/null @@ -1,40 +0,0 @@ -:101D0000112484B714BE81FF17D185E08EBD8EE00B -:101D1000FFD0D49AD29A86E023EC3FEF91E03DBD0C -:101D20002CBD9BB9589BFECFCC9AA8958150B9F792 -:101D3000BB24B39425E0A22E9FE7D92E8EECC82EAB -:101D4000D4D0813421F481E0EFD083E0B5C0823477 -:101D500011F484E103C0853419F485E0E5D0B3C003 -:101D6000853569F4C2D0E82EFF24BFD0082F10E0DB -:101D7000102F00270E291F29000F111FA3C0863521 -:101D800021F484E0D1D080E097C0843609F060C0AF -:101D9000ACD0ABD0F82EA9D0C0E0D1E0A6D08993CA -:101DA000FC16E1F783E0F80187BFE895B5D007B6E8 -:101DB00000FCFDCF0115110511F0A8012AC080918A -:101DC00000012091010130E0322F222790E0282BE2 -:101DD000392B309385012093840140910801809133 -:101DE000090190E0982F882750E0842B952B909341 -:101DF0008701809386012450304020930801232FCF -:101E0000332720930901D0920001C092010140E0E4 -:101E100050E0A0E0B1E02C9130E011968C91119748 -:101E200090E0982F8827822B932B1296FA010C01B1 -:101E3000B7BEE89511244E5F5F4FF1E0A034BF07B5 -:101E400051F7F801A7BEE89507B600FCFDCF3BC0EF -:101E5000843751F54AD049D0F82E47D05DD0E801FB -:101E6000EF2C209719F48091840114C0C130D10562 -:101E700019F4809185010EC0C830D10519F4809104 -:101E8000860108C0C930D10519F48091870102C0CC -:101E9000FE01849121961AD0EA9419F70F5F1F4F23 -:101EA000FA940F0D111D0FC0853741F435D08EE126 -:101EB0000DD083E90BD08CE009D005C0813511F439 -:101EC00088E026D029D080E101D03ACF2AE030E066 -:101ED0008095089410F4DA9802C0DA9A000014D0C1 -:101EE00013D086952A95B1F7089529E030E0CB9973 -:101EF000FECF0AD009D008D08894CB9908942A95AF -:101F000011F08795F7CF08959EE09A95F1F708951F -:101F100098E191BD81BD0895E8DF803219F088E035 -:101F2000F7DFFFCF84E1D2CF1F93182FDEDF1150F0 -:101F3000E9F7F2DF1F91089580E0EADFE4E0FF2790 -:021F4000099402 -:021EFE000304DB -:0400000300001D00DC -:00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_luminet.lst b/hardware/arduino/bootloaders/optiboot/optiboot_luminet.lst deleted file mode 100644 index e40e0ef26..000000000 --- a/hardware/arduino/bootloaders/optiboot/optiboot_luminet.lst +++ /dev/null @@ -1,617 +0,0 @@ - -optiboot_luminet.elf: file format elf32-avr - -Sections: -Idx Name Size VMA LMA File off Algn - 0 .text 00000242 00001d00 00001d00 00000054 2**1 - CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .version 00000002 00001efe 00001efe 00000296 2**0 - CONTENTS, READONLY - 2 .debug_aranges 00000028 00000000 00000000 00000298 2**0 - CONTENTS, READONLY, DEBUGGING - 3 .debug_pubnames 0000006d 00000000 00000000 000002c0 2**0 - CONTENTS, READONLY, DEBUGGING - 4 .debug_info 000002a2 00000000 00000000 0000032d 2**0 - CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 0000016f 00000000 00000000 000005cf 2**0 - CONTENTS, READONLY, DEBUGGING - 6 .debug_line 0000049d 00000000 00000000 0000073e 2**0 - CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000090 00000000 00000000 00000bdc 2**2 - CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000158 00000000 00000000 00000c6c 2**0 - CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 00000268 00000000 00000000 00000dc4 2**0 - CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000080 00000000 00000000 0000102c 2**0 - CONTENTS, READONLY, DEBUGGING - -Disassembly of section .text: - -00001d00
    : -#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) -#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) -#endif - -/* main program starts here */ -int main(void) { - 1d00: 11 24 eor r1, r1 -#ifdef __AVR_ATmega8__ - SP=RAMEND; // This is done by hardware reset -#endif - - // Adaboot no-wait mod - ch = MCUSR; - 1d02: 84 b7 in r24, 0x34 ; 52 - MCUSR = 0; - 1d04: 14 be out 0x34, r1 ; 52 - if (!(ch & _BV(EXTRF))) appStart(); - 1d06: 81 ff sbrs r24, 1 - 1d08: 17 d1 rcall .+558 ; 0x1f38 - -#if LED_START_FLASHES > 0 - // Set up Timer 1 for timeout counter - TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 - 1d0a: 85 e0 ldi r24, 0x05 ; 5 - 1d0c: 8e bd out 0x2e, r24 ; 46 - UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); -#endif -#endif - - // Set up watchdog to trigger after 500ms - watchdogConfig(WATCHDOG_1S); - 1d0e: 8e e0 ldi r24, 0x0E ; 14 - 1d10: ff d0 rcall .+510 ; 0x1f10 - - /* Set LED pin as output */ - LED_DDR |= _BV(LED); - 1d12: d4 9a sbi 0x1a, 4 ; 26 - -#ifdef SOFT_UART - /* Set TX pin as output */ - UART_DDR |= _BV(UART_TX_BIT); - 1d14: d2 9a sbi 0x1a, 2 ; 26 - 1d16: 86 e0 ldi r24, 0x06 ; 6 -} - -#if LED_START_FLASHES > 0 -void flash_led(uint8_t count) { - do { - TCNT1 = -(F_CPU/(1024*16)); - 1d18: 23 ec ldi r18, 0xC3 ; 195 - 1d1a: 3f ef ldi r19, 0xFF ; 255 - TIFR1 = _BV(TOV1); - 1d1c: 91 e0 ldi r25, 0x01 ; 1 -} - -#if LED_START_FLASHES > 0 -void flash_led(uint8_t count) { - do { - TCNT1 = -(F_CPU/(1024*16)); - 1d1e: 3d bd out 0x2d, r19 ; 45 - 1d20: 2c bd out 0x2c, r18 ; 44 - TIFR1 = _BV(TOV1); - 1d22: 9b b9 out 0x0b, r25 ; 11 - while(!(TIFR1 & _BV(TOV1))); - 1d24: 58 9b sbis 0x0b, 0 ; 11 - 1d26: fe cf rjmp .-4 ; 0x1d24 -#ifdef __AVR_ATmega8__ - LED_PORT ^= _BV(LED); -#else - LED_PIN |= _BV(LED); - 1d28: cc 9a sbi 0x19, 4 ; 25 -} -#endif - -// Watchdog functions. These are only safe with interrupts turned off. -void watchdogReset() { - __asm__ __volatile__ ( - 1d2a: a8 95 wdr - LED_PORT ^= _BV(LED); -#else - LED_PIN |= _BV(LED); -#endif - watchdogReset(); - } while (--count); - 1d2c: 81 50 subi r24, 0x01 ; 1 - 1d2e: b9 f7 brne .-18 ; 0x1d1e - /* get character from UART */ - ch = getch(); - - if(ch == STK_GET_PARAMETER) { - // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy - getNch(1); - 1d30: bb 24 eor r11, r11 - 1d32: b3 94 inc r11 - __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - addrPtr += 2; - } while (--ch); - - // Write from programming buffer - __boot_page_write_short((uint16_t)(void*)address); - 1d34: 25 e0 ldi r18, 0x05 ; 5 - 1d36: a2 2e mov r10, r18 - vect -= 4; // Instruction is a relative jump (rjmp), so recalculate. - buff[8] = vect & 0xff; - buff[9] = vect >> 8; - - // Add jump to bootloader at RESET vector - buff[0] = 0x7f; - 1d38: 9f e7 ldi r25, 0x7F ; 127 - 1d3a: d9 2e mov r13, r25 - buff[1] = 0xce; // rjmp 0x1d00 instruction - 1d3c: 8e ec ldi r24, 0xCE ; 206 - 1d3e: c8 2e mov r12, r24 -#endif - - /* Forever loop */ - for (;;) { - /* get character from UART */ - ch = getch(); - 1d40: d4 d0 rcall .+424 ; 0x1eea - - if(ch == STK_GET_PARAMETER) { - 1d42: 81 34 cpi r24, 0x41 ; 65 - 1d44: 21 f4 brne .+8 ; 0x1d4e - // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy - getNch(1); - 1d46: 81 e0 ldi r24, 0x01 ; 1 - 1d48: ef d0 rcall .+478 ; 0x1f28 - putch(0x03); - 1d4a: 83 e0 ldi r24, 0x03 ; 3 - 1d4c: b5 c0 rjmp .+362 ; 0x1eb8 - } - else if(ch == STK_SET_DEVICE) { - 1d4e: 82 34 cpi r24, 0x42 ; 66 - 1d50: 11 f4 brne .+4 ; 0x1d56 - // SET DEVICE is ignored - getNch(20); - 1d52: 84 e1 ldi r24, 0x14 ; 20 - 1d54: 03 c0 rjmp .+6 ; 0x1d5c - } - else if(ch == STK_SET_DEVICE_EXT) { - 1d56: 85 34 cpi r24, 0x45 ; 69 - 1d58: 19 f4 brne .+6 ; 0x1d60 - // SET DEVICE EXT is ignored - getNch(5); - 1d5a: 85 e0 ldi r24, 0x05 ; 5 - 1d5c: e5 d0 rcall .+458 ; 0x1f28 - 1d5e: b3 c0 rjmp .+358 ; 0x1ec6 - } - else if(ch == STK_LOAD_ADDRESS) { - 1d60: 85 35 cpi r24, 0x55 ; 85 - 1d62: 69 f4 brne .+26 ; 0x1d7e - // LOAD ADDRESS - uint16_t newAddress; - newAddress = getch(); - 1d64: c2 d0 rcall .+388 ; 0x1eea - newAddress = (newAddress & 0xff) | (getch() << 8); - 1d66: e8 2e mov r14, r24 - 1d68: ff 24 eor r15, r15 - 1d6a: bf d0 rcall .+382 ; 0x1eea - 1d6c: 08 2f mov r16, r24 - 1d6e: 10 e0 ldi r17, 0x00 ; 0 - 1d70: 10 2f mov r17, r16 - 1d72: 00 27 eor r16, r16 - 1d74: 0e 29 or r16, r14 - 1d76: 1f 29 or r17, r15 -#ifdef RAMPZ - // Transfer top bit to RAMPZ - RAMPZ = (newAddress & 0x8000) ? 1 : 0; -#endif - newAddress += newAddress; // Convert from word address to byte address - 1d78: 00 0f add r16, r16 - 1d7a: 11 1f adc r17, r17 - 1d7c: a3 c0 rjmp .+326 ; 0x1ec4 - address = newAddress; - verifySpace(); - } - else if(ch == STK_UNIVERSAL) { - 1d7e: 86 35 cpi r24, 0x56 ; 86 - 1d80: 21 f4 brne .+8 ; 0x1d8a - // UNIVERSAL command is ignored - getNch(4); - 1d82: 84 e0 ldi r24, 0x04 ; 4 - 1d84: d1 d0 rcall .+418 ; 0x1f28 - putch(0x00); - 1d86: 80 e0 ldi r24, 0x00 ; 0 - 1d88: 97 c0 rjmp .+302 ; 0x1eb8 - } - /* Write memory, length is big endian and is in bytes */ - else if(ch == STK_PROG_PAGE) { - 1d8a: 84 36 cpi r24, 0x64 ; 100 - 1d8c: 09 f0 breq .+2 ; 0x1d90 - 1d8e: 60 c0 rjmp .+192 ; 0x1e50 - // PROGRAM PAGE - we support flash programming only, not EEPROM - uint8_t *bufPtr; - uint16_t addrPtr; - - getch(); /* getlen() */ - 1d90: ac d0 rcall .+344 ; 0x1eea - length = getch(); - 1d92: ab d0 rcall .+342 ; 0x1eea - 1d94: f8 2e mov r15, r24 - getch(); - 1d96: a9 d0 rcall .+338 ; 0x1eea - 1d98: c0 e0 ldi r28, 0x00 ; 0 - 1d9a: d1 e0 ldi r29, 0x01 ; 1 - // If we are in RWW section, immediately start page erase - if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - - // While that is going on, read in page contents - bufPtr = buff; - do *bufPtr++ = getch(); - 1d9c: a6 d0 rcall .+332 ; 0x1eea - 1d9e: 89 93 st Y+, r24 - while (--length); - 1da0: fc 16 cp r15, r28 - 1da2: e1 f7 brne .-8 ; 0x1d9c - - // If we are in NRWW section, page erase has to be delayed until now. - // Todo: Take RAMPZ into account - if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 1da4: 83 e0 ldi r24, 0x03 ; 3 - 1da6: f8 01 movw r30, r16 - 1da8: 87 bf out 0x37, r24 ; 55 - 1daa: e8 95 spm - - // Read command terminator, start reply - verifySpace(); - 1dac: b5 d0 rcall .+362 ; 0x1f18 - - // If only a partial page is to be programmed, the erase might not be complete. - // So check that here - boot_spm_busy_wait(); - 1dae: 07 b6 in r0, 0x37 ; 55 - 1db0: 00 fc sbrc r0, 0 - 1db2: fd cf rjmp .-6 ; 0x1dae - -#ifdef VIRTUAL_BOOT_PARTITION - if ((uint16_t)(void*)address == 0) { - 1db4: 01 15 cp r16, r1 - 1db6: 11 05 cpc r17, r1 - 1db8: 11 f0 breq .+4 ; 0x1dbe - 1dba: a8 01 movw r20, r16 - 1dbc: 2a c0 rjmp .+84 ; 0x1e12 - // This is the reset vector page. We need to live-patch the code so the - // bootloader runs. - // - // Move RESET vector to WDT vector - uint16_t vect = buff[0] | (buff[1]<<8); - 1dbe: 80 91 00 01 lds r24, 0x0100 - 1dc2: 20 91 01 01 lds r18, 0x0101 - 1dc6: 30 e0 ldi r19, 0x00 ; 0 - 1dc8: 32 2f mov r19, r18 - 1dca: 22 27 eor r18, r18 - 1dcc: 90 e0 ldi r25, 0x00 ; 0 - 1dce: 28 2b or r18, r24 - 1dd0: 39 2b or r19, r25 - rstVect = vect; - 1dd2: 30 93 85 01 sts 0x0185, r19 - 1dd6: 20 93 84 01 sts 0x0184, r18 - wdtVect = buff[8] | (buff[9]<<8); - 1dda: 40 91 08 01 lds r20, 0x0108 - 1dde: 80 91 09 01 lds r24, 0x0109 - 1de2: 90 e0 ldi r25, 0x00 ; 0 - 1de4: 98 2f mov r25, r24 - 1de6: 88 27 eor r24, r24 - 1de8: 50 e0 ldi r21, 0x00 ; 0 - 1dea: 84 2b or r24, r20 - 1dec: 95 2b or r25, r21 - 1dee: 90 93 87 01 sts 0x0187, r25 - 1df2: 80 93 86 01 sts 0x0186, r24 - vect -= 4; // Instruction is a relative jump (rjmp), so recalculate. - 1df6: 24 50 subi r18, 0x04 ; 4 - 1df8: 30 40 sbci r19, 0x00 ; 0 - buff[8] = vect & 0xff; - 1dfa: 20 93 08 01 sts 0x0108, r18 - buff[9] = vect >> 8; - 1dfe: 23 2f mov r18, r19 - 1e00: 33 27 eor r19, r19 - 1e02: 20 93 09 01 sts 0x0109, r18 - - // Add jump to bootloader at RESET vector - buff[0] = 0x7f; - 1e06: d0 92 00 01 sts 0x0100, r13 - buff[1] = 0xce; // rjmp 0x1d00 instruction - 1e0a: c0 92 01 01 sts 0x0101, r12 - 1e0e: 40 e0 ldi r20, 0x00 ; 0 - 1e10: 50 e0 ldi r21, 0x00 ; 0 - 1e12: a0 e0 ldi r26, 0x00 ; 0 - 1e14: b1 e0 ldi r27, 0x01 ; 1 - bufPtr = buff; - addrPtr = (uint16_t)(void*)address; - ch = SPM_PAGESIZE / 2; - do { - uint16_t a; - a = *bufPtr++; - 1e16: 2c 91 ld r18, X - 1e18: 30 e0 ldi r19, 0x00 ; 0 - a |= (*bufPtr++) << 8; - 1e1a: 11 96 adiw r26, 0x01 ; 1 - 1e1c: 8c 91 ld r24, X - 1e1e: 11 97 sbiw r26, 0x01 ; 1 - 1e20: 90 e0 ldi r25, 0x00 ; 0 - 1e22: 98 2f mov r25, r24 - 1e24: 88 27 eor r24, r24 - 1e26: 82 2b or r24, r18 - 1e28: 93 2b or r25, r19 -#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) -#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) -#endif - -/* main program starts here */ -int main(void) { - 1e2a: 12 96 adiw r26, 0x02 ; 2 - ch = SPM_PAGESIZE / 2; - do { - uint16_t a; - a = *bufPtr++; - a |= (*bufPtr++) << 8; - __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - 1e2c: fa 01 movw r30, r20 - 1e2e: 0c 01 movw r0, r24 - 1e30: b7 be out 0x37, r11 ; 55 - 1e32: e8 95 spm - 1e34: 11 24 eor r1, r1 - addrPtr += 2; - 1e36: 4e 5f subi r20, 0xFE ; 254 - 1e38: 5f 4f sbci r21, 0xFF ; 255 - } while (--ch); - 1e3a: f1 e0 ldi r31, 0x01 ; 1 - 1e3c: a0 34 cpi r26, 0x40 ; 64 - 1e3e: bf 07 cpc r27, r31 - 1e40: 51 f7 brne .-44 ; 0x1e16 - - // Write from programming buffer - __boot_page_write_short((uint16_t)(void*)address); - 1e42: f8 01 movw r30, r16 - 1e44: a7 be out 0x37, r10 ; 55 - 1e46: e8 95 spm - boot_spm_busy_wait(); - 1e48: 07 b6 in r0, 0x37 ; 55 - 1e4a: 00 fc sbrc r0, 0 - 1e4c: fd cf rjmp .-6 ; 0x1e48 - 1e4e: 3b c0 rjmp .+118 ; 0x1ec6 - boot_rww_enable(); -#endif - - } - /* Read memory block mode, length is big endian. */ - else if(ch == STK_READ_PAGE) { - 1e50: 84 37 cpi r24, 0x74 ; 116 - 1e52: 51 f5 brne .+84 ; 0x1ea8 - // READ PAGE - we only read flash - getch(); /* getlen() */ - 1e54: 4a d0 rcall .+148 ; 0x1eea - length = getch(); - 1e56: 49 d0 rcall .+146 ; 0x1eea - 1e58: f8 2e mov r15, r24 - getch(); - 1e5a: 47 d0 rcall .+142 ; 0x1eea - - verifySpace(); - 1e5c: 5d d0 rcall .+186 ; 0x1f18 - 1e5e: e8 01 movw r28, r16 - 1e60: ef 2c mov r14, r15 -#ifdef VIRTUAL_BOOT_PARTITION - do { - // Undo vector patch in bottom page so verify passes - if (address == 0) ch=rstVect & 0xff; - 1e62: 20 97 sbiw r28, 0x00 ; 0 - 1e64: 19 f4 brne .+6 ; 0x1e6c - 1e66: 80 91 84 01 lds r24, 0x0184 - 1e6a: 14 c0 rjmp .+40 ; 0x1e94 - else if (address == 1) ch=rstVect >> 8; - 1e6c: c1 30 cpi r28, 0x01 ; 1 - 1e6e: d1 05 cpc r29, r1 - 1e70: 19 f4 brne .+6 ; 0x1e78 - 1e72: 80 91 85 01 lds r24, 0x0185 - 1e76: 0e c0 rjmp .+28 ; 0x1e94 - else if (address == 8) ch=wdtVect & 0xff; - 1e78: c8 30 cpi r28, 0x08 ; 8 - 1e7a: d1 05 cpc r29, r1 - 1e7c: 19 f4 brne .+6 ; 0x1e84 - 1e7e: 80 91 86 01 lds r24, 0x0186 - 1e82: 08 c0 rjmp .+16 ; 0x1e94 - else if (address == 9) ch=wdtVect >> 8; - 1e84: c9 30 cpi r28, 0x09 ; 9 - 1e86: d1 05 cpc r29, r1 - 1e88: 19 f4 brne .+6 ; 0x1e90 - 1e8a: 80 91 87 01 lds r24, 0x0187 - 1e8e: 02 c0 rjmp .+4 ; 0x1e94 - else ch = pgm_read_byte_near(address); - 1e90: fe 01 movw r30, r28 - 1e92: 84 91 lpm r24, Z+ - address++; - 1e94: 21 96 adiw r28, 0x01 ; 1 - putch(ch); - 1e96: 1a d0 rcall .+52 ; 0x1ecc - } while (--length); - 1e98: ea 94 dec r14 - 1e9a: 19 f7 brne .-58 ; 0x1e62 -#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) -#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) -#endif - -/* main program starts here */ -int main(void) { - 1e9c: 0f 5f subi r16, 0xFF ; 255 - 1e9e: 1f 4f sbci r17, 0xFF ; 255 - 1ea0: fa 94 dec r15 - 1ea2: 0f 0d add r16, r15 - 1ea4: 11 1d adc r17, r1 - 1ea6: 0f c0 rjmp .+30 ; 0x1ec6 -#endif -#endif - } - - /* Get device signature bytes */ - else if(ch == STK_READ_SIGN) { - 1ea8: 85 37 cpi r24, 0x75 ; 117 - 1eaa: 41 f4 brne .+16 ; 0x1ebc - // READ SIGN - return what Avrdude wants to hear - verifySpace(); - 1eac: 35 d0 rcall .+106 ; 0x1f18 - putch(SIGNATURE_0); - 1eae: 8e e1 ldi r24, 0x1E ; 30 - 1eb0: 0d d0 rcall .+26 ; 0x1ecc - putch(SIGNATURE_1); - 1eb2: 83 e9 ldi r24, 0x93 ; 147 - 1eb4: 0b d0 rcall .+22 ; 0x1ecc - putch(SIGNATURE_2); - 1eb6: 8c e0 ldi r24, 0x0C ; 12 - 1eb8: 09 d0 rcall .+18 ; 0x1ecc - 1eba: 05 c0 rjmp .+10 ; 0x1ec6 - } - else if (ch == 'Q') { - 1ebc: 81 35 cpi r24, 0x51 ; 81 - 1ebe: 11 f4 brne .+4 ; 0x1ec4 - // Adaboot no-wait mod - watchdogConfig(WATCHDOG_16MS); - 1ec0: 88 e0 ldi r24, 0x08 ; 8 - 1ec2: 26 d0 rcall .+76 ; 0x1f10 - verifySpace(); - } - else { - // This covers the response to commands like STK_ENTER_PROGMODE - verifySpace(); - 1ec4: 29 d0 rcall .+82 ; 0x1f18 - } - putch(STK_OK); - 1ec6: 80 e1 ldi r24, 0x10 ; 16 - 1ec8: 01 d0 rcall .+2 ; 0x1ecc - 1eca: 3a cf rjmp .-396 ; 0x1d40 - -00001ecc : -void putch(char ch) { -#ifndef SOFT_UART - while (!(UCSR0A & _BV(UDRE0))); - UDR0 = ch; -#else - __asm__ __volatile__ ( - 1ecc: 2a e0 ldi r18, 0x0A ; 10 - 1ece: 30 e0 ldi r19, 0x00 ; 0 - 1ed0: 80 95 com r24 - 1ed2: 08 94 sec - 1ed4: 10 f4 brcc .+4 ; 0x1eda - 1ed6: da 98 cbi 0x1b, 2 ; 27 - 1ed8: 02 c0 rjmp .+4 ; 0x1ede - 1eda: da 9a sbi 0x1b, 2 ; 27 - 1edc: 00 00 nop - 1ede: 14 d0 rcall .+40 ; 0x1f08 - 1ee0: 13 d0 rcall .+38 ; 0x1f08 - 1ee2: 86 95 lsr r24 - 1ee4: 2a 95 dec r18 - 1ee6: b1 f7 brne .-20 ; 0x1ed4 - [uartBit] "I" (UART_TX_BIT) - : - "r25" - ); -#endif -} - 1ee8: 08 95 ret - -00001eea : - LED_PIN |= _BV(LED); -#endif -#endif - - return ch; -} - 1eea: 29 e0 ldi r18, 0x09 ; 9 - 1eec: 30 e0 ldi r19, 0x00 ; 0 - 1eee: cb 99 sbic 0x19, 3 ; 25 - 1ef0: fe cf rjmp .-4 ; 0x1eee - 1ef2: 0a d0 rcall .+20 ; 0x1f08 - 1ef4: 09 d0 rcall .+18 ; 0x1f08 - 1ef6: 08 d0 rcall .+16 ; 0x1f08 - 1ef8: 88 94 clc - 1efa: cb 99 sbic 0x19, 3 ; 25 - 1efc: 08 94 sec - 1efe: 2a 95 dec r18 - 1f00: 11 f0 breq .+4 ; 0x1f06 - 1f02: 87 95 ror r24 - 1f04: f7 cf rjmp .-18 ; 0x1ef4 - 1f06: 08 95 ret - -00001f08 : -#if UART_B_VALUE > 255 -#error Baud rate too slow for soft UART -#endif - -void uartDelay() { - __asm__ __volatile__ ( - 1f08: 9e e0 ldi r25, 0x0E ; 14 - 1f0a: 9a 95 dec r25 - 1f0c: f1 f7 brne .-4 ; 0x1f0a - 1f0e: 08 95 ret - -00001f10 : - "wdr\n" - ); -} - -void watchdogConfig(uint8_t x) { - WDTCSR = _BV(WDCE) | _BV(WDE); - 1f10: 98 e1 ldi r25, 0x18 ; 24 - 1f12: 91 bd out 0x21, r25 ; 33 - WDTCSR = x; - 1f14: 81 bd out 0x21, r24 ; 33 -} - 1f16: 08 95 ret - -00001f18 : - do getch(); while (--count); - verifySpace(); -} - -void verifySpace() { - if (getch() != CRC_EOP) { - 1f18: e8 df rcall .-48 ; 0x1eea - 1f1a: 80 32 cpi r24, 0x20 ; 32 - 1f1c: 19 f0 breq .+6 ; 0x1f24 - watchdogConfig(WATCHDOG_16MS); // shorten WD timeout - 1f1e: 88 e0 ldi r24, 0x08 ; 8 - 1f20: f7 df rcall .-18 ; 0x1f10 - 1f22: ff cf rjmp .-2 ; 0x1f22 - while (1) // and busy-loop so that WD causes - ; // a reset and app start. - } - putch(STK_INSYNC); - 1f24: 84 e1 ldi r24, 0x14 ; 20 -} - 1f26: d2 cf rjmp .-92 ; 0x1ecc - -00001f28 : - ::[count] "M" (UART_B_VALUE) - ); -} -#endif - -void getNch(uint8_t count) { - 1f28: 1f 93 push r17 - 1f2a: 18 2f mov r17, r24 - do getch(); while (--count); - 1f2c: de df rcall .-68 ; 0x1eea - 1f2e: 11 50 subi r17, 0x01 ; 1 - 1f30: e9 f7 brne .-6 ; 0x1f2c - verifySpace(); - 1f32: f2 df rcall .-28 ; 0x1f18 -} - 1f34: 1f 91 pop r17 - 1f36: 08 95 ret - -00001f38 : - WDTCSR = _BV(WDCE) | _BV(WDE); - WDTCSR = x; -} - -void appStart() { - watchdogConfig(WATCHDOG_OFF); - 1f38: 80 e0 ldi r24, 0x00 ; 0 - 1f3a: ea df rcall .-44 ; 0x1f10 - __asm__ __volatile__ ( - 1f3c: e4 e0 ldi r30, 0x04 ; 4 - 1f3e: ff 27 eor r31, r31 - 1f40: 09 94 ijmp diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.hex b/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.hex deleted file mode 100644 index b685a4e9a..000000000 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.hex +++ /dev/null @@ -1,34 +0,0 @@ -:103E0000112484B714BE81FFE7D085E08093810040 -:103E100082E08093C00088E18093C10086E08093B7 -:103E2000C20080E18093C4008EE0C0D0259A86E075 -:103E300020E33CEF91E0309385002093840096BB13 -:103E4000B09BFECF1D9AA8958150A9F79924939411 -:103E5000A5E0AA2EF1E1BF2E9DD0813421F481E0AE -:103E6000B3D083E01FC0823411F484E103C08534F1 -:103E700019F485E0A9D083C0853579F48BD0E82E7C -:103E8000FF2488D0082F10E0102F00270E291F29AB -:103E9000000F111F91D0680172C0863529F484E0AB -:103EA00093D080E06FD06BC0843609F042C072D0EE -:103EB00071D0082F6FD080E0C81688E3D80620F4B0 -:103EC00083E0F60187BFE895C0E0D1E063D0899335 -:103ED0000C17E1F7F0E0CF16F8E3DF0620F083E0FF -:103EE000F60187BFE89568D007B600FCFDCFA601B4 -:103EF000A0E0B1E02C9130E011968C91119790E008 -:103F0000982F8827822B932B1296FA010C0197BECB -:103F1000E89511244E5F5F4FF1E0A038BF0751F7DD -:103F2000F601A7BEE89507B600FCFDCFB7BEE89541 -:103F300026C08437B1F42ED02DD0F82E2BD03CD013 -:103F4000F601EF2C8F010F5F1F4F84911BD0EA9475 -:103F5000F801C1F70894C11CD11CFA94CF0CD11CF4 -:103F60000EC0853739F428D08EE10CD084E90AD010 -:103F700086E098CF813511F488E018D01DD080E11B -:103F800001D06ACF982F8091C00085FFFCCF90931D -:103F9000C60008958091C00087FFFCCF8091C000CB -:103FA00084FD01C0A8958091C6000895E0E6F0E088 -:103FB00098E1908380830895EDDF803219F088E0E6 -:103FC000F5DFFFCF84E1DECF1F93182FE3DF115021 -:103FD000E9F7F2DF1F91089580E0E8DFEE27FF2781 -:023FE000099442 -:023FFE000304BA -:0400000300003E00BB -:00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.lst b/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.lst deleted file mode 100644 index 2c6bea1eb..000000000 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_16MHz.lst +++ /dev/null @@ -1,571 +0,0 @@ - -optiboot_pro_16MHz.elf: file format elf32-avr - -Sections: -Idx Name Size VMA LMA File off Algn - 0 .text 000001e2 00003e00 00003e00 00000054 2**1 - CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .version 00000002 00003ffe 00003ffe 00000236 2**0 - CONTENTS, READONLY - 2 .debug_aranges 00000028 00000000 00000000 00000238 2**0 - CONTENTS, READONLY, DEBUGGING - 3 .debug_pubnames 0000005f 00000000 00000000 00000260 2**0 - CONTENTS, READONLY, DEBUGGING - 4 .debug_info 0000028e 00000000 00000000 000002bf 2**0 - CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 00000171 00000000 00000000 0000054d 2**0 - CONTENTS, READONLY, DEBUGGING - 6 .debug_line 0000045e 00000000 00000000 000006be 2**0 - CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000080 00000000 00000000 00000b1c 2**2 - CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000149 00000000 00000000 00000b9c 2**0 - CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 0000027e 00000000 00000000 00000ce5 2**0 - CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000060 00000000 00000000 00000f63 2**0 - CONTENTS, READONLY, DEBUGGING - -Disassembly of section .text: - -00003e00
    : -#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) -#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) -#endif - -/* main program starts here */ -int main(void) { - 3e00: 11 24 eor r1, r1 -#ifdef __AVR_ATmega8__ - SP=RAMEND; // This is done by hardware reset -#endif - - // Adaboot no-wait mod - ch = MCUSR; - 3e02: 84 b7 in r24, 0x34 ; 52 - MCUSR = 0; - 3e04: 14 be out 0x34, r1 ; 52 - if (!(ch & _BV(EXTRF))) appStart(); - 3e06: 81 ff sbrs r24, 1 - 3e08: e7 d0 rcall .+462 ; 0x3fd8 - -#if LED_START_FLASHES > 0 - // Set up Timer 1 for timeout counter - TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 - 3e0a: 85 e0 ldi r24, 0x05 ; 5 - 3e0c: 80 93 81 00 sts 0x0081, r24 - UCSRA = _BV(U2X); //Double speed mode USART - UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx - UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 - UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); -#else - UCSR0A = _BV(U2X0); //Double speed mode USART0 - 3e10: 82 e0 ldi r24, 0x02 ; 2 - 3e12: 80 93 c0 00 sts 0x00C0, r24 - UCSR0B = _BV(RXEN0) | _BV(TXEN0); - 3e16: 88 e1 ldi r24, 0x18 ; 24 - 3e18: 80 93 c1 00 sts 0x00C1, r24 - UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); - 3e1c: 86 e0 ldi r24, 0x06 ; 6 - 3e1e: 80 93 c2 00 sts 0x00C2, r24 - UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); - 3e22: 80 e1 ldi r24, 0x10 ; 16 - 3e24: 80 93 c4 00 sts 0x00C4, r24 -#endif -#endif - - // Set up watchdog to trigger after 500ms - watchdogConfig(WATCHDOG_1S); - 3e28: 8e e0 ldi r24, 0x0E ; 14 - 3e2a: c0 d0 rcall .+384 ; 0x3fac - - /* Set LED pin as output */ - LED_DDR |= _BV(LED); - 3e2c: 25 9a sbi 0x04, 5 ; 4 - 3e2e: 86 e0 ldi r24, 0x06 ; 6 -} - -#if LED_START_FLASHES > 0 -void flash_led(uint8_t count) { - do { - TCNT1 = -(F_CPU/(1024*16)); - 3e30: 20 e3 ldi r18, 0x30 ; 48 - 3e32: 3c ef ldi r19, 0xFC ; 252 - TIFR1 = _BV(TOV1); - 3e34: 91 e0 ldi r25, 0x01 ; 1 -} - -#if LED_START_FLASHES > 0 -void flash_led(uint8_t count) { - do { - TCNT1 = -(F_CPU/(1024*16)); - 3e36: 30 93 85 00 sts 0x0085, r19 - 3e3a: 20 93 84 00 sts 0x0084, r18 - TIFR1 = _BV(TOV1); - 3e3e: 96 bb out 0x16, r25 ; 22 - while(!(TIFR1 & _BV(TOV1))); - 3e40: b0 9b sbis 0x16, 0 ; 22 - 3e42: fe cf rjmp .-4 ; 0x3e40 -#ifdef __AVR_ATmega8__ - LED_PORT ^= _BV(LED); -#else - LED_PIN |= _BV(LED); - 3e44: 1d 9a sbi 0x03, 5 ; 3 -} -#endif - -// Watchdog functions. These are only safe with interrupts turned off. -void watchdogReset() { - __asm__ __volatile__ ( - 3e46: a8 95 wdr - LED_PORT ^= _BV(LED); -#else - LED_PIN |= _BV(LED); -#endif - watchdogReset(); - } while (--count); - 3e48: 81 50 subi r24, 0x01 ; 1 - 3e4a: a9 f7 brne .-22 ; 0x3e36 - /* get character from UART */ - ch = getch(); - - if(ch == STK_GET_PARAMETER) { - // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy - getNch(1); - 3e4c: 99 24 eor r9, r9 - 3e4e: 93 94 inc r9 - __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - addrPtr += 2; - } while (--ch); - - // Write from programming buffer - __boot_page_write_short((uint16_t)(void*)address); - 3e50: a5 e0 ldi r26, 0x05 ; 5 - 3e52: aa 2e mov r10, r26 - boot_spm_busy_wait(); - -#if defined(RWWSRE) - // Reenable read access to flash - boot_rww_enable(); - 3e54: f1 e1 ldi r31, 0x11 ; 17 - 3e56: bf 2e mov r11, r31 -#endif - - /* Forever loop */ - for (;;) { - /* get character from UART */ - ch = getch(); - 3e58: 9d d0 rcall .+314 ; 0x3f94 - - if(ch == STK_GET_PARAMETER) { - 3e5a: 81 34 cpi r24, 0x41 ; 65 - 3e5c: 21 f4 brne .+8 ; 0x3e66 - // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy - getNch(1); - 3e5e: 81 e0 ldi r24, 0x01 ; 1 - 3e60: b3 d0 rcall .+358 ; 0x3fc8 - putch(0x03); - 3e62: 83 e0 ldi r24, 0x03 ; 3 - 3e64: 1f c0 rjmp .+62 ; 0x3ea4 - } - else if(ch == STK_SET_DEVICE) { - 3e66: 82 34 cpi r24, 0x42 ; 66 - 3e68: 11 f4 brne .+4 ; 0x3e6e - // SET DEVICE is ignored - getNch(20); - 3e6a: 84 e1 ldi r24, 0x14 ; 20 - 3e6c: 03 c0 rjmp .+6 ; 0x3e74 - } - else if(ch == STK_SET_DEVICE_EXT) { - 3e6e: 85 34 cpi r24, 0x45 ; 69 - 3e70: 19 f4 brne .+6 ; 0x3e78 - // SET DEVICE EXT is ignored - getNch(5); - 3e72: 85 e0 ldi r24, 0x05 ; 5 - 3e74: a9 d0 rcall .+338 ; 0x3fc8 - 3e76: 83 c0 rjmp .+262 ; 0x3f7e - } - else if(ch == STK_LOAD_ADDRESS) { - 3e78: 85 35 cpi r24, 0x55 ; 85 - 3e7a: 79 f4 brne .+30 ; 0x3e9a - // LOAD ADDRESS - uint16_t newAddress; - newAddress = getch(); - 3e7c: 8b d0 rcall .+278 ; 0x3f94 - newAddress = (newAddress & 0xff) | (getch() << 8); - 3e7e: e8 2e mov r14, r24 - 3e80: ff 24 eor r15, r15 - 3e82: 88 d0 rcall .+272 ; 0x3f94 - 3e84: 08 2f mov r16, r24 - 3e86: 10 e0 ldi r17, 0x00 ; 0 - 3e88: 10 2f mov r17, r16 - 3e8a: 00 27 eor r16, r16 - 3e8c: 0e 29 or r16, r14 - 3e8e: 1f 29 or r17, r15 -#ifdef RAMPZ - // Transfer top bit to RAMPZ - RAMPZ = (newAddress & 0x8000) ? 1 : 0; -#endif - newAddress += newAddress; // Convert from word address to byte address - 3e90: 00 0f add r16, r16 - 3e92: 11 1f adc r17, r17 - address = newAddress; - verifySpace(); - 3e94: 91 d0 rcall .+290 ; 0x3fb8 - 3e96: 68 01 movw r12, r16 - 3e98: 72 c0 rjmp .+228 ; 0x3f7e - } - else if(ch == STK_UNIVERSAL) { - 3e9a: 86 35 cpi r24, 0x56 ; 86 - 3e9c: 29 f4 brne .+10 ; 0x3ea8 - // UNIVERSAL command is ignored - getNch(4); - 3e9e: 84 e0 ldi r24, 0x04 ; 4 - 3ea0: 93 d0 rcall .+294 ; 0x3fc8 - putch(0x00); - 3ea2: 80 e0 ldi r24, 0x00 ; 0 - 3ea4: 6f d0 rcall .+222 ; 0x3f84 - 3ea6: 6b c0 rjmp .+214 ; 0x3f7e - } - /* Write memory, length is big endian and is in bytes */ - else if(ch == STK_PROG_PAGE) { - 3ea8: 84 36 cpi r24, 0x64 ; 100 - 3eaa: 09 f0 breq .+2 ; 0x3eae - 3eac: 42 c0 rjmp .+132 ; 0x3f32 - // PROGRAM PAGE - we support flash programming only, not EEPROM - uint8_t *bufPtr; - uint16_t addrPtr; - - getch(); /* getlen() */ - 3eae: 72 d0 rcall .+228 ; 0x3f94 - length = getch(); - 3eb0: 71 d0 rcall .+226 ; 0x3f94 - 3eb2: 08 2f mov r16, r24 - getch(); - 3eb4: 6f d0 rcall .+222 ; 0x3f94 - - // If we are in RWW section, immediately start page erase - if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 3eb6: 80 e0 ldi r24, 0x00 ; 0 - 3eb8: c8 16 cp r12, r24 - 3eba: 88 e3 ldi r24, 0x38 ; 56 - 3ebc: d8 06 cpc r13, r24 - 3ebe: 20 f4 brcc .+8 ; 0x3ec8 - 3ec0: 83 e0 ldi r24, 0x03 ; 3 - 3ec2: f6 01 movw r30, r12 - 3ec4: 87 bf out 0x37, r24 ; 55 - 3ec6: e8 95 spm - 3ec8: c0 e0 ldi r28, 0x00 ; 0 - 3eca: d1 e0 ldi r29, 0x01 ; 1 - - // While that is going on, read in page contents - bufPtr = buff; - do *bufPtr++ = getch(); - 3ecc: 63 d0 rcall .+198 ; 0x3f94 - 3ece: 89 93 st Y+, r24 - while (--length); - 3ed0: 0c 17 cp r16, r28 - 3ed2: e1 f7 brne .-8 ; 0x3ecc - - // If we are in NRWW section, page erase has to be delayed until now. - // Todo: Take RAMPZ into account - if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 3ed4: f0 e0 ldi r31, 0x00 ; 0 - 3ed6: cf 16 cp r12, r31 - 3ed8: f8 e3 ldi r31, 0x38 ; 56 - 3eda: df 06 cpc r13, r31 - 3edc: 20 f0 brcs .+8 ; 0x3ee6 - 3ede: 83 e0 ldi r24, 0x03 ; 3 - 3ee0: f6 01 movw r30, r12 - 3ee2: 87 bf out 0x37, r24 ; 55 - 3ee4: e8 95 spm - - // Read command terminator, start reply - verifySpace(); - 3ee6: 68 d0 rcall .+208 ; 0x3fb8 - - // If only a partial page is to be programmed, the erase might not be complete. - // So check that here - boot_spm_busy_wait(); - 3ee8: 07 b6 in r0, 0x37 ; 55 - 3eea: 00 fc sbrc r0, 0 - 3eec: fd cf rjmp .-6 ; 0x3ee8 - 3eee: a6 01 movw r20, r12 - 3ef0: a0 e0 ldi r26, 0x00 ; 0 - 3ef2: b1 e0 ldi r27, 0x01 ; 1 - bufPtr = buff; - addrPtr = (uint16_t)(void*)address; - ch = SPM_PAGESIZE / 2; - do { - uint16_t a; - a = *bufPtr++; - 3ef4: 2c 91 ld r18, X - 3ef6: 30 e0 ldi r19, 0x00 ; 0 - a |= (*bufPtr++) << 8; - 3ef8: 11 96 adiw r26, 0x01 ; 1 - 3efa: 8c 91 ld r24, X - 3efc: 11 97 sbiw r26, 0x01 ; 1 - 3efe: 90 e0 ldi r25, 0x00 ; 0 - 3f00: 98 2f mov r25, r24 - 3f02: 88 27 eor r24, r24 - 3f04: 82 2b or r24, r18 - 3f06: 93 2b or r25, r19 -#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) -#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) -#endif - -/* main program starts here */ -int main(void) { - 3f08: 12 96 adiw r26, 0x02 ; 2 - ch = SPM_PAGESIZE / 2; - do { - uint16_t a; - a = *bufPtr++; - a |= (*bufPtr++) << 8; - __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - 3f0a: fa 01 movw r30, r20 - 3f0c: 0c 01 movw r0, r24 - 3f0e: 97 be out 0x37, r9 ; 55 - 3f10: e8 95 spm - 3f12: 11 24 eor r1, r1 - addrPtr += 2; - 3f14: 4e 5f subi r20, 0xFE ; 254 - 3f16: 5f 4f sbci r21, 0xFF ; 255 - } while (--ch); - 3f18: f1 e0 ldi r31, 0x01 ; 1 - 3f1a: a0 38 cpi r26, 0x80 ; 128 - 3f1c: bf 07 cpc r27, r31 - 3f1e: 51 f7 brne .-44 ; 0x3ef4 - - // Write from programming buffer - __boot_page_write_short((uint16_t)(void*)address); - 3f20: f6 01 movw r30, r12 - 3f22: a7 be out 0x37, r10 ; 55 - 3f24: e8 95 spm - boot_spm_busy_wait(); - 3f26: 07 b6 in r0, 0x37 ; 55 - 3f28: 00 fc sbrc r0, 0 - 3f2a: fd cf rjmp .-6 ; 0x3f26 - -#if defined(RWWSRE) - // Reenable read access to flash - boot_rww_enable(); - 3f2c: b7 be out 0x37, r11 ; 55 - 3f2e: e8 95 spm - 3f30: 26 c0 rjmp .+76 ; 0x3f7e -#endif - - } - /* Read memory block mode, length is big endian. */ - else if(ch == STK_READ_PAGE) { - 3f32: 84 37 cpi r24, 0x74 ; 116 - 3f34: b1 f4 brne .+44 ; 0x3f62 - // READ PAGE - we only read flash - getch(); /* getlen() */ - 3f36: 2e d0 rcall .+92 ; 0x3f94 - length = getch(); - 3f38: 2d d0 rcall .+90 ; 0x3f94 - 3f3a: f8 2e mov r15, r24 - getch(); - 3f3c: 2b d0 rcall .+86 ; 0x3f94 - - verifySpace(); - 3f3e: 3c d0 rcall .+120 ; 0x3fb8 - 3f40: f6 01 movw r30, r12 - 3f42: ef 2c mov r14, r15 - putch(result); - address++; - } - while (--length); -#else - do putch(pgm_read_byte_near(address++)); - 3f44: 8f 01 movw r16, r30 - 3f46: 0f 5f subi r16, 0xFF ; 255 - 3f48: 1f 4f sbci r17, 0xFF ; 255 - 3f4a: 84 91 lpm r24, Z+ - 3f4c: 1b d0 rcall .+54 ; 0x3f84 - while (--length); - 3f4e: ea 94 dec r14 - 3f50: f8 01 movw r30, r16 - 3f52: c1 f7 brne .-16 ; 0x3f44 -#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) -#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) -#endif - -/* main program starts here */ -int main(void) { - 3f54: 08 94 sec - 3f56: c1 1c adc r12, r1 - 3f58: d1 1c adc r13, r1 - 3f5a: fa 94 dec r15 - 3f5c: cf 0c add r12, r15 - 3f5e: d1 1c adc r13, r1 - 3f60: 0e c0 rjmp .+28 ; 0x3f7e -#endif -#endif - } - - /* Get device signature bytes */ - else if(ch == STK_READ_SIGN) { - 3f62: 85 37 cpi r24, 0x75 ; 117 - 3f64: 39 f4 brne .+14 ; 0x3f74 - // READ SIGN - return what Avrdude wants to hear - verifySpace(); - 3f66: 28 d0 rcall .+80 ; 0x3fb8 - putch(SIGNATURE_0); - 3f68: 8e e1 ldi r24, 0x1E ; 30 - 3f6a: 0c d0 rcall .+24 ; 0x3f84 - putch(SIGNATURE_1); - 3f6c: 84 e9 ldi r24, 0x94 ; 148 - 3f6e: 0a d0 rcall .+20 ; 0x3f84 - putch(SIGNATURE_2); - 3f70: 86 e0 ldi r24, 0x06 ; 6 - 3f72: 98 cf rjmp .-208 ; 0x3ea4 - } - else if (ch == 'Q') { - 3f74: 81 35 cpi r24, 0x51 ; 81 - 3f76: 11 f4 brne .+4 ; 0x3f7c - // Adaboot no-wait mod - watchdogConfig(WATCHDOG_16MS); - 3f78: 88 e0 ldi r24, 0x08 ; 8 - 3f7a: 18 d0 rcall .+48 ; 0x3fac - verifySpace(); - } - else { - // This covers the response to commands like STK_ENTER_PROGMODE - verifySpace(); - 3f7c: 1d d0 rcall .+58 ; 0x3fb8 - } - putch(STK_OK); - 3f7e: 80 e1 ldi r24, 0x10 ; 16 - 3f80: 01 d0 rcall .+2 ; 0x3f84 - 3f82: 6a cf rjmp .-300 ; 0x3e58 - -00003f84 : - } -} - -void putch(char ch) { - 3f84: 98 2f mov r25, r24 -#ifndef SOFT_UART - while (!(UCSR0A & _BV(UDRE0))); - 3f86: 80 91 c0 00 lds r24, 0x00C0 - 3f8a: 85 ff sbrs r24, 5 - 3f8c: fc cf rjmp .-8 ; 0x3f86 - UDR0 = ch; - 3f8e: 90 93 c6 00 sts 0x00C6, r25 - [uartBit] "I" (UART_TX_BIT) - : - "r25" - ); -#endif -} - 3f92: 08 95 ret - -00003f94 : - [uartBit] "I" (UART_RX_BIT) - : - "r25" -); -#else - while(!(UCSR0A & _BV(RXC0))) - 3f94: 80 91 c0 00 lds r24, 0x00C0 - 3f98: 87 ff sbrs r24, 7 - 3f9a: fc cf rjmp .-8 ; 0x3f94 - ; - if (!(UCSR0A & _BV(FE0))) { - 3f9c: 80 91 c0 00 lds r24, 0x00C0 - 3fa0: 84 fd sbrc r24, 4 - 3fa2: 01 c0 rjmp .+2 ; 0x3fa6 -} -#endif - -// Watchdog functions. These are only safe with interrupts turned off. -void watchdogReset() { - __asm__ __volatile__ ( - 3fa4: a8 95 wdr - * don't care that an invalid char is returned...) - */ - watchdogReset(); - } - - ch = UDR0; - 3fa6: 80 91 c6 00 lds r24, 0x00C6 - LED_PIN |= _BV(LED); -#endif -#endif - - return ch; -} - 3faa: 08 95 ret - -00003fac : - "wdr\n" - ); -} - -void watchdogConfig(uint8_t x) { - WDTCSR = _BV(WDCE) | _BV(WDE); - 3fac: e0 e6 ldi r30, 0x60 ; 96 - 3fae: f0 e0 ldi r31, 0x00 ; 0 - 3fb0: 98 e1 ldi r25, 0x18 ; 24 - 3fb2: 90 83 st Z, r25 - WDTCSR = x; - 3fb4: 80 83 st Z, r24 -} - 3fb6: 08 95 ret - -00003fb8 : - do getch(); while (--count); - verifySpace(); -} - -void verifySpace() { - if (getch() != CRC_EOP) { - 3fb8: ed df rcall .-38 ; 0x3f94 - 3fba: 80 32 cpi r24, 0x20 ; 32 - 3fbc: 19 f0 breq .+6 ; 0x3fc4 - watchdogConfig(WATCHDOG_16MS); // shorten WD timeout - 3fbe: 88 e0 ldi r24, 0x08 ; 8 - 3fc0: f5 df rcall .-22 ; 0x3fac - 3fc2: ff cf rjmp .-2 ; 0x3fc2 - while (1) // and busy-loop so that WD causes - ; // a reset and app start. - } - putch(STK_INSYNC); - 3fc4: 84 e1 ldi r24, 0x14 ; 20 -} - 3fc6: de cf rjmp .-68 ; 0x3f84 - -00003fc8 : - ::[count] "M" (UART_B_VALUE) - ); -} -#endif - -void getNch(uint8_t count) { - 3fc8: 1f 93 push r17 - 3fca: 18 2f mov r17, r24 - do getch(); while (--count); - 3fcc: e3 df rcall .-58 ; 0x3f94 - 3fce: 11 50 subi r17, 0x01 ; 1 - 3fd0: e9 f7 brne .-6 ; 0x3fcc - verifySpace(); - 3fd2: f2 df rcall .-28 ; 0x3fb8 -} - 3fd4: 1f 91 pop r17 - 3fd6: 08 95 ret - -00003fd8 : - WDTCSR = _BV(WDCE) | _BV(WDE); - WDTCSR = x; -} - -void appStart() { - watchdogConfig(WATCHDOG_OFF); - 3fd8: 80 e0 ldi r24, 0x00 ; 0 - 3fda: e8 df rcall .-48 ; 0x3fac - __asm__ __volatile__ ( - 3fdc: ee 27 eor r30, r30 - 3fde: ff 27 eor r31, r31 - 3fe0: 09 94 ijmp diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.hex b/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.hex deleted file mode 100644 index 451a99c63..000000000 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.hex +++ /dev/null @@ -1,34 +0,0 @@ -:103E0000112484B714BE81FFE7D085E08093810040 -:103E100082E08093C00088E18093C10086E08093B7 -:103E2000C20085E18093C4008EE0C0D0259A86E070 -:103E30002CE33BEF91E0309385002093840096BB08 -:103E4000B09BFECF1D9AA8958150A9F79924939411 -:103E5000A5E0AA2EF1E1BF2E9DD0813421F481E0AE -:103E6000B3D083E01FC0823411F484E103C08534F1 -:103E700019F485E0A9D083C0853579F48BD0E82E7C -:103E8000FF2488D0082F10E0102F00270E291F29AB -:103E9000000F111F91D0680172C0863529F484E0AB -:103EA00093D080E06FD06BC0843609F042C072D0EE -:103EB00071D0082F6FD080E0C81688E3D80620F4B0 -:103EC00083E0F60187BFE895C0E0D1E063D0899335 -:103ED0000C17E1F7F0E0CF16F8E3DF0620F083E0FF -:103EE000F60187BFE89568D007B600FCFDCFA601B4 -:103EF000A0E0B1E02C9130E011968C91119790E008 -:103F0000982F8827822B932B1296FA010C0197BECB -:103F1000E89511244E5F5F4FF1E0A038BF0751F7DD -:103F2000F601A7BEE89507B600FCFDCFB7BEE89541 -:103F300026C08437B1F42ED02DD0F82E2BD03CD013 -:103F4000F601EF2C8F010F5F1F4F84911BD0EA9475 -:103F5000F801C1F70894C11CD11CFA94CF0CD11CF4 -:103F60000EC0853739F428D08EE10CD084E90AD010 -:103F700086E098CF813511F488E018D01DD080E11B -:103F800001D06ACF982F8091C00085FFFCCF90931D -:103F9000C60008958091C00087FFFCCF8091C000CB -:103FA00084FD01C0A8958091C6000895E0E6F0E088 -:103FB00098E1908380830895EDDF803219F088E0E6 -:103FC000F5DFFFCF84E1DECF1F93182FE3DF115021 -:103FD000E9F7F2DF1F91089580E0E8DFEE27FF2781 -:023FE000099442 -:023FFE000304BA -:0400000300003E00BB -:00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.lst b/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.lst deleted file mode 100644 index 83146479e..000000000 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_20mhz.lst +++ /dev/null @@ -1,571 +0,0 @@ - -optiboot_pro_20mhz.elf: file format elf32-avr - -Sections: -Idx Name Size VMA LMA File off Algn - 0 .text 000001e2 00003e00 00003e00 00000054 2**1 - CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .version 00000002 00003ffe 00003ffe 00000236 2**0 - CONTENTS, READONLY - 2 .debug_aranges 00000028 00000000 00000000 00000238 2**0 - CONTENTS, READONLY, DEBUGGING - 3 .debug_pubnames 0000005f 00000000 00000000 00000260 2**0 - CONTENTS, READONLY, DEBUGGING - 4 .debug_info 0000028e 00000000 00000000 000002bf 2**0 - CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 00000171 00000000 00000000 0000054d 2**0 - CONTENTS, READONLY, DEBUGGING - 6 .debug_line 0000045e 00000000 00000000 000006be 2**0 - CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000080 00000000 00000000 00000b1c 2**2 - CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000149 00000000 00000000 00000b9c 2**0 - CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 0000027e 00000000 00000000 00000ce5 2**0 - CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000060 00000000 00000000 00000f63 2**0 - CONTENTS, READONLY, DEBUGGING - -Disassembly of section .text: - -00003e00
    : -#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) -#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) -#endif - -/* main program starts here */ -int main(void) { - 3e00: 11 24 eor r1, r1 -#ifdef __AVR_ATmega8__ - SP=RAMEND; // This is done by hardware reset -#endif - - // Adaboot no-wait mod - ch = MCUSR; - 3e02: 84 b7 in r24, 0x34 ; 52 - MCUSR = 0; - 3e04: 14 be out 0x34, r1 ; 52 - if (!(ch & _BV(EXTRF))) appStart(); - 3e06: 81 ff sbrs r24, 1 - 3e08: e7 d0 rcall .+462 ; 0x3fd8 - -#if LED_START_FLASHES > 0 - // Set up Timer 1 for timeout counter - TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 - 3e0a: 85 e0 ldi r24, 0x05 ; 5 - 3e0c: 80 93 81 00 sts 0x0081, r24 - UCSRA = _BV(U2X); //Double speed mode USART - UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx - UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 - UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); -#else - UCSR0A = _BV(U2X0); //Double speed mode USART0 - 3e10: 82 e0 ldi r24, 0x02 ; 2 - 3e12: 80 93 c0 00 sts 0x00C0, r24 - UCSR0B = _BV(RXEN0) | _BV(TXEN0); - 3e16: 88 e1 ldi r24, 0x18 ; 24 - 3e18: 80 93 c1 00 sts 0x00C1, r24 - UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); - 3e1c: 86 e0 ldi r24, 0x06 ; 6 - 3e1e: 80 93 c2 00 sts 0x00C2, r24 - UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); - 3e22: 85 e1 ldi r24, 0x15 ; 21 - 3e24: 80 93 c4 00 sts 0x00C4, r24 -#endif -#endif - - // Set up watchdog to trigger after 500ms - watchdogConfig(WATCHDOG_1S); - 3e28: 8e e0 ldi r24, 0x0E ; 14 - 3e2a: c0 d0 rcall .+384 ; 0x3fac - - /* Set LED pin as output */ - LED_DDR |= _BV(LED); - 3e2c: 25 9a sbi 0x04, 5 ; 4 - 3e2e: 86 e0 ldi r24, 0x06 ; 6 -} - -#if LED_START_FLASHES > 0 -void flash_led(uint8_t count) { - do { - TCNT1 = -(F_CPU/(1024*16)); - 3e30: 2c e3 ldi r18, 0x3C ; 60 - 3e32: 3b ef ldi r19, 0xFB ; 251 - TIFR1 = _BV(TOV1); - 3e34: 91 e0 ldi r25, 0x01 ; 1 -} - -#if LED_START_FLASHES > 0 -void flash_led(uint8_t count) { - do { - TCNT1 = -(F_CPU/(1024*16)); - 3e36: 30 93 85 00 sts 0x0085, r19 - 3e3a: 20 93 84 00 sts 0x0084, r18 - TIFR1 = _BV(TOV1); - 3e3e: 96 bb out 0x16, r25 ; 22 - while(!(TIFR1 & _BV(TOV1))); - 3e40: b0 9b sbis 0x16, 0 ; 22 - 3e42: fe cf rjmp .-4 ; 0x3e40 -#ifdef __AVR_ATmega8__ - LED_PORT ^= _BV(LED); -#else - LED_PIN |= _BV(LED); - 3e44: 1d 9a sbi 0x03, 5 ; 3 -} -#endif - -// Watchdog functions. These are only safe with interrupts turned off. -void watchdogReset() { - __asm__ __volatile__ ( - 3e46: a8 95 wdr - LED_PORT ^= _BV(LED); -#else - LED_PIN |= _BV(LED); -#endif - watchdogReset(); - } while (--count); - 3e48: 81 50 subi r24, 0x01 ; 1 - 3e4a: a9 f7 brne .-22 ; 0x3e36 - /* get character from UART */ - ch = getch(); - - if(ch == STK_GET_PARAMETER) { - // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy - getNch(1); - 3e4c: 99 24 eor r9, r9 - 3e4e: 93 94 inc r9 - __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - addrPtr += 2; - } while (--ch); - - // Write from programming buffer - __boot_page_write_short((uint16_t)(void*)address); - 3e50: a5 e0 ldi r26, 0x05 ; 5 - 3e52: aa 2e mov r10, r26 - boot_spm_busy_wait(); - -#if defined(RWWSRE) - // Reenable read access to flash - boot_rww_enable(); - 3e54: f1 e1 ldi r31, 0x11 ; 17 - 3e56: bf 2e mov r11, r31 -#endif - - /* Forever loop */ - for (;;) { - /* get character from UART */ - ch = getch(); - 3e58: 9d d0 rcall .+314 ; 0x3f94 - - if(ch == STK_GET_PARAMETER) { - 3e5a: 81 34 cpi r24, 0x41 ; 65 - 3e5c: 21 f4 brne .+8 ; 0x3e66 - // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy - getNch(1); - 3e5e: 81 e0 ldi r24, 0x01 ; 1 - 3e60: b3 d0 rcall .+358 ; 0x3fc8 - putch(0x03); - 3e62: 83 e0 ldi r24, 0x03 ; 3 - 3e64: 1f c0 rjmp .+62 ; 0x3ea4 - } - else if(ch == STK_SET_DEVICE) { - 3e66: 82 34 cpi r24, 0x42 ; 66 - 3e68: 11 f4 brne .+4 ; 0x3e6e - // SET DEVICE is ignored - getNch(20); - 3e6a: 84 e1 ldi r24, 0x14 ; 20 - 3e6c: 03 c0 rjmp .+6 ; 0x3e74 - } - else if(ch == STK_SET_DEVICE_EXT) { - 3e6e: 85 34 cpi r24, 0x45 ; 69 - 3e70: 19 f4 brne .+6 ; 0x3e78 - // SET DEVICE EXT is ignored - getNch(5); - 3e72: 85 e0 ldi r24, 0x05 ; 5 - 3e74: a9 d0 rcall .+338 ; 0x3fc8 - 3e76: 83 c0 rjmp .+262 ; 0x3f7e - } - else if(ch == STK_LOAD_ADDRESS) { - 3e78: 85 35 cpi r24, 0x55 ; 85 - 3e7a: 79 f4 brne .+30 ; 0x3e9a - // LOAD ADDRESS - uint16_t newAddress; - newAddress = getch(); - 3e7c: 8b d0 rcall .+278 ; 0x3f94 - newAddress = (newAddress & 0xff) | (getch() << 8); - 3e7e: e8 2e mov r14, r24 - 3e80: ff 24 eor r15, r15 - 3e82: 88 d0 rcall .+272 ; 0x3f94 - 3e84: 08 2f mov r16, r24 - 3e86: 10 e0 ldi r17, 0x00 ; 0 - 3e88: 10 2f mov r17, r16 - 3e8a: 00 27 eor r16, r16 - 3e8c: 0e 29 or r16, r14 - 3e8e: 1f 29 or r17, r15 -#ifdef RAMPZ - // Transfer top bit to RAMPZ - RAMPZ = (newAddress & 0x8000) ? 1 : 0; -#endif - newAddress += newAddress; // Convert from word address to byte address - 3e90: 00 0f add r16, r16 - 3e92: 11 1f adc r17, r17 - address = newAddress; - verifySpace(); - 3e94: 91 d0 rcall .+290 ; 0x3fb8 - 3e96: 68 01 movw r12, r16 - 3e98: 72 c0 rjmp .+228 ; 0x3f7e - } - else if(ch == STK_UNIVERSAL) { - 3e9a: 86 35 cpi r24, 0x56 ; 86 - 3e9c: 29 f4 brne .+10 ; 0x3ea8 - // UNIVERSAL command is ignored - getNch(4); - 3e9e: 84 e0 ldi r24, 0x04 ; 4 - 3ea0: 93 d0 rcall .+294 ; 0x3fc8 - putch(0x00); - 3ea2: 80 e0 ldi r24, 0x00 ; 0 - 3ea4: 6f d0 rcall .+222 ; 0x3f84 - 3ea6: 6b c0 rjmp .+214 ; 0x3f7e - } - /* Write memory, length is big endian and is in bytes */ - else if(ch == STK_PROG_PAGE) { - 3ea8: 84 36 cpi r24, 0x64 ; 100 - 3eaa: 09 f0 breq .+2 ; 0x3eae - 3eac: 42 c0 rjmp .+132 ; 0x3f32 - // PROGRAM PAGE - we support flash programming only, not EEPROM - uint8_t *bufPtr; - uint16_t addrPtr; - - getch(); /* getlen() */ - 3eae: 72 d0 rcall .+228 ; 0x3f94 - length = getch(); - 3eb0: 71 d0 rcall .+226 ; 0x3f94 - 3eb2: 08 2f mov r16, r24 - getch(); - 3eb4: 6f d0 rcall .+222 ; 0x3f94 - - // If we are in RWW section, immediately start page erase - if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 3eb6: 80 e0 ldi r24, 0x00 ; 0 - 3eb8: c8 16 cp r12, r24 - 3eba: 88 e3 ldi r24, 0x38 ; 56 - 3ebc: d8 06 cpc r13, r24 - 3ebe: 20 f4 brcc .+8 ; 0x3ec8 - 3ec0: 83 e0 ldi r24, 0x03 ; 3 - 3ec2: f6 01 movw r30, r12 - 3ec4: 87 bf out 0x37, r24 ; 55 - 3ec6: e8 95 spm - 3ec8: c0 e0 ldi r28, 0x00 ; 0 - 3eca: d1 e0 ldi r29, 0x01 ; 1 - - // While that is going on, read in page contents - bufPtr = buff; - do *bufPtr++ = getch(); - 3ecc: 63 d0 rcall .+198 ; 0x3f94 - 3ece: 89 93 st Y+, r24 - while (--length); - 3ed0: 0c 17 cp r16, r28 - 3ed2: e1 f7 brne .-8 ; 0x3ecc - - // If we are in NRWW section, page erase has to be delayed until now. - // Todo: Take RAMPZ into account - if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 3ed4: f0 e0 ldi r31, 0x00 ; 0 - 3ed6: cf 16 cp r12, r31 - 3ed8: f8 e3 ldi r31, 0x38 ; 56 - 3eda: df 06 cpc r13, r31 - 3edc: 20 f0 brcs .+8 ; 0x3ee6 - 3ede: 83 e0 ldi r24, 0x03 ; 3 - 3ee0: f6 01 movw r30, r12 - 3ee2: 87 bf out 0x37, r24 ; 55 - 3ee4: e8 95 spm - - // Read command terminator, start reply - verifySpace(); - 3ee6: 68 d0 rcall .+208 ; 0x3fb8 - - // If only a partial page is to be programmed, the erase might not be complete. - // So check that here - boot_spm_busy_wait(); - 3ee8: 07 b6 in r0, 0x37 ; 55 - 3eea: 00 fc sbrc r0, 0 - 3eec: fd cf rjmp .-6 ; 0x3ee8 - 3eee: a6 01 movw r20, r12 - 3ef0: a0 e0 ldi r26, 0x00 ; 0 - 3ef2: b1 e0 ldi r27, 0x01 ; 1 - bufPtr = buff; - addrPtr = (uint16_t)(void*)address; - ch = SPM_PAGESIZE / 2; - do { - uint16_t a; - a = *bufPtr++; - 3ef4: 2c 91 ld r18, X - 3ef6: 30 e0 ldi r19, 0x00 ; 0 - a |= (*bufPtr++) << 8; - 3ef8: 11 96 adiw r26, 0x01 ; 1 - 3efa: 8c 91 ld r24, X - 3efc: 11 97 sbiw r26, 0x01 ; 1 - 3efe: 90 e0 ldi r25, 0x00 ; 0 - 3f00: 98 2f mov r25, r24 - 3f02: 88 27 eor r24, r24 - 3f04: 82 2b or r24, r18 - 3f06: 93 2b or r25, r19 -#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) -#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) -#endif - -/* main program starts here */ -int main(void) { - 3f08: 12 96 adiw r26, 0x02 ; 2 - ch = SPM_PAGESIZE / 2; - do { - uint16_t a; - a = *bufPtr++; - a |= (*bufPtr++) << 8; - __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - 3f0a: fa 01 movw r30, r20 - 3f0c: 0c 01 movw r0, r24 - 3f0e: 97 be out 0x37, r9 ; 55 - 3f10: e8 95 spm - 3f12: 11 24 eor r1, r1 - addrPtr += 2; - 3f14: 4e 5f subi r20, 0xFE ; 254 - 3f16: 5f 4f sbci r21, 0xFF ; 255 - } while (--ch); - 3f18: f1 e0 ldi r31, 0x01 ; 1 - 3f1a: a0 38 cpi r26, 0x80 ; 128 - 3f1c: bf 07 cpc r27, r31 - 3f1e: 51 f7 brne .-44 ; 0x3ef4 - - // Write from programming buffer - __boot_page_write_short((uint16_t)(void*)address); - 3f20: f6 01 movw r30, r12 - 3f22: a7 be out 0x37, r10 ; 55 - 3f24: e8 95 spm - boot_spm_busy_wait(); - 3f26: 07 b6 in r0, 0x37 ; 55 - 3f28: 00 fc sbrc r0, 0 - 3f2a: fd cf rjmp .-6 ; 0x3f26 - -#if defined(RWWSRE) - // Reenable read access to flash - boot_rww_enable(); - 3f2c: b7 be out 0x37, r11 ; 55 - 3f2e: e8 95 spm - 3f30: 26 c0 rjmp .+76 ; 0x3f7e -#endif - - } - /* Read memory block mode, length is big endian. */ - else if(ch == STK_READ_PAGE) { - 3f32: 84 37 cpi r24, 0x74 ; 116 - 3f34: b1 f4 brne .+44 ; 0x3f62 - // READ PAGE - we only read flash - getch(); /* getlen() */ - 3f36: 2e d0 rcall .+92 ; 0x3f94 - length = getch(); - 3f38: 2d d0 rcall .+90 ; 0x3f94 - 3f3a: f8 2e mov r15, r24 - getch(); - 3f3c: 2b d0 rcall .+86 ; 0x3f94 - - verifySpace(); - 3f3e: 3c d0 rcall .+120 ; 0x3fb8 - 3f40: f6 01 movw r30, r12 - 3f42: ef 2c mov r14, r15 - putch(result); - address++; - } - while (--length); -#else - do putch(pgm_read_byte_near(address++)); - 3f44: 8f 01 movw r16, r30 - 3f46: 0f 5f subi r16, 0xFF ; 255 - 3f48: 1f 4f sbci r17, 0xFF ; 255 - 3f4a: 84 91 lpm r24, Z+ - 3f4c: 1b d0 rcall .+54 ; 0x3f84 - while (--length); - 3f4e: ea 94 dec r14 - 3f50: f8 01 movw r30, r16 - 3f52: c1 f7 brne .-16 ; 0x3f44 -#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) -#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) -#endif - -/* main program starts here */ -int main(void) { - 3f54: 08 94 sec - 3f56: c1 1c adc r12, r1 - 3f58: d1 1c adc r13, r1 - 3f5a: fa 94 dec r15 - 3f5c: cf 0c add r12, r15 - 3f5e: d1 1c adc r13, r1 - 3f60: 0e c0 rjmp .+28 ; 0x3f7e -#endif -#endif - } - - /* Get device signature bytes */ - else if(ch == STK_READ_SIGN) { - 3f62: 85 37 cpi r24, 0x75 ; 117 - 3f64: 39 f4 brne .+14 ; 0x3f74 - // READ SIGN - return what Avrdude wants to hear - verifySpace(); - 3f66: 28 d0 rcall .+80 ; 0x3fb8 - putch(SIGNATURE_0); - 3f68: 8e e1 ldi r24, 0x1E ; 30 - 3f6a: 0c d0 rcall .+24 ; 0x3f84 - putch(SIGNATURE_1); - 3f6c: 84 e9 ldi r24, 0x94 ; 148 - 3f6e: 0a d0 rcall .+20 ; 0x3f84 - putch(SIGNATURE_2); - 3f70: 86 e0 ldi r24, 0x06 ; 6 - 3f72: 98 cf rjmp .-208 ; 0x3ea4 - } - else if (ch == 'Q') { - 3f74: 81 35 cpi r24, 0x51 ; 81 - 3f76: 11 f4 brne .+4 ; 0x3f7c - // Adaboot no-wait mod - watchdogConfig(WATCHDOG_16MS); - 3f78: 88 e0 ldi r24, 0x08 ; 8 - 3f7a: 18 d0 rcall .+48 ; 0x3fac - verifySpace(); - } - else { - // This covers the response to commands like STK_ENTER_PROGMODE - verifySpace(); - 3f7c: 1d d0 rcall .+58 ; 0x3fb8 - } - putch(STK_OK); - 3f7e: 80 e1 ldi r24, 0x10 ; 16 - 3f80: 01 d0 rcall .+2 ; 0x3f84 - 3f82: 6a cf rjmp .-300 ; 0x3e58 - -00003f84 : - } -} - -void putch(char ch) { - 3f84: 98 2f mov r25, r24 -#ifndef SOFT_UART - while (!(UCSR0A & _BV(UDRE0))); - 3f86: 80 91 c0 00 lds r24, 0x00C0 - 3f8a: 85 ff sbrs r24, 5 - 3f8c: fc cf rjmp .-8 ; 0x3f86 - UDR0 = ch; - 3f8e: 90 93 c6 00 sts 0x00C6, r25 - [uartBit] "I" (UART_TX_BIT) - : - "r25" - ); -#endif -} - 3f92: 08 95 ret - -00003f94 : - [uartBit] "I" (UART_RX_BIT) - : - "r25" -); -#else - while(!(UCSR0A & _BV(RXC0))) - 3f94: 80 91 c0 00 lds r24, 0x00C0 - 3f98: 87 ff sbrs r24, 7 - 3f9a: fc cf rjmp .-8 ; 0x3f94 - ; - if (!(UCSR0A & _BV(FE0))) { - 3f9c: 80 91 c0 00 lds r24, 0x00C0 - 3fa0: 84 fd sbrc r24, 4 - 3fa2: 01 c0 rjmp .+2 ; 0x3fa6 -} -#endif - -// Watchdog functions. These are only safe with interrupts turned off. -void watchdogReset() { - __asm__ __volatile__ ( - 3fa4: a8 95 wdr - * don't care that an invalid char is returned...) - */ - watchdogReset(); - } - - ch = UDR0; - 3fa6: 80 91 c6 00 lds r24, 0x00C6 - LED_PIN |= _BV(LED); -#endif -#endif - - return ch; -} - 3faa: 08 95 ret - -00003fac : - "wdr\n" - ); -} - -void watchdogConfig(uint8_t x) { - WDTCSR = _BV(WDCE) | _BV(WDE); - 3fac: e0 e6 ldi r30, 0x60 ; 96 - 3fae: f0 e0 ldi r31, 0x00 ; 0 - 3fb0: 98 e1 ldi r25, 0x18 ; 24 - 3fb2: 90 83 st Z, r25 - WDTCSR = x; - 3fb4: 80 83 st Z, r24 -} - 3fb6: 08 95 ret - -00003fb8 : - do getch(); while (--count); - verifySpace(); -} - -void verifySpace() { - if (getch() != CRC_EOP) { - 3fb8: ed df rcall .-38 ; 0x3f94 - 3fba: 80 32 cpi r24, 0x20 ; 32 - 3fbc: 19 f0 breq .+6 ; 0x3fc4 - watchdogConfig(WATCHDOG_16MS); // shorten WD timeout - 3fbe: 88 e0 ldi r24, 0x08 ; 8 - 3fc0: f5 df rcall .-22 ; 0x3fac - 3fc2: ff cf rjmp .-2 ; 0x3fc2 - while (1) // and busy-loop so that WD causes - ; // a reset and app start. - } - putch(STK_INSYNC); - 3fc4: 84 e1 ldi r24, 0x14 ; 20 -} - 3fc6: de cf rjmp .-68 ; 0x3f84 - -00003fc8 : - ::[count] "M" (UART_B_VALUE) - ); -} -#endif - -void getNch(uint8_t count) { - 3fc8: 1f 93 push r17 - 3fca: 18 2f mov r17, r24 - do getch(); while (--count); - 3fcc: e3 df rcall .-58 ; 0x3f94 - 3fce: 11 50 subi r17, 0x01 ; 1 - 3fd0: e9 f7 brne .-6 ; 0x3fcc - verifySpace(); - 3fd2: f2 df rcall .-28 ; 0x3fb8 -} - 3fd4: 1f 91 pop r17 - 3fd6: 08 95 ret - -00003fd8 : - WDTCSR = _BV(WDCE) | _BV(WDE); - WDTCSR = x; -} - -void appStart() { - watchdogConfig(WATCHDOG_OFF); - 3fd8: 80 e0 ldi r24, 0x00 ; 0 - 3fda: e8 df rcall .-48 ; 0x3fac - __asm__ __volatile__ ( - 3fdc: ee 27 eor r30, r30 - 3fde: ff 27 eor r31, r31 - 3fe0: 09 94 ijmp diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.hex b/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.hex deleted file mode 100644 index 2c6339554..000000000 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.hex +++ /dev/null @@ -1,34 +0,0 @@ -:103E0000112484B714BE81FFE7D085E08093810040 -:103E100082E08093C00088E18093C10086E08093B7 -:103E2000C20088E08093C4008EE0C0D0259A86E06E -:103E300028E13EEF91E0309385002093840096BB0B -:103E4000B09BFECF1D9AA8958150A9F79924939411 -:103E5000A5E0AA2EF1E1BF2E9DD0813421F481E0AE -:103E6000B3D083E01FC0823411F484E103C08534F1 -:103E700019F485E0A9D083C0853579F48BD0E82E7C -:103E8000FF2488D0082F10E0102F00270E291F29AB -:103E9000000F111F91D0680172C0863529F484E0AB -:103EA00093D080E06FD06BC0843609F042C072D0EE -:103EB00071D0082F6FD080E0C81688E3D80620F4B0 -:103EC00083E0F60187BFE895C0E0D1E063D0899335 -:103ED0000C17E1F7F0E0CF16F8E3DF0620F083E0FF -:103EE000F60187BFE89568D007B600FCFDCFA601B4 -:103EF000A0E0B1E02C9130E011968C91119790E008 -:103F0000982F8827822B932B1296FA010C0197BECB -:103F1000E89511244E5F5F4FF1E0A038BF0751F7DD -:103F2000F601A7BEE89507B600FCFDCFB7BEE89541 -:103F300026C08437B1F42ED02DD0F82E2BD03CD013 -:103F4000F601EF2C8F010F5F1F4F84911BD0EA9475 -:103F5000F801C1F70894C11CD11CFA94CF0CD11CF4 -:103F60000EC0853739F428D08EE10CD084E90AD010 -:103F700086E098CF813511F488E018D01DD080E11B -:103F800001D06ACF982F8091C00085FFFCCF90931D -:103F9000C60008958091C00087FFFCCF8091C000CB -:103FA00084FD01C0A8958091C6000895E0E6F0E088 -:103FB00098E1908380830895EDDF803219F088E0E6 -:103FC000F5DFFFCF84E1DECF1F93182FE3DF115021 -:103FD000E9F7F2DF1F91089580E0E8DFEE27FF2781 -:023FE000099442 -:023FFE000304BA -:0400000300003E00BB -:00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.lst b/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.lst deleted file mode 100644 index 1fb903ca1..000000000 --- a/hardware/arduino/bootloaders/optiboot/optiboot_pro_8MHz.lst +++ /dev/null @@ -1,571 +0,0 @@ - -optiboot_pro_8MHz.elf: file format elf32-avr - -Sections: -Idx Name Size VMA LMA File off Algn - 0 .text 000001e2 00003e00 00003e00 00000054 2**1 - CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .version 00000002 00003ffe 00003ffe 00000236 2**0 - CONTENTS, READONLY - 2 .debug_aranges 00000028 00000000 00000000 00000238 2**0 - CONTENTS, READONLY, DEBUGGING - 3 .debug_pubnames 0000005f 00000000 00000000 00000260 2**0 - CONTENTS, READONLY, DEBUGGING - 4 .debug_info 0000028e 00000000 00000000 000002bf 2**0 - CONTENTS, READONLY, DEBUGGING - 5 .debug_abbrev 00000171 00000000 00000000 0000054d 2**0 - CONTENTS, READONLY, DEBUGGING - 6 .debug_line 0000045e 00000000 00000000 000006be 2**0 - CONTENTS, READONLY, DEBUGGING - 7 .debug_frame 00000080 00000000 00000000 00000b1c 2**2 - CONTENTS, READONLY, DEBUGGING - 8 .debug_str 00000149 00000000 00000000 00000b9c 2**0 - CONTENTS, READONLY, DEBUGGING - 9 .debug_loc 0000027e 00000000 00000000 00000ce5 2**0 - CONTENTS, READONLY, DEBUGGING - 10 .debug_ranges 00000060 00000000 00000000 00000f63 2**0 - CONTENTS, READONLY, DEBUGGING - -Disassembly of section .text: - -00003e00
    : -#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) -#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) -#endif - -/* main program starts here */ -int main(void) { - 3e00: 11 24 eor r1, r1 -#ifdef __AVR_ATmega8__ - SP=RAMEND; // This is done by hardware reset -#endif - - // Adaboot no-wait mod - ch = MCUSR; - 3e02: 84 b7 in r24, 0x34 ; 52 - MCUSR = 0; - 3e04: 14 be out 0x34, r1 ; 52 - if (!(ch & _BV(EXTRF))) appStart(); - 3e06: 81 ff sbrs r24, 1 - 3e08: e7 d0 rcall .+462 ; 0x3fd8 - -#if LED_START_FLASHES > 0 - // Set up Timer 1 for timeout counter - TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 - 3e0a: 85 e0 ldi r24, 0x05 ; 5 - 3e0c: 80 93 81 00 sts 0x0081, r24 - UCSRA = _BV(U2X); //Double speed mode USART - UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx - UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 - UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); -#else - UCSR0A = _BV(U2X0); //Double speed mode USART0 - 3e10: 82 e0 ldi r24, 0x02 ; 2 - 3e12: 80 93 c0 00 sts 0x00C0, r24 - UCSR0B = _BV(RXEN0) | _BV(TXEN0); - 3e16: 88 e1 ldi r24, 0x18 ; 24 - 3e18: 80 93 c1 00 sts 0x00C1, r24 - UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); - 3e1c: 86 e0 ldi r24, 0x06 ; 6 - 3e1e: 80 93 c2 00 sts 0x00C2, r24 - UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); - 3e22: 88 e0 ldi r24, 0x08 ; 8 - 3e24: 80 93 c4 00 sts 0x00C4, r24 -#endif -#endif - - // Set up watchdog to trigger after 500ms - watchdogConfig(WATCHDOG_1S); - 3e28: 8e e0 ldi r24, 0x0E ; 14 - 3e2a: c0 d0 rcall .+384 ; 0x3fac - - /* Set LED pin as output */ - LED_DDR |= _BV(LED); - 3e2c: 25 9a sbi 0x04, 5 ; 4 - 3e2e: 86 e0 ldi r24, 0x06 ; 6 -} - -#if LED_START_FLASHES > 0 -void flash_led(uint8_t count) { - do { - TCNT1 = -(F_CPU/(1024*16)); - 3e30: 28 e1 ldi r18, 0x18 ; 24 - 3e32: 3e ef ldi r19, 0xFE ; 254 - TIFR1 = _BV(TOV1); - 3e34: 91 e0 ldi r25, 0x01 ; 1 -} - -#if LED_START_FLASHES > 0 -void flash_led(uint8_t count) { - do { - TCNT1 = -(F_CPU/(1024*16)); - 3e36: 30 93 85 00 sts 0x0085, r19 - 3e3a: 20 93 84 00 sts 0x0084, r18 - TIFR1 = _BV(TOV1); - 3e3e: 96 bb out 0x16, r25 ; 22 - while(!(TIFR1 & _BV(TOV1))); - 3e40: b0 9b sbis 0x16, 0 ; 22 - 3e42: fe cf rjmp .-4 ; 0x3e40 -#ifdef __AVR_ATmega8__ - LED_PORT ^= _BV(LED); -#else - LED_PIN |= _BV(LED); - 3e44: 1d 9a sbi 0x03, 5 ; 3 -} -#endif - -// Watchdog functions. These are only safe with interrupts turned off. -void watchdogReset() { - __asm__ __volatile__ ( - 3e46: a8 95 wdr - LED_PORT ^= _BV(LED); -#else - LED_PIN |= _BV(LED); -#endif - watchdogReset(); - } while (--count); - 3e48: 81 50 subi r24, 0x01 ; 1 - 3e4a: a9 f7 brne .-22 ; 0x3e36 - /* get character from UART */ - ch = getch(); - - if(ch == STK_GET_PARAMETER) { - // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy - getNch(1); - 3e4c: 99 24 eor r9, r9 - 3e4e: 93 94 inc r9 - __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - addrPtr += 2; - } while (--ch); - - // Write from programming buffer - __boot_page_write_short((uint16_t)(void*)address); - 3e50: a5 e0 ldi r26, 0x05 ; 5 - 3e52: aa 2e mov r10, r26 - boot_spm_busy_wait(); - -#if defined(RWWSRE) - // Reenable read access to flash - boot_rww_enable(); - 3e54: f1 e1 ldi r31, 0x11 ; 17 - 3e56: bf 2e mov r11, r31 -#endif - - /* Forever loop */ - for (;;) { - /* get character from UART */ - ch = getch(); - 3e58: 9d d0 rcall .+314 ; 0x3f94 - - if(ch == STK_GET_PARAMETER) { - 3e5a: 81 34 cpi r24, 0x41 ; 65 - 3e5c: 21 f4 brne .+8 ; 0x3e66 - // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy - getNch(1); - 3e5e: 81 e0 ldi r24, 0x01 ; 1 - 3e60: b3 d0 rcall .+358 ; 0x3fc8 - putch(0x03); - 3e62: 83 e0 ldi r24, 0x03 ; 3 - 3e64: 1f c0 rjmp .+62 ; 0x3ea4 - } - else if(ch == STK_SET_DEVICE) { - 3e66: 82 34 cpi r24, 0x42 ; 66 - 3e68: 11 f4 brne .+4 ; 0x3e6e - // SET DEVICE is ignored - getNch(20); - 3e6a: 84 e1 ldi r24, 0x14 ; 20 - 3e6c: 03 c0 rjmp .+6 ; 0x3e74 - } - else if(ch == STK_SET_DEVICE_EXT) { - 3e6e: 85 34 cpi r24, 0x45 ; 69 - 3e70: 19 f4 brne .+6 ; 0x3e78 - // SET DEVICE EXT is ignored - getNch(5); - 3e72: 85 e0 ldi r24, 0x05 ; 5 - 3e74: a9 d0 rcall .+338 ; 0x3fc8 - 3e76: 83 c0 rjmp .+262 ; 0x3f7e - } - else if(ch == STK_LOAD_ADDRESS) { - 3e78: 85 35 cpi r24, 0x55 ; 85 - 3e7a: 79 f4 brne .+30 ; 0x3e9a - // LOAD ADDRESS - uint16_t newAddress; - newAddress = getch(); - 3e7c: 8b d0 rcall .+278 ; 0x3f94 - newAddress = (newAddress & 0xff) | (getch() << 8); - 3e7e: e8 2e mov r14, r24 - 3e80: ff 24 eor r15, r15 - 3e82: 88 d0 rcall .+272 ; 0x3f94 - 3e84: 08 2f mov r16, r24 - 3e86: 10 e0 ldi r17, 0x00 ; 0 - 3e88: 10 2f mov r17, r16 - 3e8a: 00 27 eor r16, r16 - 3e8c: 0e 29 or r16, r14 - 3e8e: 1f 29 or r17, r15 -#ifdef RAMPZ - // Transfer top bit to RAMPZ - RAMPZ = (newAddress & 0x8000) ? 1 : 0; -#endif - newAddress += newAddress; // Convert from word address to byte address - 3e90: 00 0f add r16, r16 - 3e92: 11 1f adc r17, r17 - address = newAddress; - verifySpace(); - 3e94: 91 d0 rcall .+290 ; 0x3fb8 - 3e96: 68 01 movw r12, r16 - 3e98: 72 c0 rjmp .+228 ; 0x3f7e - } - else if(ch == STK_UNIVERSAL) { - 3e9a: 86 35 cpi r24, 0x56 ; 86 - 3e9c: 29 f4 brne .+10 ; 0x3ea8 - // UNIVERSAL command is ignored - getNch(4); - 3e9e: 84 e0 ldi r24, 0x04 ; 4 - 3ea0: 93 d0 rcall .+294 ; 0x3fc8 - putch(0x00); - 3ea2: 80 e0 ldi r24, 0x00 ; 0 - 3ea4: 6f d0 rcall .+222 ; 0x3f84 - 3ea6: 6b c0 rjmp .+214 ; 0x3f7e - } - /* Write memory, length is big endian and is in bytes */ - else if(ch == STK_PROG_PAGE) { - 3ea8: 84 36 cpi r24, 0x64 ; 100 - 3eaa: 09 f0 breq .+2 ; 0x3eae - 3eac: 42 c0 rjmp .+132 ; 0x3f32 - // PROGRAM PAGE - we support flash programming only, not EEPROM - uint8_t *bufPtr; - uint16_t addrPtr; - - getch(); /* getlen() */ - 3eae: 72 d0 rcall .+228 ; 0x3f94 - length = getch(); - 3eb0: 71 d0 rcall .+226 ; 0x3f94 - 3eb2: 08 2f mov r16, r24 - getch(); - 3eb4: 6f d0 rcall .+222 ; 0x3f94 - - // If we are in RWW section, immediately start page erase - if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 3eb6: 80 e0 ldi r24, 0x00 ; 0 - 3eb8: c8 16 cp r12, r24 - 3eba: 88 e3 ldi r24, 0x38 ; 56 - 3ebc: d8 06 cpc r13, r24 - 3ebe: 20 f4 brcc .+8 ; 0x3ec8 - 3ec0: 83 e0 ldi r24, 0x03 ; 3 - 3ec2: f6 01 movw r30, r12 - 3ec4: 87 bf out 0x37, r24 ; 55 - 3ec6: e8 95 spm - 3ec8: c0 e0 ldi r28, 0x00 ; 0 - 3eca: d1 e0 ldi r29, 0x01 ; 1 - - // While that is going on, read in page contents - bufPtr = buff; - do *bufPtr++ = getch(); - 3ecc: 63 d0 rcall .+198 ; 0x3f94 - 3ece: 89 93 st Y+, r24 - while (--length); - 3ed0: 0c 17 cp r16, r28 - 3ed2: e1 f7 brne .-8 ; 0x3ecc - - // If we are in NRWW section, page erase has to be delayed until now. - // Todo: Take RAMPZ into account - if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); - 3ed4: f0 e0 ldi r31, 0x00 ; 0 - 3ed6: cf 16 cp r12, r31 - 3ed8: f8 e3 ldi r31, 0x38 ; 56 - 3eda: df 06 cpc r13, r31 - 3edc: 20 f0 brcs .+8 ; 0x3ee6 - 3ede: 83 e0 ldi r24, 0x03 ; 3 - 3ee0: f6 01 movw r30, r12 - 3ee2: 87 bf out 0x37, r24 ; 55 - 3ee4: e8 95 spm - - // Read command terminator, start reply - verifySpace(); - 3ee6: 68 d0 rcall .+208 ; 0x3fb8 - - // If only a partial page is to be programmed, the erase might not be complete. - // So check that here - boot_spm_busy_wait(); - 3ee8: 07 b6 in r0, 0x37 ; 55 - 3eea: 00 fc sbrc r0, 0 - 3eec: fd cf rjmp .-6 ; 0x3ee8 - 3eee: a6 01 movw r20, r12 - 3ef0: a0 e0 ldi r26, 0x00 ; 0 - 3ef2: b1 e0 ldi r27, 0x01 ; 1 - bufPtr = buff; - addrPtr = (uint16_t)(void*)address; - ch = SPM_PAGESIZE / 2; - do { - uint16_t a; - a = *bufPtr++; - 3ef4: 2c 91 ld r18, X - 3ef6: 30 e0 ldi r19, 0x00 ; 0 - a |= (*bufPtr++) << 8; - 3ef8: 11 96 adiw r26, 0x01 ; 1 - 3efa: 8c 91 ld r24, X - 3efc: 11 97 sbiw r26, 0x01 ; 1 - 3efe: 90 e0 ldi r25, 0x00 ; 0 - 3f00: 98 2f mov r25, r24 - 3f02: 88 27 eor r24, r24 - 3f04: 82 2b or r24, r18 - 3f06: 93 2b or r25, r19 -#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) -#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) -#endif - -/* main program starts here */ -int main(void) { - 3f08: 12 96 adiw r26, 0x02 ; 2 - ch = SPM_PAGESIZE / 2; - do { - uint16_t a; - a = *bufPtr++; - a |= (*bufPtr++) << 8; - __boot_page_fill_short((uint16_t)(void*)addrPtr,a); - 3f0a: fa 01 movw r30, r20 - 3f0c: 0c 01 movw r0, r24 - 3f0e: 97 be out 0x37, r9 ; 55 - 3f10: e8 95 spm - 3f12: 11 24 eor r1, r1 - addrPtr += 2; - 3f14: 4e 5f subi r20, 0xFE ; 254 - 3f16: 5f 4f sbci r21, 0xFF ; 255 - } while (--ch); - 3f18: f1 e0 ldi r31, 0x01 ; 1 - 3f1a: a0 38 cpi r26, 0x80 ; 128 - 3f1c: bf 07 cpc r27, r31 - 3f1e: 51 f7 brne .-44 ; 0x3ef4 - - // Write from programming buffer - __boot_page_write_short((uint16_t)(void*)address); - 3f20: f6 01 movw r30, r12 - 3f22: a7 be out 0x37, r10 ; 55 - 3f24: e8 95 spm - boot_spm_busy_wait(); - 3f26: 07 b6 in r0, 0x37 ; 55 - 3f28: 00 fc sbrc r0, 0 - 3f2a: fd cf rjmp .-6 ; 0x3f26 - -#if defined(RWWSRE) - // Reenable read access to flash - boot_rww_enable(); - 3f2c: b7 be out 0x37, r11 ; 55 - 3f2e: e8 95 spm - 3f30: 26 c0 rjmp .+76 ; 0x3f7e -#endif - - } - /* Read memory block mode, length is big endian. */ - else if(ch == STK_READ_PAGE) { - 3f32: 84 37 cpi r24, 0x74 ; 116 - 3f34: b1 f4 brne .+44 ; 0x3f62 - // READ PAGE - we only read flash - getch(); /* getlen() */ - 3f36: 2e d0 rcall .+92 ; 0x3f94 - length = getch(); - 3f38: 2d d0 rcall .+90 ; 0x3f94 - 3f3a: f8 2e mov r15, r24 - getch(); - 3f3c: 2b d0 rcall .+86 ; 0x3f94 - - verifySpace(); - 3f3e: 3c d0 rcall .+120 ; 0x3fb8 - 3f40: f6 01 movw r30, r12 - 3f42: ef 2c mov r14, r15 - putch(result); - address++; - } - while (--length); -#else - do putch(pgm_read_byte_near(address++)); - 3f44: 8f 01 movw r16, r30 - 3f46: 0f 5f subi r16, 0xFF ; 255 - 3f48: 1f 4f sbci r17, 0xFF ; 255 - 3f4a: 84 91 lpm r24, Z+ - 3f4c: 1b d0 rcall .+54 ; 0x3f84 - while (--length); - 3f4e: ea 94 dec r14 - 3f50: f8 01 movw r30, r16 - 3f52: c1 f7 brne .-16 ; 0x3f44 -#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) -#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) -#endif - -/* main program starts here */ -int main(void) { - 3f54: 08 94 sec - 3f56: c1 1c adc r12, r1 - 3f58: d1 1c adc r13, r1 - 3f5a: fa 94 dec r15 - 3f5c: cf 0c add r12, r15 - 3f5e: d1 1c adc r13, r1 - 3f60: 0e c0 rjmp .+28 ; 0x3f7e -#endif -#endif - } - - /* Get device signature bytes */ - else if(ch == STK_READ_SIGN) { - 3f62: 85 37 cpi r24, 0x75 ; 117 - 3f64: 39 f4 brne .+14 ; 0x3f74 - // READ SIGN - return what Avrdude wants to hear - verifySpace(); - 3f66: 28 d0 rcall .+80 ; 0x3fb8 - putch(SIGNATURE_0); - 3f68: 8e e1 ldi r24, 0x1E ; 30 - 3f6a: 0c d0 rcall .+24 ; 0x3f84 - putch(SIGNATURE_1); - 3f6c: 84 e9 ldi r24, 0x94 ; 148 - 3f6e: 0a d0 rcall .+20 ; 0x3f84 - putch(SIGNATURE_2); - 3f70: 86 e0 ldi r24, 0x06 ; 6 - 3f72: 98 cf rjmp .-208 ; 0x3ea4 - } - else if (ch == 'Q') { - 3f74: 81 35 cpi r24, 0x51 ; 81 - 3f76: 11 f4 brne .+4 ; 0x3f7c - // Adaboot no-wait mod - watchdogConfig(WATCHDOG_16MS); - 3f78: 88 e0 ldi r24, 0x08 ; 8 - 3f7a: 18 d0 rcall .+48 ; 0x3fac - verifySpace(); - } - else { - // This covers the response to commands like STK_ENTER_PROGMODE - verifySpace(); - 3f7c: 1d d0 rcall .+58 ; 0x3fb8 - } - putch(STK_OK); - 3f7e: 80 e1 ldi r24, 0x10 ; 16 - 3f80: 01 d0 rcall .+2 ; 0x3f84 - 3f82: 6a cf rjmp .-300 ; 0x3e58 - -00003f84 : - } -} - -void putch(char ch) { - 3f84: 98 2f mov r25, r24 -#ifndef SOFT_UART - while (!(UCSR0A & _BV(UDRE0))); - 3f86: 80 91 c0 00 lds r24, 0x00C0 - 3f8a: 85 ff sbrs r24, 5 - 3f8c: fc cf rjmp .-8 ; 0x3f86 - UDR0 = ch; - 3f8e: 90 93 c6 00 sts 0x00C6, r25 - [uartBit] "I" (UART_TX_BIT) - : - "r25" - ); -#endif -} - 3f92: 08 95 ret - -00003f94 : - [uartBit] "I" (UART_RX_BIT) - : - "r25" -); -#else - while(!(UCSR0A & _BV(RXC0))) - 3f94: 80 91 c0 00 lds r24, 0x00C0 - 3f98: 87 ff sbrs r24, 7 - 3f9a: fc cf rjmp .-8 ; 0x3f94 - ; - if (!(UCSR0A & _BV(FE0))) { - 3f9c: 80 91 c0 00 lds r24, 0x00C0 - 3fa0: 84 fd sbrc r24, 4 - 3fa2: 01 c0 rjmp .+2 ; 0x3fa6 -} -#endif - -// Watchdog functions. These are only safe with interrupts turned off. -void watchdogReset() { - __asm__ __volatile__ ( - 3fa4: a8 95 wdr - * don't care that an invalid char is returned...) - */ - watchdogReset(); - } - - ch = UDR0; - 3fa6: 80 91 c6 00 lds r24, 0x00C6 - LED_PIN |= _BV(LED); -#endif -#endif - - return ch; -} - 3faa: 08 95 ret - -00003fac : - "wdr\n" - ); -} - -void watchdogConfig(uint8_t x) { - WDTCSR = _BV(WDCE) | _BV(WDE); - 3fac: e0 e6 ldi r30, 0x60 ; 96 - 3fae: f0 e0 ldi r31, 0x00 ; 0 - 3fb0: 98 e1 ldi r25, 0x18 ; 24 - 3fb2: 90 83 st Z, r25 - WDTCSR = x; - 3fb4: 80 83 st Z, r24 -} - 3fb6: 08 95 ret - -00003fb8 : - do getch(); while (--count); - verifySpace(); -} - -void verifySpace() { - if (getch() != CRC_EOP) { - 3fb8: ed df rcall .-38 ; 0x3f94 - 3fba: 80 32 cpi r24, 0x20 ; 32 - 3fbc: 19 f0 breq .+6 ; 0x3fc4 - watchdogConfig(WATCHDOG_16MS); // shorten WD timeout - 3fbe: 88 e0 ldi r24, 0x08 ; 8 - 3fc0: f5 df rcall .-22 ; 0x3fac - 3fc2: ff cf rjmp .-2 ; 0x3fc2 - while (1) // and busy-loop so that WD causes - ; // a reset and app start. - } - putch(STK_INSYNC); - 3fc4: 84 e1 ldi r24, 0x14 ; 20 -} - 3fc6: de cf rjmp .-68 ; 0x3f84 - -00003fc8 : - ::[count] "M" (UART_B_VALUE) - ); -} -#endif - -void getNch(uint8_t count) { - 3fc8: 1f 93 push r17 - 3fca: 18 2f mov r17, r24 - do getch(); while (--count); - 3fcc: e3 df rcall .-58 ; 0x3f94 - 3fce: 11 50 subi r17, 0x01 ; 1 - 3fd0: e9 f7 brne .-6 ; 0x3fcc - verifySpace(); - 3fd2: f2 df rcall .-28 ; 0x3fb8 -} - 3fd4: 1f 91 pop r17 - 3fd6: 08 95 ret - -00003fd8 : - WDTCSR = _BV(WDCE) | _BV(WDE); - WDTCSR = x; -} - -void appStart() { - watchdogConfig(WATCHDOG_OFF); - 3fd8: 80 e0 ldi r24, 0x00 ; 0 - 3fda: e8 df rcall .-48 ; 0x3fac - __asm__ __volatile__ ( - 3fdc: ee 27 eor r30, r30 - 3fde: ff 27 eor r31, r31 - 3fe0: 09 94 ijmp From c56a1293d70d27531b7351edc3aa4c11b4a6996b Mon Sep 17 00:00:00 2001 From: WestfW Date: Tue, 14 Jun 2011 23:57:41 -0700 Subject: [PATCH 31/33] Oops. Add atmega8.lst/hex and atmega168.lst/hex to controlled files. --- .../optiboot/optiboot_atmega168.hex | 35 + .../optiboot/optiboot_atmega168.lst | 598 +++++++++++++++++ .../bootloaders/optiboot/optiboot_atmega8.hex | 33 + .../bootloaders/optiboot/optiboot_atmega8.lst | 604 ++++++++++++++++++ 4 files changed, 1270 insertions(+) create mode 100644 hardware/arduino/bootloaders/optiboot/optiboot_atmega168.hex create mode 100644 hardware/arduino/bootloaders/optiboot/optiboot_atmega168.lst create mode 100644 hardware/arduino/bootloaders/optiboot/optiboot_atmega8.hex create mode 100644 hardware/arduino/bootloaders/optiboot/optiboot_atmega8.lst diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega168.hex b/hardware/arduino/bootloaders/optiboot/optiboot_atmega168.hex new file mode 100644 index 000000000..c2f2b5b53 --- /dev/null +++ b/hardware/arduino/bootloaders/optiboot/optiboot_atmega168.hex @@ -0,0 +1,35 @@ +:103E0000112484B714BE81FFF0D085E08093810037 +:103E100082E08093C00088E18093C10086E08093B7 +:103E2000C20080E18093C4008EE0C9D0259A86E06C +:103E300020E33CEF91E0309385002093840096BB13 +:103E4000B09BFECF1D9AA8958150A9F7CC24DD2404 +:103E500088248394B5E0AB2EA1E19A2EF3E0BF2E27 +:103E6000A2D0813461F49FD0082FAFD0023811F076 +:103E7000013811F484E001C083E08DD089C0823420 +:103E800011F484E103C0853419F485E0A6D080C024 +:103E9000853579F488D0E82EFF2485D0082F10E0EE +:103EA000102F00270E291F29000F111F8ED0680127 +:103EB0006FC0863521F484E090D080E0DECF843678 +:103EC00009F040C070D06FD0082F6DD080E0C816C8 +:103ED00088E3D80618F4F601B7BEE895C0E0D1E053 +:103EE00062D089930C17E1F7F0E0CF16F8E3DF0614 +:103EF00018F0F601B7BEE89568D007B600FCFDCF14 +:103F0000A601A0E0B1E02C9130E011968C911197C0 +:103F100090E0982F8827822B932B1296FA010C01A0 +:103F200087BEE89511244E5F5F4FF1E0A038BF07D0 +:103F300051F7F601A7BEE89507B600FCFDCF97BE86 +:103F4000E89526C08437B1F42ED02DD0F82E2BD092 +:103F50003CD0F601EF2C8F010F5F1F4F84911BD0D7 +:103F6000EA94F801C1F70894C11CD11CFA94CF0C53 +:103F7000D11C0EC0853739F428D08EE10CD084E9ED +:103F80000AD086E07ACF813511F488E018D01DD0B0 +:103F900080E101D065CF982F8091C00085FFFCCFD4 +:103FA0009093C60008958091C00087FFFCCF809158 +:103FB000C00084FD01C0A8958091C6000895E0E688 +:103FC000F0E098E1908380830895EDDF803219F06E +:103FD00088E0F5DFFFCF84E1DECF1F93182FE3DF0A +:103FE0001150E9F7F2DF1F91089580E0E8DFEE2736 +:043FF000FF2709940A +:023FFE000404B9 +:0400000300003E00BB +:00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega168.lst b/hardware/arduino/bootloaders/optiboot/optiboot_atmega168.lst new file mode 100644 index 000000000..06316dbba --- /dev/null +++ b/hardware/arduino/bootloaders/optiboot/optiboot_atmega168.lst @@ -0,0 +1,598 @@ + +optiboot_atmega168.elf: file format elf32-avr + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .text 000001f4 00003e00 00003e00 00000054 2**1 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 .version 00000002 00003ffe 00003ffe 00000248 2**0 + CONTENTS, READONLY + 2 .debug_aranges 00000028 00000000 00000000 0000024a 2**0 + CONTENTS, READONLY, DEBUGGING + 3 .debug_pubnames 0000005f 00000000 00000000 00000272 2**0 + CONTENTS, READONLY, DEBUGGING + 4 .debug_info 000002a8 00000000 00000000 000002d1 2**0 + CONTENTS, READONLY, DEBUGGING + 5 .debug_abbrev 00000178 00000000 00000000 00000579 2**0 + CONTENTS, READONLY, DEBUGGING + 6 .debug_line 00000488 00000000 00000000 000006f1 2**0 + CONTENTS, READONLY, DEBUGGING + 7 .debug_frame 00000080 00000000 00000000 00000b7c 2**2 + CONTENTS, READONLY, DEBUGGING + 8 .debug_str 0000014f 00000000 00000000 00000bfc 2**0 + CONTENTS, READONLY, DEBUGGING + 9 .debug_loc 000002d8 00000000 00000000 00000d4b 2**0 + CONTENTS, READONLY, DEBUGGING + 10 .debug_ranges 00000078 00000000 00000000 00001023 2**0 + CONTENTS, READONLY, DEBUGGING + +Disassembly of section .text: + +00003e00
    : +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) +#endif + +/* main program starts here */ +int main(void) { + 3e00: 11 24 eor r1, r1 +#ifdef __AVR_ATmega8__ + SP=RAMEND; // This is done by hardware reset +#endif + + // Adaboot no-wait mod + ch = MCUSR; + 3e02: 84 b7 in r24, 0x34 ; 52 + MCUSR = 0; + 3e04: 14 be out 0x34, r1 ; 52 + if (!(ch & _BV(EXTRF))) appStart(); + 3e06: 81 ff sbrs r24, 1 + 3e08: f0 d0 rcall .+480 ; 0x3fea + +#if LED_START_FLASHES > 0 + // Set up Timer 1 for timeout counter + TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 + 3e0a: 85 e0 ldi r24, 0x05 ; 5 + 3e0c: 80 93 81 00 sts 0x0081, r24 + UCSRA = _BV(U2X); //Double speed mode USART + UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx + UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 + UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); +#else + UCSR0A = _BV(U2X0); //Double speed mode USART0 + 3e10: 82 e0 ldi r24, 0x02 ; 2 + 3e12: 80 93 c0 00 sts 0x00C0, r24 + UCSR0B = _BV(RXEN0) | _BV(TXEN0); + 3e16: 88 e1 ldi r24, 0x18 ; 24 + 3e18: 80 93 c1 00 sts 0x00C1, r24 + UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); + 3e1c: 86 e0 ldi r24, 0x06 ; 6 + 3e1e: 80 93 c2 00 sts 0x00C2, r24 + UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); + 3e22: 80 e1 ldi r24, 0x10 ; 16 + 3e24: 80 93 c4 00 sts 0x00C4, r24 +#endif +#endif + + // Set up watchdog to trigger after 500ms + watchdogConfig(WATCHDOG_1S); + 3e28: 8e e0 ldi r24, 0x0E ; 14 + 3e2a: c9 d0 rcall .+402 ; 0x3fbe + + /* Set LED pin as output */ + LED_DDR |= _BV(LED); + 3e2c: 25 9a sbi 0x04, 5 ; 4 + 3e2e: 86 e0 ldi r24, 0x06 ; 6 +} + +#if LED_START_FLASHES > 0 +void flash_led(uint8_t count) { + do { + TCNT1 = -(F_CPU/(1024*16)); + 3e30: 20 e3 ldi r18, 0x30 ; 48 + 3e32: 3c ef ldi r19, 0xFC ; 252 + TIFR1 = _BV(TOV1); + 3e34: 91 e0 ldi r25, 0x01 ; 1 +} + +#if LED_START_FLASHES > 0 +void flash_led(uint8_t count) { + do { + TCNT1 = -(F_CPU/(1024*16)); + 3e36: 30 93 85 00 sts 0x0085, r19 + 3e3a: 20 93 84 00 sts 0x0084, r18 + TIFR1 = _BV(TOV1); + 3e3e: 96 bb out 0x16, r25 ; 22 + while(!(TIFR1 & _BV(TOV1))); + 3e40: b0 9b sbis 0x16, 0 ; 22 + 3e42: fe cf rjmp .-4 ; 0x3e40 +#ifdef __AVR_ATmega8__ + LED_PORT ^= _BV(LED); +#else + LED_PIN |= _BV(LED); + 3e44: 1d 9a sbi 0x03, 5 ; 3 +} +#endif + +// Watchdog functions. These are only safe with interrupts turned off. +void watchdogReset() { + __asm__ __volatile__ ( + 3e46: a8 95 wdr + LED_PORT ^= _BV(LED); +#else + LED_PIN |= _BV(LED); +#endif + watchdogReset(); + } while (--count); + 3e48: 81 50 subi r24, 0x01 ; 1 + 3e4a: a9 f7 brne .-22 ; 0x3e36 + 3e4c: cc 24 eor r12, r12 + 3e4e: dd 24 eor r13, r13 + ch = SPM_PAGESIZE / 2; + do { + uint16_t a; + a = *bufPtr++; + a |= (*bufPtr++) << 8; + __boot_page_fill_short((uint16_t)(void*)addrPtr,a); + 3e50: 88 24 eor r8, r8 + 3e52: 83 94 inc r8 + addrPtr += 2; + } while (--ch); + + // Write from programming buffer + __boot_page_write_short((uint16_t)(void*)address); + 3e54: b5 e0 ldi r27, 0x05 ; 5 + 3e56: ab 2e mov r10, r27 + boot_spm_busy_wait(); + +#if defined(RWWSRE) + // Reenable read access to flash + boot_rww_enable(); + 3e58: a1 e1 ldi r26, 0x11 ; 17 + 3e5a: 9a 2e mov r9, r26 + do *bufPtr++ = getch(); + while (--length); + + // If we are in NRWW section, page erase has to be delayed until now. + // Todo: Take RAMPZ into account + if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + 3e5c: f3 e0 ldi r31, 0x03 ; 3 + 3e5e: bf 2e mov r11, r31 +#endif + + /* Forever loop */ + for (;;) { + /* get character from UART */ + ch = getch(); + 3e60: a2 d0 rcall .+324 ; 0x3fa6 + + if(ch == STK_GET_PARAMETER) { + 3e62: 81 34 cpi r24, 0x41 ; 65 + 3e64: 61 f4 brne .+24 ; 0x3e7e + unsigned char which = getch(); + 3e66: 9f d0 rcall .+318 ; 0x3fa6 + 3e68: 08 2f mov r16, r24 + verifySpace(); + 3e6a: af d0 rcall .+350 ; 0x3fca + if (which == 0x82) { + 3e6c: 02 38 cpi r16, 0x82 ; 130 + 3e6e: 11 f0 breq .+4 ; 0x3e74 + /* + * Send optiboot version as "minor SW version" + */ + putch(OPTIBOOT_MINVER); + } else if (which == 0x81) { + 3e70: 01 38 cpi r16, 0x81 ; 129 + 3e72: 11 f4 brne .+4 ; 0x3e78 + putch(OPTIBOOT_MAJVER); + 3e74: 84 e0 ldi r24, 0x04 ; 4 + 3e76: 01 c0 rjmp .+2 ; 0x3e7a + } else { + /* + * GET PARAMETER returns a generic 0x03 reply for + * other parameters - enough to keep Avrdude happy + */ + putch(0x03); + 3e78: 83 e0 ldi r24, 0x03 ; 3 + 3e7a: 8d d0 rcall .+282 ; 0x3f96 + 3e7c: 89 c0 rjmp .+274 ; 0x3f90 + } + } + else if(ch == STK_SET_DEVICE) { + 3e7e: 82 34 cpi r24, 0x42 ; 66 + 3e80: 11 f4 brne .+4 ; 0x3e86 + // SET DEVICE is ignored + getNch(20); + 3e82: 84 e1 ldi r24, 0x14 ; 20 + 3e84: 03 c0 rjmp .+6 ; 0x3e8c + } + else if(ch == STK_SET_DEVICE_EXT) { + 3e86: 85 34 cpi r24, 0x45 ; 69 + 3e88: 19 f4 brne .+6 ; 0x3e90 + // SET DEVICE EXT is ignored + getNch(5); + 3e8a: 85 e0 ldi r24, 0x05 ; 5 + 3e8c: a6 d0 rcall .+332 ; 0x3fda + 3e8e: 80 c0 rjmp .+256 ; 0x3f90 + } + else if(ch == STK_LOAD_ADDRESS) { + 3e90: 85 35 cpi r24, 0x55 ; 85 + 3e92: 79 f4 brne .+30 ; 0x3eb2 + // LOAD ADDRESS + uint16_t newAddress; + newAddress = getch(); + 3e94: 88 d0 rcall .+272 ; 0x3fa6 + newAddress = (newAddress & 0xff) | (getch() << 8); + 3e96: e8 2e mov r14, r24 + 3e98: ff 24 eor r15, r15 + 3e9a: 85 d0 rcall .+266 ; 0x3fa6 + 3e9c: 08 2f mov r16, r24 + 3e9e: 10 e0 ldi r17, 0x00 ; 0 + 3ea0: 10 2f mov r17, r16 + 3ea2: 00 27 eor r16, r16 + 3ea4: 0e 29 or r16, r14 + 3ea6: 1f 29 or r17, r15 +#ifdef RAMPZ + // Transfer top bit to RAMPZ + RAMPZ = (newAddress & 0x8000) ? 1 : 0; +#endif + newAddress += newAddress; // Convert from word address to byte address + 3ea8: 00 0f add r16, r16 + 3eaa: 11 1f adc r17, r17 + address = newAddress; + verifySpace(); + 3eac: 8e d0 rcall .+284 ; 0x3fca + 3eae: 68 01 movw r12, r16 + 3eb0: 6f c0 rjmp .+222 ; 0x3f90 + } + else if(ch == STK_UNIVERSAL) { + 3eb2: 86 35 cpi r24, 0x56 ; 86 + 3eb4: 21 f4 brne .+8 ; 0x3ebe + // UNIVERSAL command is ignored + getNch(4); + 3eb6: 84 e0 ldi r24, 0x04 ; 4 + 3eb8: 90 d0 rcall .+288 ; 0x3fda + putch(0x00); + 3eba: 80 e0 ldi r24, 0x00 ; 0 + 3ebc: de cf rjmp .-68 ; 0x3e7a + } + /* Write memory, length is big endian and is in bytes */ + else if(ch == STK_PROG_PAGE) { + 3ebe: 84 36 cpi r24, 0x64 ; 100 + 3ec0: 09 f0 breq .+2 ; 0x3ec4 + 3ec2: 40 c0 rjmp .+128 ; 0x3f44 + // PROGRAM PAGE - we support flash programming only, not EEPROM + uint8_t *bufPtr; + uint16_t addrPtr; + + getch(); /* getlen() */ + 3ec4: 70 d0 rcall .+224 ; 0x3fa6 + length = getch(); + 3ec6: 6f d0 rcall .+222 ; 0x3fa6 + 3ec8: 08 2f mov r16, r24 + getch(); + 3eca: 6d d0 rcall .+218 ; 0x3fa6 + + // If we are in RWW section, immediately start page erase + if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + 3ecc: 80 e0 ldi r24, 0x00 ; 0 + 3ece: c8 16 cp r12, r24 + 3ed0: 88 e3 ldi r24, 0x38 ; 56 + 3ed2: d8 06 cpc r13, r24 + 3ed4: 18 f4 brcc .+6 ; 0x3edc + 3ed6: f6 01 movw r30, r12 + 3ed8: b7 be out 0x37, r11 ; 55 + 3eda: e8 95 spm + 3edc: c0 e0 ldi r28, 0x00 ; 0 + 3ede: d1 e0 ldi r29, 0x01 ; 1 + + // While that is going on, read in page contents + bufPtr = buff; + do *bufPtr++ = getch(); + 3ee0: 62 d0 rcall .+196 ; 0x3fa6 + 3ee2: 89 93 st Y+, r24 + while (--length); + 3ee4: 0c 17 cp r16, r28 + 3ee6: e1 f7 brne .-8 ; 0x3ee0 + + // If we are in NRWW section, page erase has to be delayed until now. + // Todo: Take RAMPZ into account + if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + 3ee8: f0 e0 ldi r31, 0x00 ; 0 + 3eea: cf 16 cp r12, r31 + 3eec: f8 e3 ldi r31, 0x38 ; 56 + 3eee: df 06 cpc r13, r31 + 3ef0: 18 f0 brcs .+6 ; 0x3ef8 + 3ef2: f6 01 movw r30, r12 + 3ef4: b7 be out 0x37, r11 ; 55 + 3ef6: e8 95 spm + + // Read command terminator, start reply + verifySpace(); + 3ef8: 68 d0 rcall .+208 ; 0x3fca + + // If only a partial page is to be programmed, the erase might not be complete. + // So check that here + boot_spm_busy_wait(); + 3efa: 07 b6 in r0, 0x37 ; 55 + 3efc: 00 fc sbrc r0, 0 + 3efe: fd cf rjmp .-6 ; 0x3efa + 3f00: a6 01 movw r20, r12 + 3f02: a0 e0 ldi r26, 0x00 ; 0 + 3f04: b1 e0 ldi r27, 0x01 ; 1 + bufPtr = buff; + addrPtr = (uint16_t)(void*)address; + ch = SPM_PAGESIZE / 2; + do { + uint16_t a; + a = *bufPtr++; + 3f06: 2c 91 ld r18, X + 3f08: 30 e0 ldi r19, 0x00 ; 0 + a |= (*bufPtr++) << 8; + 3f0a: 11 96 adiw r26, 0x01 ; 1 + 3f0c: 8c 91 ld r24, X + 3f0e: 11 97 sbiw r26, 0x01 ; 1 + 3f10: 90 e0 ldi r25, 0x00 ; 0 + 3f12: 98 2f mov r25, r24 + 3f14: 88 27 eor r24, r24 + 3f16: 82 2b or r24, r18 + 3f18: 93 2b or r25, r19 +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) +#endif + +/* main program starts here */ +int main(void) { + 3f1a: 12 96 adiw r26, 0x02 ; 2 + ch = SPM_PAGESIZE / 2; + do { + uint16_t a; + a = *bufPtr++; + a |= (*bufPtr++) << 8; + __boot_page_fill_short((uint16_t)(void*)addrPtr,a); + 3f1c: fa 01 movw r30, r20 + 3f1e: 0c 01 movw r0, r24 + 3f20: 87 be out 0x37, r8 ; 55 + 3f22: e8 95 spm + 3f24: 11 24 eor r1, r1 + addrPtr += 2; + 3f26: 4e 5f subi r20, 0xFE ; 254 + 3f28: 5f 4f sbci r21, 0xFF ; 255 + } while (--ch); + 3f2a: f1 e0 ldi r31, 0x01 ; 1 + 3f2c: a0 38 cpi r26, 0x80 ; 128 + 3f2e: bf 07 cpc r27, r31 + 3f30: 51 f7 brne .-44 ; 0x3f06 + + // Write from programming buffer + __boot_page_write_short((uint16_t)(void*)address); + 3f32: f6 01 movw r30, r12 + 3f34: a7 be out 0x37, r10 ; 55 + 3f36: e8 95 spm + boot_spm_busy_wait(); + 3f38: 07 b6 in r0, 0x37 ; 55 + 3f3a: 00 fc sbrc r0, 0 + 3f3c: fd cf rjmp .-6 ; 0x3f38 + +#if defined(RWWSRE) + // Reenable read access to flash + boot_rww_enable(); + 3f3e: 97 be out 0x37, r9 ; 55 + 3f40: e8 95 spm + 3f42: 26 c0 rjmp .+76 ; 0x3f90 +#endif + + } + /* Read memory block mode, length is big endian. */ + else if(ch == STK_READ_PAGE) { + 3f44: 84 37 cpi r24, 0x74 ; 116 + 3f46: b1 f4 brne .+44 ; 0x3f74 + // READ PAGE - we only read flash + getch(); /* getlen() */ + 3f48: 2e d0 rcall .+92 ; 0x3fa6 + length = getch(); + 3f4a: 2d d0 rcall .+90 ; 0x3fa6 + 3f4c: f8 2e mov r15, r24 + getch(); + 3f4e: 2b d0 rcall .+86 ; 0x3fa6 + + verifySpace(); + 3f50: 3c d0 rcall .+120 ; 0x3fca + 3f52: f6 01 movw r30, r12 + 3f54: ef 2c mov r14, r15 + putch(result); + address++; + } + while (--length); +#else + do putch(pgm_read_byte_near(address++)); + 3f56: 8f 01 movw r16, r30 + 3f58: 0f 5f subi r16, 0xFF ; 255 + 3f5a: 1f 4f sbci r17, 0xFF ; 255 + 3f5c: 84 91 lpm r24, Z+ + 3f5e: 1b d0 rcall .+54 ; 0x3f96 + while (--length); + 3f60: ea 94 dec r14 + 3f62: f8 01 movw r30, r16 + 3f64: c1 f7 brne .-16 ; 0x3f56 +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) +#endif + +/* main program starts here */ +int main(void) { + 3f66: 08 94 sec + 3f68: c1 1c adc r12, r1 + 3f6a: d1 1c adc r13, r1 + 3f6c: fa 94 dec r15 + 3f6e: cf 0c add r12, r15 + 3f70: d1 1c adc r13, r1 + 3f72: 0e c0 rjmp .+28 ; 0x3f90 +#endif +#endif + } + + /* Get device signature bytes */ + else if(ch == STK_READ_SIGN) { + 3f74: 85 37 cpi r24, 0x75 ; 117 + 3f76: 39 f4 brne .+14 ; 0x3f86 + // READ SIGN - return what Avrdude wants to hear + verifySpace(); + 3f78: 28 d0 rcall .+80 ; 0x3fca + putch(SIGNATURE_0); + 3f7a: 8e e1 ldi r24, 0x1E ; 30 + 3f7c: 0c d0 rcall .+24 ; 0x3f96 + putch(SIGNATURE_1); + 3f7e: 84 e9 ldi r24, 0x94 ; 148 + 3f80: 0a d0 rcall .+20 ; 0x3f96 + putch(SIGNATURE_2); + 3f82: 86 e0 ldi r24, 0x06 ; 6 + 3f84: 7a cf rjmp .-268 ; 0x3e7a + } + else if (ch == 'Q') { + 3f86: 81 35 cpi r24, 0x51 ; 81 + 3f88: 11 f4 brne .+4 ; 0x3f8e + // Adaboot no-wait mod + watchdogConfig(WATCHDOG_16MS); + 3f8a: 88 e0 ldi r24, 0x08 ; 8 + 3f8c: 18 d0 rcall .+48 ; 0x3fbe + verifySpace(); + } + else { + // This covers the response to commands like STK_ENTER_PROGMODE + verifySpace(); + 3f8e: 1d d0 rcall .+58 ; 0x3fca + } + putch(STK_OK); + 3f90: 80 e1 ldi r24, 0x10 ; 16 + 3f92: 01 d0 rcall .+2 ; 0x3f96 + 3f94: 65 cf rjmp .-310 ; 0x3e60 + +00003f96 : + } +} + +void putch(char ch) { + 3f96: 98 2f mov r25, r24 +#ifndef SOFT_UART + while (!(UCSR0A & _BV(UDRE0))); + 3f98: 80 91 c0 00 lds r24, 0x00C0 + 3f9c: 85 ff sbrs r24, 5 + 3f9e: fc cf rjmp .-8 ; 0x3f98 + UDR0 = ch; + 3fa0: 90 93 c6 00 sts 0x00C6, r25 + [uartBit] "I" (UART_TX_BIT) + : + "r25" + ); +#endif +} + 3fa4: 08 95 ret + +00003fa6 : + [uartBit] "I" (UART_RX_BIT) + : + "r25" +); +#else + while(!(UCSR0A & _BV(RXC0))) + 3fa6: 80 91 c0 00 lds r24, 0x00C0 + 3faa: 87 ff sbrs r24, 7 + 3fac: fc cf rjmp .-8 ; 0x3fa6 + ; + if (!(UCSR0A & _BV(FE0))) { + 3fae: 80 91 c0 00 lds r24, 0x00C0 + 3fb2: 84 fd sbrc r24, 4 + 3fb4: 01 c0 rjmp .+2 ; 0x3fb8 +} +#endif + +// Watchdog functions. These are only safe with interrupts turned off. +void watchdogReset() { + __asm__ __volatile__ ( + 3fb6: a8 95 wdr + * don't care that an invalid char is returned...) + */ + watchdogReset(); + } + + ch = UDR0; + 3fb8: 80 91 c6 00 lds r24, 0x00C6 + LED_PIN |= _BV(LED); +#endif +#endif + + return ch; +} + 3fbc: 08 95 ret + +00003fbe : + "wdr\n" + ); +} + +void watchdogConfig(uint8_t x) { + WDTCSR = _BV(WDCE) | _BV(WDE); + 3fbe: e0 e6 ldi r30, 0x60 ; 96 + 3fc0: f0 e0 ldi r31, 0x00 ; 0 + 3fc2: 98 e1 ldi r25, 0x18 ; 24 + 3fc4: 90 83 st Z, r25 + WDTCSR = x; + 3fc6: 80 83 st Z, r24 +} + 3fc8: 08 95 ret + +00003fca : + do getch(); while (--count); + verifySpace(); +} + +void verifySpace() { + if (getch() != CRC_EOP) { + 3fca: ed df rcall .-38 ; 0x3fa6 + 3fcc: 80 32 cpi r24, 0x20 ; 32 + 3fce: 19 f0 breq .+6 ; 0x3fd6 + watchdogConfig(WATCHDOG_16MS); // shorten WD timeout + 3fd0: 88 e0 ldi r24, 0x08 ; 8 + 3fd2: f5 df rcall .-22 ; 0x3fbe + 3fd4: ff cf rjmp .-2 ; 0x3fd4 + while (1) // and busy-loop so that WD causes + ; // a reset and app start. + } + putch(STK_INSYNC); + 3fd6: 84 e1 ldi r24, 0x14 ; 20 +} + 3fd8: de cf rjmp .-68 ; 0x3f96 + +00003fda : + ::[count] "M" (UART_B_VALUE) + ); +} +#endif + +void getNch(uint8_t count) { + 3fda: 1f 93 push r17 + 3fdc: 18 2f mov r17, r24 + do getch(); while (--count); + 3fde: e3 df rcall .-58 ; 0x3fa6 + 3fe0: 11 50 subi r17, 0x01 ; 1 + 3fe2: e9 f7 brne .-6 ; 0x3fde + verifySpace(); + 3fe4: f2 df rcall .-28 ; 0x3fca +} + 3fe6: 1f 91 pop r17 + 3fe8: 08 95 ret + +00003fea : + WDTCSR = _BV(WDCE) | _BV(WDE); + WDTCSR = x; +} + +void appStart() { + watchdogConfig(WATCHDOG_OFF); + 3fea: 80 e0 ldi r24, 0x00 ; 0 + 3fec: e8 df rcall .-48 ; 0x3fbe + __asm__ __volatile__ ( + 3fee: ee 27 eor r30, r30 + 3ff0: ff 27 eor r31, r31 + 3ff2: 09 94 ijmp diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega8.hex b/hardware/arduino/bootloaders/optiboot/optiboot_atmega8.hex new file mode 100644 index 000000000..b04f27685 --- /dev/null +++ b/hardware/arduino/bootloaders/optiboot/optiboot_atmega8.hex @@ -0,0 +1,33 @@ +:101E000011248FE594E09EBF8DBF84B714BE81FF7F +:101E1000E2D085E08EBD82E08BB988E18AB986E8A0 +:101E200080BD80E189B98EE0C2D0BD9A96E020E302 +:101E30003CEF54E040E23DBD2CBD58BF08B602FE69 +:101E4000FDCF88B3842788BBA8959150A1F7CC24F7 +:101E5000DD2488248394B5E0AB2EA1E19A2EF3E033 +:101E6000BF2E9ED0813461F49BD0082FA4D00238BD +:101E700011F0013811F484E001C083E08DD089C0F5 +:101E8000823411F484E103C0853419F485E09BD0D9 +:101E900080C0853579F484D0E82EFF2481D0082FC6 +:101EA00010E0102F00270E291F29000F111F83D0CB +:101EB00068016FC0863521F484E085D080E0DECFF4 +:101EC000843609F040C06CD06BD0082F69D080E018 +:101ED000C81688E1D80618F4F601B7BEE895C0E048 +:101EE000D1E05ED089930C17E1F7F0E0CF16F8E16E +:101EF000DF0618F0F601B7BEE8955DD007B600FC26 +:101F0000FDCFA601A0E0B1E02C9130E011968C91BC +:101F1000119790E0982F8827822B932B1296FA0125 +:101F20000C0187BEE89511244E5F5F4FF1E0A034AD +:101F3000BF0751F7F601A7BEE89507B600FCFDCF35 +:101F400097BEE89526C08437B1F42AD029D0F82E60 +:101F500027D031D0F601EF2C8F010F5F1F4F8491F6 +:101F60001BD0EA94F801C1F70894C11CD11CFA9463 +:101F7000CF0CD11C0EC0853739F41DD08EE10CD0AA +:101F800083E90AD087E07ACF813511F488E00FD059 +:101F900012D080E101D065CF5D9BFECF8CB9089552 +:101FA0005F9BFECF5C9901C0A8958CB1089598E124 +:101FB00091BD81BD0895F4DF803219F088E0F7DF2C +:101FC000FFCF84E1E9CF1F93182FEADF1150E9F723 +:101FD000F2DF1F91089580E0EADFEE27FF270994E2 +:021FFE000404D9 +:0400000300001E00DB +:00000001FF diff --git a/hardware/arduino/bootloaders/optiboot/optiboot_atmega8.lst b/hardware/arduino/bootloaders/optiboot/optiboot_atmega8.lst new file mode 100644 index 000000000..d92189582 --- /dev/null +++ b/hardware/arduino/bootloaders/optiboot/optiboot_atmega8.lst @@ -0,0 +1,604 @@ + +optiboot_atmega8.elf: file format elf32-avr + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .text 000001e0 00001e00 00001e00 00000054 2**1 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 .version 00000002 00001ffe 00001ffe 00000234 2**0 + CONTENTS, READONLY + 2 .debug_aranges 00000028 00000000 00000000 00000236 2**0 + CONTENTS, READONLY, DEBUGGING + 3 .debug_pubnames 0000005f 00000000 00000000 0000025e 2**0 + CONTENTS, READONLY, DEBUGGING + 4 .debug_info 000002a6 00000000 00000000 000002bd 2**0 + CONTENTS, READONLY, DEBUGGING + 5 .debug_abbrev 00000169 00000000 00000000 00000563 2**0 + CONTENTS, READONLY, DEBUGGING + 6 .debug_line 00000498 00000000 00000000 000006cc 2**0 + CONTENTS, READONLY, DEBUGGING + 7 .debug_frame 00000080 00000000 00000000 00000b64 2**2 + CONTENTS, READONLY, DEBUGGING + 8 .debug_str 0000014f 00000000 00000000 00000be4 2**0 + CONTENTS, READONLY, DEBUGGING + 9 .debug_loc 000002ba 00000000 00000000 00000d33 2**0 + CONTENTS, READONLY, DEBUGGING + 10 .debug_ranges 00000078 00000000 00000000 00000fed 2**0 + CONTENTS, READONLY, DEBUGGING + +Disassembly of section .text: + +00001e00
    : +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) +#endif + +/* main program starts here */ +int main(void) { + 1e00: 11 24 eor r1, r1 + // + // If not, uncomment the following instructions: + // cli(); + asm volatile ("clr __zero_reg__"); +#ifdef __AVR_ATmega8__ + SP=RAMEND; // This is done by hardware reset + 1e02: 8f e5 ldi r24, 0x5F ; 95 + 1e04: 94 e0 ldi r25, 0x04 ; 4 + 1e06: 9e bf out 0x3e, r25 ; 62 + 1e08: 8d bf out 0x3d, r24 ; 61 +#endif + + // Adaboot no-wait mod + ch = MCUSR; + 1e0a: 84 b7 in r24, 0x34 ; 52 + MCUSR = 0; + 1e0c: 14 be out 0x34, r1 ; 52 + if (!(ch & _BV(EXTRF))) appStart(); + 1e0e: 81 ff sbrs r24, 1 + 1e10: e2 d0 rcall .+452 ; 0x1fd6 + +#if LED_START_FLASHES > 0 + // Set up Timer 1 for timeout counter + TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 + 1e12: 85 e0 ldi r24, 0x05 ; 5 + 1e14: 8e bd out 0x2e, r24 ; 46 +#endif +#ifndef SOFT_UART +#ifdef __AVR_ATmega8__ + UCSRA = _BV(U2X); //Double speed mode USART + 1e16: 82 e0 ldi r24, 0x02 ; 2 + 1e18: 8b b9 out 0x0b, r24 ; 11 + UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx + 1e1a: 88 e1 ldi r24, 0x18 ; 24 + 1e1c: 8a b9 out 0x0a, r24 ; 10 + UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 + 1e1e: 86 e8 ldi r24, 0x86 ; 134 + 1e20: 80 bd out 0x20, r24 ; 32 + UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); + 1e22: 80 e1 ldi r24, 0x10 ; 16 + 1e24: 89 b9 out 0x09, r24 ; 9 + UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); +#endif +#endif + + // Set up watchdog to trigger after 500ms + watchdogConfig(WATCHDOG_1S); + 1e26: 8e e0 ldi r24, 0x0E ; 14 + 1e28: c2 d0 rcall .+388 ; 0x1fae + + /* Set LED pin as output */ + LED_DDR |= _BV(LED); + 1e2a: bd 9a sbi 0x17, 5 ; 23 + 1e2c: 96 e0 ldi r25, 0x06 ; 6 +} + +#if LED_START_FLASHES > 0 +void flash_led(uint8_t count) { + do { + TCNT1 = -(F_CPU/(1024*16)); + 1e2e: 20 e3 ldi r18, 0x30 ; 48 + 1e30: 3c ef ldi r19, 0xFC ; 252 + TIFR1 = _BV(TOV1); + 1e32: 54 e0 ldi r21, 0x04 ; 4 + while(!(TIFR1 & _BV(TOV1))); +#ifdef __AVR_ATmega8__ + LED_PORT ^= _BV(LED); + 1e34: 40 e2 ldi r20, 0x20 ; 32 +} + +#if LED_START_FLASHES > 0 +void flash_led(uint8_t count) { + do { + TCNT1 = -(F_CPU/(1024*16)); + 1e36: 3d bd out 0x2d, r19 ; 45 + 1e38: 2c bd out 0x2c, r18 ; 44 + TIFR1 = _BV(TOV1); + 1e3a: 58 bf out 0x38, r21 ; 56 + while(!(TIFR1 & _BV(TOV1))); + 1e3c: 08 b6 in r0, 0x38 ; 56 + 1e3e: 02 fe sbrs r0, 2 + 1e40: fd cf rjmp .-6 ; 0x1e3c +#ifdef __AVR_ATmega8__ + LED_PORT ^= _BV(LED); + 1e42: 88 b3 in r24, 0x18 ; 24 + 1e44: 84 27 eor r24, r20 + 1e46: 88 bb out 0x18, r24 ; 24 +} +#endif + +// Watchdog functions. These are only safe with interrupts turned off. +void watchdogReset() { + __asm__ __volatile__ ( + 1e48: a8 95 wdr + LED_PORT ^= _BV(LED); +#else + LED_PIN |= _BV(LED); +#endif + watchdogReset(); + } while (--count); + 1e4a: 91 50 subi r25, 0x01 ; 1 + 1e4c: a1 f7 brne .-24 ; 0x1e36 + 1e4e: cc 24 eor r12, r12 + 1e50: dd 24 eor r13, r13 + ch = SPM_PAGESIZE / 2; + do { + uint16_t a; + a = *bufPtr++; + a |= (*bufPtr++) << 8; + __boot_page_fill_short((uint16_t)(void*)addrPtr,a); + 1e52: 88 24 eor r8, r8 + 1e54: 83 94 inc r8 + addrPtr += 2; + } while (--ch); + + // Write from programming buffer + __boot_page_write_short((uint16_t)(void*)address); + 1e56: b5 e0 ldi r27, 0x05 ; 5 + 1e58: ab 2e mov r10, r27 + boot_spm_busy_wait(); + +#if defined(RWWSRE) + // Reenable read access to flash + boot_rww_enable(); + 1e5a: a1 e1 ldi r26, 0x11 ; 17 + 1e5c: 9a 2e mov r9, r26 + do *bufPtr++ = getch(); + while (--length); + + // If we are in NRWW section, page erase has to be delayed until now. + // Todo: Take RAMPZ into account + if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + 1e5e: f3 e0 ldi r31, 0x03 ; 3 + 1e60: bf 2e mov r11, r31 +#endif + + /* Forever loop */ + for (;;) { + /* get character from UART */ + ch = getch(); + 1e62: 9e d0 rcall .+316 ; 0x1fa0 + + if(ch == STK_GET_PARAMETER) { + 1e64: 81 34 cpi r24, 0x41 ; 65 + 1e66: 61 f4 brne .+24 ; 0x1e80 + unsigned char which = getch(); + 1e68: 9b d0 rcall .+310 ; 0x1fa0 + 1e6a: 08 2f mov r16, r24 + verifySpace(); + 1e6c: a4 d0 rcall .+328 ; 0x1fb6 + if (which == 0x82) { + 1e6e: 02 38 cpi r16, 0x82 ; 130 + 1e70: 11 f0 breq .+4 ; 0x1e76 + /* + * Send optiboot version as "minor SW version" + */ + putch(OPTIBOOT_MINVER); + } else if (which == 0x81) { + 1e72: 01 38 cpi r16, 0x81 ; 129 + 1e74: 11 f4 brne .+4 ; 0x1e7a + putch(OPTIBOOT_MAJVER); + 1e76: 84 e0 ldi r24, 0x04 ; 4 + 1e78: 01 c0 rjmp .+2 ; 0x1e7c + } else { + /* + * GET PARAMETER returns a generic 0x03 reply for + * other parameters - enough to keep Avrdude happy + */ + putch(0x03); + 1e7a: 83 e0 ldi r24, 0x03 ; 3 + 1e7c: 8d d0 rcall .+282 ; 0x1f98 + 1e7e: 89 c0 rjmp .+274 ; 0x1f92 + } + } + else if(ch == STK_SET_DEVICE) { + 1e80: 82 34 cpi r24, 0x42 ; 66 + 1e82: 11 f4 brne .+4 ; 0x1e88 + // SET DEVICE is ignored + getNch(20); + 1e84: 84 e1 ldi r24, 0x14 ; 20 + 1e86: 03 c0 rjmp .+6 ; 0x1e8e + } + else if(ch == STK_SET_DEVICE_EXT) { + 1e88: 85 34 cpi r24, 0x45 ; 69 + 1e8a: 19 f4 brne .+6 ; 0x1e92 + // SET DEVICE EXT is ignored + getNch(5); + 1e8c: 85 e0 ldi r24, 0x05 ; 5 + 1e8e: 9b d0 rcall .+310 ; 0x1fc6 + 1e90: 80 c0 rjmp .+256 ; 0x1f92 + } + else if(ch == STK_LOAD_ADDRESS) { + 1e92: 85 35 cpi r24, 0x55 ; 85 + 1e94: 79 f4 brne .+30 ; 0x1eb4 + // LOAD ADDRESS + uint16_t newAddress; + newAddress = getch(); + 1e96: 84 d0 rcall .+264 ; 0x1fa0 + newAddress = (newAddress & 0xff) | (getch() << 8); + 1e98: e8 2e mov r14, r24 + 1e9a: ff 24 eor r15, r15 + 1e9c: 81 d0 rcall .+258 ; 0x1fa0 + 1e9e: 08 2f mov r16, r24 + 1ea0: 10 e0 ldi r17, 0x00 ; 0 + 1ea2: 10 2f mov r17, r16 + 1ea4: 00 27 eor r16, r16 + 1ea6: 0e 29 or r16, r14 + 1ea8: 1f 29 or r17, r15 +#ifdef RAMPZ + // Transfer top bit to RAMPZ + RAMPZ = (newAddress & 0x8000) ? 1 : 0; +#endif + newAddress += newAddress; // Convert from word address to byte address + 1eaa: 00 0f add r16, r16 + 1eac: 11 1f adc r17, r17 + address = newAddress; + verifySpace(); + 1eae: 83 d0 rcall .+262 ; 0x1fb6 + 1eb0: 68 01 movw r12, r16 + 1eb2: 6f c0 rjmp .+222 ; 0x1f92 + } + else if(ch == STK_UNIVERSAL) { + 1eb4: 86 35 cpi r24, 0x56 ; 86 + 1eb6: 21 f4 brne .+8 ; 0x1ec0 + // UNIVERSAL command is ignored + getNch(4); + 1eb8: 84 e0 ldi r24, 0x04 ; 4 + 1eba: 85 d0 rcall .+266 ; 0x1fc6 + putch(0x00); + 1ebc: 80 e0 ldi r24, 0x00 ; 0 + 1ebe: de cf rjmp .-68 ; 0x1e7c + } + /* Write memory, length is big endian and is in bytes */ + else if(ch == STK_PROG_PAGE) { + 1ec0: 84 36 cpi r24, 0x64 ; 100 + 1ec2: 09 f0 breq .+2 ; 0x1ec6 + 1ec4: 40 c0 rjmp .+128 ; 0x1f46 + // PROGRAM PAGE - we support flash programming only, not EEPROM + uint8_t *bufPtr; + uint16_t addrPtr; + + getch(); /* getlen() */ + 1ec6: 6c d0 rcall .+216 ; 0x1fa0 + length = getch(); + 1ec8: 6b d0 rcall .+214 ; 0x1fa0 + 1eca: 08 2f mov r16, r24 + getch(); + 1ecc: 69 d0 rcall .+210 ; 0x1fa0 + + // If we are in RWW section, immediately start page erase + if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + 1ece: 80 e0 ldi r24, 0x00 ; 0 + 1ed0: c8 16 cp r12, r24 + 1ed2: 88 e1 ldi r24, 0x18 ; 24 + 1ed4: d8 06 cpc r13, r24 + 1ed6: 18 f4 brcc .+6 ; 0x1ede + 1ed8: f6 01 movw r30, r12 + 1eda: b7 be out 0x37, r11 ; 55 + 1edc: e8 95 spm + 1ede: c0 e0 ldi r28, 0x00 ; 0 + 1ee0: d1 e0 ldi r29, 0x01 ; 1 + + // While that is going on, read in page contents + bufPtr = buff; + do *bufPtr++ = getch(); + 1ee2: 5e d0 rcall .+188 ; 0x1fa0 + 1ee4: 89 93 st Y+, r24 + while (--length); + 1ee6: 0c 17 cp r16, r28 + 1ee8: e1 f7 brne .-8 ; 0x1ee2 + + // If we are in NRWW section, page erase has to be delayed until now. + // Todo: Take RAMPZ into account + if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + 1eea: f0 e0 ldi r31, 0x00 ; 0 + 1eec: cf 16 cp r12, r31 + 1eee: f8 e1 ldi r31, 0x18 ; 24 + 1ef0: df 06 cpc r13, r31 + 1ef2: 18 f0 brcs .+6 ; 0x1efa + 1ef4: f6 01 movw r30, r12 + 1ef6: b7 be out 0x37, r11 ; 55 + 1ef8: e8 95 spm + + // Read command terminator, start reply + verifySpace(); + 1efa: 5d d0 rcall .+186 ; 0x1fb6 + + // If only a partial page is to be programmed, the erase might not be complete. + // So check that here + boot_spm_busy_wait(); + 1efc: 07 b6 in r0, 0x37 ; 55 + 1efe: 00 fc sbrc r0, 0 + 1f00: fd cf rjmp .-6 ; 0x1efc + 1f02: a6 01 movw r20, r12 + 1f04: a0 e0 ldi r26, 0x00 ; 0 + 1f06: b1 e0 ldi r27, 0x01 ; 1 + bufPtr = buff; + addrPtr = (uint16_t)(void*)address; + ch = SPM_PAGESIZE / 2; + do { + uint16_t a; + a = *bufPtr++; + 1f08: 2c 91 ld r18, X + 1f0a: 30 e0 ldi r19, 0x00 ; 0 + a |= (*bufPtr++) << 8; + 1f0c: 11 96 adiw r26, 0x01 ; 1 + 1f0e: 8c 91 ld r24, X + 1f10: 11 97 sbiw r26, 0x01 ; 1 + 1f12: 90 e0 ldi r25, 0x00 ; 0 + 1f14: 98 2f mov r25, r24 + 1f16: 88 27 eor r24, r24 + 1f18: 82 2b or r24, r18 + 1f1a: 93 2b or r25, r19 +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) +#endif + +/* main program starts here */ +int main(void) { + 1f1c: 12 96 adiw r26, 0x02 ; 2 + ch = SPM_PAGESIZE / 2; + do { + uint16_t a; + a = *bufPtr++; + a |= (*bufPtr++) << 8; + __boot_page_fill_short((uint16_t)(void*)addrPtr,a); + 1f1e: fa 01 movw r30, r20 + 1f20: 0c 01 movw r0, r24 + 1f22: 87 be out 0x37, r8 ; 55 + 1f24: e8 95 spm + 1f26: 11 24 eor r1, r1 + addrPtr += 2; + 1f28: 4e 5f subi r20, 0xFE ; 254 + 1f2a: 5f 4f sbci r21, 0xFF ; 255 + } while (--ch); + 1f2c: f1 e0 ldi r31, 0x01 ; 1 + 1f2e: a0 34 cpi r26, 0x40 ; 64 + 1f30: bf 07 cpc r27, r31 + 1f32: 51 f7 brne .-44 ; 0x1f08 + + // Write from programming buffer + __boot_page_write_short((uint16_t)(void*)address); + 1f34: f6 01 movw r30, r12 + 1f36: a7 be out 0x37, r10 ; 55 + 1f38: e8 95 spm + boot_spm_busy_wait(); + 1f3a: 07 b6 in r0, 0x37 ; 55 + 1f3c: 00 fc sbrc r0, 0 + 1f3e: fd cf rjmp .-6 ; 0x1f3a + +#if defined(RWWSRE) + // Reenable read access to flash + boot_rww_enable(); + 1f40: 97 be out 0x37, r9 ; 55 + 1f42: e8 95 spm + 1f44: 26 c0 rjmp .+76 ; 0x1f92 +#endif + + } + /* Read memory block mode, length is big endian. */ + else if(ch == STK_READ_PAGE) { + 1f46: 84 37 cpi r24, 0x74 ; 116 + 1f48: b1 f4 brne .+44 ; 0x1f76 + // READ PAGE - we only read flash + getch(); /* getlen() */ + 1f4a: 2a d0 rcall .+84 ; 0x1fa0 + length = getch(); + 1f4c: 29 d0 rcall .+82 ; 0x1fa0 + 1f4e: f8 2e mov r15, r24 + getch(); + 1f50: 27 d0 rcall .+78 ; 0x1fa0 + + verifySpace(); + 1f52: 31 d0 rcall .+98 ; 0x1fb6 + 1f54: f6 01 movw r30, r12 + 1f56: ef 2c mov r14, r15 + putch(result); + address++; + } + while (--length); +#else + do putch(pgm_read_byte_near(address++)); + 1f58: 8f 01 movw r16, r30 + 1f5a: 0f 5f subi r16, 0xFF ; 255 + 1f5c: 1f 4f sbci r17, 0xFF ; 255 + 1f5e: 84 91 lpm r24, Z+ + 1f60: 1b d0 rcall .+54 ; 0x1f98 + while (--length); + 1f62: ea 94 dec r14 + 1f64: f8 01 movw r30, r16 + 1f66: c1 f7 brne .-16 ; 0x1f58 +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) +#endif + +/* main program starts here */ +int main(void) { + 1f68: 08 94 sec + 1f6a: c1 1c adc r12, r1 + 1f6c: d1 1c adc r13, r1 + 1f6e: fa 94 dec r15 + 1f70: cf 0c add r12, r15 + 1f72: d1 1c adc r13, r1 + 1f74: 0e c0 rjmp .+28 ; 0x1f92 +#endif +#endif + } + + /* Get device signature bytes */ + else if(ch == STK_READ_SIGN) { + 1f76: 85 37 cpi r24, 0x75 ; 117 + 1f78: 39 f4 brne .+14 ; 0x1f88 + // READ SIGN - return what Avrdude wants to hear + verifySpace(); + 1f7a: 1d d0 rcall .+58 ; 0x1fb6 + putch(SIGNATURE_0); + 1f7c: 8e e1 ldi r24, 0x1E ; 30 + 1f7e: 0c d0 rcall .+24 ; 0x1f98 + putch(SIGNATURE_1); + 1f80: 83 e9 ldi r24, 0x93 ; 147 + 1f82: 0a d0 rcall .+20 ; 0x1f98 + putch(SIGNATURE_2); + 1f84: 87 e0 ldi r24, 0x07 ; 7 + 1f86: 7a cf rjmp .-268 ; 0x1e7c + } + else if (ch == 'Q') { + 1f88: 81 35 cpi r24, 0x51 ; 81 + 1f8a: 11 f4 brne .+4 ; 0x1f90 + // Adaboot no-wait mod + watchdogConfig(WATCHDOG_16MS); + 1f8c: 88 e0 ldi r24, 0x08 ; 8 + 1f8e: 0f d0 rcall .+30 ; 0x1fae + verifySpace(); + } + else { + // This covers the response to commands like STK_ENTER_PROGMODE + verifySpace(); + 1f90: 12 d0 rcall .+36 ; 0x1fb6 + } + putch(STK_OK); + 1f92: 80 e1 ldi r24, 0x10 ; 16 + 1f94: 01 d0 rcall .+2 ; 0x1f98 + 1f96: 65 cf rjmp .-310 ; 0x1e62 + +00001f98 : + } +} + +void putch(char ch) { +#ifndef SOFT_UART + while (!(UCSR0A & _BV(UDRE0))); + 1f98: 5d 9b sbis 0x0b, 5 ; 11 + 1f9a: fe cf rjmp .-4 ; 0x1f98 + UDR0 = ch; + 1f9c: 8c b9 out 0x0c, r24 ; 12 + [uartBit] "I" (UART_TX_BIT) + : + "r25" + ); +#endif +} + 1f9e: 08 95 ret + +00001fa0 : + [uartBit] "I" (UART_RX_BIT) + : + "r25" +); +#else + while(!(UCSR0A & _BV(RXC0))) + 1fa0: 5f 9b sbis 0x0b, 7 ; 11 + 1fa2: fe cf rjmp .-4 ; 0x1fa0 + ; + if (!(UCSR0A & _BV(FE0))) { + 1fa4: 5c 99 sbic 0x0b, 4 ; 11 + 1fa6: 01 c0 rjmp .+2 ; 0x1faa +} +#endif + +// Watchdog functions. These are only safe with interrupts turned off. +void watchdogReset() { + __asm__ __volatile__ ( + 1fa8: a8 95 wdr + * don't care that an invalid char is returned...) + */ + watchdogReset(); + } + + ch = UDR0; + 1faa: 8c b1 in r24, 0x0c ; 12 + LED_PIN |= _BV(LED); +#endif +#endif + + return ch; +} + 1fac: 08 95 ret + +00001fae : + "wdr\n" + ); +} + +void watchdogConfig(uint8_t x) { + WDTCSR = _BV(WDCE) | _BV(WDE); + 1fae: 98 e1 ldi r25, 0x18 ; 24 + 1fb0: 91 bd out 0x21, r25 ; 33 + WDTCSR = x; + 1fb2: 81 bd out 0x21, r24 ; 33 +} + 1fb4: 08 95 ret + +00001fb6 : + do getch(); while (--count); + verifySpace(); +} + +void verifySpace() { + if (getch() != CRC_EOP) { + 1fb6: f4 df rcall .-24 ; 0x1fa0 + 1fb8: 80 32 cpi r24, 0x20 ; 32 + 1fba: 19 f0 breq .+6 ; 0x1fc2 + watchdogConfig(WATCHDOG_16MS); // shorten WD timeout + 1fbc: 88 e0 ldi r24, 0x08 ; 8 + 1fbe: f7 df rcall .-18 ; 0x1fae + 1fc0: ff cf rjmp .-2 ; 0x1fc0 + while (1) // and busy-loop so that WD causes + ; // a reset and app start. + } + putch(STK_INSYNC); + 1fc2: 84 e1 ldi r24, 0x14 ; 20 +} + 1fc4: e9 cf rjmp .-46 ; 0x1f98 + +00001fc6 : + ::[count] "M" (UART_B_VALUE) + ); +} +#endif + +void getNch(uint8_t count) { + 1fc6: 1f 93 push r17 + 1fc8: 18 2f mov r17, r24 + do getch(); while (--count); + 1fca: ea df rcall .-44 ; 0x1fa0 + 1fcc: 11 50 subi r17, 0x01 ; 1 + 1fce: e9 f7 brne .-6 ; 0x1fca + verifySpace(); + 1fd0: f2 df rcall .-28 ; 0x1fb6 +} + 1fd2: 1f 91 pop r17 + 1fd4: 08 95 ret + +00001fd6 : + WDTCSR = _BV(WDCE) | _BV(WDE); + WDTCSR = x; +} + +void appStart() { + watchdogConfig(WATCHDOG_OFF); + 1fd6: 80 e0 ldi r24, 0x00 ; 0 + 1fd8: ea df rcall .-44 ; 0x1fae + __asm__ __volatile__ ( + 1fda: ee 27 eor r30, r30 + 1fdc: ff 27 eor r31, r31 + 1fde: 09 94 ijmp From c93fd746c4da47730ab6a4a8d4399eb2135968b5 Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Wed, 29 Jun 2011 22:48:07 -0400 Subject: [PATCH 32/33] Disabling terminal / monitor. --- .../arduino/bootloaders/stk500v2/stk500boot.c | 3 +- .../stk500v2/stk500boot_v2_mega2560.hex | 648 ++++-------------- 2 files changed, 140 insertions(+), 511 deletions(-) diff --git a/hardware/arduino/bootloaders/stk500v2/stk500boot.c b/hardware/arduino/bootloaders/stk500v2/stk500boot.c index 13dec8951..3d5b09582 100755 --- a/hardware/arduino/bootloaders/stk500v2/stk500boot.c +++ b/hardware/arduino/bootloaders/stk500v2/stk500boot.c @@ -95,7 +95,8 @@ LICENSE: #include "command.h" -#if defined(_MEGA_BOARD_) || defined(_BOARD_AMBER128_) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) +//#if defined(_MEGA_BOARD_) || defined(_BOARD_AMBER128_) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) +#if 0 #define ENABLE_MONITOR static void RunMonitor(void); #endif diff --git a/hardware/arduino/bootloaders/stk500v2/stk500boot_v2_mega2560.hex b/hardware/arduino/bootloaders/stk500v2/stk500boot_v2_mega2560.hex index 4f366997c..ace9cb1f7 100644 --- a/hardware/arduino/bootloaders/stk500v2/stk500boot_v2_mega2560.hex +++ b/hardware/arduino/bootloaders/stk500v2/stk500boot_v2_mega2560.hex @@ -1,513 +1,141 @@ :020000023000CC -:10E000000D94F6F20D941FF30D941FF30D941FF36E -:10E010000D941FF30D941FF30D941FF30D941FF334 -:10E020000D941FF30D941FF30D941FF30D941FF324 -:10E030000D941FF30D941FF30D941FF30D941FF314 -:10E040000D941FF30D941FF30D941FF30D941FF304 -:10E050000D941FF30D941FF30D941FF30D941FF3F4 -:10E060000D941FF30D941FF30D941FF30D941FF3E4 -:10E070000D941FF30D941FF30D941FF30D941FF3D4 -:10E080000D941FF30D941FF30D941FF30D941FF3C4 -:10E090000D941FF30D941FF30D941FF30D941FF3B4 -:10E0A0000D941FF30D941FF30D941FF30D941FF3A4 -:10E0B0000D941FF30D941FF30D941FF30D941FF394 -:10E0C0000D941FF30D941FF30D941FF30D941FF384 -:10E0D0000D941FF30D941FF30D941FF30D941FF374 -:10E0E0000D941FF341546D65676132353630004140 -:10E0F000726475696E6F206578706C6F72657220DE -:10E1000073746B3530305632206279204D4C530099 -:10E11000426F6F746C6F616465723E004875683F52 -:10E1200000436F6D70696C6564206F6E20203D2028 -:10E1300000435055205479706520202020203D2038 -:10E14000005F5F4156525F415243485F5F203D2070 -:10E1500000415652204C69624320566572203D2092 -:10E16000004743432056657273696F6E20203D203F -:10E1700000435055207369676E61747572653D2068 -:10E18000004C6F77206675736520202020203D208D -:10E1900000486967682066757365202020203D204F -:10E1A00000457874206675736520202020203D206E -:10E1B000004C6F636B2066757365202020203D2026 -:10E1C00000536570202039203230313000312E3636 -:10E1D0002E3700342E332E33005623202020414486 -:10E1E00044522020206F7020636F6465202020201F -:10E1F00020696E737472756374696F6E20616464F4 -:10E2000072202020496E74657272757074006E6F92 -:10E2100020766563746F7200726A6D702020006AE8 -:10E220006D7020005768617420706F72743A0050EE -:10E230006F7274206E6F7420737570706F72746576 -:10E2400064004D7573742062652061206C65747480 -:10E2500065720020005772697474696E67204545C5 -:10E260000052656164696E6720454500656570729E -:10E270006F6D206572726F7220636F756E743D00F2 -:10E28000504F525400303D5A65726F206164647281 -:10E290006573732063747273003F3D435055207360 -:10E2A0007461747300403D454550524F4D20746574 -:10E2B000737400423D426C696E6B204C45440045CE -:10E2C0003D44756D7020454550524F4D00463D44CC -:10E2D000756D7020464C41534800483D48656C7050 -:10E2E000004C3D4C69737420492F4F20506F72745D -:10E2F0007300513D517569742026206A756D702038 -:10E30000746F20757365722070676D00523D44759F -:10E310006D702052414D00563D73686F7720696ED5 -:10E320007465727275707420566563746F727300D1 -:10E33000593D506F727420626C696E6B002A0052F6 -:10E340004553455400494E543000494E543100491C -:10E350004E543200494E543300494E543400494E15 -:10E36000543500494E543600494E54370050434905 -:10E370004E5430005043494E5431005043494E549E -:10E3800032005744540054494D45523020434F4DBC -:10E3900050410054494D45523020434F4D504200AA -:10E3A00054494D455230204F56460054494D455230 -:10E3B0003120434150540054494D45523120434F80 -:10E3C0004D50410054494D45523120434F4D50422C -:10E3D0000054494D45523120434F4D50430054495C -:10E3E0004D455231204F56460054494D455232203A -:10E3F000434F4D50410054494D45523220434F4DFB -:10E4000050420054494D455232204F56460054491F -:10E410004D45523320434150540054494D455233E9 -:10E4200020434F4D50410054494D45523320434FF6 -:10E430004D50420054494D45523320434F4D5043B7 -:10E440000054494D455233204F56460054494D45DE -:10E45000523420434150540054494D4552342043D6 -:10E460004F4D50410054494D45523420434F4D507B -:10E47000420054494D45523420434F4D50430054BF -:10E48000494D455234204F56460054494D4552356A -:10E4900020434150540054494D45523520434F4D7F -:10E4A00050410054494D45523520434F4D50420094 -:10E4B00054494D45523520434F4D50430054494D2A -:10E4C000455235204F564600555341525430205244 -:10E4D000580055534152543020554452450055532D -:10E4E0004152543020545800555341525431205217 -:10E4F000580055534152543120554452450055530C -:10E5000041525431205458005553415254322052F4 -:10E5100058005553415254322055445245005553EA -:10E5200041525432205458005553415254332052D2 -:10E5300058005553415254332055445245005553C9 -:10E5400041525433205458005350492053544300EF -:10E5500041444300414E414C4F4720434F4D5000F2 -:10E560004545205245414459005457490053504DA8 -:10E57000205245414459002A003FE345E34AE34F16 -:10E58000E354E359E35EE363E368E36DE374E37B41 -:10E59000E382E3E9E3F6E303E4ABE3B7E3C4E3D107 -:10E5A000E3DEE386E393E3A0E348E5C8E4D2E4DEF8 -:10E5B000E454E550E560E50EE41AE427E434E44170 -:10E5C000E4E8E4F2E4FEE469E56DE54CE458E46572 -:10E5D000E472E47FE48AE496E4A3E4B0E4BDE408F2 -:10E5E000E512E51EE528E532E53EE50011241FBEF3 -:10E5F000CFEFD1E2DEBFCDBF01E00CBF12E0A0E063 -:10E60000B2E0EAEDFFEF03E00BBF02C007900D920E -:10E61000A030B107D9F712E0A0E0B2E001C01D922E -:10E62000AC30B107E1F70F94FBF40D94EBFF01E27E -:10E630000EBF0FEF0DBF11241FBE0D94FBF40D9400 -:10E6400000F020E030E040ED57E005C0FA013197DE -:10E65000F1F72F5F3F4F28173907C0F308959C014A -:10E66000442737FD4095542FDA01C901860F911DCB -:10E67000A11DB11DABBFFC018791882369F0809378 -:10E68000C6008091C00086FFFCCF8091C0008064EE -:10E690008093C0006F5FE8CF08958DE08093C6003F -:10E6A0008091C00086FFFCCF8091C0008064809381 -:10E6B000C0008AE08093C6008091C00086FFFCCF36 -:10E6C0008091C00080648093C00008950F942FF360 -:10E6D0000F944DF30895FC019081992359F0909384 -:10E6E000C6008091C00086FFFCCF8091C00080648E -:10E6F0008093C0003196992379F70895282F982F99 -:10E7000092959F70892F805D8A3308F0895F80938E -:10E71000C6008091C00086FFFCCF8091C00080645D -:10E720008093C000822F8F70982F905D9A3308F0ED -:10E73000995F9093C6008091C00086FFFCCF8091C6 -:10E74000C00080648093C00008959C01FB01853661 -:10E7500091051CF46330710594F0C90164E670E022 -:10E760000F948CFF605D7F4F6093C6008091C00066 -:10E7700086FFFCCF8091C00080648093C0002B3066 -:10E78000310514F43297B4F0C90164E670E00F94D7 -:10E790008CFF6AE070E00F948CFF605D7F4F6093A8 -:10E7A000C6008091C00086FFFCCF8091C0008064CD -:10E7B0008093C000C9016AE070E00F948CFFC0969E -:10E7C0008093C6008091C00086FFFCCF8091C0007E -:10E7D00080648093C0000895282F277020642093C0 -:10E7E0007C0020917B0086958695869590E08170CF -:10E7F000907033E0880F991F3A95E1F7277F282B17 -:10E8000020937B0080917A00806480937A008091CD -:10E810007A0086FDFCCF2091780040917900942FFA -:10E8200080E030E0282B392BC90108951F93182F61 -:10E8300080E892EE60E00F942FF31093C600809171 -:10E84000C00086FFFCCF8091C00080648093C00030 -:10E850000F944DF31F9108952F923F924F925F9224 -:10E860006F927F928F929F92AF92BF92CF92DF92E0 -:10E87000EF92FF920F931F93DF93CF93CDB7DEB745 -:10E8800062970FB6F894DEBF0FBECDBF382E622E52 -:10E89000CA01DB015C016D01772460E2262E2E01A6 -:10E8A0000894411C511C8BC081E0A81680E0B8067A -:10E8B00081E0C80680E0D80628F0C601AA27BB2759 -:10E8C0000F947EF3BB27AD2D9C2D8B2D0F947EF3E3 -:10E8D0008A2D0F947EF32092C6008091C00086FF9F -:10E8E000FCCF8091C00080648093C0009DE2909333 -:10E8F000C6008091C00086FFFCCF8091C00080647C -:10E900008093C0002092C6008091C00086FFFCCF9B -:10E910008091C00080648093C000198286017501D7 -:10E9200088249924A1E03A1651F03A1620F0B2E07A -:10E930003B1661F409C00BBFF701779007C0C70110 -:10E940000F94D5FF782E02C0F7017080872D0F94A9 -:10E950007EF32092C6008091C00086FFFCCF80919C -:10E96000C00080648093C000872D8052F401EF7056 -:10E97000F0708F3520F4E40DF51D708204C0E40DB5 -:10E98000F51D8EE280830894E11CF11C011D111D10 -:10E990000894811C911C90E18916910409F0C2CF62 -:10E9A00080E190E0A0E0B0E0A80EB91ECA1EDB1E18 -:10E9B000198AC2010F946BF30F944DF36A94662089 -:10E9C00009F072CF62960FB6F894DEBF0FBECDBFCE -:10E9D000CF91DF911F910F91FF90EF90DF90CF903B -:10E9E000BF90AF909F908F907F906F905F904F906F -:10E9F0003F902F9008952F923F924F925F926F9287 -:10EA00007F928F929F92AF92BF92CF92DF92EF92BE -:10EA1000FF920F931F93DF93CF93CDB7DEB7CD5304 -:10EA2000D1400FB6F894DEBF0FBECDBF279A2F9A04 -:10EA30008091C00082608093C00080E18093C40018 -:10EA400088E18093C1000000EE24FF248701B4E038 -:10EA5000AB2EB12CCC24DD2424C0C5010197F1F7E5 -:10EA60000894E11CF11C011D111D21E2E2162EE4A7 -:10EA7000F20620E0020720E0120718F0A1E0CA2EFB -:10EA8000D12CC801B70128E53BE140E050E00F94EC -:10EA90009FFF611571058105910519F485B18058B5 -:10EAA00085B98091C00087FD03C0C114D104A9F2CB -:10EAB000A6014F5F5F4FC25EDE4F59834883CE5140 -:10EAC000D140C25EDE4F68817981CE51D140613044 -:10EAD000710511F00D946EFFC05DDE4F1982188232 -:10EAE000C053D14060E0C15DDE4F1882CF52D140AB -:10EAF000AA24BB24C05EDE4F188219821A821B82B0 -:10EB0000C052D140CE5CDE4F188219821A821B821D -:10EB1000C253D14080E090E0A0E0B0E0ABBFFC0188 -:10EB2000A791B691C45CDE4FB983A883CC53D14082 -:10EB30000D9469FFC25EDE4FE881F981CE51D1406C -:10EB4000319709F52091C600C25EDE4F1982188206 -:10EB5000CE51D14022C02F5F3F4F4F4F5F4F2130EA -:10EB6000F2E13F07FAE74F07F0E05F0780F0C45C8F -:10EB7000DE4F08811981CC53D1400F5F1F4F19F030 -:10EB8000EE27FF27099420E030E040E050E080913C -:10EB9000C00087FFE0CF2091C600213209F094C663 -:10EBA0000894A11CB11C33E0A316B10409F08EC671 -:10EBB00000E010E018C041E24093C6008091C00020 -:10EBC00086FFFCCF8091C00080648093C0002F5FDF -:10EBD0003F4F2931310579F70F944DF30F5F1F4FE8 -:10EBE0000530110519F020E030E0E5CF1092080261 -:10EBF0001092090210920A0210920B021092040263 -:10EC00001092050210920602109207021092000262 -:10EC10001092010210920202109203028FEE90EE07 -:10EC200060E00F9466F380E191EE60E00F942FF3C3 -:10EC30008091C00087FFFCCF9091C600903608F00D -:10EC40009F759032B8F09093C6008091C00086FF07 -:10EC5000FCCF8091C00080648093C00080E28093EC -:10EC6000C6008091C00086FFFCCF8091C000806408 -:10EC70008093C000983409F4DBC19934B8F492341D -:10EC800009F45DC1933458F4903319F1903308F4CA -:10EC900018C69F33A1F1903409F013C6BDC0953456 -:10ECA00009F474C1963409F00CC69CC1923509F47C -:10ECB0002FC2933538F49C3409F4F9C1913509F029 -:10ECC00000C61CC2963509F449C2993509F0F9C548 -:10ECD0009CC485E892EE62E00F9466F31092040201 -:10ECE000109205021092060210920702109208027A -:10ECF0001092090210920A0210920B0217C189E9C0 -:10ED000092EE62E00F9466F38FEE90EE60E00F9467 -:10ED100066F381E291EE60E00F942FF381EC91EEC7 -:10ED200060E00F9466F381E391EE60E00F942FF3BF -:10ED300084EE90EE60E00F9466F381E491EE60E083 -:10ED40000F942FF386E090E061E070E00F94A5F35C -:10ED50000F944DF381E691EE60E00F942FF383ED75 -:10ED600091EE60E00F9466F381E591EE60E00F9420 -:10ED70002FF38DEC91EE60E00F9466F381E791EE56 -:10ED800060E00F942FF38EE10F947EF388E90F94E7 -:10ED90007EF381E00F947EF30F944DF381E891EEC2 -:10EDA00060E00F942FF319E0E0E0F0E010935700DB -:10EDB000E4918E2F0F947EF30F944DF381E991EE41 -:10EDC00060E00F942FF3E3E0F0E010935700E4913C -:10EDD0008E2F0F947EF30F944DF381EA91EE60E055 -:10EDE0000F942FF3E2E0F0E010935700E4918E2FA0 -:10EDF0000F947EF30F944DF381EB91EE60E00F944E -:10EE00002FF3E1E0F0E0109357001491812F0F945D -:10EE10007EF30F944DF307CF85EA92EE62E00F94F4 -:10EE200066F385E592EE60E00F9466F30F944DF380 -:10EE300000E010E019C0C8016F2D0F94DDFFFF2026 -:10EE400031F483E592EE60E00F942FF30BC0F09263 -:10EE5000C6008091C00086FFFCCF8091C000806416 -:10EE60008093C0000F5F1F4FC80181519F41AA27A7 -:10EE700097FDA095BA2FABBFFC01F7905AE2F516AB -:10EE800021F062E000301607B1F60F944DF30F94B5 -:10EE90004DF381E692EE60E00F9466F30F944DF32C -:10EEA000CC24DD2400E010E01EC0C8010F94D5FF83 -:10EEB000F82E882331F483E592EE60E00F942FF36F -:10EEC0000BC08093C6008091C00086FFFCCF80916C -:10EED000C00080648093C000FE1419F00894C11C27 -:10EEE000D11C0F5F1F4FC80181519F41AA2797FD79 -:10EEF000A095BA2FABBFFC01E7907AE2E71621F0AC -:10EF000082E00030180789F60F944DF30F944DF30B -:10EF10008CE692EE60E00F942FF3C60161E070E0A2 -:10EF20000F94A5F30F944DF30F944DF3109200023C -:10EF300010920102109202021092030274CE83EB2F -:10EF400092EE62E00F9466F3279A2F9A16C02F98DC -:10EF500080E090E0E0EDF7E03197F1F7019684363C -:10EF60009105C1F72F9A80E090E0E0EDF7E031974E -:10EF7000F1F7019684369105C1F78091C00087FFB3 -:10EF8000E6CF8091C00087FFFCCF95C48FEB92EE57 -:10EF900062E00F9466F3409100025091010260918B -:10EFA00002027091030281E020E10F942CF4809121 -:10EFB000000290910102A0910202B09103028050E0 -:10EFC0009F4FAF4FBF4F8093000290930102A093D9 -:10EFD0000202B093030280509041A040B04008F478 -:10EFE00022CEA4CF8DEC92EE62E00F9466F34091B6 -:10EFF000040250910502609106027091070280E0C0 -:10F0000020E10F942CF48091040290910502A091CC -:10F010000602B091070280509F4FAF4FBF4F8093C1 -:10F02000040290930502A0930602B0930702FBCD61 -:10F030008AED92EE62E00F9466F385E892EE60E06E -:10F040000F9466F389E992EE60E00F9466F385EA27 -:10F0500092EE60E00F9466F383EB92EE60E00F9423 -:10F0600066F38FEB92EE60E00F9466F38DEC92EE18 -:10F0700060E00F9466F38AED92EE60E00F9466F321 -:10F0800081EE92EE60E00F9466F382EF92EE60E024 -:10F090000F9466F38CE093EE60E00F9466F387E1E3 -:10F0A00093EE60E00F9466F380E393EEB9CD81EECA -:10F0B00092EE62E00F9466F381E40F9416F482E41A -:10F0C0000F9416F483E40F9416F484E40F9416F46A -:10F0D00085E40F9416F486E40F9416F487E40F94F5 -:10F0E00016F488E40F9416F48AE40F9416F48BE473 -:10F0F0000F9416F48CE40F9416F495CD82EF92EEF3 -:10F1000062E00F9466F399249394AA24BB2445C427 -:10F110008CE093EE62E00F9466F340910802509108 -:10F12000090260910A0270910B0282E020E10F94C3 -:10F130002CF48091080290910902A0910A02B091EA -:10F140000B0280509F4FAF4FBF4F809308029093A8 -:10F150000902A0930A02B0930B0265CD87E193EEFA -:10F1600062E00F9466F384EE90EE60E00F9466F335 -:10F1700089ED91EE60E00F9466F309E715EECC5D42 -:10F18000DE4F19830883C452D1406624772443019B -:10F19000CA5DDE4F19821882C652D140A401930184 -:10F1A0005695479537952795C85DDE4F2883398357 -:10F1B0004A835B83C852D140CA5DDE4F4881598182 -:10F1C000C652D1404F5F5F4FCA5DDE4F59834883BF -:10F1D000C652D140CA0162E070E00F94A5F350E23C -:10F1E0005093C6008091C00086FFFCCF8091C00084 -:10F1F00080648093C0006DE26093C6008091C0007F -:10F2000086FFFCCF8091C00080648093C00070E2D4 -:10F210007093C6008091C00086FFFCCF8091C00033 -:10F2200080648093C000C85DDE4FE880F9800A8169 -:10F230001B81C852D140BB27A12F902F8F2D0F9437 -:10F240007EF3C85DDE4F8881C852D1400F947EF3B3 -:10F2500070E2F72EF092C6008091C00086FFFCCFCE -:10F260008091C00080648093C0000DE30093C600CD -:10F270008091C00086FFFCCF8091C00080648093A5 -:10F28000C00010E21093C6008091C00086FFFCCF42 -:10F290008091C00080648093C0008BBEF3012791F1 -:10F2A000C45DDE4F2883CC52D140A22EBB24CC2497 -:10F2B000DD240894611C711C811C911C8BBEF30120 -:10F2C0008791282E332444245524142D032DF22C09 -:10F2D000EE24EA0CFB1C0C1D1D1D0894611C711C06 -:10F2E000811C911C8BBEF3013791C35DDE4F3883C7 -:10F2F000CD52D1400894611C711C811C911C8BBEA5 -:10F30000F3014791C25DDE4F4883CE52D1402DEFCD -:10F310003FEF4FEF5FEF620E731E841E951E0F943A -:10F320007EF330E23093C6008091C00086FFFCCFB0 -:10F330008091C00080648093C000C45DDE4F8881EE -:10F34000CC52D1400F947EF340E24093C6008091AE -:10F35000C00086FFFCCF8091C00080648093C00015 -:10F36000C25DDE4F8881CE52D1400F947EF350E2D1 -:10F370005093C6008091C00086FFFCCF8091C000F2 -:10F3800080648093C000C35DDE4F8881CD52D14040 -:10F390000F947EF360E26093C6008091C00086FF08 -:10F3A000FCCF8091C00080648093C0007FEFE7169F -:10F3B0007FEFF70670E0070770E0170731F48EE083 -:10F3C00092EE60E00F942FF3DFC0D801C701807088 -:10F3D000907CA070B0708050904CA040B040D1F5AF -:10F3E0002FEF3FE340E050E0E222F3220423152315 -:10F3F000C85DDE4FA880B980CA80DB80C852D1408A -:10F40000AE0CBF1CC01ED11EAA0CBB1CCC1CDD1C2C -:10F4100088E192EE60E00F942FF3BB27A12F902F8D -:10F420008F2D0F947EF38E2D0F947EF330E2309368 -:10F43000C6008091C00086FFFCCF8091C000806430 -:10F440008093C0004EE34093C6008091C00086FFC9 -:10F45000FCCF87C06EE07EEF80E090E0E622F722EE -:10F46000082319237CE0E71674E9F70670E0070724 -:10F4700070E0170709F088C0C25DDE4F8881CE5268 -:10F48000D140E82EFF2400E010E0102F0F2DFE2CBD -:10F49000EE24C35DDE4F9881CD52D140E90EF11CC0 -:10F4A000011D111DD601C50181709070A070B07052 -:10F4B000DC0199278827E80EF91E0A1F1B1F20EF81 -:10F4C00030E040E050E0A222B322C422D522F1E194 -:10F4D000AA0CBB1CCC1CDD1CFA95D1F7EA0CFB1C5A -:10F4E0000C1D1D1D41E050E060E070E0242235223B -:10F4F00046225722E5E1220C331C441C551CEA9598 -:10F50000D1F7E20CF31C041D151D57016801AA0C6C -:10F51000BB1CCC1CDD1C8FE192EE60E00F942FF33E -:10F52000C801AA27BB270F947EF3BB27A12F902FDA -:10F530008F2D0F947EF38E2D0F947EF350E2509317 -:10F54000C6008091C00086FFFCCF8091C00080641F -:10F550008093C0006EE36093C6008091C00086FF78 -:10F56000FCCF8091C00080648093C000C601AA27B0 -:10F57000BB270F947EF3BB27AD2D9C2D8B2D0F94B5 -:10F580007EF38A2D0F947EF370E27093C600809113 -:10F59000C00086FFFCCF8091C00080648093C000D3 -:10F5A000CC5DDE4FE881F981C452D140CF01AA275A -:10F5B00097FDA095BA2FABBFFC018791969160E0B3 -:10F5C0000F942FF30F944DF3CC5DDE4F088119811A -:10F5D000C452D1400E5F1F4FCC5DDE4F19830883AC -:10F5E000C452D140CA5DDE4F28813981C652D14014 -:10F5F0002933310509F417CB44E050E060E070E0B6 -:10F60000640E751E861E971EC9CD80E393EE62E0E0 -:10F610000F9466F384E292EE60E00F942FF38091F2 -:10F62000C00087FFFCCF1091C6001F751093C60065 -:10F630008091C00086FFFCCF8091C00080648093E1 -:10F64000C0000F944DF3812F81548A3108F036C1E8 -:10F65000163409F495C0173490F4133409F44EC0ED -:10F66000143430F41134F1F0123409F01DC130C0FB -:10F67000143409F459C0153409F016C16BC01A349A -:10F6800009F4C4C01B3438F4173409F48FC018349B -:10F6900009F00AC1A1C01B3409F4D2C01C3409F01E -:10F6A00003C1E8C08FEF81B90DC082B1809582B9E6 -:10F6B00080E090E0E0EDF7E03197F1F70196883CCB -:10F6C0009105C1F78091C00087FFEFCF12B8EFC05E -:10F6D0008FEF84B90DC085B1809585B980E090E049 -:10F6E000E0EDF7E03197F1F70196883C9105C1F71D -:10F6F0008091C00087FFEFCF15B8D9C08FEF87B9D1 -:10F700000DC088B1809588B980E090E0E0EDF7E029 -:10F710003197F1F70196883C9105C1F78091C000BF -:10F7200087FFEFCF18B8C3C08FEF8AB90DC08BB178 -:10F7300080958BB980E090E0E0EDF7E03197F1F74C -:10F740000196883C9105C1F78091C00087FFEFCFFB -:10F750001BB8ADC08FEF8DB90DC08EB180958EB93D -:10F7600080E090E0E0EDF7E03197F1F70196883C1A -:10F770009105C1F78091C00087FFEFCF1EB897C0F9 -:10F780008FEF80BB0DC081B3809581BB80E090E09E -:10F79000E0EDF7E03197F1F70196883C9105C1F76C -:10F7A0008091C00087FFEFCF11BA81C08FEF83BB7C -:10F7B0000DC084B3809584BB80E090E0E0EDF7E07D -:10F7C0003197F1F70196883C9105C1F78091C0000F -:10F7D00087FFEFCF14BA6BC08FEF809301010FC08A -:10F7E0008091020180958093020180E090E0E0ED3D -:10F7F000F7E03197F1F70196883C9105C1F78091C8 -:10F80000C00087FFEDCF1092020151C08FEF8093AF -:10F8100004010FC08091050180958093050180E06F -:10F8200090E0E0EDF7E03197F1F70196883C910523 -:10F83000C1F78091C00087FFEDCF1092050137C05E -:10F840008FEF809307010FC080910801809580930E -:10F85000080180E090E0E0EDF7E03197F1F70196E4 -:10F86000883C9105C1F78091C00087FFEDCF1092D1 -:10F8700008011DC08FEF80930A010FC080910B011A -:10F88000809580930B0180E090E0E0EDF7E0319708 -:10F89000F1F70196883C9105C1F78091C00087FF80 -:10F8A000EDCF10920B0103C08FE292EEB9C98091A7 -:10F8B000C00087FFFCCF8091C600B5C982E492EEFC -:10F8C000AFC98CE191EEACC9AA24BB24933061F19D -:10F8D000943028F4913089F0923008F508C09530C2 -:10F8E000B1F1953040F1963009F053C04EC02B3144 -:10F8F00009F020C991E06BE11DC9213041F0C15DE3 -:10F90000DE4F5881CF52D140251709F002C362273C -:10F91000C15DDE4F2883CF52D14092E00BC9B22F98 -:10F92000A0E0622793E006C9822F90E0A82BB92BB4 -:10F93000622794E0FFC82E3009F0EBC2622795E001 -:10F94000C05DDE4F19821882C053D140F3C8E1E098 -:10F95000F0E0EC0FFD1FC05DDE4FE880F980C05382 -:10F96000D140EE0DFF1D208387010F5F1F4FC05D4B -:10F97000DE4F19830883C053D14062270A171B0743 -:10F9800009F0D8C8D80196E0D5C8261709F0C1C239 -:10F9900003C0973009F0CEC899248981833109F4D6 -:10F9A000FCC08431C8F4863009F4C2C0873050F4FA -:10F9B000823009F4F0C0833009F458C0813009F076 -:10F9C0000AC23EC0813109F462C0823108F0A6C08B -:10F9D000803109F000C2DFC0883109F472C089317A -:10F9E00050F4853109F4D9C0853108F477C18631E6 -:10F9F00009F0F1C173C18A3109F457C08A3108F4A2 -:10FA00007CC08B3109F446C08D3109F0E4C18D8191 -:10FA1000803311F090E00AC08F81882311F49EE1B9 -:10FA200005C0813011F091E001C098E91A821B8273 -:10FA30008D818C831D829E831F8227E030E0CFC1A1 -:10FA40001A8288E08B8381E48C8386E58D8382E54E -:10FA50008E8389E48F8383E5888780E589878FE5B6 -:10FA60008A8782E38B872BE030E0B9C18A818139B4 -:10FA700041F0823941F0803911F48FE005C080E017 -:10FA800003C082E001C08AE01A828B8344C09924BB -:10FA9000939481C08D81882311F48EE12CC0813034 -:10FAA00011F081E028C088E926C01A82E1E0F0E088 -:10FAB00089E08093570084918B831C8224E030E09E -:10FAC0008EC18B81803589F48C81883039F4E2E0F5 -:10FAD000F0E089E08093570084910DC0E0E0F0E011 -:10FAE00089E080935700849106C0E3E0F0E089E06C -:10FAF0008093570084911A82DFCF8D81836C99E0C7 -:10FB0000E1E0F0E0082E90935700E89507B600FC7E -:10FB1000FDCF1A821B8223E030E061C11A82CE5CE5 -:10FB2000DE4F188219821A821B82C253D14055C1FE -:10FB30008A8190E0A0E0B0E0582F442733272227A5 -:10FB40008B8190E0A0E0B0E0DC0199278827282B8A -:10FB5000392B4A2B5B2B8D8190E0A0E0B0E0282B65 -:10FB6000392B4A2B5B2B8C8190E0A0E0B0E0BA2FC0 -:10FB7000A92F982F8827282B392B4A2B5B2B220F54 -:10FB8000331F441F551FC05EDE4F288339834A83CD -:10FB90005B83C052D1401A8220C19A812B8183316C -:10FBA00049F0C05EDE4F488159816A817B81C05235 -:10FBB000D1408AC0CE5CDE4F488159816A817B8109 -:10FBC000C253D140403080EC580783E0680780E0A2 -:10FBD0007807F0F483E0FA0160935B0080935700AC -:10FBE000E89507B600FCFDCFCE5CDE4F4881598119 -:10FBF0006A817B81C253D14040505F4F6F4F7F4F2E -:10FC0000CE5CDE4F488359836A837B83C253D140E5 -:10FC1000C95CDE4F9883C753D140CA5CDE4F18825F -:10FC2000C653D140022F10E0CA5CDE4F6881798153 -:10FC3000C653D140062B172BC05EDE4F4881598139 -:10FC40006A817B81C052D140DE011B9631E08C91EC -:10FC500011962C9111971296C75CDE4F2883C953D9 -:10FC6000D140C85CDE4F1882C853D14090E0C85CD8 -:10FC7000DE4FE881F981C853D1408E2B9F2B0C01B8 -:10FC8000FA0160935B0030935700E89511244E5FB2 -:10FC90005F4F6F4F7F4F02501040C9F685E0C05E46 -:10FCA000DE4FE880F9800A811B81C052D140F70104 -:10FCB00000935B0080935700E89507B600FCFDCFEA -:10FCC00081E180935700E8951A82C05EDE4F488339 -:10FCD00059836A837B83C052D1407FC0FA80C55C60 -:10FCE000DE4FF882CB53D140C65CDE4F1882CA5338 -:10FCF000D1408B81C82EDD24C65CDE4F088119817E -:10FD0000CA53D140C02AD12A1A828981BE016D5FAF -:10FD10007F4F843121F59601C05EDE4FE880F98087 -:10FD20000A811B81C052D1400BBFF7018791969188 -:10FD3000DB018C9311969C936E5F7F4FD801C701B6 -:10FD40000296A11DB11DC05EDE4F88839983AA83F0 -:10FD5000BB83C052D14022503040F1F636C0C05E65 -:10FD6000DE4F288139814A815B81C052D14008949D -:10FD7000C108D108760100E010E00894C11CD11C34 -:10FD80000894E11CF11C011D111DE20EF31E041F5D -:10FD9000151F21BDBB27A52F942F832F82BD2F5F59 -:10FDA0003F4F4F4F5F4FF89A80B5DB018D93BD01F8 -:10FDB0002E153F054007510761F7C05EDE4F2883CF -:10FDC00039834A835B83C052D14096012D5F3F4FF8 -:10FDD000FB01108204C080EC8A8322E030E08BE1DA -:10FDE0008093C6008091C00086FFFCCF8091C00048 -:10FDF00080648093C000C15DDE4FF881CF52D14056 -:10FE0000F093C6008091C00086FFFCCF8091C000B7 -:10FE100080648093C000432F3093C6008091C0005F -:10FE200086FFFCCF8091C00080648093C000922F39 -:10FE30002093C6008091C00086FFFCCF8091C00057 -:10FE400080648093C0008EE08093C6008091C000E3 -:10FE500086FFFCCF8091C00080648093C00065E184 -:10FE6000C15DDE4FE880CF52D1406E2569276427FF -:10FE7000FE01319610C090819093C6008091C00021 -:10FE800086FFFCCF31968091C00080648093C000D3 -:10FE90006927215030402115310569F76093C6006C -:10FEA0008091C00086FFFCCF8091C0008064809369 -:10FEB000C00085B1805885B9992081F4C15DDE4FBD -:10FEC0000881CF52D1400F5FC15DDE4F0883CF5212 -:10FED000D14090E0A0E0B0E00D949AF527982F98DB -:10FEE00080E090E020ED37E0F9013197F1F70196DD -:10FEF00084369105C9F700008091C0008D7F809302 -:10FF0000C00081E180935700E895EE27FF27099410 -:10FF1000FFCF90E00D949AF597FB092E07260AD0A3 -:10FF200077FD04D02ED006D000201AF4709561958C -:10FF30007F4F0895F6F7909581959F4F0895A1E220 -:10FF40001A2EAA1BBB1BFD010DC0AA1FBB1FEE1F53 -:10FF5000FF1FA217B307E407F50720F0A21BB30B9E -:10FF6000E40BF50B661F771F881F991F1A9469F71A -:10FF700060957095809590959B01AC01BD01CF0176 -:10FF80000895AA1BBB1B51E107C0AA1FBB1FA617E0 -:10FF9000B70710F0A61BB70B881F991F5A95A9F732 -:10FFA00080959095BC01CD010895F999FECF92BD41 -:10FFB00081BDF89A992780B50895262FF999FECF2B -:10FFC0001FBA92BD81BD20BD0FB6F894FA9AF99A76 -:0AFFD0000FBE01960895F894FFCFCC +:10E000000D9472F00D9493F00D9493F00D9493F0A1 +:10E010000D9493F00D9493F00D9493F00D9493F070 +:10E020000D9493F00D9493F00D9493F00D9493F060 +:10E030000D9493F00D9493F00D9493F00D9493F050 +:10E040000D9493F00D9493F00D9493F00D9493F040 +:10E050000D9493F00D9493F00D9493F00D9493F030 +:10E060000D9493F00D9493F00D9493F00D9493F020 +:10E070000D9493F00D9493F00D9493F00D9493F010 +:10E080000D9493F00D9493F00D9493F00D9493F000 +:10E090000D9493F00D9493F00D9493F00D9493F0F0 +:10E0A0000D9493F00D9493F00D9493F00D9493F0E0 +:10E0B0000D9493F00D9493F00D9493F00D9493F0D0 +:10E0C0000D9493F00D9493F00D9493F00D9493F0C0 +:10E0D0000D9493F00D9493F00D9493F00D9493F0B0 +:10E0E0000D9493F011241FBECFEFD1E2DEBFCDBF60 +:10E0F00001E00CBF12E0A0E0B2E0E0EAF8EE03E0DD +:10E100000BBF02C007900D92A030B107D9F70F9452 +:10E11000A3F00D944EF401E20EBF0FEF0DBF1124DA +:10E120001FBE0D94A3F00D9400F020E030E040ED10 +:10E1300057E005C0FA013197F1F72F5F3F4F2817DD +:10E140003907C0F308952F923F924F925F926F92DA +:10E150007F928F929F92AF92BF92CF92DF92EF9277 +:10E16000FF920F931F93DF93CF93CDB7DEB7C852C3 +:10E17000D1400FB6F894DEBF0FBECDBF279A2F9ABD +:10E180008091C00082608093C00080E18093C400D1 +:10E1900088E18093C1000000EE24FF248701E4E0C1 +:10E1A000AE2EB12CCC24DD2424C0C5010197F1F79B +:10E1B0000894E11CF11C011D111D21E2E2162EE460 +:10E1C000F20620E0020720E0120718F071E0C72EE7 +:10E1D000D12CC801B70128E53BE140E050E00F94A5 +:10E1E0002CF4611571058105910519F485B18058EC +:10E1F00085B98091C00087FD03C0C114D104A9F284 +:10E20000A6014F5F5F4FC25EDE4F59834883CE51F8 +:10E21000D140C25EDE4F68817981CE51D1406130FC +:10E22000710509F0FCC222243324A0E0C05EDE4F59 +:10E230001882C052D1408824992454014424552482 +:10E240003201ABBEF40187919691C95DDE4F99838F +:10E250008883C752D140DFC2C25EDE4FE881F981B8 +:10E26000CE51D140319709F53091C600C25EDE4FE4 +:10E2700019821882CE51D14022C04F5F5F4F6F4F3D +:10E280007F4F4130F2E15F07FAE76F07F0E07F0769 +:10E2900080F0C95DDE4F28813981C752D1402F5FA0 +:10E2A0003F4F19F0EE27FF27099440E050E060E06F +:10E2B00070E08091C00087FFE0CF3091C6009330BE +:10E2C00061F1943028F4913089F0923008F508C05B +:10E2D000953091F1953040F1963009F043C03EC041 +:10E2E0003B3109F0B9CF91E0ABE1B6CF313041F02D +:10E2F000C05EDE4F5881C052D140351709F0AAC226 +:10E30000A327C05EDE4F3883C052D14092E0A4CF35 +:10E31000132F00E0A32793E09FCF832F90E0082BDB +:10E32000192BA32794E098CF3E3009F093C2A3277E +:10E3300095E02224332490CFE1E0F0E0EC0FFD1FC4 +:10E34000E20DF31D30830894211C311CA3272016F5 +:10E35000310609F081CF810196E07ECF3A1709F0AE +:10E3600079C203C0973009F077CF8981833109F4EE +:10E37000F4C08431C0F4863009F4C2C0873048F458 +:10E38000823069F1833009F45BC0813009F0C4C187 +:10E3900041C0813109F465C0823108F0ACC08031E0 +:10E3A00009F0BAC11CC0883109F474C0893150F435 +:10E3B000853109F4D2C0853108F443C1863109F0B2 +:10E3C000ABC13FC18A3109F45CC08A3108F482C014 +:10E3D0008B3109F44BC08D3109F09EC102C090E031 +:10E3E00041C08D81803311F090E00AC08F81882375 +:10E3F00011F49EE105C0813011F091E001C098E96F +:10E400001A821B828D818C831D829E831F8247E02E +:10E4100050E086C11A8288E08B8381E48C8386E594 +:10E420008D8382E58E8389E48F8383E5888780E509 +:10E4300089878FE58A8782E38B874BE050E070C144 +:10E440008A81813941F0823941F0803911F48FE0BD +:10E4500005C080E003C082E001C08AE01A828B839D +:10E4600047C091E01A8242E050E05BC18D81882371 +:10E4700011F48EE129C0813011F081E025C088E9D6 +:10E4800023C01A82E1E0F0E069E060935700E49174 +:10E49000EB831CC08B81803589F48C81883039F402 +:10E4A00029E0E2E0F0E02093570084910DC029E0DC +:10E4B000E0E0F0E020935700849106C0E3E0F0E054 +:10E4C00039E03093570084911A828B831C8244E098 +:10E4D00050E026C18D81836C49E0E1E0F0E0082E38 +:10E4E00040935700E89507B600FCFDCF1A821B82C7 +:10E4F00043E050E015C11A824424552432010EC174 +:10E500008A8190E0A0E0B0E0B82EAA249924882463 +:10E510008B8190E0A0E0B0E0DC0199278827882A71 +:10E52000992AAA2ABB2A8D8190E0A0E0B0E0882A2F +:10E53000992AAA2ABB2A8C8190E0A0E0B0E0BA2FE9 +:10E54000A92F982F8827882A992AAA2ABB2A880CBB +:10E55000991CAA1CBB1C1A82E1C09A813B818331A1 +:10E5600019F0B501A40169C050E0451650EC5506FC +:10E5700053E0650650E0750690F463E0F2016092A6 +:10E580005B0060935700E89507B600FCFDCF40E0C4 +:10E5900051E060E070E0440E551E661E771ECE5DB1 +:10E5A000DE4F9883C252D140CF5DDE4F1882C152F8 +:10E5B000D140032F10E0CF5DDE4F68817981C152D9 +:10E5C000D140062B172BB501A401DE011B968C91BF +:10E5D00011962C9111971296CC5DDE4F2883C45270 +:10E5E000D140CD5DDE4F1882C352D14090E0CD5D69 +:10E5F000DE4FE881F981C352D1408E2B9F2B21E061 +:10E600000C01FA0160935B0020935700E8951124F8 +:10E610004E5F5F4F6F4F7F4F02501040C1F635E0A5 +:10E62000F401A0925B0030935700E89507B600FC18 +:10E63000FDCF81E180935700E8951A824A015B0182 +:10E640006DC09A81CA5DDE4F9883C652D140CB5DC2 +:10E65000DE4F1882C552D1408B81C82EDD24CB5DA0 +:10E66000DE4FA881B981C552D140CA2ADB2A1A825D +:10E6700089818431E9F4A60123E0E22EF12CEC0E2D +:10E68000FD1EABBEF40187919691F70180839183C3 +:10E6900022E030E0E20EF31E62E070E080E090E005 +:10E6A000860E971EA81EB91E4250504051F72EC02C +:10E6B000B501A40193E0E92EF12CEC0EFD1E0894A7 +:10E6C000C108D108860120E030E00894C11CD11CAB +:10E6D0000F5F1F4F2F4F3F4F080D191D2A1D3B1D68 +:10E6E00041BDBB27A72F962F852F82BD4F5F5F4F60 +:10E6F0006F4F7F4FF89A80B5D7018D937D014017FA +:10E7000051076207730761F74A015B01A6014D5F7C +:10E710005F4FF701108204C0F0ECFA8342E050E052 +:10E7200090E02BE12093C6008091C00086FFFCCFD3 +:10E730008091C00080648093C000C05EDE4F38814D +:10E74000C052D1403093C6008091C00086FFFCCFFC +:10E750008091C00080648093C000652F5093C600F4 +:10E760008091C00086FFFCCF8091C00080648093C0 +:10E77000C000342F4093C6008091C00086FFFCCFBC +:10E780008091C00080648093C0008EE08093C600BA +:10E790008091C00086FFFCCF8091C0008064809390 +:10E7A000C000A5E1C05EDE4F7881C052D140A727EE +:10E7B000A327A627FE01319610C030813093C600F2 +:10E7C0008091C00086FFFCCF31968091C0008064AC +:10E7D0008093C000A327415050404115510569F76F +:10E7E000A093C6008091C00086FFFCCF8091C0003E +:10E7F00080648093C00085B1805885B9992379F4ED +:10E80000C05EDE4F8881C052D1408F5FC05EDE4F58 +:10E810008883C052D14090E000E010E01DCD2798E1 +:10E820002F9880E090E020ED37E0F9013197F1F783 +:10E83000019684369105C9F700008091C0008D7F54 +:10E840008093C00081E180935700E895EE27FF2771 +:10E850000994FFCF90E000CDA1E21A2EAA1BBB1BAA +:10E86000FD010DC0AA1FBB1FEE1FFF1FA217B3079C +:10E87000E407F50720F0A21BB30BE40BF50B661FB2 +:10E88000771F881F991F1A9469F760957095809576 +:10E8900090959B01AC01BD01CF010895F894FFCF85 :040000033000E000E9 :00000001FF From fc8cacb9a3b7c1d9cf96ae9891c7c3cd21f3c181 Mon Sep 17 00:00:00 2001 From: WestfW Date: Wed, 5 Oct 2011 01:41:03 -0700 Subject: [PATCH 33/33] Explicitly set the SHELL variable when OS=windows, so that we'll use the same shell regardless of whether other shells are installed (different shells have different behavior WRT directory component separators, so this matters. http://code.google.com/p/arduino/issues/detail?id=667 ) --- hardware/arduino/bootloaders/optiboot/Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hardware/arduino/bootloaders/optiboot/Makefile b/hardware/arduino/bootloaders/optiboot/Makefile index c2e03e3a6..b9f3ed5a4 100644 --- a/hardware/arduino/bootloaders/optiboot/Makefile +++ b/hardware/arduino/bootloaders/optiboot/Makefile @@ -57,8 +57,10 @@ AVRDUDE_CONF = -C$(TOOLROOT)/avr/etc/avrdude.conf ifeq ($(OS), windows) # On windows, SOME of the tool paths will need to have backslashes instead # of forward slashes (because they use windows cmd.exe for execution instead -# of a unix/mingw shell?) +# of a unix/mingw shell?) We also have to ensure that a consistent shell +# is used even if a unix shell is installed (ie as part of WINAVR) fixpath = $(subst /,\,$1) +SHELL = cmd.exe endif else ifeq ($(ENV), arduinodev)