Add flash writing code.
authorKeith Packard <keithp@keithp.com>
Fri, 19 Dec 2008 19:04:16 +0000 (11:04 -0800)
committerKeith Packard <keithp@keithp.com>
Fri, 19 Dec 2008 19:04:16 +0000 (11:04 -0800)
Signed-off-by: Keith Packard <keithp@keithp.com>
Makefile
Makefile.blink
blink.c
ccdbg-command.c
ccdbg-flash.c [new file with mode: 0644]
ccdbg-hex.c
ccdbg-io.c
ccdbg-memory.c
ccdbg.c
ccdbg.h

index 801068cdbdd4a3679a05e7d0c8f5cbb13382c419..d3bafe2ce72e546ef73f4b9ddafebd470789c2db 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,4 @@
+.NOTPARALLEL: blink-ram blink-flash
 KERNEL=/local/src/linux-2.6-aiko-64
 KINC=$(KERNEL)/drivers/usb/serial
 
 KERNEL=/local/src/linux-2.6-aiko-64
 KINC=$(KERNEL)/drivers/usb/serial
 
@@ -9,14 +10,17 @@ LIBS=-lusb
 KERNEL_OBJS=cccp.o
 LIBUSB_OBJS=cp-usb.o
 
 KERNEL_OBJS=cccp.o
 LIBUSB_OBJS=cp-usb.o
 
-OBJS=ccdbg.o ccdbg-command.o ccdbg-debug.o \
-       ccdbg-hex.o ccdbg-io.o ccdbg-memory.o \
+SRCS=ccdbg.c ccdbg-command.c ccdbg-debug.c ccdbg-flash.c \
+       ccdbg-hex.c ccdbg-io.c ccdbg-memory.c \
        $(LIBUSB_OBJS)
        $(LIBUSB_OBJS)
+
+OBJS=$(SRCS:.c=.o)
+
 INCS=ccdbg.h cccp.h
 
 PROG=ccdbg
 
 INCS=ccdbg.h cccp.h
 
 PROG=ccdbg
 
-LOAD=blink
+LOAD=blinks
 
 all: $(PROG) $(LOAD)
 
 
 all: $(PROG) $(LOAD)
 
@@ -25,8 +29,9 @@ $(PROG): $(OBJS)
 
 clean:
        rm -f $(PROG) $(OBJS)
 
 clean:
        rm -f $(PROG) $(OBJS)
+       make -f Makefile.blink clean
 
 $(OBJS): $(INCS)
 
 
 $(OBJS): $(INCS)
 
-blink: blink.c Makefile.blink
-       make -f Makefile.blink
+blinks: blink.c Makefile.blink
+       make -j1 -f Makefile.blink
index 37c3c672d880d4d95641d86a04a74aa9595ffaa9..b23f0d69cb77e5d430c93810415a71fbb4801422 100644 (file)
@@ -1,3 +1,4 @@
+.NOTPARALLEL:
 CC=sdcc
 NO_OPT=--nogcse --noinvariant --noinduction --nojtbound --noloopreverse \
        --nolabelopt --nooverlay --peep-asm
 CC=sdcc
 NO_OPT=--nogcse --noinvariant --noinduction --nojtbound --noloopreverse \
        --nolabelopt --nooverlay --peep-asm
@@ -6,15 +7,39 @@ DEBUG=--debug
 CFLAGS=--model-large $(DEBUG) --less-pedantic --xram-size 4096\
        --stack-auto --no-peep --int-long-reent --float-reent
 
 CFLAGS=--model-large $(DEBUG) --less-pedantic --xram-size 4096\
        --stack-auto --no-peep --int-long-reent --float-reent
 
-LDFLAGS=-L/usr/share/sdcc/lib/large \
-       --code-loc 0xf000 --xram-loc 0xf400
+LDFLAGS=-L/usr/share/sdcc/lib/large --out-fmt-ihx
+LDFLAGS_RAM=$(LDFLAGS) --code-loc 0xf000 --xram-loc 0xf400
+
+LDFLAGS_FLASH=$(LDFLAGS) --code-loc 0x0000 --xram-loc 0xf000
 
 SRC=blink.c
 
 SRC=blink.c
-OBJ=$(SRC:.c=.rel)
+ADB=$(SRC:.c=.adb)
+ASM=$(SRC:.c=.asm)
+LNK=$(SRC:.c=.lnk)
+LST=$(SRC:.c=.lst)
+REL=$(SRC:.c=.rel)
+RST=$(SRC:.c=.rst)
+SYM=$(SRC:.c=.sym)
+
+PROGS=blink-flash blink-ram
+PCDB=$(PROGS:=.cdb)
+PLNK=$(PROGS:=.lnk)
+PMAP=$(PROGS:=.map)
+PMEM=$(PROGS:=.mem)
 
 %.rel : %.c
        $(CC) -c $(CFLAGS) -o$*.rel $<
 
 
 %.rel : %.c
        $(CC) -c $(CFLAGS) -o$*.rel $<
 
