From: Keith Packard Date: Fri, 19 Dec 2008 19:04:16 +0000 (-0800) Subject: Add flash writing code. X-Git-Tag: 0.5~58^2~94 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=55995515b9d4fc1e193039eab697c5d03db417c2;hp=0bc52385b8f86f9ca1c450ad106e6d8afe3bc153 Add flash writing code. Signed-off-by: Keith Packard --- diff --git a/Makefile b/Makefile index 801068cd..d3bafe2c 100644 --- 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 @@ -9,14 +10,17 @@ LIBS=-lusb 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) + +OBJS=$(SRCS:.c=.o) + INCS=ccdbg.h cccp.h PROG=ccdbg -LOAD=blink +LOAD=blinks all: $(PROG) $(LOAD) @@ -25,8 +29,9 @@ $(PROG): $(OBJS) clean: rm -f $(PROG) $(OBJS) + make -f Makefile.blink clean $(OBJS): $(INCS) -blink: blink.c Makefile.blink - make -f Makefile.blink +blinks: blink.c Makefile.blink + make -j1 -f Makefile.blink diff --git a/Makefile.blink b/Makefile.blink index 37c3c672..b23f0d69 100644 --- a/Makefile.blink +++ b/Makefile.blink @@ -1,3 +1,4 @@ +.NOTPARALLEL: 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 -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 -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 $< -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 1f8a5192..a5906f6d 100644 --- a/blink.c +++ b/blink.c @@ -11,7 +11,7 @@ sfr at 0xA0 P2; 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; @@ -24,6 +24,7 @@ sfr at 0xF7 P2INP; nop \ _endasm; +#if 0 void delay (int n) { @@ -62,14 +63,29 @@ wordspace () { delay(8); } +#define _ dit(); +#define ___ dah(); +#define C charspace(); +#define W wordspace(); + +#endif + main () { +#if 0 /* 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 } diff --git a/ccdbg-command.c b/ccdbg-command.c index 50dd1fd4..38c006cb 100644 --- a/ccdbg-command.c +++ b/ccdbg-command.c @@ -65,7 +65,7 @@ ccdbg_rd_config(struct ccdbg *dbg) 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); @@ -146,3 +146,37 @@ ccdbg_execute(struct ccdbg *dbg, uint8_t *inst) 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 index 00000000..ee4e8589 --- /dev/null +++ b/ccdbg-flash.c @@ -0,0 +1,309 @@ +/* + * 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" + +/* 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; +} diff --git a/ccdbg-hex.c b/ccdbg-hex.c index d9d27cdf..ff155ff3 100644 --- a/ccdbg-hex.c +++ b/ccdbg-hex.c @@ -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]); - free (hex); + free(hex); } static int @@ -249,7 +249,7 @@ ccdbg_hex_file_read(FILE *file, char *name) 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; @@ -282,3 +282,45 @@ bail: 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; +} diff --git a/ccdbg-io.c b/ccdbg-io.c index 765bde84..b78e3aad 100644 --- a/ccdbg-io.c +++ b/ccdbg-io.c @@ -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; -// nanosleep(&req, &rem); + nanosleep(&req, &rem); } struct ccdbg * diff --git a/ccdbg-memory.c b/ccdbg-memory.c index fa953d17..ec173225 100644 --- a/ccdbg-memory.c +++ b/ccdbg-memory.c @@ -22,72 +22,77 @@ * 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, + 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, + 2, MOV_A_data, 0, #define DATA_BYTE 2 - 1, MOVX_atdptr_a, - 1, INC_dptr, + 1, MOVX_atDPTR_A, + 1, INC_DPTR, 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) { + int i, nl = 0; 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); + 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) { + int i, nl = 0; 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); + 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_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; } + +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 3a34d0e9..4533fd0c 100644 --- a/ccdbg.c +++ b/ccdbg.c @@ -18,12 +18,7 @@ #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, @@ -33,27 +28,32 @@ static uint8_t instructions[] = { 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_Rn_data(0), 0xff, - MOV_Rn_data(1), 0xff, 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_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 + 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) @@ -62,9 +62,8 @@ main (int argc, char **argv) uint8_t status; uint16_t chip_id; uint16_t pc; - uint8_t memory[0x10]; - int i; struct hex_file *hex; + struct hex_image *image; dbg = ccdbg_open("/dev/ttyUSB0"); if (!dbg) @@ -72,28 +71,46 @@ main (int argc, char **argv) #if 0 ccdbg_manual(dbg, stdin); #endif +#if 1 hex = ccdbg_hex_file_read(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); - 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)); diff --git a/ccdbg.h b/ccdbg.h index 05abc97f..d5ef8940 100644 --- a/ccdbg.h +++ b/ccdbg.h @@ -47,6 +47,53 @@ /* 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; @@ -57,6 +104,29 @@ struct ccdbg { 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 @@ -111,7 +181,7 @@ ccdbg_wr_config(struct ccdbg *dbg, uint8_t config); uint8_t ccdbg_rd_config(struct ccdbg *dbg); -uint8_t +uint16_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_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, ...); @@ -151,30 +227,26 @@ ccdbg_add_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_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); @@ -255,7 +327,10 @@ 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