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