-blink: $(OBJ)
-       $(CC) $(LDFLAGS) $(CFLAGS) -o$@ $(OBJ)
+all: $(PROGS)
+
+blink-ram: $(REL)
+       $(CC) $(LDFLAGS_RAM) $(CFLAGS) -oblink $(REL)
+       mv blink $@
+
+blink-flash: $(REL)
+       $(CC) $(LDFLAGS_FLASH) $(CFLAGS) -oblink $(REL)
+       mv blink $@
 
 
+clean:
+       rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM)
+       rm -f $(PROGS) $(PCDB) $(PLNK) $(PMAP) $(PMEM)
diff --git a/blink.c b/blink.c
index 1f8a5192c03b8df909b580dcae0ab5d1d973728b..a5906f6dd52796a690550c45dce159587b88e0bb 100644 (file)
--- a/blink.c
+++ b/blink.c
@@ -11,7 +11,7 @@ sfr at 0xA0 P2;
 
 sfr at 0xFD P0DIR;
 sfr at 0xFE P1DIR;
 
 sfr at 0xFD P0DIR;
 sfr at 0xFE P1DIR;
-sfr at 0xFE P2DIR;
+sfr at 0xFF P2DIR;
 sfr at 0x8F P0INP;
 sfr at 0xF6 P1INP;
 sfr at 0xF7 P2INP;
 sfr at 0x8F P0INP;
 sfr at 0xF6 P1INP;
 sfr at 0xF7 P2INP;
@@ -24,6 +24,7 @@ sfr at 0xF7 P2INP;
                nop \
                _endasm;
 
                nop \
                _endasm;
 
+#if 0
 void
 delay (int n)
 {
 void
 delay (int n)
 {
@@ -62,14 +63,29 @@ wordspace () {
        delay(8);
 }
 
        delay(8);
 }
 
+#define _ dit();
+#define ___ dah();
+#define C charspace();
+#define W wordspace();
+
+#endif
+
 main ()
 {
 main ()
 {
+#if 0
        /* Set p1_1 to output */
        P1DIR = 0x02;
        P1INP = 0x00;
        P2INP = 0x00;
        for (;;) {
        /* Set p1_1 to output */
        P1DIR = 0x02;
        P1INP = 0x00;
        P2INP = 0x00;
        for (;;) {
-               dah(); dit(); dah(); dit(); charspace ();
-               dah(); dah(); dit(); dah(); wordspace();
+               ___ _ ___ _ C ___ ___ _ ___ W   /* cq */
+               ___ _ _ C _ W                   /* de */
+               ___ _ ___ C ___ _ _ C           /* kd */
+               ___ ___ _ _ _ C _ _ _ C         /* 7s */
+               ___ ___ _ ___ C ___ ___ _ W     /* qg */
        }
        }
+#else
+       P1DIR = 0x02;
+       for (;;);
+#endif
 }
 }
index 50dd1fd4500612e3fe002b666e18b9a04b8b104a..38c006cb99c4ee303493b5baa59f75ad2211ebe0 100644 (file)
@@ -65,7 +65,7 @@ ccdbg_rd_config(struct ccdbg *dbg)
        return ccdbg_cmd_write_read8(dbg, CC_RD_CONFIG, NULL, 0);
 }
 
        return ccdbg_cmd_write_read8(dbg, CC_RD_CONFIG, NULL, 0);
 }
 
-uint8_t
+uint16_t
 ccdbg_get_pc(struct ccdbg *dbg)
 {
        return ccdbg_cmd_write_read16(dbg, CC_GET_PC, NULL, 0);
 ccdbg_get_pc(struct ccdbg *dbg)
 {
        return ccdbg_cmd_write_read16(dbg, CC_GET_PC, NULL, 0);
@@ -146,3 +146,37 @@ ccdbg_execute(struct ccdbg *dbg, uint8_t *inst)
        return status;
 }
 
        return status;
 }
 
