diff options
| author | Keith Packard <keithp@keithp.com> | 2008-12-18 12:07:06 -0800 | 
|---|---|---|
| committer | Keith Packard <keithp@keithp.com> | 2008-12-18 12:07:06 -0800 | 
| commit | dc03adc179669d41e3551d74b3c5a60db41ff217 (patch) | |
| tree | dc9558efc881efbb3c22cde85cb870889becb37f | |
| parent | 807e2adacb025af77bb53c03209e9c8e0d7a5f95 (diff) | |
Add ability to load Intel HEX files. Add sample sdcc LED blinker.
Signed-off-by: Keith Packard <keithp@keithp.com>
| -rw-r--r-- | Makefile | 9 | ||||
| -rw-r--r-- | Makefile.blink | 20 | ||||
| -rw-r--r-- | blink.c | 44 | ||||
| -rw-r--r-- | ccdbg-hex.c | 284 | ||||
| -rw-r--r-- | ccdbg-memory.c | 18 | ||||
| -rw-r--r-- | ccdbg.c | 15 | ||||
| -rw-r--r-- | ccdbg.h | 27 | 
7 files changed, 412 insertions, 5 deletions
| @@ -10,12 +10,16 @@ KERNEL_OBJS=cccp.o  LIBUSB_OBJS=cp-usb.o  OBJS=ccdbg.o ccdbg-command.o ccdbg-debug.o \ -	ccdbg-io.o ccdbg-memory.o \ +	ccdbg-hex.o ccdbg-io.o ccdbg-memory.o \  	$(LIBUSB_OBJS)  INCS=ccdbg.h cccp.h  PROG=ccdbg +LOAD=blink + +all: $(PROG) $(LOAD) +  $(PROG): $(OBJS)  	$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) @@ -23,3 +27,6 @@ clean:  	rm -f $(PROG) $(OBJS)  $(OBJS): $(INCS) + +blink: blink.c Makefile.blink +	make -f Makefile.blink diff --git a/Makefile.blink b/Makefile.blink new file mode 100644 index 00000000..37c3c672 --- /dev/null +++ b/Makefile.blink @@ -0,0 +1,20 @@ +CC=sdcc +NO_OPT=--nogcse --noinvariant --noinduction --nojtbound --noloopreverse \ +	--nolabelopt --nooverlay --peep-asm +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 + +SRC=blink.c +OBJ=$(SRC:.c=.rel) + +%.rel : %.c +	$(CC) -c $(CFLAGS) -o$*.rel $< + +blink: $(OBJ) +	$(CC) $(LDFLAGS) $(CFLAGS) -o$@ $(OBJ) + diff --git a/blink.c b/blink.c new file mode 100644 index 00000000..fcbc04d0 --- /dev/null +++ b/blink.c @@ -0,0 +1,44 @@ + +sfr at 0x80 P0; +sfr at 0x90 P1; +sfr at 0xA0 P2; + +#define PERCFG	SFR(0xF1) +#define ADCCFG	SFR(0xF2) +#define P0SEL	SFR(0xF3) +#define P1SEL	SFR(0xF4) +#define P2SEL	SFR(0xF5) + +sfr at 0xFD P0DIR; +sfr at 0xFE P1DIR; +sfr at 0xFE P2DIR; +sfr at 0x8F P0INP; +sfr at 0xF6 P1INP; +sfr at 0xF7 P2INP; + +#define P0IFG	SFR(0x89) +#define P1IFG	SFR(0x8A) +#define P2IFG	SFR(0x8B) + +#define nop()	_asm \ +		nop \ +		_endasm; + +main () +{ +	int	i, j; +	/* Set p1_1 to output */ +	P1DIR = 0x02; +	P1INP = 0x00; +	P2INP = 0x00; +	for (;;) { +		P1 = 0xff; +		for (j = 0; j < 100; j++) +			for (i = 0; i < 1000; i++) +				nop(); +		P1 = 0xfd; +		for (j = 0; j < 100; j++) +			for (i = 0; i < 1000; i++) +				nop(); +	} +} diff --git a/ccdbg-hex.c b/ccdbg-hex.c new file mode 100644 index 00000000..d9d27cdf --- /dev/null +++ b/ccdbg-hex.c @@ -0,0 +1,284 @@ +/* + * 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" +#include <stdarg.h> +#include <ctype.h> + +struct hex_input { +	FILE	*file; +	int	line; +	char	*name; +}; + +enum hex_read_state { +	read_marker, +	read_length, +	read_address, +	read_type, +	read_data, +	read_checksum, +	read_newline, +	read_white, +	read_done, +}; + + +static void +ccdbg_hex_error(struct hex_input *input, char *format, ...) +{ +	va_list ap; + +	va_start(ap, format); +	fprintf(stderr, "Hex error %s:%d: ", input->name, input->line); +	vfprintf(stderr, format, ap); +	fprintf(stderr, "\n"); +	va_end(ap); +} + +static void +ccdbg_hex_free(struct hex_record *record) +{ +	if (!record) return; +	free(record); +} + +static struct hex_record * +ccdbg_hex_alloc(uint8_t length) +{ +	struct hex_record *record; + +	record = calloc(1, sizeof(struct hex_record) + length); +	record->length = length; +	return record; +} + +static int +ishex(char c) +{ +	return isdigit(c) || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'); +} + +static int +fromhex(char c) +{ +	if (isdigit(c)) +		return c - '0'; +	if ('a' <= c && c <= 'f') +		return c - 'a' + 10; +	if ('A' <= c && c <= 'F') +		return c - 'A' + 10; +	abort(); +	return 0; +} + +static uint8_t +ccdbg_hex_checksum(struct hex_record *record) +{ +	uint8_t	checksum = 0; +	int i; + +	checksum += record->length; +	checksum += record->address >> 8; +	checksum += record->address & 0xff; +	checksum += record->type; +	for (i = 0; i < record->length; i++) +		checksum += record->data[i]; +	return -checksum; +} + +static struct hex_record * +ccdbg_hex_read_record(struct hex_input *input) +{ +	struct hex_record *record = NULL; +	enum hex_read_state state = read_marker; +	char c; +	int nhexbytes; +	uint32_t hex; +	uint32_t ndata; +	uint8_t checksum; + +	while (state != read_done) { +		c = getc(input->file); +		if (c == EOF && state != read_white) { +			ccdbg_hex_error(input, "Unexpected EOF"); +			goto bail; +		} +		if (c == '\n') +			input->line++; +		switch (state) { +		case read_marker: +			if (c != ':') { +				ccdbg_hex_error(input, "Missing ':'"); +				goto bail; +			} +			state = read_length; +			nhexbytes = 2; +			hex = 0; +			break; +		case read_length: +		case read_address: +		case read_type: +		case read_data: +		case read_checksum: +			if (!ishex(c)) { +				ccdbg_hex_error(input, "Non-hex char '%c'", +						c); +				goto bail; +			} +			hex = hex << 4 | fromhex(c); +			--nhexbytes; +			if (nhexbytes != 0) +				break; +			 +			switch (state) { +			case read_length: +				record = ccdbg_hex_alloc(hex); +				if (!record) { +					ccdbg_hex_error(input, "Out of memory"); +					goto bail; +				} +				state = read_address; +				nhexbytes = 4; +				break; +			case read_address: +				record->address = hex; +				state = read_type; +				nhexbytes = 2; +				break; +			case read_type: +				record->type = hex; +				state = read_data; +				nhexbytes = 2; +				ndata = 0; +				break; +			case read_data: +				record->data[ndata] = hex; +				ndata++; +				nhexbytes = 2; +				break; +			case read_checksum: +				record->checksum = hex; +				state = read_newline; +				break; +			default: +				break; +			} +			if (state == read_data) +				if (ndata == record->length) { +					nhexbytes = 2; +					state = read_checksum; +				} +			hex = 0; +			break; +		case read_newline: +			if (c != '\n' && c != '\r') { +				ccdbg_hex_error(input, "Missing newline"); +				goto bail; +			} +			state = read_white; +			break; +		case read_white: +			if (!isspace(c)) { +				if (c == '\n') +					input->line--; +				if (c != EOF) +					ungetc(c, input->file); +				state = read_done; +			} +			break; +		case read_done: +			break; +		} +	} +	checksum = ccdbg_hex_checksum(record); +	if (checksum != record->checksum) { +		ccdbg_hex_error(input, "Invalid checksum (read 0x%02x computed 0x%02x)\n", +				record->checksum, checksum); +		goto bail; +	} +	return record; + +bail: +	ccdbg_hex_free(record); +	return NULL; +} + +void +ccdbg_hex_file_free(struct hex_file *hex) +{ +	int	i; + +	if (!hex) +		return; +	for (i = 0; i < hex->nrecord; i++) +		ccdbg_hex_free(hex->records[i]); +	free (hex); +} + +static int +ccdbg_hex_record_compar(const void *av, const void *bv) +{ +	const struct hex_record *a = *(struct hex_record **) av; +	const struct hex_record *b = *(struct hex_record **) bv; + +	return (int) a->address - (int) b->address; +} + +struct hex_file * +ccdbg_hex_file_read(FILE *file, char *name) +{ +	struct hex_input input; +	struct hex_file	*hex = NULL, *newhex; +	struct hex_record *record; +	int srecord = 1; +	int done = 0; + +	hex = calloc (1, sizeof (struct hex_file) + sizeof (struct hex_record *)); +	input.name = name; +	input.line = 1; +	input.file = file; +	while (!done) { +		record = ccdbg_hex_read_record(&input); +		if (!record) +			goto bail; +		if (hex->nrecord == srecord) { +			srecord *= 2; +			newhex = realloc(hex,  +					 sizeof (struct hex_file) + +					 srecord * sizeof (struct hex_record *)); +			if (!newhex) +				goto bail; +			hex = newhex; +		} +		hex->records[hex->nrecord++] = record; +		if (record->type == HEX_RECORD_EOF) +			done = 1; +	} +	/* +	 * Sort them into increasing addresses, except for EOF +	 */ +	qsort(hex->records, hex->nrecord - 1, sizeof (struct hex_record *), +	      ccdbg_hex_record_compar); +	return hex; + +bail: +	ccdbg_hex_file_free(hex); +	return NULL; +} + diff --git a/ccdbg-memory.c b/ccdbg-memory.c index ffc09679..fa953d17 100644 --- a/ccdbg-memory.c +++ b/ccdbg-memory.c @@ -73,3 +73,21 @@ ccdbg_read_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes)  		*bytes++ = ccdbg_execute(dbg, read8);  	return 0;  } + +uint8_t +ccdbg_write_hex(struct ccdbg *dbg, struct hex_file *hex) +{ +	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); +	} +	return 0; +} @@ -64,6 +64,7 @@ main (int argc, char **argv)  	uint16_t	pc;  	uint8_t		memory[0x10];  	int		i; +	struct hex_file	*hex;  	dbg = ccdbg_open("/dev/ttyUSB0");  	if (!dbg) @@ -71,7 +72,9 @@ 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);  	ccdbg_reset(dbg);  	ccdbg_debug_mode(dbg);  	status = ccdbg_read_status(dbg); @@ -80,9 +83,9 @@ 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_execute(dbg, instructions); */ -	ccdbg_write_memory(dbg, 0xf000, mem_instr, sizeof (mem_instr)); -	ccdbg_read_memory(dbg, 0xf000, memory, sizeof (memory)); +	 +	ccdbg_write_hex(dbg, hex); +	ccdbg_hex_file_free(hex);  	for (i = 0; i < sizeof (memory); i++)  		printf (" %02x", memory[i]);  	printf ("\n"); @@ -91,6 +94,10 @@ main (int argc, char **argv)  	printf ("pc starts at 0x%04x\n", pc);  	status = ccdbg_resume(dbg);  	printf ("resume status: 0x%02x\n", status); +#if 0 +/*	ccdbg_execute(dbg, instructions); */ +	ccdbg_write_memory(dbg, 0xf000, mem_instr, sizeof (mem_instr)); +	ccdbg_read_memory(dbg, 0xf000, memory, sizeof (memory));  #endif  	ccdbg_close(dbg);  	exit (0); @@ -151,6 +151,30 @@ 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 + +struct hex_file * +ccdbg_hex_file_read(FILE *file, char *name); + +void +ccdbg_hex_file_free(struct hex_file *hex); +  /* ccdbg-io.c */  void  ccdbg_half_clock(struct ccdbg *dbg); @@ -230,6 +254,9 @@ 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); +uint8_t +ccdbg_write_hex(struct ccdbg *dbg, struct hex_file *hex); +  /* cp-usb.c */  void  cp_usb_init(struct ccdbg *dbg); | 
