FreeCalypso > hg > fc-usbser-tools
changeset 55:c0084bf153e5
cp2102: Intel HEX reading implemented
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 11 Sep 2023 19:45:56 +0000 |
parents | 10789bcf07c4 |
children | 842cff427588 |
files | .hgignore cp2102/Makefile cp2102/file_rw_test.c cp2102/intel_hex_in.c |
diffstat | 4 files changed, 179 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgignore Mon Sep 11 18:56:04 2023 +0000 +++ b/.hgignore Mon Sep 11 19:45:56 2023 +0000 @@ -4,6 +4,7 @@ ^cp2102/cp2102-read-eeprom$ ^cp2102/cp2102-read-partno$ +^cp2102/file_rw_test$ ^duart28/fc-duart28-conf$
--- a/cp2102/Makefile Mon Sep 11 18:56:04 2023 +0000 +++ b/cp2102/Makefile Mon Sep 11 19:45:56 2023 +0000 @@ -1,6 +1,7 @@ CC= gcc CFLAGS= -O2 PROGS= cp2102-read-eeprom cp2102-read-partno +NOINST= file_rw_test LIBS= ../libuwrap/libuwrap.a INSTALL_PREFIX= /opt/freecalypso @@ -9,7 +10,9 @@ READ_EEPROM_OBJS= intel_hex_out.o read_eeprom.o read_eeprom_main.o -all: ${PROGS} +RW_TEST_OBJS= intel_hex_in.o intel_hex_out.o file_rw_test.o + +all: ${PROGS} ${NOINST} cp2102-read-eeprom: ${READ_EEPROM_OBJS} ${LIBS} ${CC} ${CFLAGS} -o $@ ${READ_EEPROM_OBJS} ${LIBS} -lusb @@ -17,9 +20,12 @@ cp2102-read-partno: read_partno.o ${LIBS} ${CC} ${CFLAGS} -o $@ read_partno.o ${LIBS} -lusb +file_rw_test: ${RW_TEST_OBJS} + ${CC} ${CFLAGS} -o $@ ${RW_TEST_OBJS} + install: mkdir -p ${INSTBIN} install -c ${PROGS} ${INSTBIN} clean: - rm -f ${PROGS} *.o *errs *.out + rm -f ${PROGS} ${NOINST} *.o *errs *.out
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cp2102/file_rw_test.c Mon Sep 11 19:45:56 2023 +0000 @@ -0,0 +1,22 @@ +/* + * This little program is a unit test for our Intel HEX reading function. + */ + +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include "cp210x_defs.h" + +u_char eeprom[SIZE_EEPROM]; + +main(argc, argv) + char **argv; +{ + if (argc != 2) { + fprintf(stderr, "usage: %s ihex-file\n", argv[0]); + exit(1); + } + read_intel_hex(argv[1]); + intel_hex_out(eeprom, stdout); + exit(0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cp2102/intel_hex_in.c Mon Sep 11 19:45:56 2023 +0000 @@ -0,0 +1,148 @@ +/* + * This module implements a function for reading CP2102 EEPROM images + * in the Intel HEX format which we've copied from cp210x-program-1.0, + * the Python-language tool from 2014. + */ + +#include <sys/types.h> +#include <ctype.h> +#include <string.h> +#include <strings.h> +#include <stdio.h> +#include <stdlib.h> +#include "cp210x_defs.h" + +extern u_char eeprom[SIZE_EEPROM]; + +static int +decode_hex_digit(c) +{ + if (c >= '0' && c <= '9') + return(c - '0'); + if (c >= 'A' && c <= 'F') + return(c - 'A' + 10); + if (c >= 'a' && c <= 'f') + return(c - 'a' + 10); + return(-1); +} + +static int +decode_hex_byte(str) + char *str; +{ + int u, l; + + u = decode_hex_digit(str[0]); + l = decode_hex_digit(str[1]); + return (u << 4) | l; +} + +void +read_intel_hex(filename) + char *filename; +{ + FILE *inf; + char linebuf[1024], *cp; + int lineno; + unsigned eeprom_offset; + unsigned payload_len, record_len, n; + u_char record[21], csum; + unsigned record_addr, expect_addr; + + inf = fopen(filename, "r"); + if (!inf) { + perror(filename); + exit(1); + } + eeprom_offset = 0; + for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++) { + if (!index(linebuf, '\n')) { + fprintf(stderr, + "%s line %d: too long or missing newline\n", + filename, lineno); + exit(1); + } + if (linebuf[0] != ':') + continue; + if (!isxdigit(linebuf[1]) || !isxdigit(linebuf[2])) { +inv_record: fprintf(stderr, + "%s line %d: invalid Intex HEX record\n", + filename, lineno); + exit(1); + } + payload_len = decode_hex_byte(linebuf + 1); + if (payload_len > 16) { +bad_payload_len: fprintf(stderr, + "%s line %d: unsupported payload length\n", + filename, lineno); + exit(1); + } + record_len = payload_len + 5; + cp = linebuf + 1; + csum = 0; + for (n = 0; n < payload_len; n++) { + if (!isxdigit(cp[0]) || !isxdigit(cp[1])) + goto inv_record; + record[n] = decode_hex_byte(cp); + cp += 2; + csum += record[n]; + } + if (csum) { + fprintf(stderr, + "%s line %d: bad Intel HEX record checksum\n", + filename, lineno); + exit(1); + } + if (record[3] == 0x00) { + if (payload_len != 16) + goto bad_payload_len; + if (eeprom_offset >= SIZE_EEPROM) { + fprintf(stderr, + "%s line %d: data continues past valid EEPROM size\n", + filename, lineno); + exit(1); + } + record_addr = (record[1] << 8) | record[2]; + expect_addr = EEPROM_START_ADDR + eeprom_offset; + if (record_addr != expect_addr) { + fprintf(stderr, + "%s line %d: record addr is %04X, but we expect %04X\n", + filename, lineno, record_addr, + expect_addr); + exit(1); + } + bcopy(record + 4, eeprom + eeprom_offset, 16); + eeprom_offset += 16; + } else if (record[3] == 0x01) { + if (payload_len) { + fprintf(stderr, + "%s line %d: nonzero payload length in end-marker record\n", + filename, lineno); + exit(1); + } + if (eeprom_offset < SIZE_EEPROM) { + fprintf(stderr, + "%s line %d: end-marker without full data\n", + filename, lineno); + exit(1); + } + break; + } else { + fprintf(stderr, + "%s line %d: unsupported Intel HEX record type\n", + filename, lineno); + exit(1); + } + } + fclose(inf); + if (!eeprom_offset) { + fprintf(stderr, "error: no Intel HEX EEPROM data found in %s\n", + filename); + exit(1); + } + if (eeprom_offset < SIZE_EEPROM) { + fprintf(stderr, "error: %s contains truncated data\n", + filename); + exit(1); + } +}