+static uint8_t jump_mem[] = {
+       3, LJMP, 0xf0, 0x00,
+#define PC_HIGH        2
+#define PC_LOW 3
+       0
+};
+
+uint8_t
+ccdbg_set_pc(struct ccdbg *dbg, uint16_t pc)
+{
+       jump_mem[PC_HIGH] = pc >> 8;
+       jump_mem[PC_LOW] = pc & 0xff;
+       return ccdbg_execute(dbg, jump_mem);
+}
+
+uint8_t
+ccdbg_execute_hex_image(struct ccdbg *dbg, struct hex_image *image)
+{
+       uint16_t pc;
+       uint8_t status;
+       
+       if (image->address < 0xf000) {
+               fprintf(stderr, "Cannot execute program starting at 0x%04x\n", image->address);
+               return -1;
+       }
+       ccdbg_write_hex_image(dbg, image, 0);
+       ccdbg_set_pc(dbg, image->address);
+       pc = ccdbg_get_pc(dbg);
+       printf ("pc starts at 0x%04x\n", pc);
+       status = ccdbg_resume(dbg);
+       printf ("resume status: 0x%02x\n", status);
+       return 0;
+}
+
diff --git a/ccdbg-flash.c b/ccdbg-flash.c
new file mode 100644 (file)
index 0000000..ee4e858
--- /dev/null
@@ -0,0 +1,309 @@
+/*
+ * Copyright © 2008 Keith Packard <keithp@keithp.com>
+ *
+ * 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"
+
+/* From SWRA124 section 3.1.6 */
+
+static uint8_t flash_page[] = {
+
+       MOV_direct_data, P1DIR, 0x02,
+       MOV_direct_data, P1,    0xFF,
+
+       MOV_direct_data, FADDRH, 0,
+#define FLASH_ADDR_HIGH        8
+
+       MOV_direct_data, FADDRL, 0,
+#define FLASH_ADDR_LOW 11
+
+       MOV_DPTR_data16, 0, 0,
+#define RAM_ADDR_HIGH  13
+#define RAM_ADDR_LOW   14
+
+       MOV_Rn_data(7), 0,
+#define FLASH_WORDS_HIGH       16
+       
+       MOV_Rn_data(6), 0,
+#define FLASH_WORDS_LOW                18
+       
+       MOV_direct_data, FWT, 0x20,
+#define FLASH_TIMING           21
+
+       MOV_direct_data, FCTL, FCTL_ERASE,
+/* eraseWaitLoop: */
+               MOV_A_direct,           FCTL,
+       JB, ACC(FCTL_BUSY_BIT), 0xfb,
+
+       MOV_direct_data, P1, 0xfd,
+
+       MOV_direct_data, FCTL, FCTL_WRITE,
+/* writeLoop: */
+               MOV_Rn_data(5), 2,
+/* writeWordLoop: */
+                       MOVX_A_atDPTR,
+                       INC_DPTR,
+                       MOV_direct_A, FWDATA,
+               DJNZ_Rn_rel(5), 0xfa,           /* writeWordLoop */
+/* writeWaitLoop: */
+                       MOV_A_direct, FCTL,
+               JB, ACC(FCTL_SWBSY_BIT), 0xfb,          /* writeWaitLoop */
+       DJNZ_Rn_rel(6), 0xf1,                   /* writeLoop */
+       DJNZ_Rn_rel(7), 0xef,                   /* writeLoop */
+
+       MOV_direct_data, P1DIR, 0x00,
+       MOV_direct_data, P1,    0xFF,
+       TRAP,
+};
+
+#define FLASH_RAM      0xf000
+
+static uint8_t flash_erase_page[] = {
+       3,      MOV_direct_data, FADDRH, 0,
+#define ERASE_PAGE_HIGH        3
+       
+       3,      MOV_direct_data, FADDRL, 0,
+#define ERASE_PAGE_LOW 7
+
+       3,      MOV_direct_data, FWT, 0x2A,
+       3,      MOV_direct_data, FCTL, FCTL_ERASE,
+       0
+};
+
+static uint8_t flash_read_control[] = {
+       2,      MOV_A_direct,   FCTL,
+       0
+};
+
+static uint8_t flash_control_clear[] = {
+       3,      MOV_direct_data,        FCTL, 0,
+       2,      MOV_A_direct,           FCTL,
+       0
+};
+
+static uint8_t
+ccdbg_flash_erase_page(struct ccdbg *dbg, uint16_t addr)
+{
+       uint16_t        page_addr = addr >> 1;
+       uint8_t         status;
+       uint8_t         old[0x10], new[0x10];
+       int             i;
+       
+       ccdbg_read_memory(dbg, addr, old, 0x10);
+       flash_erase_page[ERASE_PAGE_HIGH] = page_addr >> 8;
+       flash_erase_page[ERASE_PAGE_LOW] = page_addr & 0xff;
+       status = ccdbg_execute(dbg, flash_erase_page);
+       printf("erase status 0x%02x\n", status);
+       do {
+               status = ccdbg_execute(dbg, flash_read_control);
+               printf("fctl 0x%02x\n", status);
+       } while (status & FCTL_BUSY);
+       ccdbg_read_memory(dbg, addr, new, 0x10);
+       for (i = 0; i < 0x10; i++)
+               printf("0x%02x -> 0x%02x\n", old[i], new[i]);
+       status = ccdbg_execute(dbg, flash_control_clear);
+       printf("clear fctl 0x%02x\n", status);
+       return 0;
+}
+
+static uint8_t flash_write[] = {
+       MOV_direct_data, P1DIR, 0x02,
+       MOV_direct_data, P1,    0xFD,
+       
+       MOV_A_direct, FCTL,
+       JB,     ACC(FCTL_BUSY_BIT), 0xf1,
+
+       MOV_direct_data, FCTL, 0x20,
+
+       MOV_direct_data, FADDRH, 0,
+#define WRITE_PAGE_HIGH        16
+       
+       MOV_direct_data, FADDRL, 0,
+#define WRITE_PAGE_LOW 19
+       
+       MOV_direct_data, FCTL, FCTL_WRITE,
+       MOV_direct_data, FWDATA, 0,
+#define WRITE_BYTE_0   25
+       MOV_direct_data, FWDATA, 0,
+#define WRITE_BYTE_1   28
+       MOV_A_direct, FCTL,
+       JB,     ACC(FCTL_SWBSY_BIT), 0xf1,
+
+       MOV_direct_data, P1,    0xFF,
+       TRAP,
+};
+
+static uint8_t
+ccdbg_clock_init(struct ccdbg *dbg)
+{
+       static uint8_t set_clkcon_fast[] = {
+               3,      MOV_direct_data,        CLKCON, 0x00,
+               0
+       };
+
+       static uint8_t get_sleep[] = {
+               2,      MOV_A_direct, SLEEP,
+               0
+       };
+
+       uint8_t status;
+
+       ccdbg_execute(dbg, set_clkcon_fast);
+       do {
+               status = ccdbg_execute(dbg, get_sleep);
+       } while (!(status & 0x40));
+       return 0;
+}
+
+static uint8_t
+ccdbg_flash_write_word(struct ccdbg *dbg, uint16_t addr, uint8_t data[2])
+{
+       uint16_t page_addr = addr >> 1;
+       uint8_t check[2];
+       uint8_t status;
+       int i;
+
+       flash_write[WRITE_PAGE_HIGH] = page_addr >> 8;
+       flash_write[WRITE_PAGE_LOW] = page_addr & 0xff;
+       flash_write[WRITE_BYTE_0] = data[0];
+       flash_write[WRITE_BYTE_1] = data[1];
+       printf("upload flash write\n");
+       ccdbg_write_memory(dbg, 0xf000, flash_write, sizeof(flash_write));
+       ccdbg_set_pc(dbg, 0xf000);
+       ccdbg_resume(dbg);
+       for (;;) {
+               status = ccdbg_read_status(dbg);
+               printf("waiting for write 0x%02x\n", status);
+               if ((status & CC_STATUS_CPU_HALTED) != 0)
+                       break;
+               sleep (1);
+       }
+       status = ccdbg_execute(dbg, flash_control_clear);
+       printf("clear fctl 0x%02x\n", status);
+       ccdbg_read_memory(dbg, addr, check, 2);
+       for (i = 0; i < 2; i++)
+               printf("0x%02x : 0x%02x\n", data[i], check[i]);
+       return 0;
+}
+
+#define TIMERS_OFF             0x08
+#define DMA_PAUSE              0x04
+#define TIMER_SUSPEND          0x02
+#define SEL_FLASH_INFO_PAGE    0x01
+
+static uint8_t
+ccdbg_flash_lock(struct ccdbg *dbg, uint8_t lock)
+{
+       uint8_t config;
+       uint8_t bytes[2];
+       uint8_t old[1], new[1];
+
+       config = ccdbg_rd_config(dbg);
+       ccdbg_wr_config(dbg, config|SEL_FLASH_INFO_PAGE);
+       bytes[0] = lock;
+       bytes[1] = 0;
+       ccdbg_flash_erase_page(dbg, 0);
+       ccdbg_read_memory(dbg, 0, old, 1);
+       ccdbg_flash_write_word(dbg, 0, bytes);
+       ccdbg_read_memory(dbg, 0, new, 1);
+       printf ("flash lock 0x%02x -> 0x%02x\n", old[0], new[0]);
+       ccdbg_wr_config(dbg, config & ~SEL_FLASH_INFO_PAGE);
+       return 0;
+}
+
+uint8_t
+ccdbg_flash_hex_image(struct ccdbg *dbg, struct hex_image *image)
+{
+       uint16_t offset;
+       struct hex_image *test_image;
+       uint16_t flash_prog;
+       uint16_t flash_len;
+       uint8_t fwt;
+       uint16_t flash_word_addr;
+       uint16_t flash_words;
+       uint16_t ram_addr;
+       uint16_t pc;
+       uint8_t status;
+
+       ccdbg_clock_init(dbg);
+       if (image->address + image->length > 0x8000) {
+               fprintf(stderr, "cannot flash image from 0x%04x to 0x%04x\n",
+                       image->address, image->address + image->length);
+               return 1;
+       }
+       flash_word_addr = image->address >> 1;
+       if (flash_word_addr & 0x1ff) {
+               fprintf(stderr, "flash image must start on page boundary\n");
+               return 1;
+       }
+       ram_addr = 0xf000;
+       offset = ram_addr - image->address;
+
+#if 0
+       printf("Downloading flash to check\n");
+       test_image = ccdbg_read_hex_image(dbg, image->address, image->length);
+       if (!ccdbg_hex_image_equal(image, test_image)) {
+               int i;
+               fprintf(stderr, "Image not loaded\n");
+               for (i = 0;i < 0x10; i++)
+                       printf ("0x%02x : 0x%02x\n", image->data[i], test_image->data[i]);
+               return 1;
+       }
+       return 0;
+#endif
+       
+       printf("Upload %d bytes at 0x%04x\n", image->length, ram_addr);
+       ccdbg_write_hex_image(dbg, image, offset);
+       printf("Verify %d bytes\n", image->length);
+       test_image = ccdbg_read_hex_image(dbg, ram_addr, image->length);
+       if (!ccdbg_hex_image_equal(image, test_image)) {
+               ccdbg_hex_image_free(test_image);
+               fprintf(stderr, "image verify failed\n");
+               return 1;
+       }
+       ccdbg_hex_image_free(test_image);
+       flash_len = image->length + (image->length & 1);
+       flash_words = flash_len >> 1;
+       flash_prog = ram_addr + flash_len;
+
+       fwt = 0x20;
+       flash_page[FLASH_ADDR_HIGH] = flash_word_addr >> 8;
+       flash_page[FLASH_ADDR_LOW] = flash_word_addr & 0xff;
+
+       flash_page[RAM_ADDR_HIGH] = ram_addr >> 8;
+       flash_page[RAM_ADDR_LOW] = ram_addr & 0xff;
+
+       flash_page[FLASH_WORDS_HIGH] = flash_words >> 8;
+       flash_page[FLASH_WORDS_LOW] = flash_words & 0xff;
+
+       flash_page[FLASH_TIMING] = fwt;
+       
+       printf("Upload %d flash program bytes to 0x%04x\n",
+              sizeof (flash_prog), flash_prog);
+       ccdbg_write_memory(dbg, flash_prog, flash_page, sizeof(flash_page));
+       ccdbg_set_pc(dbg, flash_prog);
+       pc = ccdbg_get_pc(dbg);
+       printf("Starting flash program at 0x%04x\n", pc);
+       status = ccdbg_resume(dbg);
+       printf("resume status is 0x%02x\n", status);
+       do {
+               status = ccdbg_read_status(dbg);
+               printf("chip status is 0x%02x\n", status);
+               sleep(1);
+       } while ((status & CC_STATUS_CPU_HALTED) == 0);
+       return 0;
+}
index d9d27cdf00a1b2fc42a3128f64c2f2b929cdacf1..ff155ff3f8fcbc0d6967b03d0408d95ad800593e 100644 (file)
@@ -228,7 +228,7 @@ ccdbg_hex_file_free(struct hex_file *hex)
                return;
        for (i = 0; i < hex->nrecord; i++)
                ccdbg_hex_free(hex->records[i]);
                return;
        for (i = 0; i < hex->nrecord; i++)
                ccdbg_hex_free(hex->records[i]);
