From 807e2adacb025af77bb53c03209e9c8e0d7a5f95 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 18 Dec 2008 00:18:50 -0800 Subject: [PATCH 1/1] Add ability to read/write arbitrary memory. Write LED blinker program. Signed-off-by: Keith Packard --- Makefile | 4 ++- ccdbg-command.c | 23 +++++++++++++++ ccdbg-io.c | 12 ++++---- ccdbg-memory.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++ ccdbg.c | 61 ++++++++++++++++++++++++++++++---------- ccdbg.h | 14 ++++++--- 6 files changed, 162 insertions(+), 27 deletions(-) create mode 100644 ccdbg-memory.c diff --git a/Makefile b/Makefile index 965032e4..2fd8ec6d 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,9 @@ LIBS=-lusb KERNEL_OBJS=cccp.o LIBUSB_OBJS=cp-usb.o -OBJS=ccdbg.o ccdbg-command.o ccdbg-debug.o ccdbg-io.o $(LIBUSB_OBJS) +OBJS=ccdbg.o ccdbg-command.o ccdbg-debug.o \ + ccdbg-io.o ccdbg-memory.o \ + $(LIBUSB_OBJS) INCS=ccdbg.h cccp.h PROG=ccdbg diff --git a/ccdbg-command.c b/ccdbg-command.c index 415010f8..50dd1fd4 100644 --- a/ccdbg-command.c +++ b/ccdbg-command.c @@ -123,3 +123,26 @@ ccdbg_get_chip_id(struct ccdbg *dbg) { return ccdbg_cmd_write_read16(dbg, CC_GET_CHIP_ID, NULL, 0); } + +/* + * Execute a sequence of instructions + */ +uint8_t +ccdbg_execute(struct ccdbg *dbg, uint8_t *inst) +{ + uint8_t status = 0; + while(inst[0] != 0) { + uint8_t len = inst[0]; + int i; + 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); + for (; i < 3; i++) + ccdbg_debug(CC_DEBUG_INSTRUCTIONS, " "); + ccdbg_debug(CC_DEBUG_INSTRUCTIONS, " -> %02x\n", status); + inst += len + 1; + } + return status; +} + diff --git a/ccdbg-io.c b/ccdbg-io.c index c69fc0d8..765bde84 100644 --- a/ccdbg-io.c +++ b/ccdbg-io.c @@ -17,17 +17,15 @@ */ #include "ccdbg.h" - -void -ccdbg_quarter_clock(struct ccdbg *dbg) -{ - usleep(CC_CLOCK_US / 4); -} +#include void ccdbg_half_clock(struct ccdbg *dbg) { - usleep(CC_CLOCK_US / 2); + struct timespec req, rem; + req.tv_sec = (CC_CLOCK_US / 2) / 1000000; + req.tv_nsec = ((CC_CLOCK_US / 2) % 1000000) * 1000; +// nanosleep(&req, &rem); } struct ccdbg * diff --git a/ccdbg-memory.c b/ccdbg-memory.c new file mode 100644 index 00000000..ffc09679 --- /dev/null +++ b/ccdbg-memory.c @@ -0,0 +1,75 @@ +/* + * 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" + +/* + * Read and write arbitrary memory through the debug port + */ + +#define MOV_dptr_data16 0x90 + +static uint8_t memory_init[] = { + 3, MOV_dptr_data16, 0, 0, +#define HIGH_START 2 +#define LOW_START 3 + 0, +}; + +#define MOV_a_data 0x74 +#define MOVX_atdptr_a 0xf0 +#define MOVX_a_atdptr 0xe0 +#define INC_dptr 0xa3 + +static uint8_t write8[] = { + 2, MOV_a_data, 0, +#define DATA_BYTE 2 + 1, MOVX_atdptr_a, + 1, INC_dptr, + 0 +}; + +static uint8_t read8[] = { + 1, MOVX_a_atdptr, + 1, INC_dptr, + 0, +}; + +uint8_t +ccdbg_write_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes) +{ + memory_init[HIGH_START] = addr >> 8; + memory_init[LOW_START] = addr; + (void) ccdbg_execute(dbg, memory_init); + while (nbytes-- > 0) { + write8[DATA_BYTE] = *bytes++; + ccdbg_execute(dbg, write8); + } + return 0; +} + +uint8_t +ccdbg_read_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes) +{ + memory_init[HIGH_START] = addr >> 8; + memory_init[LOW_START] = addr; + (void) ccdbg_execute(dbg, memory_init); + while (nbytes-- > 0) + *bytes++ = ccdbg_execute(dbg, read8); + return 0; +} diff --git a/ccdbg.c b/ccdbg.c index b682372a..a3548143 100644 --- a/ccdbg.c +++ b/ccdbg.c @@ -18,25 +18,42 @@ #include "ccdbg.h" -#define MOV 0x75 +#define MOV_direct_data 0x75 +#define LJMP 0x02 +#define MOV_Rn_data(n) (0x78 | (n)) +#define DJNZ_Rn_rel(n) (0xd8 | (n)) +#if 0 static uint8_t instructions[] = { - 3, MOV, 0xfe, 0x02, - 3, MOV, 0x90, 0xff, + 3, MOV_direct_data, 0xfe, 0x02, + 3, MOV_direct_data, 0x90, 0xff, 0 }; +#endif -static void -ccdbg_instructions(struct ccdbg *dbg, uint8_t *inst) -{ - while(inst[0] != 0) { - uint8_t len = inst[0]; - uint8_t status; - status = ccdbg_debug_instr(dbg, inst+1, len); - printf ("inst status 0x%02x\n", status); - inst += len + 1; - } -} +static uint8_t mem_instr[] = { + MOV_direct_data, 0xfe, 0x02, + MOV_direct_data, 0x90, 0xff, + MOV_Rn_data(2), 0x10, + MOV_Rn_data(0), 0xff, + MOV_Rn_data(1), 0xff, + DJNZ_Rn_rel(1), 0xfe, + DJNZ_Rn_rel(0), 0xfa, + DJNZ_Rn_rel(2), 0xf6, + MOV_direct_data, 0x90, 0xfd, + MOV_Rn_data(2), 0x10, + MOV_Rn_data(0), 0xff, + MOV_Rn_data(1), 0xff, + DJNZ_Rn_rel(1), 0xfe, + DJNZ_Rn_rel(0), 0xfa, + DJNZ_Rn_rel(2), 0xf6, + LJMP, 0xf0, 0x03 +}; + +static uint8_t jump_mem[] = { + 3, LJMP, 0xf0, 0x00, + 0 +}; int main (int argc, char **argv) @@ -44,6 +61,9 @@ main (int argc, char **argv) struct ccdbg *dbg; uint8_t status; uint16_t chip_id; + uint16_t pc; + uint8_t memory[0x10]; + int i; dbg = ccdbg_open("/dev/ttyUSB0"); if (!dbg) @@ -52,6 +72,7 @@ main (int argc, char **argv) ccdbg_manual(dbg, stdin); #endif #if 1 + ccdbg_reset(dbg); ccdbg_debug_mode(dbg); status = ccdbg_read_status(dbg); printf("Status: 0x%02x\n", status); @@ -59,7 +80,17 @@ main (int argc, char **argv) printf("Chip id: 0x%04x\n", chip_id); status = ccdbg_halt(dbg); printf ("halt status: 0x%02x\n", status); - ccdbg_instructions(dbg, instructions); +/* ccdbg_execute(dbg, instructions); */ + ccdbg_write_memory(dbg, 0xf000, mem_instr, sizeof (mem_instr)); + ccdbg_read_memory(dbg, 0xf000, memory, sizeof (memory)); + for (i = 0; i < sizeof (memory); i++) + printf (" %02x", memory[i]); + printf ("\n"); + ccdbg_execute(dbg, jump_mem); + pc = ccdbg_get_pc(dbg); + printf ("pc starts at 0x%04x\n", pc); + status = ccdbg_resume(dbg); + printf ("resume status: 0x%02x\n", status); #endif ccdbg_close(dbg); exit (0); diff --git a/ccdbg.h b/ccdbg.h index 7d9940c3..0f07e2e9 100644 --- a/ccdbg.h +++ b/ccdbg.h @@ -93,6 +93,7 @@ struct ccdbg { #define CC_DEBUG_BITBANG 0x00000001 #define CC_DEBUG_COMMAND 0x00000002 +#define CC_DEBUG_INSTRUCTIONS 0x00000004 /* ccdbg-command.c */ void @@ -137,7 +138,8 @@ ccdbg_step_replace(struct ccdbg *dbg, uint8_t *instr, int nbytes); uint16_t ccdbg_get_chip_id(struct ccdbg *dbg); - +uint8_t +ccdbg_execute(struct ccdbg *dbg, uint8_t *inst); /* ccdbg-debug.c */ void @@ -150,9 +152,6 @@ void ccdbg_clear_debug(int level); /* ccdbg-io.c */ -void -ccdbg_quarter_clock(struct ccdbg *dbg); - void ccdbg_half_clock(struct ccdbg *dbg); @@ -224,6 +223,13 @@ ccdbg_print(char *format, uint8_t mask, uint8_t set); void ccdbg_manual(struct ccdbg *dbg, FILE *input); +/* ccdbg-memory.c */ +uint8_t +ccdbg_write_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes); + +uint8_t +ccdbg_read_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes); + /* cp-usb.c */ void cp_usb_init(struct ccdbg *dbg); -- 2.30.2