altos: Rename telemega-v0.3 to telemega-v1.0
[fw/altos] / altoslib / AltosSelfFlash.java
1 /*
2  * Copyright © 2013 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 package org.altusmetrum.altoslib_2;
19
20 import java.io.*;
21
22 public class AltosSelfFlash extends AltosProgrammer {
23         File                    file;
24         FileInputStream         input;
25         AltosHexfile            image;
26         AltosLink               link;
27         boolean                 aborted;
28         AltosFlashListener      listener;
29         AltosRomconfig          rom_config;
30
31         void action(String s, int percent) {
32                 if (listener != null && !aborted)
33                         listener.position(s, percent);
34         }
35
36         void action(int part, int total) {
37                 int percent = 100 * part / total;
38                 action(String.format("%d/%d (%d%%)",
39                                      part, total, percent),
40                        percent);
41         }
42
43         byte[] read_memory(long addr, int len) throws InterruptedException, IOException {
44                 int b;
45                 byte[]  data = new byte[len];
46
47                 for (int offset = 0; offset < len; offset += 0x100) {
48                         link.printf("R %x\n", addr + offset);
49                         byte[]  reply = link.get_binary_reply(5000, 0x100);
50                         
51                         if (reply == null)
52                                 throw new IOException("Read device memory timeout");
53                         for (b = 0; b < len; b++)
54                                 data[b+offset] = reply[b];
55                 }
56                 return data;
57         }
58                 
59         void write_memory(long addr, byte[] data, int start, int len) {
60                 int b;
61                 System.out.printf ("write_memory %x %d\n", addr, len);
62                 link.printf("W %x\n", addr);
63                 link.flush_output();
64                 for (b = 0; b < len; b++)
65                         link.putchar(data[start + b]);
66                 for (; b < 0x100; b++)
67                         link.putchar((byte) 0xff);
68         }
69
70         void reboot() {
71                 System.out.printf("reboot\n");
72                 link.printf("a\n");
73                 link.flush_output();
74         }
75
76         public void flash() {
77                 try {
78                         if (!check_rom_config())
79                                 throw new IOException("Invalid rom config settings");
80
81                         /*
82                          * Store desired config values into image
83                          */
84                         rom_config.write(image);
85
86                         int remain = image.data.length;
87                         long flash_addr = image.address;
88                         int image_start = 0;
89
90                         action("start", 0);
91                         action(0, image.data.length);
92                         while (remain > 0 && !aborted) {
93                                 int this_time = remain;
94                                 if (this_time > 0x100)
95                                         this_time = 0x100;
96
97                                 if (link != null) {
98                                         /* write the data */
99                                         write_memory(flash_addr, image.data, image_start, this_time);
100
101                                         byte[] check = read_memory(flash_addr, this_time);
102                                         for (int i = 0; i < this_time; i++)
103                                                 if (check[i] != image.data[image_start + i])
104                                                         throw new IOException(String.format("Flash write failed at 0x%x (%02x != %02x)",
105                                                                                             image.address + image_start + i,
106                                                                                             check[i], image.data[image_start + i]));
107                                 } else {
108                                         Thread.sleep(100);
109                                 }
110
111                                 remain -= this_time;
112                                 flash_addr += this_time;
113                                 image_start += this_time;
114
115                                 action(image.data.length - remain, image.data.length);
116                         }
117                         if (!aborted) {
118                                 System.out.printf ("done\n");
119                                 action("done", 100);
120                         }
121                         close();
122                 } catch (IOException ie) {
123                         action(ie.getMessage(), -1);
124                         abort();
125                 } catch (InterruptedException ie) {
126                         abort();
127                 }
128         }
129
130         public void close() {
131                 if (link != null) {
132                         reboot();
133                         link.close();
134                         link = null;
135                 }
136         }
137
138         synchronized public void abort() {
139                 aborted = true;
140                 close();
141         }
142
143         private AltosHexfile get_rom() {
144                 System.out.printf("get rom\n");
145                 try {
146                         int base = AltosRomconfig.fetch_base(image);
147                         int bounds = AltosRomconfig.fetch_bounds(image);
148                         byte[] data = read_memory(base, bounds - base);
149                         AltosHexfile hexfile = new AltosHexfile(data, base);
150                         hexfile.add_symbols(image);
151                         return hexfile;
152                 } catch (AltosNoSymbol none) {
153                         System.out.printf("no symbol %s\n", none.getMessage());
154                         return null;
155                 } catch (InterruptedException ie) {
156                         return null;
157                 } catch (IOException ie) {
158                         return null;
159                 }
160
161         }
162
163         public boolean check_rom_config() {
164                 if (link == null) {
165                         System.out.printf ("no link\n");
166                         return true;
167                 }
168                 if (rom_config == null) {
169                         AltosHexfile hexfile = get_rom();
170                         if (hexfile != null)
171                                 rom_config = new AltosRomconfig(hexfile);
172                 }
173                 return rom_config != null && rom_config.valid();
174         }
175
176         public void set_romconfig (AltosRomconfig romconfig) {
177                 rom_config = romconfig;
178         }
179
180         public AltosRomconfig romconfig() {
181                 System.out.printf("fetch romconfig\n");
182                 if (!check_rom_config())
183                         return null;
184                 return rom_config;
185         }
186
187         public AltosSelfFlash(File file, AltosLink link, AltosFlashListener listener)
188                 throws IOException, FileNotFoundException, InterruptedException {
189                 this.file = file;
190                 this.link = link;
191                 this.listener = listener;
192                 input = new FileInputStream(file);
193                 image = new AltosHexfile(input);
194                 System.out.printf ("AltosSelfFlash %x\n", image.address);
195         }
196 }