2 * Copyright © 2009 Keith Packard <keithp@keithp.com>
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.
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.
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.
22 ao_dbg_send_bits(uint8_t msk, uint8_t val) __reentrant
24 DBG_PORT = (DBG_PORT & ~msk) | (val & msk);
32 ao_dbg_send_byte(uint8_t byte)
37 DBG_PORT_DIR |= DBG_DATA;
38 for (b = 0; b < 8; b++) {
43 ao_dbg_send_bits(DBG_CLOCK|DBG_DATA, DBG_CLOCK|d);
44 ao_dbg_send_bits(DBG_CLOCK|DBG_DATA, 0 |d);
46 DBG_PORT_DIR &= ~DBG_DATA;
50 ao_dbg_recv_byte(void)
52 __xdata uint8_t byte, b;
55 for (b = 0; b < 8; b++) {
57 ao_dbg_send_bits(DBG_CLOCK, DBG_CLOCK);
60 ao_dbg_send_bits(DBG_CLOCK, 0);
68 #define MOV_direct_data 0x75
70 #define MOV_Rn_data(n) (0x78 | (n))
71 #define DJNZ_Rn_rel(n) (0xd8 | (n))
72 #define MOV_A_direct 0xe5
73 #define MOV_direct1_direct2 0x85
74 #define MOV_direct_A 0xf5
75 #define MOV_DPTR_data16 0x90
76 #define MOV_A_data 0x74
77 #define MOVX_atDPTR_A 0xf0
78 #define MOVX_A_atDPTR 0xe0
84 #define DEBUG_INSTR(l) (0x54 | (l))
92 __xdata uint8_t save_acc;
93 __xdata uint8_t save_psw;
94 __xdata uint8_t save_dpl0;
95 __xdata uint8_t save_dph0;
96 __xdata uint8_t save_dpl1;
97 __xdata uint8_t save_dph1;
100 ao_dbg_inst1(uint8_t a) __reentrant
102 ao_dbg_send_byte(DEBUG_INSTR(1));
104 return ao_dbg_recv_byte();
108 ao_dbg_inst2(uint8_t a, uint8_t b) __reentrant
110 ao_dbg_send_byte(DEBUG_INSTR(2));
113 return ao_dbg_recv_byte();
117 ao_dbg_inst3(uint8_t a, uint8_t b, uint8_t c) __reentrant
119 ao_dbg_send_byte(DEBUG_INSTR(3));
123 return ao_dbg_recv_byte();
127 ao_dbg_start_transfer(uint16_t addr)
129 save_acc = ao_dbg_inst1(NOP);
130 save_psw = ao_dbg_inst2(MOV_A_direct, SFR_PSW);
131 save_dpl0 = ao_dbg_inst2(MOV_A_direct, SFR_DPL0);
132 save_dph0 = ao_dbg_inst2(MOV_A_direct, SFR_DPH0);
133 save_dpl1 = ao_dbg_inst2(MOV_A_direct, SFR_DPL1);
134 save_dph1 = ao_dbg_inst2(MOV_A_direct, SFR_DPH1);
135 ao_dbg_inst3(MOV_DPTR_data16, addr >> 8, addr);
139 ao_dbg_end_transfer(void)
141 ao_dbg_inst3(MOV_direct_data, SFR_DPL0, save_dpl0);
142 ao_dbg_inst3(MOV_direct_data, SFR_DPH0, save_dph0);
143 ao_dbg_inst3(MOV_direct_data, SFR_DPL1, save_dpl1);
144 ao_dbg_inst3(MOV_direct_data, SFR_DPH1, save_dph1);
145 ao_dbg_inst3(MOV_direct_data, SFR_PSW, save_psw);
146 ao_dbg_inst2(MOV_A_data, save_acc);
150 ao_dbg_write_byte(uint8_t byte)
152 ao_dbg_inst2(MOV_A_data, byte);
153 ao_dbg_inst1(MOVX_atDPTR_A);
154 ao_dbg_inst1(INC_DPTR);
158 ao_dbg_read_byte(void)
160 ao_dbg_inst1(MOVX_A_atDPTR);
161 return ao_dbg_inst1(INC_DPTR);
165 ao_dbg_set_pins(void)
167 /* Make the DBG pins GPIOs. On TeleMetrum, this will
168 * disable the SPI link, so don't expect SPI to work after
169 * using the debugger.
171 DBG_PORT_SEL &= ~(DBG_CLOCK|DBG_DATA|DBG_RESET_N);
173 /* make DBG_DATA tri-state */
174 DBG_PORT_INP |= DBG_DATA;
176 /* Raise RESET_N and CLOCK */
177 DBG_PORT |= DBG_RESET_N | DBG_CLOCK;
179 /* RESET_N and CLOCK are outputs now */
180 DBG_PORT_DIR |= DBG_RESET_N | DBG_CLOCK;
181 DBG_PORT_DIR &= ~DBG_DATA;
185 ao_dbg_long_delay(void)
189 for (n = 0; n < 20; n++)
193 #define AO_RESET_LOW_DELAY AO_MS_TO_TICKS(100)
194 #define AO_RESET_HIGH_DELAY AO_MS_TO_TICKS(100)
197 ao_dbg_debug_mode(void)
201 ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N);
203 ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 );
204 ao_delay(AO_RESET_LOW_DELAY);
205 ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 );
207 ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 );
209 ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 );
211 ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA|DBG_RESET_N);
212 ao_delay(AO_RESET_HIGH_DELAY);
220 ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N);
222 ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 );
223 ao_delay(AO_RESET_LOW_DELAY);
224 ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 );
226 ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 );
228 ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 );
230 ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N);
231 ao_delay(AO_RESET_HIGH_DELAY);
251 if (ao_cmd_lex_c == '\n')
254 if (ao_cmd_status != ao_cmd_success)
256 ao_dbg_send_byte(ao_cmd_lex_i);
263 __xdata uint16_t count;
265 __xdata uint8_t byte;
267 if (ao_cmd_status != ao_cmd_success)
269 count = ao_cmd_lex_i;
271 ao_cmd_status = ao_cmd_syntax_error;
274 for (i = 0; i < count; i++) {
275 if (i && (i & 7) == 0)
277 byte = ao_dbg_recv_byte();
290 if ('0' <= c && c <= '9')
292 if ('a' <= c && c <= 'f')
293 return c - ('a' - 10);
294 if ('A' <= c && c <= 'F')
295 return c - ('A' - 10);
296 ao_cmd_status = ao_cmd_lex_error;
303 __xdata uint16_t count;
304 __xdata uint16_t addr;
309 count = ao_cmd_lex_i;
312 if (ao_cmd_status != ao_cmd_success)
314 ao_dbg_start_transfer(addr);
319 b = ao_dbg_read_byte();
322 ao_dbg_end_transfer();
329 __xdata uint16_t count;
330 __xdata uint16_t addr;
334 count = ao_cmd_lex_i;
337 if (ao_cmd_status != ao_cmd_success)
339 ao_dbg_start_transfer(addr);
341 b = getnibble() << 4;
343 if (ao_cmd_status != ao_cmd_success)
345 ao_dbg_write_byte(b);
347 ao_dbg_end_transfer();
350 __code struct ao_cmds ao_dbg_cmds[7] = {
351 { 'D', debug_enable, "D Enable debug mode" },
352 { 'G', debug_get, "G <count> Get data from debug port" },
353 { 'I', debug_input, "I <count> <addr> Input <count> bytes to target at <addr>" },
354 { 'O', debug_output, "O <count> <addr> Output <count> bytes to target at <addr>" },
355 { 'P', debug_put, "P <byte> ... Put data to debug port" },
356 { 'R', debug_reset, "R Reset target" },
357 { 0, debug_reset, 0 },
363 ao_cmd_register(&ao_dbg_cmds[0]);