-       free (hex);
+       free(hex);
 }
 
 static int
 }
 
 static int
@@ -249,7 +249,7 @@ ccdbg_hex_file_read(FILE *file, char *name)
        int srecord = 1;
        int done = 0;
 
        int srecord = 1;
        int done = 0;
 
-       hex = calloc (1, sizeof (struct hex_file) + sizeof (struct hex_record *));
+       hex = calloc(sizeof (struct hex_file) + sizeof (struct hex_record *), 1);
        input.name = name;
        input.line = 1;
        input.file = file;
        input.name = name;
        input.line = 1;
        input.file = file;
@@ -282,3 +282,45 @@ bail:
        return NULL;
 }
 
        return NULL;
 }
 
+struct hex_image *
+ccdbg_hex_image_create(struct hex_file *hex)
+{
+       struct hex_image *image;
+       struct hex_record *first, *last, *record;
+       int i;
+       uint32_t base, bound;
+       uint32_t offset;
+
+       first = hex->records[0];
+       last = hex->records[hex->nrecord - 2];  /* skip EOF */
+       base = (uint32_t) first->address;
+       bound = (uint32_t) last->address + (uint32_t) last->length - 1;
+       image = calloc(sizeof(struct hex_image) + bound - base, 1);
+       if (!image)
+               return NULL;
+       image->address = base;
+       image->length = bound - base;
+       memset(image->data, 0xff, image->length);
+       for (i = 0; i < hex->nrecord - 1; i++) {
+               record = hex->records[i];
+               offset = record->address - base;
+               memcpy(image->data + offset, record->data, record->length);
+       }
+       return image;
+}
+
+void
+ccdbg_hex_image_free(struct hex_image *image)
+{
+       free(image);
+}
+
+int
+ccdbg_hex_image_equal(struct hex_image *a, struct hex_image *b)
+{
+       if (a->length != b->length)
+               return 0;
+       if (memcmp(a->data, b->data, a->length) != 0)
+               return 0;
+       return 1;
+}
index 765bde845cabedcd643fe270b5b3c0363063f3e7..b78e3aad2d5795a5c2bc8ad968a2843e671bc0cf 100644 (file)
@@ -25,7 +25,7 @@ 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;
        struct timespec req, rem;
        req.tv_sec = (CC_CLOCK_US / 2) / 1000000;
        req.tv_nsec = ((CC_CLOCK_US / 2) % 1000000) * 1000;
