altosui: Add debug dongle API, split flash UI out
[fw/altos] / ao-tools / 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.LinkedBlockingQueue;
23 import java.util.LinkedList;
24 import java.util.Iterator;
25 import altosui.AltosSerial;
26 import altosui.AltosRomconfig;
27
28 public class AltosDebug extends AltosSerial {
29
30         static final byte WR_CONFIG =           0x1d;
31         static final byte RD_CONFIG =           0x24;
32         static final byte CONFIG_TIMERS_OFF =           (1 << 3);
33         static final byte CONFIG_DMA_PAUSE =            (1 << 2);
34         static final byte CONFIG_TIMER_SUSPEND =                (1 << 1);
35         static final byte SET_FLASH_INFO_PAGE =         (1 << 0);
36
37         static final byte GET_PC        =               0x28;
38         static final byte READ_STATUS =         0x34;
39         static final byte STATUS_CHIP_ERASE_DONE =      (byte) (1 << 7);
40         static final byte STATUS_PCON_IDLE =            (1 << 6);
41         static final byte STATUS_CPU_HALTED =           (1 << 5);
42         static final byte STATUS_POWER_MODE_0 =         (1 << 4);
43         static final byte STATUS_HALT_STATUS =          (1 << 3);
44         static final byte STATUS_DEBUG_LOCKED =         (1 << 2);
45         static final byte STATUS_OSCILLATOR_STABLE =    (1 << 1);
46         static final byte STATUS_STACK_OVERFLOW =       (1 << 0);
47
48         static final byte SET_HW_BRKPNT =       0x3b;
49         static byte       HW_BRKPNT_N(byte n)   { return (byte) ((n) << 3); }
50         static final byte HW_BRKPNT_N_MASK =            (0x3 << 3);
51         static final byte HW_BRKPNT_ENABLE =            (1 << 2);
52
53         static final byte HALT =                        0x44;
54         static final byte RESUME        =               0x4c;
55         static       byte DEBUG_INSTR(byte n)   { return (byte) (0x54|(n)); }
56         static final byte STEP_INSTR =          0x5c;
57         static        byte STEP_REPLACE(byte n) { return  (byte) (0x64|(n)); }
58         static final byte GET_CHIP_ID =         0x68;
59
60
61         static boolean ishex(int c) {
62                 if ('0' <= c && c <= '9')
63                         return true;
64                 if ('a' <= c && c <= 'f')
65                         return true;
66                 if ('A' <= c && c <= 'F')
67                         return true;
68                 return false;
69         }
70
71         static boolean ishex(String s) {
72                 for (int i = 0; i < s.length(); i++)
73                         if (!ishex(s.charAt(i)))
74                                 return false;
75                 return true;
76         }
77         static boolean isspace(int c) {
78                 switch (c) {
79                 case ' ':
80                 case '\t':
81                         return true;
82                 }
83                 return false;
84         }
85
86         static int fromhex(int c) {
87                 if ('0' <= c && c <= '9')
88                         return c - '0';
89                 if ('a' <= c && c <= 'f')
90                         return c - 'a' + 10;
91                 if ('A' <= c && c <= 'F')
92                         return c - 'A' + 10;
93                 return -1;
94         }
95
96         boolean debug_mode;
97
98         void ensure_debug_mode() {
99                 if (!debug_mode) {
100                         printf("D\n");
101                         debug_mode = true;
102                 }
103         }
104
105         /*
106          * Write target memory
107          */
108         public void write_memory(int address, byte[] bytes) {
109                 ensure_debug_mode();
110                 printf("O %x %x\n", bytes.length, address);
111                 for (int i = 0; i < bytes.length; i++)
112                         printf("%02x", bytes[i]);
113         }
114
115         /*
116          * Read target memory
117          */
118         public byte[] read_memory(int address, int length)
119                 throws IOException, InterruptedException {
120                 byte[]  data = new byte[length];
121
122                 flush_reply();
123                 ensure_debug_mode();
124                 printf("I %x %x\n", length, address);
125                 int i = 0;
126                 while (i < length) {
127                         String  line = get_reply().trim();
128                         if (!ishex(line) || line.length() % 2 != 0)
129                                 throw new IOException(
130                                         String.format
131                                         ("Invalid reply \"%s\"", line));
132                         int this_time = line.length() / 2;
133                         for (int j = 0; j < this_time; j++)
134                                 data[j] = (byte) ((fromhex(line.charAt(j*2)) << 4) +
135                                                   fromhex(line.charAt(j*2+1)));
136                         i += this_time;
137                 }
138
139                 return data;
140         }
141
142         /*
143          * Write raw bytes to the debug link using the 'P' command
144          */
145         public void write_bytes(byte[] bytes) throws IOException {
146                 int i = 0;
147                 ensure_debug_mode();
148                 while (i < bytes.length) {
149                         int this_time = bytes.length - i;
150                         if (this_time > 8)
151                                 this_time = 0;
152                         printf("P");
153                         for (int j = 0; j < this_time; j++)
154                                 printf(" %02x", bytes[i+j]);
155                         printf("\n");
156                         i += this_time;
157                 }
158         }
159
160         public void write_byte(byte b) throws IOException {
161                 byte[] bytes = { b };
162                 write_bytes(bytes);
163         }
164
165         /*
166          * Read raw bytes from the debug link using the 'G' command
167          */
168         public byte[] read_bytes(int length)
169                 throws IOException, InterruptedException {
170
171                 flush_reply();
172                 ensure_debug_mode();
173                 printf("G %x\n", length);
174                 int i = 0;
175                 byte[] data = new byte[length];
176                 while (i < length) {
177                         String line = get_reply().trim();
178                         String tokens[] = line.split("\\s+");
179                         for (int j = 0; j < tokens.length; j++) {
180                                 if (!ishex(tokens[j]) ||
181                                     tokens[j].length() != 2)
182                                         throw new IOException(
183                                                 String.format
184                                                 ("Invalid read_bytes reply \"%s\"", line));
185                                 try {
186                                         data[i + j] = (byte) Integer.parseInt(tokens[j], 16);
187                                 } catch (NumberFormatException ne) {
188                                         throw new IOException(
189                                                 String.format
190                                                 ("Invalid read_bytes reply \"%s\"", line));
191                                 }
192                         }
193                         i += tokens.length;
194                 }
195                 return data;
196         }
197
198         public byte read_status() throws IOException, InterruptedException {
199                 write_byte(READ_STATUS);
200                 return read_bytes(2)[0];
201         }
202
203         public boolean check_connection() throws IOException, InterruptedException {
204                 byte reply = read_status();
205                 System.out.printf("status %x\n", reply);
206                 if ((reply & STATUS_CHIP_ERASE_DONE) == 0)
207                         return false;
208                 if ((reply & STATUS_PCON_IDLE) != 0)
209                         return false;
210                 if ((reply & STATUS_POWER_MODE_0) == 0)
211                         return false;
212                 return true;
213         }
214
215         public AltosRomconfig romconfig() {
216                 try {
217                         byte[] bytes = read_memory(0xa0, 10);
218                         return new AltosRomconfig(bytes, 0);
219                 } catch (IOException ie) {
220                 } catch (InterruptedException ie) {
221                 }
222                 return new AltosRomconfig();
223         }
224
225         /*
226          * Reset target
227          */
228         public void reset() {
229                 printf ("R\n");
230         }
231 }