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