-//     nanosleep(&req, &rem);
+       nanosleep(&req, &rem);
 }
 
 struct ccdbg *
 }
 
 struct ccdbg *
index fa953d17ca7f45668294a71c773f6b95aff7785f..ec1732251322b5816b4be9768c147d7ba65ec0f0 100644 (file)
  * Read and write arbitrary memory through the debug port
  */
 
  * Read and write arbitrary memory through the debug port
  */
 
-#define MOV_dptr_data16                0x90
-
 static uint8_t memory_init[] = {
 static uint8_t memory_init[] = {
-       3,      MOV_dptr_data16,        0,      0,
+       3,      MOV_DPTR_data16,        0,      0,
 #define HIGH_START     2
 #define LOW_START      3
        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[] = {
 
 static uint8_t write8[] = {
-       2,      MOV_a_data,     0,
+       2,      MOV_A_data,     0,
 #define DATA_BYTE      2
 #define DATA_BYTE      2
-       1,      MOVX_atdptr_a,
-       1,      INC_dptr,
+       1,      MOVX_atDPTR_A,
+       1,      INC_DPTR,
        0
 };
 
 static uint8_t read8[] = {
        0
 };
 
 static uint8_t read8[] = {
-       1,      MOVX_a_atdptr,
-       1,      INC_dptr,
+       1,      MOVX_A_atDPTR,
+       1,      INC_DPTR,
        0,
 };
 
 uint8_t
 ccdbg_write_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes)
 {
        0,
 };
 
 uint8_t
 ccdbg_write_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes)
 {
+       int i, nl = 0;
        memory_init[HIGH_START] = addr >> 8;
        memory_init[LOW_START] = addr;
        (void) ccdbg_execute(dbg, memory_init);
        memory_init[HIGH_START] = addr >> 8;
        memory_init[LOW_START] = addr;
        (void) ccdbg_execute(dbg, memory_init);
-       while (nbytes-- > 0) {
+       for (i = 0; i < nbytes; i++) {
                write8[DATA_BYTE] = *bytes++;
                ccdbg_execute(dbg, write8);
                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 (nl) printf ("\n");
        return 0;
 }
 
 uint8_t
 ccdbg_read_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes)
 {
        return 0;
 }
 
 uint8_t
 ccdbg_read_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes)
 {
+       int i, nl = 0;
        memory_init[HIGH_START] = addr >> 8;
        memory_init[LOW_START] = addr;
        (void) ccdbg_execute(dbg, memory_init);
        memory_init[HIGH_START] = addr >> 8;
        memory_init[LOW_START] = addr;
        (void) ccdbg_execute(dbg, memory_init);
-       while (nbytes-- > 0)
+       for (i = 0; i < nbytes; i++) {
                *bytes++ = ccdbg_execute(dbg, read8);
                *bytes++ = ccdbg_execute(dbg, read8);
+               if ((i & 0xf) == 0xf) { printf ("."); fflush(stdout); nl = 1; }
+               if ((i & 0xff) == 0xff) { printf ("\n"); nl = 0; }
+       }
+       if (nl) printf ("\n");
        return 0;
 }
 
 uint8_t
        return 0;
 }
 
 uint8_t
