diff options
| author | Keith Packard <keithp@keithp.com> | 2008-12-19 11:04:16 -0800 | 
|---|---|---|
| committer | Keith Packard <keithp@keithp.com> | 2008-12-19 11:04:16 -0800 | 
| commit | 55995515b9d4fc1e193039eab697c5d03db417c2 (patch) | |
| tree | 26fe03c8e599a60cdaf2b4d1ebc3b17549584320 | |
| parent | 0bc52385b8f86f9ca1c450ad106e6d8afe3bc153 (diff) | |
Add flash writing code.
Signed-off-by: Keith Packard <keithp@keithp.com>
| -rw-r--r-- | Makefile | 15 | ||||
| -rw-r--r-- | Makefile.blink | 35 | ||||
| -rw-r--r-- | blink.c | 22 | ||||
| -rw-r--r-- | ccdbg-command.c | 36 | ||||
| -rw-r--r-- | ccdbg-flash.c | 309 | ||||
| -rw-r--r-- | ccdbg-hex.c | 46 | ||||
| -rw-r--r-- | ccdbg-io.c | 2 | ||||
| -rw-r--r-- | ccdbg-memory.c | 59 | ||||
| -rw-r--r-- | ccdbg.c | 91 | ||||
| -rw-r--r-- | ccdbg.h | 113 | 
10 files changed, 628 insertions, 100 deletions
@@ -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) @@ -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 <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; +} 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; +} @@ -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; +} @@ -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, "<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)); @@ -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  | 
