Provide file format I: Intel HEX with comments that ignores checksum errors

The new file type I is essentially Intel HEX that, on download, inserts
comments next to data records with the resolved effective address and an
ASCII dump of that same record. On upload the `I` format is permissive
with respect to check sum errors, eg, after manipulated an Intel HEX file
for debugging.
This commit is contained in:
Stefan Rueger 2022-07-16 23:40:36 +01:00
parent c81f52ff10
commit 79921e52dc
5 changed files with 50 additions and 19 deletions

View File

@ -709,6 +709,8 @@ can be one of:
.Bl -tag -width sss .Bl -tag -width sss
.It Ar i .It Ar i
Intel Hex Intel Hex
.It Ar I
Intel Hex with comments on download and tolerance of checksum errors on upload
.It Ar s .It Ar s
Motorola S-record Motorola S-record
.It Ar r .It Ar r

View File

@ -768,6 +768,9 @@ the file to read or write. Possible values are:
@item i @item i
Intel Hex Intel Hex
@item I
Intel Hex with comments on download and tolerance of checksum errors on upload
@item s @item s
Motorola S-record Motorola S-record

View File

@ -59,10 +59,11 @@ struct ihexrec {
static int b2ihex(unsigned char * inbuf, int bufsize, static int b2ihex(unsigned char * inbuf, int bufsize,
int recsize, int startaddr, int recsize, int startaddr,
char * outfile, FILE * outf); char * outfile, FILE * outf, FILEFMT ffmt);
static int ihex2b(char * infile, FILE * inf, static int ihex2b(char * infile, FILE * inf,
AVRMEM * mem, int bufsize, unsigned int fileoffset); AVRMEM * mem, int bufsize, unsigned int fileoffset,
FILEFMT ffmt);
static int b2srec(unsigned char * inbuf, int bufsize, static int b2srec(unsigned char * inbuf, int bufsize,
int recsize, int startaddr, int recsize, int startaddr,
@ -79,7 +80,8 @@ static int fileio_rbin(struct fioparms * fio,
char * filename, FILE * f, AVRMEM * mem, int size); char * filename, FILE * f, AVRMEM * mem, int size);
static int fileio_ihex(struct fioparms * fio, static int fileio_ihex(struct fioparms * fio,
char * filename, FILE * f, AVRMEM * mem, int size); char * filename, FILE * f, AVRMEM * mem, int size,
FILEFMT ffmt);
static int fileio_srec(struct fioparms * fio, static int fileio_srec(struct fioparms * fio,
char * filename, FILE * f, AVRMEM * mem, int size); char * filename, FILE * f, AVRMEM * mem, int size);
@ -108,6 +110,7 @@ char * fmtstr(FILEFMT format)
case FMT_AUTO : return "auto-detect"; break; case FMT_AUTO : return "auto-detect"; break;
case FMT_SREC : return "Motorola S-Record"; break; case FMT_SREC : return "Motorola S-Record"; break;
case FMT_IHEX : return "Intel Hex"; break; case FMT_IHEX : return "Intel Hex"; break;
case FMT_IHXC : return "Intel Hex with comments"; break;
case FMT_RBIN : return "raw binary"; break; case FMT_RBIN : return "raw binary"; break;
case FMT_ELF : return "ELF"; break; case FMT_ELF : return "ELF"; break;
default : return "invalid format"; break; default : return "invalid format"; break;
@ -115,10 +118,9 @@ char * fmtstr(FILEFMT format)
} }
static int b2ihex(unsigned char * inbuf, int bufsize, static int b2ihex(unsigned char * inbuf, int bufsize,
int recsize, int startaddr, int recsize, int startaddr,
char * outfile, FILE * outf) char * outfile, FILE * outf, FILEFMT ffmt)
{ {
unsigned char * buf; unsigned char * buf;
unsigned int nextaddr; unsigned int nextaddr;
@ -154,8 +156,20 @@ static int b2ihex(unsigned char * inbuf, int bufsize,
cksum += buf[i]; cksum += buf[i];
} }
cksum = -cksum; cksum = -cksum;
fprintf(outf, "%02X\n", cksum); fprintf(outf, "%02X", cksum);
if(ffmt == FMT_IHXC) { /* Print comment with address and ASCII dump */
for(i=n; i<recsize; i++)
fprintf(outf, " ");
fprintf(outf, " // %05x> ", n_64k*0x10000 + nextaddr);
for (i=0; i<n; i++) {
unsigned char c = buf[i] & 0x7f;
/* Print space as _ so that line is one word */
putc(c == ' '? '_': c < ' ' || c == 0x7f? '.': c, outf);
}
}
putc('\n', outf);
nextaddr += n; nextaddr += n;
nbytes += n; nbytes += n;
} }
@ -283,7 +297,8 @@ static int ihex_readrec(struct ihexrec * ihex, char * rec)
* *
* */ * */
static int ihex2b(char * infile, FILE * inf, static int ihex2b(char * infile, FILE * inf,
AVRMEM * mem, int bufsize, unsigned int fileoffset) AVRMEM * mem, int bufsize, unsigned int fileoffset,
FILEFMT ffmt)
{ {
char buffer [ MAX_LINE_LEN ]; char buffer [ MAX_LINE_LEN ];
unsigned int nextaddr, baseaddr, maxaddr; unsigned int nextaddr, baseaddr, maxaddr;
@ -312,11 +327,18 @@ static int ihex2b(char * infile, FILE * inf,
return -1; return -1;
} }
else if (rc != ihex.cksum) { else if (rc != ihex.cksum) {
avrdude_message(MSG_INFO, "%s: ERROR: checksum mismatch at line %d of \"%s\"\n", if(ffmt == FMT_IHEX) {
progname, lineno, infile); avrdude_message(MSG_INFO, "%s: ERROR: checksum mismatch at line %d of \"%s\"\n",
avrdude_message(MSG_INFO, "%s: checksum=0x%02x, computed checksum=0x%02x\n", progname, lineno, infile);
progname, ihex.cksum, rc); avrdude_message(MSG_INFO, "%s: checksum=0x%02x, computed checksum=0x%02x\n",
return -1; progname, ihex.cksum, rc);
return -1;
} else { /* Just warn with more permissive format FMT_IHXC */
avrdude_message(MSG_NOTICE, "%s: warning: checksum mismatch at line %d of \"%s\"\n",
progname, lineno, infile);
avrdude_message(MSG_NOTICE, "%s: checksum=0x%02x, computed checksum=0x%02x\n",
progname, ihex.cksum, rc);
}
} }
switch (ihex.rectyp) { switch (ihex.rectyp) {
@ -1152,21 +1174,22 @@ static int fileio_imm(struct fioparms * fio,
} }
static int fileio_ihex(struct fioparms * fio, static int fileio_ihex(struct fioparms * fio,
char * filename, FILE * f, AVRMEM * mem, int size) char * filename, FILE * f, AVRMEM * mem, int size,
FILEFMT ffmt)
{ {
int rc; int rc;
switch (fio->op) { switch (fio->op) {
case FIO_WRITE: case FIO_WRITE:
rc = b2ihex(mem->buf, size, 32, fio->fileoffset, filename, f); rc = b2ihex(mem->buf, size, 32, fio->fileoffset, filename, f, ffmt);
if (rc < 0) { if (rc < 0) {
return -1; return -1;
} }
break; break;
case FIO_READ: case FIO_READ:
rc = ihex2b(filename, f, mem, size, fio->fileoffset); rc = ihex2b(filename, f, mem, size, fio->fileoffset, ffmt);
if (rc < 0) if (rc < 0)
return -1; return -1;
break; break;
@ -1547,7 +1570,8 @@ int fileio(int oprwv, char * filename, FILEFMT format,
switch (format) { switch (format) {
case FMT_IHEX: case FMT_IHEX:
rc = fileio_ihex(&fio, fname, f, mem, size); case FMT_IHXC:
rc = fileio_ihex(&fio, fname, f, mem, size, format);
break; break;
case FMT_SREC: case FMT_SREC:

View File

@ -822,7 +822,8 @@ typedef enum {
FMT_DEC, FMT_DEC,
FMT_OCT, FMT_OCT,
FMT_BIN, FMT_BIN,
FMT_ELF FMT_ELF,
FMT_IHXC,
} FILEFMT; } FILEFMT;
struct fioparms { struct fioparms {

View File

@ -130,6 +130,7 @@ UPDATE * parse_op(char * s)
case 'a': upd->format = FMT_AUTO; break; case 'a': upd->format = FMT_AUTO; break;
case 's': upd->format = FMT_SREC; break; case 's': upd->format = FMT_SREC; break;
case 'i': upd->format = FMT_IHEX; break; case 'i': upd->format = FMT_IHEX; break;
case 'I': upd->format = FMT_IHXC; break;
case 'r': upd->format = FMT_RBIN; break; case 'r': upd->format = FMT_RBIN; break;
case 'e': upd->format = FMT_ELF; break; case 'e': upd->format = FMT_ELF; break;
case 'm': upd->format = FMT_IMM; break; case 'm': upd->format = FMT_IMM; break;