-ccdbg_write_hex(struct ccdbg *dbg, struct hex_file *hex)
+ccdbg_write_hex_image(struct ccdbg *dbg, struct hex_image *image, uint16_t offset)
 {
 {
-       int     i;
-       struct hex_record *record;
-
-       for (i = 0; i < hex->nrecord; i++) {
-               record = hex->records[i];
-               if (record->type == HEX_RECORD_EOF)
-                       break;
-               printf("Write %d bytes at 0x%04x\n",
-                      record->length, record->address);
-               ccdbg_write_memory(dbg, record->address,
-                                  record->data, record->length);
-       }
+       ccdbg_write_memory(dbg, image->address + offset, image->data, image->length);
        return 0;
 }
        return 0;
 }
+
+struct hex_image *
+ccdbg_read_hex_image(struct ccdbg *dbg, uint16_t address, uint16_t length)
+{
+       struct hex_image *image;
+       
+       image = calloc(sizeof(struct hex_image) + length, 1);
+       image->address = address;
+       image->length = length;
+       memset(image->data, 0xff, length);
+       ccdbg_read_memory(dbg, address, image->data, length);
+       return image;
+}
diff --git a/ccdbg.c b/ccdbg.c
index 3a34d0e9e65ac44dc317c625a4e82cc83df840f1..4533fd0caeee643c553471cbf31a8ab744715837 100644 (file)
--- a/ccdbg.c
+++ b/ccdbg.c
 
 #include "ccdbg.h"
 
 
 #include "ccdbg.h"
 
