From: Keith Packard Date: Thu, 18 Dec 2008 20:07:06 +0000 (-0800) Subject: Add ability to load Intel HEX files. Add sample sdcc LED blinker. X-Git-Tag: 0.5~58^2~97 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=dc03adc179669d41e3551d74b3c5a60db41ff217;ds=sidebyside Add ability to load Intel HEX files. Add sample sdcc LED blinker. Signed-off-by: Keith Packard --- diff --git a/Makefile b/Makefile index 2fd8ec6d..801068cd 100644 --- a/Makefile +++ b/Makefile @@ -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 + * + * 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 +#include + +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; +} diff --git a/ccdbg.c b/ccdbg.c index a3548143..3a34d0e9 100644 --- a/ccdbg.c +++ b/ccdbg.c @@ -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, ""); + 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); diff --git a/ccdbg.h b/ccdbg.h index 0f07e2e9..05abc97f 100644 --- a/ccdbg.h +++ b/ccdbg.h @@ -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);