From: Keith Packard Date: Mon, 9 Dec 2013 04:09:10 +0000 (-0800) Subject: altoslib: Add self-flashing code X-Git-Tag: 1.3~57 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=2cdb90d9214f8e66b3574cbd9c5ed073a7861681;ds=sidebyside altoslib: Add self-flashing code This adds the ability to use the AltOS flash-loader on both STM and NXP processors. Signed-off-by: Keith Packard --- diff --git a/altoslib/AltosSelfFlash.java b/altoslib/AltosSelfFlash.java index 0ae797a0..07952d7f 100644 --- a/altoslib/AltosSelfFlash.java +++ b/altoslib/AltosSelfFlash.java @@ -19,14 +19,14 @@ package org.altusmetrum.altoslib_2; import java.io.*; -public class AltosSelfFlash { +public class AltosSelfFlash extends AltosProgrammer { File file; FileInputStream input; AltosHexfile image; AltosLink link; boolean aborted; AltosFlashListener listener; - byte[] read_block, write_block; + AltosRomconfig rom_config; void action(String s, int percent) { if (listener != null && !aborted) @@ -40,23 +40,49 @@ public class AltosSelfFlash { percent); } - void read_block(long addr) { - link.printf("R %x\n", addr); - - } - - void read_memory(long addr, int len) { + byte[] read_memory(long addr, int len) throws InterruptedException, IOException { + int b; + byte[] data = new byte[len]; + + for (int offset = 0; offset < len; offset += 0x100) { + link.printf("R %x\n", addr + offset); + byte[] reply = link.get_binary_reply(5000, 0x100); + + if (reply == null) + throw new IOException("Read device memory timeout"); + for (b = 0; b < len; b++) + data[b+offset] = reply[b]; + } + return data; } void write_memory(long addr, byte[] data, int start, int len) { - + int b; + System.out.printf ("write_memory %x %d\n", addr, len); + link.printf("W %x\n", addr); + link.flush_output(); + for (b = 0; b < len; b++) + link.putchar(data[start + b]); + for (; b < 0x100; b++) + link.putchar((byte) 0xff); } void reboot() { + System.out.printf("reboot\n"); + link.printf("a\n"); + link.flush_output(); } public void flash() { try { + if (!check_rom_config()) + throw new IOException("Invalid rom config settings"); + + /* + * Store desired config values into image + */ + rom_config.write(image); + int remain = image.data.length; long flash_addr = image.address; int image_start = 0; @@ -89,13 +115,10 @@ public class AltosSelfFlash { action(image.data.length - remain, image.data.length); } if (!aborted) { + System.out.printf ("done\n"); action("done", 100); - if (link != null) { - reboot(); - } } - if (link != null) - link.close(); + close(); } catch (IOException ie) { action(ie.getMessage(), -1); abort(); @@ -105,8 +128,11 @@ public class AltosSelfFlash { } public void close() { - if (link != null) + if (link != null) { + reboot(); link.close(); + link = null; + } } synchronized public void abort() { @@ -114,11 +140,36 @@ public class AltosSelfFlash { close(); } + private AltosHexfile get_rom() { + System.out.printf("get rom\n"); + try { + int base = AltosRomconfig.fetch_base(image); + int bounds = AltosRomconfig.fetch_bounds(image); + byte[] data = read_memory(base, bounds - base); + AltosHexfile hexfile = new AltosHexfile(data, base); + hexfile.add_symbols(image); + return hexfile; + } catch (AltosNoSymbol none) { + System.out.printf("no symbol %s\n", none.getMessage()); + return null; + } catch (InterruptedException ie) { + return null; + } catch (IOException ie) { + return null; + } + + } + public boolean check_rom_config() { - if (link == null) + if (link == null) { + System.out.printf ("no link\n"); return true; - if (rom_config == null) - rom_config = debug.romconfig(); + } + if (rom_config == null) { + AltosHexfile hexfile = get_rom(); + if (hexfile != null) + rom_config = new AltosRomconfig(hexfile); + } return rom_config != null && rom_config.valid(); } @@ -127,23 +178,19 @@ public class AltosSelfFlash { } public AltosRomconfig romconfig() { + System.out.printf("fetch romconfig\n"); if (!check_rom_config()) return null; return rom_config; } - public AltosFlash(File file, AltosLink link, AltosFlashListener listener) + public AltosSelfFlash(File file, AltosLink link, AltosFlashListener listener) throws IOException, FileNotFoundException, InterruptedException { this.file = file; this.link = link; this.listener = listener; - this.read_block = new byte[256]; - this.write_block = new byte[256]; input = new FileInputStream(file); image = new AltosHexfile(input); - if (link != null) { - debug.close(); - throw new IOException("Debug port not connected"); - } + System.out.printf ("AltosSelfFlash %x\n", image.address); } } \ No newline at end of file diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index 919d098f..2c26220b 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -76,6 +76,7 @@ altoslib_JAVA = \ AltosProgrammer.java \ AltosReplayReader.java \ AltosRomconfig.java \ + AltosSelfFlash.java \ AltosSensorMM.java \ AltosSensorEMini.java \ AltosSensorTM.java \ diff --git a/altosui/AltosFlashUI.java b/altosui/AltosFlashUI.java index 6eccface..7e4cddb1 100644 --- a/altosui/AltosFlashUI.java +++ b/altosui/AltosFlashUI.java @@ -45,18 +45,42 @@ public class AltosFlashUI File file; // Debug connection - AltosDevice debug_dongle; + AltosDevice device; + + AltosLink link; // Desired Rom configuration AltosRomconfig rom_config; // Flash controller - AltosFlash flash; + AltosProgrammer programmer; + + private static String[] pair_programmed = { + "teleballoon", + "telebt", + "teledongle", + "telefire", + "telemetrum-v0", + "telemetrum-v1", + "telemini", + "telenano", + "teleshield", + "teleterra" + }; + + private boolean is_pair_programmed() { + String name = file.getName(); + for (int i = 0; i < pair_programmed.length; i++) { + if (name.startsWith(pair_programmed[i])) + return true; + } + return false; + } public void actionPerformed(ActionEvent e) { if (e.getSource() == cancel) { - if (flash != null) - flash.abort(); + if (programmer != null) + programmer.abort(); setVisible(false); dispose(); } else { @@ -156,6 +180,33 @@ public class AltosFlashUI serial_value.setText(String.format("%d", serial_number)); } + static class AltosHexfileFilter extends javax.swing.filechooser.FileFilter { + int product; + String head; + String description; + + public AltosHexfileFilter(int product, String head, String description) { + this.product = product; + this.head = head; + this.description = description; + } + + public boolean accept(File file) { + return file.getName().startsWith(head) && file.getName().endsWith(".ihx"); + } + + public String getDescription() { + return description; + } + } + + static AltosHexfileFilter[] filters = { + new AltosHexfileFilter(AltosLib.product_telemetrum, "telemetrum", "TeleMetrum Image"), + new AltosHexfileFilter(AltosLib.product_teledongle, "teledongle", "TeleDongle Image"), + new AltosHexfileFilter(AltosLib.product_telemega, "telemega", "TeleMega Image"), + new AltosHexfileFilter(AltosLib.product_easymini, "easymini", "EasyMini Image"), + }; + boolean select_source_file() { JFileChooser hexfile_chooser = new JFileChooser(); @@ -164,7 +215,24 @@ public class AltosFlashUI hexfile_chooser.setCurrentDirectory(firmwaredir); hexfile_chooser.setDialogTitle("Select Flash Image"); - hexfile_chooser.setFileFilter(new FileNameExtensionFilter("Flash Image", "ihx")); + + for (int i = 0; i < filters.length; i++) { + hexfile_chooser.addChoosableFileFilter(filters[i]); + } + javax.swing.filechooser.FileFilter ihx_filter = new FileNameExtensionFilter("Flash Image", "ihx"); + hexfile_chooser.addChoosableFileFilter(ihx_filter); + hexfile_chooser.setFileFilter(ihx_filter); + + if (!device.matchProduct(AltosLib.product_altusmetrum)) { + for (int i = 0; i < filters.length; i++) { + System.out.printf ("device %s filter %d\n", device, filters[i].product); + if (device != null && device.matchProduct(filters[i].product)) { + System.out.printf ("select filter %s\n", filters[i].head); + hexfile_chooser.setFileFilter(filters[i]); + } + } + } + int returnVal = hexfile_chooser.showOpenDialog(frame); if (returnVal != JFileChooser.APPROVE_OPTION) @@ -173,13 +241,16 @@ public class AltosFlashUI if (file == null) return false; AltosUIPreferences.set_firmwaredir(file.getParentFile()); + return true; } - boolean select_debug_dongle() { - debug_dongle = AltosDeviceUIDialog.show(frame, Altos.product_any); + boolean select_device() { + int product = Altos.product_any; - if (debug_dongle == null) + device = AltosDeviceUIDialog.show(frame, Altos.product_any); + + if (device == null) return false; return true; } @@ -204,7 +275,7 @@ public class AltosFlashUI } else if (e instanceof AltosSerialInUseException) { JOptionPane.showMessageDialog(frame, String.format("Device \"%s\" already in use", - debug_dongle.toShortString()), + device.toShortString()), "Device in use", JOptionPane.ERROR_MESSAGE); } else if (e instanceof IOException) { @@ -218,7 +289,7 @@ public class AltosFlashUI class flash_task implements Runnable, AltosFlashListener { AltosFlashUI ui; Thread t; - AltosFlash flash; + AltosProgrammer programmer; public void position(String in_s, int in_percent) { final String s = in_s; @@ -238,14 +309,17 @@ public class AltosFlashUI public void run () { try { - flash = new AltosFlash(ui.file, new AltosSerial(ui.debug_dongle), this); + if (ui.is_pair_programmed()) + programmer = new AltosFlash(ui.file, link, this); + else + programmer = new AltosSelfFlash(ui.file, link, this); - final AltosRomconfig current_config = flash.romconfig(); + final AltosRomconfig current_config = programmer.romconfig(); final Semaphore await_rom_config = new Semaphore(0); SwingUtilities.invokeLater(new Runnable() { public void run() { - ui.flash = flash; + ui.programmer = programmer; ui.update_rom_config_info(current_config); await_rom_config.release(); } @@ -253,8 +327,8 @@ public class AltosFlashUI await_rom_config.acquire(); if (ui.rom_config != null) { - flash.set_romconfig(ui.rom_config); - flash.flash(); + programmer.set_romconfig(ui.rom_config); + programmer.flash(); } } catch (InterruptedException ee) { final Exception e = ee; @@ -270,16 +344,9 @@ public class AltosFlashUI ui.exception(e); } }); - } catch (AltosSerialInUseException ee) { - final Exception e = ee; - SwingUtilities.invokeLater(new Runnable() { - public void run() { - ui.exception(e); - } - }); } finally { - if (flash != null) - flash.close(); + if (programmer != null) + programmer.close(); } } @@ -292,16 +359,51 @@ public class AltosFlashUI flash_task flasher; + private boolean open_device() { + try { + link = new AltosSerial(device); + if (is_pair_programmed()) + return true; + + if (link == null) + throw new IOException(String.format("%s: open failed", device.toShortString())); + + while (!link.is_loader()) { + link.to_loader(); + + java.util.List devices = AltosUSBDevice.list(AltosLib.product_altusmetrum); + if (devices.size() == 1) + device = devices.get(0); + else { + device = AltosDeviceUIDialog.show(frame, AltosLib.product_altusmetrum); + if (device == null) + return false; + } + link = new AltosSerial(device); + } + return true; + } catch (AltosSerialInUseException ee) { + exception(ee); + } catch (FileNotFoundException fe) { + exception(fe); + } catch (IOException ie) { + exception (ie); + } + return false; + } + /* * Execute the steps for flashing * a device. Note that this returns immediately; * this dialog is not modal */ void showDialog() { - if (!select_debug_dongle()) + if (!select_device()) return; if (!select_source_file()) return; + if (!open_device()) + return; build_dialog(); flash_task f = new flash_task(this); }