-#define MOV_direct_data                0x75
-#define LJMP                   0x02
-#define MOV_Rn_data(n)         (0x78 | (n))
-#define DJNZ_Rn_rel(n)         (0xd8 | (n))
-
-#if 0
+#if 1
 static uint8_t instructions[] = {
        3, MOV_direct_data, 0xfe, 0x02,
        3, MOV_direct_data, 0x90, 0xff,
 static uint8_t instructions[] = {
        3, MOV_direct_data, 0xfe, 0x02,
        3, MOV_direct_data, 0x90, 0xff,
@@ -33,27 +28,32 @@ static uint8_t instructions[] = {
 
 static uint8_t mem_instr[] = {
        MOV_direct_data, 0xfe, 0x02,
 
 static uint8_t mem_instr[] = {
        MOV_direct_data, 0xfe, 0x02,
+       MOV_Rn_data(0), 0x00,
+       MOV_Rn_data(1), 0x00,
        MOV_direct_data, 0x90, 0xff,
        MOV_Rn_data(2), 0x10,
        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(1), 0xfe,
-       DJNZ_Rn_rel(0), 0xfa,
-       DJNZ_Rn_rel(2), 0xf6,
+       DJNZ_Rn_rel(0), 0xfc,
+       DJNZ_Rn_rel(2), 0xfa,
        MOV_direct_data, 0x90, 0xfd,
        MOV_Rn_data(2), 0x10,
        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(1), 0xfe,
-       DJNZ_Rn_rel(0), 0xfa,
-       DJNZ_Rn_rel(2), 0xf6,
-       LJMP, 0xf0, 0x03
+       DJNZ_Rn_rel(0), 0xfc,
+       DJNZ_Rn_rel(2), 0xfa,
+       SJMP, 0xe7,
 };
 
 };
 
-static uint8_t jump_mem[] = {
-       3, LJMP, 0xf0, 0x00,
-       0
-};
+static struct hex_image *
+make_hex_image(uint16_t addr, uint8_t *data, uint16_t length)
+{
+       struct hex_image        *image;
+
+       image = malloc(sizeof (struct hex_image) + length);
+       image->address = addr;
+       image->length = length;
+       memcpy(image->data, data, length);
+       return image;
+}
 
 int
 main (int argc, char **argv)
 
 int
 main (int argc, char **argv)
@@ -62,9 +62,8 @@ main (int argc, char **argv)
        uint8_t         status;
        uint16_t        chip_id;
        uint16_t        pc;
        uint8_t         status;
        uint16_t        chip_id;
        uint16_t        pc;
-       uint8_t         memory[0x10];
-       int             i;
        struct hex_file *hex;
        struct hex_file *hex;
+       struct hex_image *image;
 
        dbg = ccdbg_open("/dev/ttyUSB0");
        if (!dbg)
 
        dbg = ccdbg_open("/dev/ttyUSB0");
        if (!dbg)
@@ -72,28 +71,46 @@ main (int argc, char **argv)
 #if 0
        ccdbg_manual(dbg, stdin);
 #endif
 #if 0
        ccdbg_manual(dbg, stdin);
 #endif
+#if 1
        hex = ccdbg_hex_file_read(stdin, "<stdin>");
        if (!hex)
                exit (1);
        hex = ccdbg_hex_file_read(stdin, "<stdin>");
        if (!hex)
                exit (1);
+       image = ccdbg_hex_image_create(hex);
+       ccdbg_hex_file_free(hex);
+#else
+       image = make_hex_image(0xf000, mem_instr, sizeof (mem_instr));
+#endif
+       
        ccdbg_reset(dbg);
        ccdbg_debug_mode(dbg);
        ccdbg_reset(dbg);
        ccdbg_debug_mode(dbg);
-       status = ccdbg_read_status(dbg);
-       printf("Status: 0x%02x\n", status);
-       chip_id = ccdbg_get_chip_id(dbg);
-       printf("Chip id: 0x%04x\n", chip_id);
-       status = ccdbg_halt(dbg);
-       printf ("halt status: 0x%02x\n", status);
+       ccdbg_halt(dbg);
        
        
-       ccdbg_write_hex(dbg, hex);
-       ccdbg_hex_file_free(hex);
-       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);
+#if 1
+       if (!image) {
+               fprintf(stderr, "image create failed\n");
+               exit (1);
+       }
+       if (image->address == 0xf000) {
+               printf("Loading code to execute from RAM\n");
+               ccdbg_execute_hex_image(dbg, image);
+       } else if (image->address == 0x0000) {
+               printf("Loading code to execute from FLASH\n");
+               ccdbg_flash_hex_image(dbg, image);
+               ccdbg_set_pc(dbg, 0);
+               ccdbg_resume(dbg);
+       } else {
+               printf("Cannot load code to 0x%04x\n",
+                      image->address);
+               ccdbg_hex_image_free(image);
+               ccdbg_close(dbg);
+               exit(1);
+       }
+#endif
+       for (;;) {
+               pc = ccdbg_get_pc(dbg);
+               status = ccdbg_read_status(dbg);
+               printf("pc: 0x%04x.  status: 0x%02x\n", pc, status);
+       }
 #if 0
 /*     ccdbg_execute(dbg, instructions); */
        ccdbg_write_memory(dbg, 0xf000, mem_instr, sizeof (mem_instr));
 #if 0
 /*     ccdbg_execute(dbg, instructions); */
        ccdbg_write_memory(dbg, 0xf000, mem_instr, sizeof (mem_instr));
diff --git a/ccdbg.h b/ccdbg.h
index 05abc97fb3b4993eae9caf6bfff3f0461b773a5b..d5ef894096a44c0d0c8cf92b15be764f5ccad7b7 100644 (file)
--- a/ccdbg.h
+++ b/ccdbg.h
 /* painfully slow for now */
 #define CC_CLOCK_US    (50)
 
 /* painfully slow for now */
 #define CC_CLOCK_US    (50)
 
+#define MOV_direct_data                0x75
+#define LJMP                   0x02
+#define MOV_Rn_data(n)         (0x78 | (n))
+#define DJNZ_Rn_rel(n)         (0xd8 | (n))
+#define MOV_A_direct           0xe5
+#define MOV_direct_A           0xf5
+#define MOV_DPTR_data16                0x90
+#define MOV_A_data     0x74
+#define MOVX_atDPTR_A  0xf0
+#define MOVX_A_atDPTR  0xe0
+#define INC_DPTR       0xa3
+#define TRAP           0xa5
+
+#define SJMP           0x80
+
+#define FWT            0xAB
+#define FADDRL         0xAC
+#define FADDRH         0xAD
+#define FCTL           0xAE
+# define FCTL_BUSY     0x80
+# define FCTL_BUSY_BIT 7
+# define FCTL_SWBSY    0x40
+# define FCTL_SWBSY_BIT        6
+# define FCTL_CONTRD   0x10
+# define FCTL_WRITE    0x02
+# define FCTL_ERASE    0x01
+#define FWDATA         0xAF
+
+#define CLKCON         0xC6
+#define  CLKCON_OSC32K 0x80
+#define  CLKCON_OSC    0x40
+#define  CLKCON_TICKSPD        0x38
+#define  CLKCON_CLKSPD 0x07
+
+#define P0             0x80
+#define P1             0x90
+#define P2             0xA0
+#define P0DIR          0xFD
+#define P1DIR          0xFE
+#define P2DIR          0xFF
+
+#define SLEEP          0xBE
+
+#define JB             0x20
+
+#define ACC(bit)       (0xE0 | (bit))
+
 struct ccdbg {
        usb_dev_handle  *usb_dev;
        uint8_t gpio;
 struct ccdbg {
        usb_dev_handle  *usb_dev;
        uint8_t gpio;
@@ -57,6 +104,29 @@ struct ccdbg {
        int     clock;
 };
 
        int     clock;
 };
 
+struct hex_record {
+       uint8_t length;
+       uint16_t address;
+       uint8_t type;
+       uint8_t checksum;
+       uint8_t data[0];
+};
+
+struct hex_file {
+       int                     nrecord;
+       struct hex_record       *records[0];
+};
+
+struct hex_image {
+       uint16_t        address;
+       uint16_t        length;
+       uint8_t         data[0];
+};
+
+#define HEX_RECORD_NORMAL              0x00
+#define HEX_RECORD_EOF                 0x01
+#define HEX_RECORD_EXTENDED_ADDRESS    0x02
+
 #include "cccp.h"
 
 #define CC_CHIP_ERASE          0x14
 #include "cccp.h"
 
 #define CC_CHIP_ERASE          0x14
@@ -111,7 +181,7 @@ ccdbg_wr_config(struct ccdbg *dbg, uint8_t config);
 uint8_t
 ccdbg_rd_config(struct ccdbg *dbg);
 
 uint8_t
 ccdbg_rd_config(struct ccdbg *dbg);
 
-uint8_t
+uint16_t
 ccdbg_get_pc(struct ccdbg *dbg);
 
 uint8_t
 ccdbg_get_pc(struct ccdbg *dbg);
 
 uint8_t
@@ -141,6 +211,12 @@ ccdbg_get_chip_id(struct ccdbg *dbg);
 uint8_t
 ccdbg_execute(struct ccdbg *dbg, uint8_t *inst);
        
 uint8_t
 ccdbg_execute(struct ccdbg *dbg, uint8_t *inst);
        
+uint8_t
+ccdbg_set_pc(struct ccdbg *dbg, uint16_t pc);
+       
+uint8_t
+ccdbg_execute_hex_image(struct ccdbg *dbg, struct hex_image *image);
+
 /* ccdbg-debug.c */
 void
 ccdbg_debug(int level, char *format, ...);
 /* ccdbg-debug.c */
 void
 ccdbg_debug(int level, char *format, ...);
@@ -151,30 +227,26 @@ ccdbg_add_debug(int level);
 void
 ccdbg_clear_debug(int level);
 
 void
 ccdbg_clear_debug(int level);
 
-/* ccdbg-hex.c */
-struct hex_record {
-       uint8_t length;
-       uint16_t address;
-       uint8_t type;
-       uint8_t checksum;
-       uint8_t data[0];
-};
-
-struct hex_file {
-       int                     nrecord;
-       struct hex_record       *records[0];
-};
-
-#define HEX_RECORD_NORMAL              0x00
-#define HEX_RECORD_EOF                 0x01
-#define HEX_RECORD_EXTENDED_ADDRESS    0x02
+/* ccdbg-flash.c */
+uint8_t
+ccdbg_flash_hex_image(struct ccdbg *dbg, struct hex_image *image);
 
 
+/* ccdbg-hex.c */
 struct hex_file *
 ccdbg_hex_file_read(FILE *file, char *name);
 
 void
 ccdbg_hex_file_free(struct hex_file *hex);
 
 struct hex_file *
 ccdbg_hex_file_read(FILE *file, char *name);
 
 void
 ccdbg_hex_file_free(struct hex_file *hex);
 
+struct hex_image *
+ccdbg_hex_image_create(struct hex_file *hex);
+
+void
+ccdbg_hex_image_free(struct hex_image *image);
+
+int
+ccdbg_hex_image_equal(struct hex_image *a, struct hex_image *b);
+
 /* ccdbg-io.c */
 void
 ccdbg_half_clock(struct ccdbg *dbg);
 /* ccdbg-io.c */
 void
 ccdbg_half_clock(struct ccdbg *dbg);
@@ -255,7 +327,10 @@ uint8_t
 ccdbg_read_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);
 
 uint8_t
-ccdbg_write_hex(struct ccdbg *dbg, struct hex_file *hex);
+ccdbg_write_hex_image(struct ccdbg *dbg, struct hex_image *image, uint16_t offset);
+
+struct hex_image *
+ccdbg_read_hex_image(struct ccdbg *dbg, uint16_t address, uint16_t length);
 
 /* cp-usb.c */
 void
 
 /* cp-usb.c */
 void