Bump java library versions
[fw/altos] / altoslib / AltosDebug.java
1 /*
2  * Copyright © 2010 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_11;
19
20 import java.io.*;
21
22 public class AltosDebug {
23
24         public static final byte WR_CONFIG =            0x1d;
25         public static final byte RD_CONFIG =            0x24;
26         public static final byte CONFIG_TIMERS_OFF =            (1 << 3);
27         public static final byte CONFIG_DMA_PAUSE =             (1 << 2);
28         public static final byte CONFIG_TIMER_SUSPEND =         (1 << 1);
29         public static final byte SET_FLASH_INFO_PAGE =          (1 << 0);
30
31         public static final byte GET_PC =               0x28;
32         public static final byte READ_STATUS =          0x34;
33         public static final byte STATUS_CHIP_ERASE_DONE =       (byte) (1 << 7);
34         public static final byte STATUS_PCON_IDLE =             (1 << 6);
35         public static final byte STATUS_CPU_HALTED =            (1 << 5);
36         public static final byte STATUS_POWER_MODE_0 =          (1 << 4);
37         public static final byte STATUS_HALT_STATUS =           (1 << 3);
38         public static final byte STATUS_DEBUG_LOCKED =          (1 << 2);
39         public static final byte STATUS_OSCILLATOR_STABLE =     (1 << 1);
40         public static final byte STATUS_STACK_OVERFLOW =        (1 << 0);
41
42         public static final byte SET_HW_BRKPNT =        0x3b;
43         public static byte       HW_BRKPNT_N(byte n)    { return (byte) ((n) << 3); }
44         public static final byte HW_BRKPNT_N_MASK =             (0x3 << 3);
45         public static final byte HW_BRKPNT_ENABLE =             (1 << 2);
46
47         public static final byte HALT =                 0x44;
48         public static final byte RESUME =               0x4c;
49         public static       byte DEBUG_INSTR(byte n)    { return (byte) (0x54|(n)); }
50         public static final byte STEP_INSTR =           0x5c;
51         public static        byte STEP_REPLACE(byte n)  { return  (byte) (0x64|(n)); }
52         public static final byte GET_CHIP_ID =          0x68;
53
54
55         private AltosLink       link;
56
57         boolean debug_mode;
58
59         void ensure_debug_mode() throws InterruptedException {
60                 if (!debug_mode) {
61                         link.printf("D\n");
62                         link.flush_input();
63                         debug_mode = true;
64                 }
65         }
66
67         void dump_memory(String header, int address, byte[] bytes, int start, int len) {
68                 System.out.printf("%s\n", header);
69                 for (int j = 0; j < len; j++) {
70                         if ((j & 15) == 0) {
71                                 if (j != 0)
72                                         System.out.printf("\n");
73                                 System.out.printf ("%04x:", address + j);
74                         }
75                         System.out.printf(" %02x", bytes[start + j]);
76                 }
77                 System.out.printf("\n");
78         }
79
80         public void close() {
81                 try {
82                         link.close();
83                 } catch (InterruptedException ie) {
84                 }
85         }
86
87         /*
88          * Write target memory
89          */
90         public void write_memory(int address, byte[] bytes, int start, int len) throws InterruptedException {
91                 ensure_debug_mode();
92 //              dump_memory("write_memory", address, bytes, start, len);
93                 link.printf("O %x %x\n", len, address);
94                 for (int i = 0; i < len; i++)
95                         link.printf("%02x", bytes[start + i]);
96         }
97
98         public void write_memory(int address, byte[] bytes) throws InterruptedException {
99                 write_memory(address, bytes, 0, bytes.length);
100         }
101
102         /*
103          * Read target memory
104          */
105         public byte[] read_memory(int address, int length)
106                 throws IOException, InterruptedException {
107                 byte[]  data = new byte[length];
108
109                 link.flush_input();
110                 ensure_debug_mode();
111                 link.printf("I %x %x\n", length, address);
112                 int i = 0;
113                 int start = 0;
114                 while (i < length) {
115                         String  line = link.get_reply();
116                         if (line == null)
117                                 throw new IOException("No reply");
118
119                         line = line.trim();
120                         if (!AltosLib.ishex(line) || line.length() % 2 != 0)
121                                 throw new IOException(
122                                         String.format
123                                         ("Invalid reply \"%s\"", line));
124                         int this_time = line.length() / 2;
125                         for (int j = 0; j < this_time; j++)
126                                 data[start + j] = (byte) ((AltosLib.fromhex(line.charAt(j*2)) << 4) +
127                                                   AltosLib.fromhex(line.charAt(j*2+1)));
128                         start += this_time;
129                         i += this_time;
130                 }
131 //              dump_memory("read_memory", address, data, 0, length);
132
133                 return data;
134         }
135
136         /*
137          * Write raw bytes to the debug link using the 'P' command
138          */
139         public void write_bytes(byte[] bytes) throws IOException, InterruptedException {
140                 int i = 0;
141                 ensure_debug_mode();
142                 while (i < bytes.length) {
143                         int this_time = bytes.length - i;
144                         if (this_time > 8)
145                                 this_time = 0;
146                         link.printf("P");
147                         for (int j = 0; j < this_time; j++)
148                                 link.printf(" %02x", bytes[i+j]);
149                         link.printf("\n");
150                         i += this_time;
151                 }
152         }
153
154         public void write_byte(byte b) throws IOException, InterruptedException {
155                 byte[] bytes = { b };
156                 write_bytes(bytes);
157         }
158
159         /*
160          * Read raw bytes from the debug link using the 'G' command
161          */
162         public byte[] read_bytes(int length)
163                 throws IOException, InterruptedException {
164
165                 link.flush_input();
166                 ensure_debug_mode();
167                 link.printf("G %x\n", length);
168                 int i = 0;
169                 byte[] data = new byte[length];
170                 while (i < length) {
171                         String line = link.get_reply();
172
173                         if (line == null)
174                                 throw new IOException("Timeout in read_bytes");
175                         line = line.trim();
176                         String tokens[] = line.split("\\s+");
177                         for (int j = 0; j < tokens.length; j++) {
178                                 if (!AltosLib.ishex(tokens[j]) ||
179                                     tokens[j].length() != 2)
180                                         throw new IOException(
181                                                 String.format
182                                                 ("Invalid read_bytes reply \"%s\"", line));
183                                 try {
184                                         if (i + j >= length)
185                                                 throw new IOException(
186                                                         String.format
187                                                         ("Invalid read_bytes reply \"%s\"", line));
188                                         else
189                                                 data[i + j] = (byte) Integer.parseInt(tokens[j], 16);
190                                 } catch (NumberFormatException ne) {
191                                         throw new IOException(
192                                                 String.format
193                                                 ("Invalid read_bytes reply \"%s\"", line));
194                                 }
195                         }
196                         i += tokens.length;
197                 }
198                 return data;
199         }
200
201         public byte read_byte() throws IOException, InterruptedException {
202                 return read_bytes(1)[0];
203         }
204
205         public byte debug_instr(byte[] instruction) throws IOException, InterruptedException {
206                 byte[] command = new byte[1 + instruction.length];
207                 command[0] = DEBUG_INSTR((byte) instruction.length);
208                 for (int i = 0; i < instruction.length; i++)
209                         command[i+1] = instruction[i];
210                 write_bytes(command);
211                 return read_byte();
212         }
213
214         public byte resume() throws IOException, InterruptedException {
215                 write_byte(RESUME);
216                 return read_byte();
217         }
218
219         public int read_uint16() throws IOException, InterruptedException {
220                 byte[] d = read_bytes(2);
221                 return ((int) (d[0] & 0xff) << 8) | (d[1] & 0xff);
222         }
223
224         public int read_uint8()  throws IOException, InterruptedException {
225                 byte[] d = read_bytes(1);
226                 return (int) (d[0] & 0xff);
227         }
228
229         public int get_chip_id() throws IOException, InterruptedException {
230                 write_byte(GET_CHIP_ID);
231                 return read_uint16();
232         }
233
234         public int get_pc() throws IOException, InterruptedException {
235                 write_byte(GET_PC);
236                 return read_uint16();
237         }
238
239         public byte read_status() throws IOException, InterruptedException {
240                 write_byte(READ_STATUS);
241                 return read_byte();
242         }
243
244         static final byte LJMP                  = 0x02;
245
246         public void set_pc(int pc) throws IOException, InterruptedException {
247                 byte high = (byte) (pc >> 8);
248                 byte low = (byte) pc;
249                 byte[] jump_mem = { LJMP, high, low };
250                 debug_instr(jump_mem);
251         }
252
253         public boolean check_connection() throws IOException, InterruptedException {
254                 byte reply = read_status();
255                 if ((reply & STATUS_CHIP_ERASE_DONE) == 0)
256                         return false;
257                 if ((reply & STATUS_PCON_IDLE) != 0)
258                         return false;
259                 if ((reply & STATUS_POWER_MODE_0) == 0)
260                         return false;
261                 return true;
262         }
263
264         public AltosRomconfig romconfig() throws InterruptedException {
265                 try {
266                         byte[] bytes = read_memory(0xa0, 10);
267                         AltosHexfile hexfile = new AltosHexfile (bytes, 0xa0);
268                         return new AltosRomconfig(hexfile);
269                 } catch (IOException ie) {
270                 }
271                 return new AltosRomconfig();
272         }
273
274         /*
275          * Reset target
276          */
277         public void reset() {
278                 link.printf ("R\n");
279         }
280
281         public AltosDebug (AltosLink link) {
282                 this.link = link;
283         }
284 }