From 9025eb792861930e6af918d2727c4f5d97a69936 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 19 Dec 2008 21:11:45 -0800 Subject: Autotools. Signed-off-by: Keith Packard --- lib/ccdbg-debug.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 lib/ccdbg-debug.c (limited to 'lib/ccdbg-debug.c') diff --git a/lib/ccdbg-debug.c b/lib/ccdbg-debug.c new file mode 100644 index 00000000..2e67bc8d --- /dev/null +++ b/lib/ccdbg-debug.c @@ -0,0 +1,47 @@ +/* + * Copyright © 2008 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ccdbg.h" +#include + +int +ccdbg_level = 0; + +void +ccdbg_add_debug(int level) +{ + ccdbg_level |= level; +} + +void +ccdbg_clear_debug(int level) +{ + ccdbg_level &= ~level; +} + +void +ccdbg_debug(int level, char *format, ...) +{ + va_list ap; + + if (ccdbg_level & level) { + va_start(ap, format); + vprintf(format, ap); + va_end(ap); + } +} -- cgit v1.2.3 From 55eba4fa08b022197106245d36a70f575a070b0a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Dec 2008 19:10:27 -0800 Subject: Make read_memory debug output use ccdbg_debug. This makes it default to not being presented, which makes s51 much happier Signed-off-by: Keith Packard --- lib/ccdbg-debug.c | 6 ++++++ lib/ccdbg-io.c | 1 + lib/ccdbg-memory.c | 28 ++++++++++++++++++++++------ lib/ccdbg.h | 4 ++++ 4 files changed, 33 insertions(+), 6 deletions(-) (limited to 'lib/ccdbg-debug.c') diff --git a/lib/ccdbg-debug.c b/lib/ccdbg-debug.c index 2e67bc8d..8f6f9e11 100644 --- a/lib/ccdbg-debug.c +++ b/lib/ccdbg-debug.c @@ -45,3 +45,9 @@ ccdbg_debug(int level, char *format, ...) va_end(ap); } } + +void +ccdbg_flush(void) +{ + fflush(stdout); +} diff --git a/lib/ccdbg-io.c b/lib/ccdbg-io.c index 6999dbec..5ecea769 100644 --- a/lib/ccdbg-io.c +++ b/lib/ccdbg-io.c @@ -129,6 +129,7 @@ ccdbg_recv_bit(struct ccdbg *dbg, int first) ccdbg_send(dbg, CC_CLOCK|mask|CC_RESET_N, CC_CLOCK|CC_DATA|CC_RESET_N); read = ccdbg_read(dbg); + ccdbg_print("#\t%c %c %c\n", CC_DATA, read); ccdbg_send(dbg, CC_CLOCK| CC_RESET_N, CC_RESET_N); return (read & CC_DATA) ? 1 : 0; } diff --git a/lib/ccdbg-memory.c b/lib/ccdbg-memory.c index 105295db..3406a1b1 100644 --- a/lib/ccdbg-memory.c +++ b/lib/ccdbg-memory.c @@ -54,10 +54,18 @@ ccdbg_write_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes) for (i = 0; i < nbytes; i++) { write8[DATA_BYTE] = *bytes++; ccdbg_execute(dbg, write8); - if ((i & 0xf) == 0xf) { printf ("."); fflush(stdout); nl = 1; } - if ((i & 0xff) == 0xff) { printf ("\n"); nl = 0; } + if ((i & 0xf) == 0xf) { + ccdbg_debug(CC_DEBUG_MEMORY, "."); + ccdbg_flush(); + nl = 1; + } + if ((i & 0xff) == 0xff) { + ccdbg_debug(CC_DEBUG_MEMORY, "\n"); + nl = 0; + } } - if (nl) printf ("\n"); + if (nl) + ccdbg_debug(CC_DEBUG_MEMORY, "\n"); return 0; } @@ -70,10 +78,18 @@ ccdbg_read_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes) (void) ccdbg_execute(dbg, memory_init); for (i = 0; i < nbytes; i++) { *bytes++ = ccdbg_execute(dbg, read8); - if ((i & 0xf) == 0xf) { printf ("."); fflush(stdout); nl = 1; } - if ((i & 0xff) == 0xff) { printf ("\n"); nl = 0; } + if ((i & 0xf) == 0xf) { + ccdbg_debug(CC_DEBUG_MEMORY, "."); + ccdbg_flush(); + nl = 1; + } + if ((i & 0xff) == 0xff) { + ccdbg_debug(CC_DEBUG_MEMORY, "\n"); + nl = 0; + } } - if (nl) printf ("\n"); + if (nl) + ccdbg_debug(CC_DEBUG_MEMORY, "\n"); return 0; } diff --git a/lib/ccdbg.h b/lib/ccdbg.h index 4d4a648d..e0e58104 100644 --- a/lib/ccdbg.h +++ b/lib/ccdbg.h @@ -160,6 +160,7 @@ struct hex_image { #define CC_DEBUG_INSTRUCTIONS 0x00000004 #define CC_DEBUG_EXECUTE 0x00000008 #define CC_DEBUG_FLASH 0x00000010 +#define CC_DEBUG_MEMORY 0x00000020 /* ccdbg-command.c */ void @@ -223,6 +224,9 @@ ccdbg_add_debug(int level); void ccdbg_clear_debug(int level); +void +ccdbg_flush(void); + /* ccdbg-flash.c */ uint8_t ccdbg_flash_hex_image(struct ccdbg *dbg, struct hex_image *image); -- cgit v1.2.3 From 6c2a65c743a4ffae96ed27dbc38c1bf9242ed1df Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 30 Dec 2008 22:35:53 -0800 Subject: Save/restore registers to host during memory operations. Cache ROM data. Because the debug port uses instructions for most operations, the debug code will clobber registers used by the running program. Save and restore these to avoid corrupting application data. If the ROM file is known, use that to return data instead of fetching it from the target to improve performance. Signed-off-by: Keith Packard --- lib/Makefile.am | 2 + lib/ccdbg-debug.c | 5 ++- lib/ccdbg-debug.h | 2 +- lib/ccdbg-flash.c | 8 +++- lib/ccdbg-memory.c | 54 +++++++++------------- lib/ccdbg-rom.c | 63 ++++++++++++++++++++++++++ lib/ccdbg-state.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/ccdbg.h | 43 ++++++++++++++++++ s51/s51-command.c | 74 ++++++++++++++++++++++++++++--- s51/s51-parse.c | 71 +++++++++++++++-------------- s51/s51.h | 23 ++++++++++ 11 files changed, 396 insertions(+), 77 deletions(-) create mode 100644 lib/ccdbg-rom.c create mode 100644 lib/ccdbg-state.c (limited to 'lib/ccdbg-debug.c') diff --git a/lib/Makefile.am b/lib/Makefile.am index 16f5b921..ba6f9725 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -11,5 +11,7 @@ libcc_a_SOURCES = \ ccdbg-io.c \ ccdbg-manual.c \ ccdbg-memory.c \ + ccdbg-rom.c \ + ccdbg-state.c \ cp-usb.c \ cp-usb-async.c diff --git a/lib/ccdbg-debug.c b/lib/ccdbg-debug.c index 8f6f9e11..847361c7 100644 --- a/lib/ccdbg-debug.c +++ b/lib/ccdbg-debug.c @@ -47,7 +47,8 @@ ccdbg_debug(int level, char *format, ...) } void -ccdbg_flush(void) +ccdbg_flush(int level) { - fflush(stdout); + if (ccdbg_level & level) + fflush(stdout); } diff --git a/lib/ccdbg-debug.h b/lib/ccdbg-debug.h index a09148d3..0b5b44c1 100644 --- a/lib/ccdbg-debug.h +++ b/lib/ccdbg-debug.h @@ -39,6 +39,6 @@ void ccdbg_clear_debug(int level); void -ccdbg_flush(void); +ccdbg_flush(int level); #endif /* _CCDBG_DEBUG_H_ */ diff --git a/lib/ccdbg-flash.c b/lib/ccdbg-flash.c index 8b3390c7..8a586a21 100644 --- a/lib/ccdbg-flash.c +++ b/lib/ccdbg-flash.c @@ -288,13 +288,14 @@ ccdbg_flash_hex_image(struct ccdbg *dbg, struct hex_image *image) ccdbg_debug(CC_DEBUG_FLASH, "Upload %d bytes at 0x%04x\n", this_time, ram_addr); ccdbg_write_memory(dbg, ram_addr, image->data + start, this_time); - +#if 0 ccdbg_debug(CC_DEBUG_FLASH, "Verify %d bytes in ram\n", this_time); ccdbg_read_memory(dbg, ram_addr, verify, this_time); if (memcmp (image->data + start, verify, this_time) != 0) { fprintf(stderr, "ram verify failed\n"); return 1; } +#endif flash_addr = image->address + start; flash_word_addr = flash_addr >> 1; @@ -324,10 +325,13 @@ ccdbg_flash_hex_image(struct ccdbg *dbg, struct hex_image *image) status = ccdbg_resume(dbg); for (times = 0; times < 10; times++) { status = ccdbg_read_status(dbg); - ccdbg_debug(CC_DEBUG_FLASH, "chip status is 0x%02x\n", status); + ccdbg_debug(CC_DEBUG_FLASH, "."); + ccdbg_flush(CC_DEBUG_FLASH); if ((status & CC_STATUS_CPU_HALTED) != 0) break; + usleep(10000); } + ccdbg_debug(CC_DEBUG_FLASH, "\n"); if (times == 10) { fprintf(stderr, "flash page timed out\n"); return 1; diff --git a/lib/ccdbg-memory.c b/lib/ccdbg-memory.c index d74726fb..20a24799 100644 --- a/lib/ccdbg-memory.c +++ b/lib/ccdbg-memory.c @@ -23,14 +23,9 @@ */ static uint8_t memory_init[] = { - 2, MOV_direct_A, 0x7f, - 3, MOV_direct1_direct2, 0x7e, SFR_DPL0, - 3, MOV_direct1_direct2, 0x7d, SFR_DPH0, - 3, MOV_direct1_direct2, 0x7c, SFR_DPL1, - 3, MOV_direct1_direct2, 0x7b, SFR_DPH1, 3, MOV_DPTR_data16, 0, 0, -#define HIGH_START 21 -#define LOW_START 22 +#define HIGH_START 2 +#define LOW_START 3 0, }; @@ -49,19 +44,13 @@ static uint8_t read8[] = { 0, }; -static uint8_t memory_fini[] = { - 2, MOV_A_direct, 0x7f, - 3, MOV_direct1_direct2, SFR_DPL0, 0x7e, - 3, MOV_direct1_direct2, SFR_DPH0, 0x7d, - 3, MOV_direct1_direct2, SFR_DPL1, 0x7c, - 3, MOV_direct1_direct2, SFR_DPH1, 0x7b, - 0, -}; - uint8_t ccdbg_write_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes) { int i, nl = 0; + struct ccstate state; + + ccdbg_state_save(dbg, &state, CC_STATE_ACC | CC_STATE_PSW | CC_STATE_DP); memory_init[HIGH_START] = addr >> 8; memory_init[LOW_START] = addr; (void) ccdbg_execute(dbg, memory_init); @@ -70,7 +59,7 @@ ccdbg_write_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes) ccdbg_execute(dbg, write8); if ((i & 0xf) == 0xf) { ccdbg_debug(CC_DEBUG_MEMORY, "."); - ccdbg_flush(); + ccdbg_flush(CC_DEBUG_MEMORY); nl = 1; } if ((i & 0xff) == 0xff) { @@ -78,7 +67,7 @@ ccdbg_write_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes) nl = 0; } } - (void) ccdbg_execute(dbg, memory_fini); + ccdbg_state_restore(dbg, &state); if (nl) ccdbg_debug(CC_DEBUG_MEMORY, "\n"); return 0; @@ -88,6 +77,13 @@ uint8_t ccdbg_read_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes) { int i, nl = 0; + struct ccstate state; + + if (ccdbg_rom_contains(dbg, addr, nbytes)) { + ccdbg_rom_replace_xmem(dbg, addr, bytes, nbytes); + return 0; + } + ccdbg_state_save(dbg, &state, CC_STATE_ACC | CC_STATE_PSW | CC_STATE_DP); memory_init[HIGH_START] = addr >> 8; memory_init[LOW_START] = addr; (void) ccdbg_execute(dbg, memory_init); @@ -95,7 +91,7 @@ ccdbg_read_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes) *bytes++ = ccdbg_execute(dbg, read8); if ((i & 0xf) == 0xf) { ccdbg_debug(CC_DEBUG_MEMORY, "."); - ccdbg_flush(); + ccdbg_flush(CC_DEBUG_MEMORY); nl = 1; } if ((i & 0xff) == 0xff) { @@ -103,7 +99,8 @@ ccdbg_read_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes) nl = 0; } } - (void) ccdbg_execute(dbg, memory_fini); + ccdbg_state_replace_xmem(dbg, &state, addr, bytes, nbytes); + ccdbg_state_restore(dbg, &state); if (nl) ccdbg_debug(CC_DEBUG_MEMORY, "\n"); return 0; @@ -135,16 +132,6 @@ ccdbg_read_hex_image(struct ccdbg *dbg, uint16_t address, uint16_t length) return image; } -static uint8_t sfr_init[] = { - 2, MOV_direct_A, 0x7f, - 0, -}; - -static uint8_t sfr_fini[] = { - 2, MOV_A_direct, 0x7f, - 0, -}; - static uint8_t sfr_read[] = { 2, MOV_A_direct, 0, #define SFR_READ_ADDR 2 @@ -162,12 +149,15 @@ uint8_t ccdbg_read_sfr(struct ccdbg *dbg, uint8_t addr, uint8_t *bytes, int nbytes) { int i; - (void) ccdbg_execute(dbg, sfr_init); + struct ccstate state; + + ccdbg_state_save(dbg, &state, CC_STATE_ACC); for (i = 0; i < nbytes; i++) { sfr_read[SFR_READ_ADDR] = addr + i; *bytes++ = ccdbg_execute(dbg, sfr_read); } - (void) ccdbg_execute(dbg, sfr_fini); + ccdbg_state_replace_sfr(dbg, &state, addr, bytes, nbytes); + ccdbg_state_restore(dbg, &state); return 0; } diff --git a/lib/ccdbg-rom.c b/lib/ccdbg-rom.c new file mode 100644 index 00000000..4559b4e7 --- /dev/null +++ b/lib/ccdbg-rom.c @@ -0,0 +1,63 @@ +/* + * Copyright © 2008 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ccdbg.h" + +uint8_t +ccdbg_set_rom(struct ccdbg *dbg, struct hex_image *rom) +{ + if (dbg->rom) + ccdbg_hex_image_free(dbg->rom); + dbg->rom = rom; + return 0; +} + +uint8_t +ccdbg_rom_contains(struct ccdbg *dbg, uint16_t addr, int nbytes) +{ + struct hex_image *rom = dbg->rom; + if (!rom) + return 0; + if (addr < rom->address || rom->address + rom->length < addr + nbytes) + return 0; + return 1; +} + +uint8_t +ccdbg_rom_replace_xmem(struct ccdbg *dbg, + uint16_t addr, uint8_t *bytes, int nbytes) +{ + struct hex_image *rom = dbg->rom; + if (!rom) + return 0; + + if (rom->address < addr + nbytes && addr < rom->address + rom->length) { + int start, stop; + + start = addr; + if (addr < rom->address) + start = rom->address; + stop = addr + nbytes; + if (rom->address + rom->length < stop) + stop = rom->address + rom->length; + memcpy(bytes + start - addr, rom->data + start - rom->address, + stop - start); + return 1; + } + return 0; +} diff --git a/lib/ccdbg-state.c b/lib/ccdbg-state.c new file mode 100644 index 00000000..9aca8d2e --- /dev/null +++ b/lib/ccdbg-state.c @@ -0,0 +1,128 @@ +/* + * Copyright © 2008 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ccdbg.h" + +static uint8_t save_acc[] = { + 1, NOP, + 0 +}; + +static uint8_t save_sfr[] = { + 2, MOV_A_direct, 0, +#define SAVE_SFR_ADDR 2 + 0, +}; + +struct sfr_state { + uint8_t address; + uint16_t mask; + char *name; +}; + +static struct sfr_state sfrs[CC_STATE_NSFR] = { + { SFR_DPL0, CC_STATE_DP, "dpl0" }, + { SFR_DPH0, CC_STATE_DP, "dph0" }, + { SFR_DPL1, CC_STATE_DP, "dpl1" }, + { SFR_DPH1, CC_STATE_DP, "dph1" }, + { PSW(0), CC_STATE_PSW, "psw" }, +}; + +uint8_t +ccdbg_state_save(struct ccdbg *dbg, struct ccstate *state, unsigned int mask) +{ + int i; + + mask |= CC_STATE_ACC; + if (mask & CC_STATE_ACC) + state->acc = ccdbg_execute(dbg, save_acc); + for (i = 0; i < CC_STATE_NSFR; i++) { + if (sfrs[i].mask & mask) { + save_sfr[SAVE_SFR_ADDR] = sfrs[i].address; + state->sfr[i] = ccdbg_execute(dbg, save_sfr); + } + } + state->mask = mask; + return 0; +} + +static uint8_t restore_sfr[] = { + 3, MOV_direct_data, 0, 0, +#define RESTORE_SFR_ADDR 2 +#define RESTORE_SFR_DATA 3 + 0 +}; + +static uint8_t restore_acc[] = { + 2, MOV_A_data, 0, +#define RESTORE_ACC_DATA 2 + 0 +}; + +uint8_t +ccdbg_state_restore(struct ccdbg *dbg, struct ccstate *state) +{ + int i; + for (i = CC_STATE_NSFR - 1; i >= 0; i--) { + if (sfrs[i].mask & state->mask) { + restore_sfr[RESTORE_SFR_ADDR] = sfrs[i].address; + restore_sfr[RESTORE_SFR_DATA] = state->sfr[i]; + ccdbg_execute(dbg, restore_sfr); + } + } + if (state->mask & CC_STATE_ACC) { + restore_acc[RESTORE_ACC_DATA] = state->acc; + ccdbg_execute(dbg, restore_acc); + } + state->mask = 0; + return 0; +} + +static void +ccdbg_state_replace(uint16_t sfr_addr, uint8_t sfr, char *name, + uint16_t addr, uint8_t *bytes, int nbytes) +{ + sfr_addr += 0xdf00; + + if (addr <= sfr_addr && sfr_addr < addr + nbytes) { + fprintf(stderr, "replacing %s at 0x%04x - read 0x%02x saved 0x%02x\n", + name, sfr_addr, bytes[sfr_addr - addr], sfr); + bytes[sfr_addr - addr] = sfr; + } +} + +void +ccdbg_state_replace_xmem(struct ccdbg *dbg, struct ccstate *state, + uint16_t addr, uint8_t *bytes, int nbytes) +{ + int i; + if (state->mask & CC_STATE_ACC) + ccdbg_state_replace(ACC(0), state->acc, "acc", + addr, bytes, nbytes); + for (i = 0; i < CC_STATE_NSFR; i++) + if (state->mask & sfrs[i].mask) + ccdbg_state_replace(sfrs[i].address, state->sfr[i], + sfrs[i].name, addr, bytes, nbytes); +} + +void +ccdbg_state_replace_sfr(struct ccdbg *dbg, struct ccstate *state, + uint8_t addr, uint8_t *bytes, int nbytes) +{ + ccdbg_state_replace_xmem(dbg, state, (uint16_t) addr + 0xdf00, bytes, nbytes); +} diff --git a/lib/ccdbg.h b/lib/ccdbg.h index 203b5aeb..241c4eec 100644 --- a/lib/ccdbg.h +++ b/lib/ccdbg.h @@ -39,6 +39,7 @@ /* 8051 instructions */ +#define NOP 0x00 #define MOV_direct_data 0x75 #define LJMP 0x02 #define MOV_Rn_data(n) (0x78 | (n)) @@ -99,6 +100,9 @@ /* Bit-addressable accumulator */ #define ACC(bit) (0xE0 | (bit)) +/* Bit-addressable status word */ +#define PSW(bit) (0xD0 | (bit)) + #define CP_USB_ASYNC struct ccdbg { @@ -107,6 +111,7 @@ struct ccdbg { #else struct cp_usb *cp; #endif + struct hex_image *rom; }; /* Intel hex file format data @@ -130,6 +135,18 @@ struct hex_image { uint8_t data[0]; }; +#define CC_STATE_ACC 0x1 +#define CC_STATE_PSW 0x2 +#define CC_STATE_DP 0x4 + +#define CC_STATE_NSFR 5 + +struct ccstate { + uint16_t mask; + uint8_t acc; + uint8_t sfr[CC_STATE_NSFR]; +}; + #define HEX_RECORD_NORMAL 0x00 #define HEX_RECORD_EOF 0x01 #define HEX_RECORD_EXTENDED_ADDRESS 0x02 @@ -337,4 +354,30 @@ ccdbg_read_sfr(struct ccdbg *dbg, uint8_t addr, uint8_t *bytes, int nbytes); uint8_t ccdbg_write_sfr(struct ccdbg *dbg, uint8_t addr, uint8_t *bytes, int nbytes); +/* ccdbg-rom.c */ +uint8_t +ccdbg_set_rom(struct ccdbg *dbg, struct hex_image *rom); + +uint8_t +ccdbg_rom_contains(struct ccdbg *dbg, uint16_t addr, int nbytes); + +uint8_t +ccdbg_rom_replace_xmem(struct ccdbg *dbg, + uint16_t addrp, uint8_t *bytesp, int nbytes); + +/* ccdbg-state.c */ +uint8_t +ccdbg_state_save(struct ccdbg *dbg, struct ccstate *state, unsigned int mask); + +uint8_t +ccdbg_state_restore(struct ccdbg *dbg, struct ccstate *state); + +void +ccdbg_state_replace_xmem(struct ccdbg *dbg, struct ccstate *state, + uint16_t addr, uint8_t *bytes, int nbytes); + +void +ccdbg_state_replace_sfr(struct ccdbg *dbg, struct ccstate *state, + uint8_t addr, uint8_t *bytes, int nbytes); + #endif /* _CCDBG_H_ */ diff --git a/s51/s51-command.c b/s51/s51-command.c index 25328f1e..63d142f4 100644 --- a/s51/s51-command.c +++ b/s51/s51-command.c @@ -69,12 +69,12 @@ command_quit (int argc, char **argv) } static void -dump_bytes(uint8_t *memory, int length, uint16_t start) +dump_bytes(uint8_t *memory, int length, uint16_t start, char *format) { int group, i; for (group = 0; group < length; group += 8) { - s51_printf("0x%04x ", start + group); + s51_printf(format, start + group); for (i = group; i < length && i < group + 8; i++) s51_printf("%02x ", memory[i]); for (; i < group + 8; i++) @@ -105,7 +105,7 @@ command_di (int argc, char **argv) return command_error; length = (int) end - (int) start + 1; status = ccdbg_read_memory(s51_dbg, start + 0xff00, memory, length); - dump_bytes(memory, length, start); + dump_bytes(memory, length, start, "0x%02x "); return command_success; } @@ -125,7 +125,7 @@ command_ds (int argc, char **argv) return command_error; length = (int) end - (int) start + 1; status = ccdbg_read_sfr(s51_dbg, start, memory, length); - dump_bytes(memory, length, start); + dump_bytes(memory, length, start, "0x%02x "); return command_success; } @@ -145,7 +145,7 @@ command_dx (int argc, char **argv) return command_error; length = (int) end - (int) start + 1; status = ccdbg_read_memory(s51_dbg, start, memory, length); - dump_bytes(memory, length, start); + dump_bytes(memory, length, start, "0x%04x "); return command_success; } @@ -174,6 +174,7 @@ enum command_result command_file (int argc, char **argv) { struct hex_file *hex; + struct hex_image *image; FILE *file; if (argc != 2) @@ -189,7 +190,10 @@ command_file (int argc, char **argv) ccdbg_hex_file_free(hex); return command_error; } - start_address = hex->records[0]->address; + image = ccdbg_hex_image_create(hex); + ccdbg_hex_file_free(hex); + start_address = image->address; + ccdbg_set_rom(s51_dbg, image); return command_success; } @@ -473,6 +477,12 @@ command_halt (int argc, char **argv) return command_success; } +enum command_result +command_stop (int argc, char **argv) +{ + return command_success; +} + enum command_result command_reset (int argc, char **argv) { @@ -511,6 +521,58 @@ command_status(int argc, char **argv) return command_success; } +static enum command_result +info_breakpoints(int argc, char **argv) +{ + int b; + uint16_t address; + enum command_result result; + + if (argc == 1) { + s51_printf("Num Type Disp Hit Cnt Address What\n"); + for (b = 0; b < CC_NUM_BREAKPOINTS; b++) + if (breakpoints[b].enabled) { + s51_printf("%-3d fetch %s 1 1 0x%04x uc::disass() unimplemented\n", + b, + breakpoints[b].temporary ? "del " : "keep", + breakpoints[b].address); + } + return command_success; + } + +} + +static enum command_result +info_help(int argc, char **argv); + +static struct command_function infos[] = { + { "breakpoints", "b", info_breakpoints, "[b]reakpoints", + "List current breakpoints\n" }, + { "help", "?", info_help, "help", + "Print this list\n" }, + + { NULL, NULL, NULL, NULL, NULL }, +}; + +static enum command_result +info_help(int argc, char **argv) +{ + return command_function_help(infos, argc, argv); +} + +enum command_result +command_info(int argc, char **argv) +{ + struct command_function *func; + + if (argc < 2) + return command_error; + func = command_string_to_function(infos, argv[1]); + if (!func) + return command_syntax; + return (*func->func)(argc-1, argv+1); +} + enum command_result cc_wait(void) { diff --git a/s51/s51-parse.c b/s51/s51-parse.c index d0bfb45b..749d7bd8 100644 --- a/s51/s51-parse.c +++ b/s51/s51-parse.c @@ -18,14 +18,6 @@ #include "s51.h" -struct command_function { - char *name; - char *alias; - enum command_result (*func)(int argc, char **argv); - char *usage; - char *help; -}; - static struct command_function functions[] = { { "help", "?", command_help, "help", "Print this list\n" }, { "quit", "q", command_quit, "[q]uit", "Quit\n" }, @@ -50,6 +42,8 @@ static struct command_function functions[] = { "Clear break point\n" }, { "run", "r", command_run, "[r]un [start] [stop]", "Run with optional start and temp breakpoint addresses\n" }, + { "go", "g", command_run, "[g]o [start] [stop]", + "Run with optional start and temp breakpoint addresses\n" }, { "next", "n", command_next, "[n]ext", "Step over one instruction, past any call\n" }, { "step", "s", command_step, "[s]tep", @@ -62,10 +56,13 @@ static struct command_function functions[] = { "Reset the CPU\n" }, { "status","status",command_status, "status", "Display CC1111 debug status\n" }, + { "info", "i", command_info, "[i]info", + "Get information\n" }, + { "stop", "stop", command_stop, "stop", + "Ignored\n" }, + { NULL, NULL, NULL, NULL, NULL }, }; -#define NUM_FUNCTIONS (sizeof functions / sizeof functions[0]) - #ifndef FALSE #define FALSE 0 #define TRUE 1 @@ -106,17 +103,41 @@ string_to_int(char *s, int *v) return TRUE; } -static struct command_function * -command_string_to_function(char *name) +struct command_function * +command_string_to_function(struct command_function *functions, char *name) { int i; - for (i = 0; i < NUM_FUNCTIONS; i++) + for (i = 0; functions[i].name; i++) if (!strcmp(name, functions[i].name) || !strcmp(name, functions[i].alias)) return &functions[i]; return NULL; } +enum command_result +command_function_help(struct command_function *functions, int argc, char **argv) +{ + int i; + struct command_function *func; + + if (argc == 1) { + for (i = 0; functions[i].name; i++) + s51_printf("%-10s%s\n", functions[i].name, + functions[i].usage); + } else { + for (i = 1; i < argc; i++) { + func = command_string_to_function(functions, argv[i]); + if (!func) { + s51_printf("%-10s unknown command\n", argv[i]); + return command_syntax; + } + s51_printf("%-10s %s\n%s", func->name, + func->usage, func->help); + } + } + return command_debug; +} + static int command_split_into_words(char *line, char **argv) { @@ -153,28 +174,10 @@ command_split_into_words(char *line, char **argv) enum command_result command_help(int argc, char **argv) { - int i; - struct command_function *func; - - if (argc == 1) { - for (i = 0; i < NUM_FUNCTIONS; i++) - s51_printf("%-10s%s\n", functions[i].name, - functions[i].usage); - } else { - for (i = 1; i < argc; i++) { - func = command_string_to_function(argv[i]); - if (!func) { - s51_printf("%-10s unknown command\n", argv[i]); - return command_syntax; - } - s51_printf("%-10s %s\n%s", func->name, - func->usage, func->help); - } - } - return command_debug; + return command_function_help(functions, argc, argv); } -static void +void command_syntax_error(int argc, char **argv) { s51_printf("Syntax error in:"); @@ -206,7 +209,7 @@ command_read (void) s51_interrupted = 0; argc = command_split_into_words(line, argv); if (argc > 0) { - func = command_string_to_function(argv[0]); + func = command_string_to_function(functions, argv[0]); if (!func) command_syntax_error(argc, argv); else diff --git a/s51/s51.h b/s51/s51.h index eab61452..f4dcce66 100644 --- a/s51/s51.h +++ b/s51/s51.h @@ -27,12 +27,32 @@ enum command_result { command_success, command_debug, command_syntax, command_interrupt, command_error, }; +struct command_function { + char *name; + char *alias; + enum command_result (*func)(int argc, char **argv); + char *usage; + char *help; +}; + +struct command_function * +command_string_to_function(struct command_function *functions, char *name); + +enum command_result +command_function_help(struct command_function *functions, int argc, char **argv); + +void +command_syntax_error(int argc, char **argv); + enum command_result command_quit (int argc, char **argv); enum command_result command_help (int argc, char **argv); +enum command_result +command_stop (int argc, char **argv); + enum command_result command_di (int argc, char **argv); @@ -81,6 +101,9 @@ command_reset (int argc, char **argv); enum command_result command_status (int argc, char **argv); +enum command_result +command_info (int argc, char **argv); + enum command_result cc_wait(void); -- cgit v1.2.3 From 2d9b8a83a2d9f495199033e43f519d26f27938fe Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 6 Apr 2009 11:31:49 -0700 Subject: Add support for a serial-connected custom debug dongle This uses the cc1111 board as a custom debug dongle with faster methods for communicating with the debug target. --- lib/Makefile.am | 4 + lib/cc-bitbang.c | 270 +++++++++++++++++++++++++++++++++++++++ lib/cc-bitbang.h | 94 ++++++++++++++ lib/cc-usb.c | 355 ++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/cc-usb.h | 53 ++++++++ lib/ccdbg-command.c | 52 +++----- lib/ccdbg-debug.c | 9 ++ lib/ccdbg-io.c | 213 ++++++++----------------------- lib/ccdbg-manual.c | 15 ++- lib/ccdbg-memory.c | 4 + lib/ccdbg.h | 88 +++---------- lib/cp-usb.c | 1 + 12 files changed, 885 insertions(+), 273 deletions(-) create mode 100644 lib/cc-bitbang.c create mode 100644 lib/cc-bitbang.h create mode 100644 lib/cc-usb.c create mode 100644 lib/cc-usb.h (limited to 'lib/ccdbg-debug.c') diff --git a/lib/Makefile.am b/lib/Makefile.am index ba6f9725..4d9ded3a 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -13,5 +13,9 @@ libcc_a_SOURCES = \ ccdbg-memory.c \ ccdbg-rom.c \ ccdbg-state.c \ + cc-usb.c \ + cc-usb.h \ + cc-bitbang.c \ + cc-bitbang.h \ cp-usb.c \ cp-usb-async.c diff --git a/lib/cc-bitbang.c b/lib/cc-bitbang.c new file mode 100644 index 00000000..a5d2d369 --- /dev/null +++ b/lib/cc-bitbang.c @@ -0,0 +1,270 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#include "ccdbg-debug.h" +#include "cc-bitbang.h" + +#define CP_USB_ASYNC + +#ifdef CP_USB_ASYNC +#include "cp-usb-async.h" +#else +#include "cp-usb.h" +#endif + +struct cc_bitbang { +#ifdef CP_USB_ASYNC + struct cp_usb_async *cp_async; +#else + struct cp_usb *cp; +#endif +}; + +static uint32_t cc_clock_us = CC_CLOCK_US; +static uint32_t cc_reset_us = CC_RESET_US; + +void +cc_bitbang_set_clock(uint32_t us) +{ + cc_clock_us = us; +} + +void +cc_bitbang_half_clock(struct cc_bitbang *bb) +{ + struct timespec req, rem; + req.tv_sec = (cc_clock_us / 2) / 1000000; + req.tv_nsec = ((cc_clock_us / 2) % 1000000) * 1000; + nanosleep(&req, &rem); +} + +void +cc_bitbang_wait_reset(struct cc_bitbang *bb) +{ + struct timespec req, rem; + + cc_bitbang_sync(bb); + req.tv_sec = (cc_reset_us) / 1000000; + req.tv_nsec = ((cc_reset_us) % 1000000) * 1000; + nanosleep(&req, &rem); +} + +struct cc_bitbang * +cc_bitbang_open(void) +{ + struct cc_bitbang *bb; + + bb = calloc(sizeof (struct cc_bitbang), 1); + if (!bb) { + perror("calloc"); + return NULL; + } +#ifdef CP_USB_ASYNC + bb->cp_async = cp_usb_async_open(); + if (!bb->cp_async) { + free (bb); + return NULL; + } +#else + bb->cp = cp_usb_open (); + if (!bb->cp) { + free (bb); + return NULL; + } +#endif + return bb; +} + +void +cc_bitbang_close(struct cc_bitbang *bb) +{ +#ifdef CP_USB_ASYNC + cp_usb_async_close(bb->cp_async); +#else + cp_usb_close(bb->cp); +#endif + free (bb); +} + +void +cc_bitbang_debug_mode(struct cc_bitbang *bb) +{ + /* force two rising clocks while holding RESET_N low */ + ccdbg_debug(CC_DEBUG_COMMAND, "#\n"); + ccdbg_debug(CC_DEBUG_COMMAND, "# Debug mode\n"); + ccdbg_debug(CC_DEBUG_COMMAND, "#\n"); + cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA|CC_RESET_N); + cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_DATA ); + cc_bitbang_wait_reset(bb); + cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA ); + cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_DATA ); + cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA ); + cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_DATA|CC_RESET_N); + cc_bitbang_wait_reset(bb); +} + +void +cc_bitbang_reset(struct cc_bitbang *bb) +{ + ccdbg_debug(CC_DEBUG_COMMAND, "#\n"); + ccdbg_debug(CC_DEBUG_COMMAND, "# Reset\n"); + ccdbg_debug(CC_DEBUG_COMMAND, "#\n"); + cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA|CC_RESET_N); + cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA ); + cc_bitbang_wait_reset(bb); + cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA ); + cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA ); + cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA ); + cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA|CC_RESET_N); + cc_bitbang_wait_reset(bb); +} + +int +cc_bitbang_write(struct cc_bitbang *bb, uint8_t mask, uint8_t value) +{ +#ifdef CP_USB_ASYNC + cp_usb_async_write(bb->cp_async, mask, value); +#else + cp_usb_write(bb->cp, mask, value); +#endif + return 0; +} + +void +cc_bitbang_read(struct cc_bitbang *bb, uint8_t *valuep) +{ +#ifdef CP_USB_ASYNC + cp_usb_async_read(bb->cp_async, valuep); +#else + *valuep = cp_usb_read(bb->cp); +#endif +} + +void +cc_bitbang_sync(struct cc_bitbang *bb) +{ +#ifdef CP_USB_ASYNC + cp_usb_async_sync(bb->cp_async); +#endif +} + +static char +is_bit(uint8_t get, uint8_t mask, char on, uint8_t bit) +{ + if (mask&bit) { + if (get&bit) + return on; + else + return '.'; + } else + return '-'; +} + +void +cc_bitbang_print(char *format, uint8_t mask, uint8_t set) +{ + ccdbg_debug (CC_DEBUG_BITBANG, format, + is_bit(set, mask, 'C', CC_CLOCK), + is_bit(set, mask, 'D', CC_DATA), + is_bit(set, mask, 'R', CC_RESET_N)); +} + +void +cc_bitbang_send(struct cc_bitbang *bb, uint8_t mask, uint8_t set) +{ + cc_bitbang_write(bb, mask, set); + cc_bitbang_print("%c %c %c\n", mask, set); + cc_bitbang_half_clock(bb); +} + +void +cc_bitbang_send_bit(struct cc_bitbang *bb, uint8_t bit) +{ + if (bit) bit = CC_DATA; + cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|bit|CC_RESET_N); + cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, bit|CC_RESET_N); +} + +void +cc_bitbang_send_byte(struct cc_bitbang *bb, uint8_t byte) +{ + int bit; + ccdbg_debug(CC_DEBUG_BITBANG, "#\n# Send Byte 0x%02x\n#\n", byte); + for (bit = 7; bit >= 0; bit--) { + cc_bitbang_send_bit(bb, (byte >> bit) & 1); + if (bit == 3) + ccdbg_debug(CC_DEBUG_BITBANG, "\n"); + } + cc_bitbang_sync(bb); +} + +void +cc_bitbang_send_bytes(struct cc_bitbang *bb, uint8_t *bytes, int nbytes) +{ + while (nbytes--) + cc_bitbang_send_byte(bb, *bytes++); +} + +void +cc_bitbang_recv_bit(struct cc_bitbang *bb, int first, uint8_t *bit) +{ + uint8_t mask = first ? CC_DATA : 0; + + cc_bitbang_send(bb, CC_CLOCK|mask|CC_RESET_N, CC_CLOCK|CC_DATA|CC_RESET_N); + cc_bitbang_read(bb, bit); + cc_bitbang_send(bb, CC_CLOCK| CC_RESET_N, CC_RESET_N); +} + +void +cc_bitbang_recv_byte(struct cc_bitbang *bb, int first, uint8_t *bytep) +{ + uint8_t byte = 0; + uint8_t bits[8]; + int bit; + + ccdbg_debug(CC_DEBUG_BITBANG, "#\n# Recv byte\n#\n"); + for (bit = 0; bit < 8; bit++) { + cc_bitbang_recv_bit(bb, first, &bits[bit]); + first = 0; + } + cc_bitbang_sync(bb); + for (bit = 0; bit < 8; bit++) { + byte = byte << 1; + byte |= (bits[bit] & CC_DATA) ? 1 : 0; + cc_bitbang_print("#\t%c %c %c\n", CC_DATA, bits[bit]); + if (bit == 3) + ccdbg_debug(CC_DEBUG_BITBANG, "\n"); + } + ccdbg_debug(CC_DEBUG_BITBANG, "#\n# Recv 0x%02x\n#\n", byte); + *bytep = byte; +} + +void +cc_bitbang_recv_bytes(struct cc_bitbang *bb, uint8_t *bytes, int nbytes) +{ + int i; + int first = 1; + for (i = 0; i < nbytes; i++) { + cc_bitbang_recv_byte(bb, first, &bytes[i]); + first = 0; + } +} + diff --git a/lib/cc-bitbang.h b/lib/cc-bitbang.h new file mode 100644 index 00000000..54b20e2c --- /dev/null +++ b/lib/cc-bitbang.h @@ -0,0 +1,94 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _CC_BITBANG_H_ +#define _CC_BITBANG_H_ + +#include + +#define CC_CLOCK 0x1 +#define CC_DATA 0x2 +#define CC_RESET_N 0x4 +#define CC_CLOCK_US (2) + +/* Telemetrum has a 10k pull-up to 3.3v, a 0.001uF cap to ground + * and a 2.7k resistor to the reset line. This takes about 6us + * to settle, so we'll wait longer than that after changing the reset line + */ +#define CC_RESET_US (12) + +struct cc_bitbang; + +void +cc_bitbang_set_clock(uint32_t us); + +void +cc_bitbang_half_clock(struct cc_bitbang *bb); + +void +cc_bitbang_wait_reset(struct cc_bitbang *bb); + +struct cc_bitbang * +cc_bitbang_open(void); + +void +cc_bitbang_close(struct cc_bitbang *bb); + +void +cc_bitbang_debug_mode(struct cc_bitbang *bb); + +void +cc_bitbang_reset(struct cc_bitbang *bb); + +int +cc_bitbang_write(struct cc_bitbang *bb, uint8_t mask, uint8_t value); + +void +cc_bitbang_read(struct cc_bitbang *bb, uint8_t *valuep); + +void +cc_bitbang_sync(struct cc_bitbang *bb); + +void +cc_bitbang_print(char *format, uint8_t mask, uint8_t set); + +void +cc_bitbang_print(char *format, uint8_t mask, uint8_t set); + +void +cc_bitbang_send(struct cc_bitbang *bb, uint8_t mask, uint8_t set); + +void +cc_bitbang_send_bit(struct cc_bitbang *bb, uint8_t bit); + +void +cc_bitbang_send_byte(struct cc_bitbang *bb, uint8_t byte); + +void +cc_bitbang_send_bytes(struct cc_bitbang *bb, uint8_t *bytes, int nbytes); + +void +cc_bitbang_recv_bit(struct cc_bitbang *bb, int first, uint8_t *bit); + +void +cc_bitbang_recv_byte(struct cc_bitbang *bb, int first, uint8_t *bytep); + +void +cc_bitbang_recv_bytes(struct cc_bitbang *bb, uint8_t *bytes, int nbytes); + +#endif /* _CC_BITBANG_H_ */ diff --git a/lib/cc-usb.c b/lib/cc-usb.c new file mode 100644 index 00000000..a85765af --- /dev/null +++ b/lib/cc-usb.c @@ -0,0 +1,355 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ccdbg-debug.h" +#include "cc-usb.h" + + +#define CC_NUM_READ 16 +#define CC_BUF 1024 +#define DEFAULT_TTY "/dev/ttyACM0" + +struct cc_read { + uint8_t *buf; + int len; +}; + +struct cc_usb { + int fd; + uint8_t in_buf[CC_BUF]; + int in_count; + uint8_t out_buf[CC_BUF]; + int out_count; + struct cc_read read_buf[CC_NUM_READ]; + int read_count; +}; + +#define NOT_HEX 0xff + +static uint8_t +cc_hex_nibble(uint8_t c) +{ + if ('0' <= c && c <= '9') + return c - '0'; + if ('a' <= c && c <= 'f') + return c - 'a' + 10; + if ('A' <= c && c <= 'F') + return c - 'A' + 10; + return NOT_HEX; +} + +/* + * Take raw input bytes, parse them as hex + * and write them to the waiting buffer + */ +static void +cc_handle_in(struct cc_usb *cc) +{ + uint8_t h, l; + int in_pos; + int read_pos; + + in_pos = 0; + read_pos = 0; + while (read_pos < cc->read_count && in_pos < cc->in_count) { + /* + * Skip to next hex character + */ + while (in_pos < cc->in_count && + cc_hex_nibble(cc->in_buf[in_pos]) == NOT_HEX) + in_pos++; + /* + * Make sure we have two characters left + */ + if (cc->in_count - in_pos < 2) + break; + /* + * Parse hex number + */ + h = cc_hex_nibble(cc->in_buf[in_pos]); + l = cc_hex_nibble(cc->in_buf[in_pos+1]); + if (h == NOT_HEX || l == NOT_HEX) { + fprintf(stderr, "hex read error\n"); + break; + } + in_pos += 2; + /* + * Store hex number + */ + *cc->read_buf[read_pos].buf++ = (h << 4) | l; + if (--cc->read_buf[read_pos].len <= 0) + read_pos++; + } + + /* Move remaining bytes to the start of the input buffer */ + if (in_pos) { + memmove(cc->in_buf, cc->in_buf + in_pos, + cc->in_count - in_pos); + cc->in_count -= in_pos; + } + + /* Move pending reads to the start of the array */ + if (read_pos) { + memmove(cc->read_buf, cc->read_buf + read_pos, + (cc->read_count - read_pos) * sizeof (cc->read_buf[0])); + cc->read_count -= read_pos; + } + + /* Once we're done reading, flush any pending input */ + if (cc->read_count == 0) + cc->in_count = 0; +} + +static void +cc_usb_dbg(int indent, uint8_t *bytes, int len) +{ + int eol = 1; + int i; + uint8_t c; + while (len--) { + c = *bytes++; + if (eol) { + for (i = 0; i < indent; i++) + ccdbg_debug(CC_DEBUG_BITBANG, " "); + eol = 0; + } + switch (c) { + case '\r': + ccdbg_debug(CC_DEBUG_BITBANG, "^M"); + break; + case '\n': + eol = 1; + default: + ccdbg_debug(CC_DEBUG_BITBANG, "%c", c); + } + } +} + +/* + * Flush pending writes, fill pending reads + */ +void +cc_usb_sync(struct cc_usb *cc) +{ + int ret; + struct pollfd fds; + int timeout; + + fds.fd = cc->fd; + for (;;) { + if (cc->read_count || cc->out_count) + timeout = -1; + else + timeout = 0; + fds.events = 0; + if (cc->in_count < CC_BUF) + fds.events |= POLLIN; + if (cc->out_count) + fds.events |= POLLOUT; + ret = poll(&fds, 1, timeout); + if (ret == 0) + break; + if (ret < 0) { + perror("poll"); + break; + } + if (fds.revents & POLLIN) { + ret = read(cc->fd, cc->in_buf + cc->in_count, + CC_BUF - cc->in_count); + if (ret > 0) { + cc_usb_dbg(24, cc->in_buf + cc->in_count, ret); + cc->in_count += ret; + cc_handle_in(cc); + } + } + if (fds.revents & POLLOUT) { + ret = write(cc->fd, cc->out_buf, + cc->out_count); + if (ret > 0) { + cc_usb_dbg(0, cc->out_buf, ret); + memmove(cc->out_buf, + cc->out_buf + ret, + cc->out_count - ret); + cc->out_count -= ret; + } + } + } +} + +static void +cc_usb_printf(struct cc_usb *cc, char *format, ...) +{ + char buf[1024], *b; + va_list ap; + int ret, this_time; + + /* sprintf to a local buffer */ + va_start(ap, format); + ret = vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + if (ret > sizeof(buf)) { + fprintf(stderr, "printf overflow for format %s\n", + format); + } + + /* flush local buffer to the wire */ + b = buf; + while (ret > 0) { + this_time = ret; + if (this_time > CC_BUF - cc->out_count) + this_time = CC_BUF - cc->out_count; + memcpy(cc->out_buf + cc->out_count, b, this_time); + cc->out_count += this_time; + ret -= this_time; + while (cc->out_count >= CC_BUF) + cc_usb_sync(cc); + } +} + +int +cc_usb_send_bytes(struct cc_usb *cc, uint8_t *bytes, int len) +{ + int this_len; + int ret = len; + + while (len) { + this_len = len; + if (this_len > 8) + this_len = 8; + len -= this_len; + cc_usb_printf(cc, "P"); + while (this_len--) + cc_usb_printf (cc, " %02x", (*bytes++) & 0xff); + cc_usb_printf(cc, "\n"); + } + return ret; +} + +static void +cc_queue_read(struct cc_usb *cc, uint8_t *buf, int len) +{ + struct cc_read *read_buf; + while (cc->read_count >= CC_NUM_READ) + cc_usb_sync(cc); + read_buf = &cc->read_buf[cc->read_count++]; + read_buf->buf = buf; + read_buf->len = len; +} + +int +cc_usb_recv_bytes(struct cc_usb *cc, uint8_t *buf, int len) +{ + cc_queue_read(cc, buf, len); + cc_usb_printf(cc, "G %x\n", len); + return len; +} + +int +cc_usb_write_memory(struct cc_usb *cc, uint16_t addr, uint8_t *bytes, int len) +{ + cc_usb_printf(cc, "O %x %x\n", len, addr); + while (len--) + cc_usb_printf(cc, "%02x", *bytes++); + return 0; +} + +int +cc_usb_read_memory(struct cc_usb *cc, uint16_t addr, uint8_t *bytes, int len) +{ + int i; + cc_queue_read(cc, bytes, len); + cc_usb_printf(cc, "I %x %x\n", len, addr); + cc_usb_sync(cc); + for (i = 0; i < len; i++) { + if ((i & 15) == 0) { + if (i) + ccdbg_debug(CC_DEBUG_MEMORY, "\n"); + ccdbg_debug(CC_DEBUG_MEMORY, "\t%04x", addr + i); + } + ccdbg_debug(CC_DEBUG_MEMORY, " %02x", bytes[i]); + } + ccdbg_debug(CC_DEBUG_MEMORY, "\n"); + return 0; +} + +int +cc_usb_debug_mode(struct cc_usb *cc) +{ + cc_usb_sync(cc); + cc_usb_printf(cc, "D\n"); + return 1; +} + +int +cc_usb_reset(struct cc_usb *cc) +{ + cc_usb_sync(cc); + cc_usb_printf(cc, "R\n"); + return 1; +} + +static struct termios save_termios; + +struct cc_usb * +cc_usb_open(void) +{ + struct cc_usb *cc; + char *tty; + struct termios termios; + + tty = getenv("CCDBG_TTY"); + if (!tty) + tty = DEFAULT_TTY; + cc = calloc (sizeof (struct cc_usb), 1); + if (!cc) + return NULL; + cc->fd = open(tty, O_RDWR | O_NONBLOCK); + if (cc->fd < 0) { + perror(tty); + free (cc); + return NULL; + } + tcgetattr(cc->fd, &termios); + save_termios = termios; + cfmakeraw(&termios); + tcsetattr(cc->fd, TCSAFLUSH, &termios); + cc_usb_printf(cc, "E 0\n"); + cc_usb_sync(cc); + sleep(1); + cc_usb_sync(cc); + return cc; +} + +void +cc_usb_close(struct cc_usb *cc) +{ + tcsetattr(cc->fd, TCSAFLUSH, &save_termios); + close (cc->fd); + free (cc); +} + diff --git a/lib/cc-usb.h b/lib/cc-usb.h new file mode 100644 index 00000000..235e9918 --- /dev/null +++ b/lib/cc-usb.h @@ -0,0 +1,53 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _CC_USB_H_ +#define _CC_USB_H_ + +#include + +struct cc_usb; + +struct cc_usb * +cc_usb_open(void); + +void +cc_usb_close(struct cc_usb *cc); + +int +cc_usb_send_bytes(struct cc_usb *cc, uint8_t *bytes, int len); + +int +cc_usb_recv_bytes(struct cc_usb *cc, uint8_t *bytes, int len); + +int +cc_usb_write_memory(struct cc_usb *cc, uint16_t addr, uint8_t *bytes, int len); + +int +cc_usb_read_memory(struct cc_usb *cc, uint16_t addr, uint8_t *bytes, int len); + +int +cc_usb_debug_mode(struct cc_usb *cc); + +int +cc_usb_reset(struct cc_usb *cc); + +void +cc_usb_sync(struct cc_usb *cc); + +#endif /* _CC_USB_H_ */ diff --git a/lib/ccdbg-command.c b/lib/ccdbg-command.c index 74313bdf..7d1ae067 100644 --- a/lib/ccdbg-command.c +++ b/lib/ccdbg-command.c @@ -18,39 +18,6 @@ #include "ccdbg.h" -void -ccdbg_debug_mode(struct ccdbg *dbg) -{ - /* force two rising clocks while holding RESET_N low */ - ccdbg_debug(CC_DEBUG_COMMAND, "#\n"); - ccdbg_debug(CC_DEBUG_COMMAND, "# Debug mode\n"); - ccdbg_debug(CC_DEBUG_COMMAND, "#\n"); - ccdbg_send(dbg, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA|CC_RESET_N); - ccdbg_send(dbg, CC_CLOCK|CC_DATA|CC_RESET_N, CC_DATA ); - ccdbg_wait_reset(dbg); - ccdbg_send(dbg, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA ); - ccdbg_send(dbg, CC_CLOCK|CC_DATA|CC_RESET_N, CC_DATA ); - ccdbg_send(dbg, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA ); - ccdbg_send(dbg, CC_CLOCK|CC_DATA|CC_RESET_N, CC_DATA|CC_RESET_N); - ccdbg_wait_reset(dbg); -} - -void -ccdbg_reset(struct ccdbg *dbg) -{ - ccdbg_debug(CC_DEBUG_COMMAND, "#\n"); - ccdbg_debug(CC_DEBUG_COMMAND, "# Reset\n"); - ccdbg_debug(CC_DEBUG_COMMAND, "#\n"); - ccdbg_send(dbg, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA|CC_RESET_N); - ccdbg_send(dbg, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA ); - ccdbg_wait_reset(dbg); - ccdbg_send(dbg, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA ); - ccdbg_send(dbg, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA ); - ccdbg_send(dbg, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA ); - ccdbg_send(dbg, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA|CC_RESET_N); - ccdbg_wait_reset(dbg); -} - uint8_t ccdbg_chip_erase(struct ccdbg *dbg) { @@ -117,6 +84,22 @@ ccdbg_debug_instr(struct ccdbg *dbg, uint8_t *instr, int nbytes) return ccdbg_cmd_write_read8(dbg, CC_DEBUG_INSTR(nbytes), instr, nbytes); } +void +ccdbg_debug_instr_discard(struct ccdbg *dbg, uint8_t *instr, int nbytes) +{ + static uint8_t discard; + ccdbg_cmd_write_queue8(dbg, CC_DEBUG_INSTR(nbytes), + instr, nbytes, &discard); +} + +void +ccdbg_debug_instr_queue(struct ccdbg *dbg, uint8_t *instr, int nbytes, + uint8_t *reply) +{ + return ccdbg_cmd_write_queue8(dbg, CC_DEBUG_INSTR(nbytes), + instr, nbytes, reply); +} + uint8_t ccdbg_step_instr(struct ccdbg *dbg) { @@ -148,12 +131,13 @@ ccdbg_execute(struct ccdbg *dbg, uint8_t *inst) ccdbg_debug(CC_DEBUG_INSTRUCTIONS, "\t%02x", inst[1]); for (i = 0; i < len - 1; i++) ccdbg_debug(CC_DEBUG_INSTRUCTIONS, " %02x", inst[i+2]); - status = ccdbg_debug_instr(dbg, inst+1, len); + ccdbg_debug_instr_queue(dbg, inst+1, len, &status); for (; i < 3; i++) ccdbg_debug(CC_DEBUG_INSTRUCTIONS, " "); ccdbg_debug(CC_DEBUG_INSTRUCTIONS, " -> %02x\n", status); inst += len + 1; } + ccdbg_sync(dbg); return status; } diff --git a/lib/ccdbg-debug.c b/lib/ccdbg-debug.c index 847361c7..6eb4e0c5 100644 --- a/lib/ccdbg-debug.c +++ b/lib/ccdbg-debug.c @@ -34,11 +34,20 @@ ccdbg_clear_debug(int level) ccdbg_level &= ~level; } +static int initialized; + void ccdbg_debug(int level, char *format, ...) { va_list ap; + if (!initialized) { + char *level; + initialized = 1; + level = getenv("CCDEBUG"); + if (level) + ccdbg_level |= strtoul(level, NULL, 0); + } if (ccdbg_level & level) { va_start(ap, format); vprintf(format, ap); diff --git a/lib/ccdbg-io.c b/lib/ccdbg-io.c index 3606c57c..acd44f10 100644 --- a/lib/ccdbg-io.c +++ b/lib/ccdbg-io.c @@ -18,41 +18,10 @@ #include "ccdbg.h" #include -#ifdef CP_USB_ASYNC -#include "cp-usb-async.h" -#else -#include "cp-usb.h" -#endif +#include "cc-usb.h" +#include "cc-bitbang.h" -static uint32_t cc_clock_us = CC_CLOCK_US; -static uint32_t cc_reset_us = CC_RESET_US; -void -ccdbg_set_clock(uint32_t us) -{ - cc_clock_us = us; -} - -void -ccdbg_half_clock(struct ccdbg *dbg) -{ - struct timespec req, rem; - req.tv_sec = (cc_clock_us / 2) / 1000000; - req.tv_nsec = ((cc_clock_us / 2) % 1000000) * 1000; - nanosleep(&req, &rem); -} - -void -ccdbg_wait_reset(struct ccdbg *dbg) -{ - struct timespec req, rem; - - ccdbg_sync_io(dbg); - req.tv_sec = (cc_reset_us) / 1000000; - req.tv_nsec = ((cc_reset_us) % 1000000) * 1000; - nanosleep(&req, &rem); -} - struct ccdbg * ccdbg_open(void) { @@ -63,170 +32,77 @@ ccdbg_open(void) perror("calloc"); return NULL; } -#ifdef CP_USB_ASYNC - dbg->cp_async = cp_usb_async_open(); - if (!dbg->cp_async) { - free (dbg); - return NULL; - } -#else - dbg->cp = cp_usb_open (); - if (!dbg->cp) { - free (dbg); - return NULL; + dbg->usb = cc_usb_open(); + if (!dbg->usb) { + dbg->bb = cc_bitbang_open(); + if (!dbg->bb) { + free(dbg); + return NULL; + } } -#endif return dbg; } void ccdbg_close(struct ccdbg *dbg) { -#ifdef CP_USB_ASYNC - cp_usb_async_close(dbg->cp_async); -#else - cp_usb_close(dbg->cp); -#endif + if (dbg->usb) + cc_usb_close(dbg->usb); + if (dbg->bb) + cc_bitbang_close(dbg->bb); free (dbg); } -int -ccdbg_write(struct ccdbg *dbg, uint8_t mask, uint8_t value) -{ -#ifdef CP_USB_ASYNC - cp_usb_async_write(dbg->cp_async, mask, value); -#else - cp_usb_write(dbg->cp, mask, value); -#endif - return 0; -} - -void -ccdbg_read(struct ccdbg *dbg, uint8_t *valuep) -{ -#ifdef CP_USB_ASYNC - cp_usb_async_read(dbg->cp_async, valuep); -#else - *valuep = cp_usb_read(dbg->cp); -#endif -} - -void -ccdbg_sync_io(struct ccdbg *dbg) -{ -#ifdef CP_USB_ASYNC - cp_usb_async_sync(dbg->cp_async); -#endif -} - -static char -is_bit(uint8_t get, uint8_t mask, char on, uint8_t bit) -{ - if (mask&bit) { - if (get&bit) - return on; - else - return '.'; - } else - return '-'; -} -void -ccdbg_print(char *format, uint8_t mask, uint8_t set) -{ - ccdbg_debug (CC_DEBUG_BITBANG, format, - is_bit(set, mask, 'C', CC_CLOCK), - is_bit(set, mask, 'D', CC_DATA), - is_bit(set, mask, 'R', CC_RESET_N)); -} - void -ccdbg_send(struct ccdbg *dbg, uint8_t mask, uint8_t set) +ccdbg_debug_mode(struct ccdbg *dbg) { - ccdbg_write(dbg, mask, set); - ccdbg_print("%c %c %c\n", mask, set); - ccdbg_half_clock(dbg); + if (dbg->usb) + cc_usb_debug_mode(dbg->usb); + else if (dbg->bb) + cc_bitbang_debug_mode(dbg->bb); } void -ccdbg_send_bit(struct ccdbg *dbg, uint8_t bit) +ccdbg_reset(struct ccdbg *dbg) { - if (bit) bit = CC_DATA; - ccdbg_send(dbg, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|bit|CC_RESET_N); - ccdbg_send(dbg, CC_CLOCK|CC_DATA|CC_RESET_N, bit|CC_RESET_N); -} - -void -ccdbg_send_byte(struct ccdbg *dbg, uint8_t byte) -{ - int bit; - ccdbg_debug(CC_DEBUG_BITBANG, "#\n# Send Byte 0x%02x\n#\n", byte); - for (bit = 7; bit >= 0; bit--) { - ccdbg_send_bit(dbg, (byte >> bit) & 1); - if (bit == 3) - ccdbg_debug(CC_DEBUG_BITBANG, "\n"); - } - ccdbg_sync_io(dbg); + if (dbg->usb) + cc_usb_reset(dbg->usb); + else if (dbg->bb) + cc_bitbang_reset(dbg->bb); } void ccdbg_send_bytes(struct ccdbg *dbg, uint8_t *bytes, int nbytes) { - while (nbytes--) - ccdbg_send_byte(dbg, *bytes++); -} - -void -ccdbg_recv_bit(struct ccdbg *dbg, int first, uint8_t *bit) -{ - uint8_t mask = first ? CC_DATA : 0; - - ccdbg_send(dbg, CC_CLOCK|mask|CC_RESET_N, CC_CLOCK|CC_DATA|CC_RESET_N); - ccdbg_read(dbg, bit); - ccdbg_send(dbg, CC_CLOCK| CC_RESET_N, CC_RESET_N); + if (dbg->usb) + cc_usb_send_bytes(dbg->usb, bytes, nbytes); + else if (dbg->bb) + cc_bitbang_send_bytes(dbg->bb, bytes, nbytes); } void -ccdbg_recv_byte(struct ccdbg *dbg, int first, uint8_t *bytep) +ccdbg_recv_bytes(struct ccdbg *dbg, uint8_t *bytes, int nbytes) { - uint8_t byte = 0; - uint8_t bits[8]; - int bit; - - ccdbg_debug(CC_DEBUG_BITBANG, "#\n# Recv byte\n#\n"); - for (bit = 0; bit < 8; bit++) { - ccdbg_recv_bit(dbg, first, &bits[bit]); - first = 0; - } - ccdbg_sync_io(dbg); - for (bit = 0; bit < 8; bit++) { - byte = byte << 1; - byte |= (bits[bit] & CC_DATA) ? 1 : 0; - ccdbg_print("#\t%c %c %c\n", CC_DATA, bits[bit]); - if (bit == 3) - ccdbg_debug(CC_DEBUG_BITBANG, "\n"); - } - ccdbg_debug(CC_DEBUG_BITBANG, "#\n# Recv 0x%02x\n#\n", byte); - *bytep = byte; + if (dbg->usb) + cc_usb_recv_bytes(dbg->usb, bytes, nbytes); + else if (dbg->bb) + cc_bitbang_recv_bytes(dbg->bb, bytes, nbytes); } void -ccdbg_recv_bytes(struct ccdbg *dbg, uint8_t *bytes, int nbytes) +ccdbg_sync(struct ccdbg *dbg) { - int i; - int first = 1; - for (i = 0; i < nbytes; i++) { - ccdbg_recv_byte(dbg, first, &bytes[i]); - first = 0; - } + if (dbg->usb) + cc_usb_sync(dbg->usb); + else if (dbg->bb) + cc_bitbang_sync(dbg->bb); } void ccdbg_cmd_write(struct ccdbg *dbg, uint8_t cmd, uint8_t *data, int len) { - int i; - ccdbg_send_byte(dbg, cmd); - for (i = 0; i < len; i++) - ccdbg_send_byte(dbg, data[i]); + ccdbg_send_bytes(dbg, &cmd, 1); + ccdbg_send_bytes(dbg, data, len); } uint8_t @@ -235,6 +111,7 @@ ccdbg_cmd_write_read8(struct ccdbg *dbg, uint8_t cmd, uint8_t *data, int len) uint8_t byte[1]; ccdbg_cmd_write(dbg, cmd, data, len); ccdbg_recv_bytes(dbg, byte, 1); + ccdbg_sync(dbg); return byte[0]; } @@ -244,5 +121,15 @@ ccdbg_cmd_write_read16(struct ccdbg *dbg, uint8_t cmd, uint8_t *data, int len) uint8_t byte[2]; ccdbg_cmd_write(dbg, cmd, data, len); ccdbg_recv_bytes(dbg, byte, 2); + ccdbg_sync(dbg); return (byte[0] << 8) | byte[1]; } + +void +ccdbg_cmd_write_queue8(struct ccdbg *dbg, uint8_t cmd, + uint8_t *data, int len, + uint8_t *reply) +{ + ccdbg_cmd_write(dbg, cmd, data, len); + ccdbg_recv_bytes(dbg, reply, 1); +} diff --git a/lib/ccdbg-manual.c b/lib/ccdbg-manual.c index df79d88d..0e811b76 100644 --- a/lib/ccdbg-manual.c +++ b/lib/ccdbg-manual.c @@ -17,6 +17,7 @@ */ #include "ccdbg.h" +#include "cc-bitbang.h" /* * Manual bit-banging to debug the low level protocol @@ -47,6 +48,10 @@ ccdbg_manual(struct ccdbg *dbg, FILE *input) char line[80]; uint8_t set, mask; + if (dbg->bb == NULL) { + fprintf(stderr, "Must use bitbang API for manual mode\n"); + return; + } while (fgets(line, sizeof line, input)) { if (line[0] == '#' || line[0] == '\n') { printf ("%s", line); @@ -59,14 +64,14 @@ ccdbg_manual(struct ccdbg *dbg, FILE *input) get_bit(line, 4, 'R', CC_RESET_N, &set, &mask); if (mask != (CC_CLOCK|CC_DATA|CC_RESET_N)) { uint8_t read; - ccdbg_read(dbg, &read); - ccdbg_sync_io(dbg); - ccdbg_print("\t%c %c %c", CC_CLOCK|CC_DATA|CC_RESET_N, read); + cc_bitbang_read(dbg->bb, &read); + cc_bitbang_sync(dbg->bb); + cc_bitbang_print("\t%c %c %c", CC_CLOCK|CC_DATA|CC_RESET_N, read); if ((set & CC_CLOCK) == 0) printf ("\t%d", (read&CC_DATA) ? 1 : 0); printf ("\n"); } - ccdbg_send(dbg, mask, set); - ccdbg_sync_io(dbg); + cc_bitbang_send(dbg->bb, mask, set); + cc_bitbang_sync(dbg->bb); } } diff --git a/lib/ccdbg-memory.c b/lib/ccdbg-memory.c index 20a24799..878c5f97 100644 --- a/lib/ccdbg-memory.c +++ b/lib/ccdbg-memory.c @@ -50,6 +50,8 @@ ccdbg_write_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes) int i, nl = 0; struct ccstate state; + if (dbg->usb) + return cc_usb_write_memory(dbg->usb, addr, bytes, nbytes); ccdbg_state_save(dbg, &state, CC_STATE_ACC | CC_STATE_PSW | CC_STATE_DP); memory_init[HIGH_START] = addr >> 8; memory_init[LOW_START] = addr; @@ -83,6 +85,8 @@ ccdbg_read_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes) ccdbg_rom_replace_xmem(dbg, addr, bytes, nbytes); return 0; } + if (dbg->usb) + return cc_usb_read_memory(dbg->usb, addr, bytes, nbytes); ccdbg_state_save(dbg, &state, CC_STATE_ACC | CC_STATE_PSW | CC_STATE_DP); memory_init[HIGH_START] = addr >> 8; memory_init[LOW_START] = addr; diff --git a/lib/ccdbg.h b/lib/ccdbg.h index e0e12c8b..fe0ea3a0 100644 --- a/lib/ccdbg.h +++ b/lib/ccdbg.h @@ -31,17 +31,8 @@ #include #include #include "ccdbg-debug.h" - -#define CC_CLOCK 0x1 -#define CC_DATA 0x2 -#define CC_RESET_N 0x4 -#define CC_CLOCK_US (2) - -/* Telemetrum has a 10k pull-up to 3.3v, a 0.001uF cap to ground - * and a 2.7k resistor to the reset line. This takes about 6us - * to settle, so we'll wait longer than that after changing the reset line - */ -#define CC_RESET_US (12) +#include "cc-bitbang.h" +#include "cc-usb.h" /* 8051 instructions */ @@ -109,15 +100,10 @@ /* Bit-addressable status word */ #define PSW(bit) (0xD0 | (bit)) -#define CP_USB_ASYNC - struct ccdbg { -#ifdef CP_USB_ASYNC - struct cp_usb_async *cp_async; -#else - struct cp_usb *cp; -#endif - struct hex_image *rom; + struct cc_bitbang *bb; + struct cc_usb *usb; + struct hex_image *rom; }; /* Intel hex file format data @@ -225,6 +211,13 @@ ccdbg_resume(struct ccdbg *dbg); uint8_t ccdbg_debug_instr(struct ccdbg *dbg, uint8_t *instr, int nbytes); +void +ccdbg_debug_instr_discard(struct ccdbg *dbg, uint8_t *instr, int nbytes); + +void +ccdbg_debug_instr_queue(struct ccdbg *dbg, uint8_t *instr, int nbytes, + uint8_t *reply); + uint8_t ccdbg_step_instr(struct ccdbg *dbg); @@ -264,80 +257,33 @@ int ccdbg_hex_image_equal(struct hex_image *a, struct hex_image *b); /* ccdbg-io.c */ -void -ccdbg_set_clock(uint32_t us); - -void -ccdbg_half_clock(struct ccdbg *dbg); - -void -ccdbg_wait_reset(struct ccdbg *dbg); - -int -ccdbg_write(struct ccdbg *dbg, uint8_t mask, uint8_t value); - -void -ccdbg_read(struct ccdbg *dbg, uint8_t *valuep); - struct ccdbg * ccdbg_open(void); void ccdbg_close(struct ccdbg *dbg); -void -ccdbg_clock_1_0(struct ccdbg *dbg); - -void -ccdbg_clock_0_1(struct ccdbg *dbg); - -void -ccdbg_write_bit(struct ccdbg *dbg, uint8_t bit); - -void -ccdbg_write_byte(struct ccdbg *dbg, uint8_t byte); - -uint8_t -ccdbg_read_bit(struct ccdbg *dbg); - -uint8_t -ccdbg_read_byte(struct ccdbg *dbg); - void ccdbg_cmd_write(struct ccdbg *dbg, uint8_t cmd, uint8_t *data, int len); uint8_t ccdbg_cmd_write_read8(struct ccdbg *dbg, uint8_t cmd, uint8_t *data, int len); -uint16_t -ccdbg_cmd_write_read16(struct ccdbg *dbg, uint8_t cmd, uint8_t *data, int len); - void -ccdbg_send(struct ccdbg *dbg, uint8_t mask, uint8_t set); +ccdbg_cmd_write_queue8(struct ccdbg *dbg, uint8_t cmd, + uint8_t *data, int len, uint8_t *reply); -void -ccdbg_send_bit(struct ccdbg *dbg, uint8_t bit); - -void -ccdbg_send_byte(struct ccdbg *dbg, uint8_t byte); +uint16_t +ccdbg_cmd_write_read16(struct ccdbg *dbg, uint8_t cmd, uint8_t *data, int len); void ccdbg_send_bytes(struct ccdbg *dbg, uint8_t *bytes, int nbytes); -void -ccdbg_recv_bit(struct ccdbg *dbg, int first, uint8_t *bit); - -void -ccdbg_recv_byte(struct ccdbg *dbg, int first, uint8_t *byte); - void ccdbg_recv_bytes(struct ccdbg *dbg, uint8_t *bytes, int nbytes); void -ccdbg_sync_io(struct ccdbg *dbg); - -void -ccdbg_print(char *format, uint8_t mask, uint8_t set); +ccdbg_sync(struct ccdbg *dbg); /* ccdbg-manual.c */ diff --git a/lib/cp-usb.c b/lib/cp-usb.c index 6ab9092c..d227b78c 100644 --- a/lib/cp-usb.c +++ b/lib/cp-usb.c @@ -25,6 +25,7 @@ #include "cp-usb.h" #include #include +#include struct cp_usb { usb_dev_handle *usb_dev; -- cgit v1.2.3