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; either version 2 of the License, or
7 * (at your option) any later version.
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.
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.
23 ao_dbg_send_bits(uint8_t msk, uint8_t val) __reentrant
25 DBG_PORT = (DBG_PORT & ~msk) | (val & msk);
33 ao_dbg_send_byte(uint8_t byte)
38 DBG_PORT_DIR |= DBG_DATA;
39 for (b = 0; b < 8; b++) {
44 ao_dbg_send_bits(DBG_CLOCK|DBG_DATA, DBG_CLOCK|d);
45 ao_dbg_send_bits(DBG_CLOCK|DBG_DATA, 0 |d);
47 DBG_PORT_DIR &= ~DBG_DATA;
51 ao_dbg_recv_byte(void)
53 __pdata uint8_t byte, b;
56 for (b = 0; b < 8; b++) {
58 ao_dbg_send_bits(DBG_CLOCK, DBG_CLOCK);
61 ao_dbg_send_bits(DBG_CLOCK, 0);
69 #define MOV_direct_data 0x75
71 #define MOV_Rn_data(n) (0x78 | (n))
72 #define DJNZ_Rn_rel(n) (0xd8 | (n))
73 #define MOV_A_direct 0xe5
74 #define MOV_direct1_direct2 0x85
75 #define MOV_direct_A 0xf5
76 #define MOV_DPTR_data16 0x90
77 #define MOV_A_data 0x74
78 #define MOVX_atDPTR_A 0xf0
79 #define MOVX_A_atDPTR 0xe0
85 #define DEBUG_INSTR(l) (0x54 | (l))
93 __pdata uint8_t save_acc;
94 __pdata uint8_t save_psw;
95 __pdata uint8_t save_dpl0;
96 __pdata uint8_t save_dph0;
97 __pdata uint8_t save_dpl1;
98 __pdata uint8_t save_dph1;
101 ao_dbg_inst1(uint8_t a) __reentrant
103 ao_dbg_send_byte(DEBUG_INSTR(1));
105 return ao_dbg_recv_byte();
109 ao_dbg_inst2(uint8_t a, uint8_t b) __reentrant
111 ao_dbg_send_byte(DEBUG_INSTR(2));
114 return ao_dbg_recv_byte();
118 ao_dbg_inst3(uint8_t a, uint8_t b, uint8_t c) __reentrant
120 ao_dbg_send_byte(DEBUG_INSTR(3));
124 return ao_dbg_recv_byte();
128 ao_dbg_start_transfer(uint16_t addr)
130 save_acc = ao_dbg_inst1(NOP);
131 save_psw = ao_dbg_inst2(MOV_A_direct, SFR_PSW);
132 save_dpl0 = ao_dbg_inst2(MOV_A_direct, SFR_DPL0);
133 save_dph0 = ao_dbg_inst2(MOV_A_direct, SFR_DPH0);
134 save_dpl1 = ao_dbg_inst2(MOV_A_direct, SFR_DPL1);
135 save_dph1 = ao_dbg_inst2(MOV_A_direct, SFR_DPH1);
136 ao_dbg_inst3(MOV_DPTR_data16, addr >> 8, addr);
140 ao_dbg_end_transfer(void)
142 ao_dbg_inst3(MOV_direct_data, SFR_DPL0, save_dpl0);
143 ao_dbg_inst3(MOV_direct_data, SFR_DPH0, save_dph0);
144 ao_dbg_inst3(MOV_direct_data, SFR_DPL1, save_dpl1);
145 ao_dbg_inst3(MOV_direct_data, SFR_DPH1, save_dph1);
146 ao_dbg_inst3(MOV_direct_data, SFR_PSW, save_psw);
147 ao_dbg_inst2(MOV_A_data, save_acc);
151 ao_dbg_write_byte(uint8_t byte)
153 ao_dbg_inst2(MOV_A_data, byte);
154 ao_dbg_inst1(MOVX_atDPTR_A);
155 ao_dbg_inst1(INC_DPTR);
159 ao_dbg_read_byte(void)
161 ao_dbg_inst1(MOVX_A_atDPTR);
162 return ao_dbg_inst1(INC_DPTR);
166 ao_dbg_set_pins(void)
168 /* Make the DBG pins GPIOs. On TeleMetrum, this will
169 * disable the SPI link, so don't expect SPI to work after
170 * using the debugger.
172 DBG_PORT_SEL &= ~(DBG_CLOCK|DBG_DATA|DBG_RESET_N);
174 /* make DBG_DATA tri-state */
175 DBG_PORT_INP |= DBG_DATA;
177 /* Raise RESET_N and CLOCK */
178 DBG_PORT |= DBG_RESET_N | DBG_CLOCK;
180 /* RESET_N and CLOCK are outputs now */
181 DBG_PORT_DIR |= DBG_RESET_N | DBG_CLOCK;
182 DBG_PORT_DIR &= ~DBG_DATA;
186 ao_dbg_long_delay(void)
190 for (n = 0; n < 20; n++)
194 #define AO_RESET_LOW_DELAY AO_MS_TO_TICKS(100)
195 #define AO_RESET_HIGH_DELAY AO_MS_TO_TICKS(100)
198 ao_dbg_send_bits_delay(uint8_t msk, uint8_t val)
201 ao_dbg_send_bits(msk, val);
205 ao_dbg_do_reset(uint8_t clock_up)
208 ao_dbg_send_bits_delay(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N);
209 ao_dbg_send_bits_delay(DBG_CLOCK|DBG_DATA|DBG_RESET_N, clock_up |DBG_DATA| 0 );
210 ao_delay(AO_RESET_LOW_DELAY);
211 ao_dbg_send_bits (DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 );
212 ao_dbg_send_bits_delay(DBG_CLOCK|DBG_DATA|DBG_RESET_N, clock_up |DBG_DATA| 0 );
213 ao_dbg_send_bits_delay(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 );
214 ao_dbg_send_bits_delay(DBG_CLOCK|DBG_DATA|DBG_RESET_N, clock_up |DBG_DATA|DBG_RESET_N);
215 ao_delay(AO_RESET_HIGH_DELAY);
221 /* toggle clock line while holding reset low */
228 /* hold clock high while holding reset low */
229 ao_dbg_do_reset(DBG_CLOCK);
237 if (ao_cmd_lex_c == '\n')
240 if (ao_cmd_status != ao_cmd_success)
242 ao_dbg_send_byte(ao_cmd_lex_i);
249 __pdata uint16_t count;
251 __pdata uint8_t byte;
253 if (ao_cmd_status != ao_cmd_success)
255 count = ao_cmd_lex_i;
257 ao_cmd_status = ao_cmd_syntax_error;
260 for (i = 0; i < count; i++) {
261 if (i && (i & 7) == 0)
263 byte = ao_dbg_recv_byte();
273 __pdata uint16_t count;
274 __pdata uint16_t addr;
279 count = ao_cmd_lex_i;
282 if (ao_cmd_status != ao_cmd_success)
284 ao_dbg_start_transfer(addr);
289 b = ao_dbg_read_byte();
292 ao_dbg_end_transfer();
299 __pdata uint16_t count;
300 __pdata uint16_t addr;
304 count = ao_cmd_lex_i;
307 if (ao_cmd_status != ao_cmd_success)
309 ao_dbg_start_transfer(addr);
311 b = ao_getnibble() << 4;
313 if (ao_cmd_status != ao_cmd_success)
315 ao_dbg_write_byte(b);
317 ao_dbg_end_transfer();
320 __code struct ao_cmds ao_dbg_cmds[7] = {
321 { debug_enable, "D\0Enable debug" },
322 { debug_get, "G <count>\0Get data" },
323 { debug_input, "I <count> <addr>\0Input <count> at <addr>" },
324 { debug_output, "O <count> <addr>\0Output <count> at <addr>" },
325 { debug_put, "P <byte> ...\0Put data" },
326 { debug_reset, "R\0Reset" },
333 ao_cmd_register(&ao_dbg_cmds[0]);