From 8e4434caffc71abb2fd984e807c70bb211c99a68 Mon Sep 17 00:00:00 2001 From: Michel Date: Wed, 10 Mar 2010 18:04:53 +0000 Subject: [PATCH] hex: Added a new reader for multiple chunks .hex files can contain more than one section of data this new loader handles that, allowing to have multiple section of flash (app + bootloader) and/or eeprom. Oh, a test unit too. Signed-off-by: Michel Pollet --- simavr/sim/sim_hex.c | 95 ++++++++++++++++++++++++++++++++++++++++++++ simavr/sim/sim_hex.h | 14 +++++++ 2 files changed, 109 insertions(+) diff --git a/simavr/sim/sim_hex.c b/simavr/sim/sim_hex.c index 6280320..0a8b10f 100644 --- a/simavr/sim/sim_hex.c +++ b/simavr/sim/sim_hex.c @@ -137,3 +137,98 @@ uint8_t * read_ihex_file(const char * fname, uint32_t * dsize, uint32_t * start) fclose(f); return res; } + + +int read_ihex_chunks(const char * fname, struct ihex_chunk_t * chunks, int max_chunks) +{ + if (!fname || !chunks || !max_chunks) + return -1; + memset((void*)chunks, 0, sizeof(chunks[0]) * max_chunks); + FILE * f = fopen(fname, "r"); + if (!f) { + perror(fname); + return -1; + } + uint32_t segment = 0; // segment address + int chunk = 0; + chunks[0].baseaddr = ~0; + + while (!feof(f)) { + char line[128]; + if (!fgets(line, sizeof(line)-1, f)) + continue; + if (line[0] != ':') { + fprintf(stderr, "AVR: '%s' invalid ihex format (%.4s)\n", fname, line); + break; + } + uint8_t bline[64]; + + int len = read_hex_string(line + 1, bline, sizeof(bline)); + if (len <= 0) + continue; + + uint8_t chk = 0; + { // calculate checksum + uint8_t * src = bline; + int tlen = len-1; + while (tlen--) + chk += *src++; + chk = 0x100 - chk; + } + if (chk != bline[len-1]) { + fprintf(stderr, "%s: %s, invalid checksum %02x/%02x\n", __FUNCTION__, fname, chk, bline[len-1]); + break; + } + uint32_t addr = 0; + switch (bline[3]) { + case 0: // normal data + addr = segment + (bline[1] << 8) | bline[2]; + break; + case 1: // end of file + continue; + case 2: // extended address 2 bytes + segment = ((bline[4] << 8) | bline[5]) << 4; + continue; + case 4: + segment = ((bline[4] << 8) | bline[5]) << 16; + continue; + default: + fprintf(stderr, "%s: %s, unsupported check type %02x\n", __FUNCTION__, fname, bline[3]); + continue; + } + if (addr != chunks[chunk].baseaddr + chunks[chunk].size) { + if (chunks[chunk].size) + chunk++; + chunks[chunk].baseaddr = addr; + } + chunks[chunk].data = realloc(chunks[chunk].data, chunks[chunk].size + bline[0]); + memcpy(chunks[chunk].data + chunks[chunk].size, bline + 4, bline[0]); + chunks[chunk].size += bline[0]; + } + if (chunks[chunk].size) + chunk++; + fclose(f); + return chunk; +} + + +#ifdef IHEX_TEST +// gcc -std=gnu99 -Isimavr/sim simavr/sim/sim_hex.c -o sim_hex -DIHEX_TEST +int main(int argc, char * argv[]) +{ + struct ihex_chunk_t chunk[4]; + + for (int fi = 1; fi < argc; fi++) { + int c = read_ihex_chunks(argv[fi], chunk, 4); + if (c == -1) { + perror(argv[fi]); + continue; + } + for (int ci = 0; ci < c; ci++) { + char n[96]; + sprintf(n, "%s[%d] = %08x", argv[fi], ci, chunk[ci].baseaddr); + hdump(n, chunk[ci].data, chunk[ci].size); + } + } +} +#endif diff --git a/simavr/sim/sim_hex.h b/simavr/sim/sim_hex.h index caf0afc..83f50db 100644 --- a/simavr/sim/sim_hex.h +++ b/simavr/sim/sim_hex.h @@ -28,6 +28,20 @@ // parses a hex text string 'src' of at max 'maxlen' characters, decodes it into 'buffer' int read_hex_string(const char * src, uint8_t * buffer, int maxlen); +// a .hex file chunk (base address + size) +struct ihex_chunk_t { + uint32_t baseaddr; // offset it started at in the .hex file + uint8_t * data; // read data + uint32_t size; // read data size +}; + +/* + * Read a .hex file, detects the various different chunks in it from their starting + * addresses and fills up the chunks passed as arguments up to max_chunks. + * Returns the number of chunks found, or -1 if an error occurs. + */ +int read_ihex_chunks(const char * fname, struct ihex_chunk_t * chunks, int max_chunks); + // reads IHEX file 'fname', puts it's decoded size in *'dsize' and returns // a newly allocated buffer with the binary data (or NULL, if error) uint8_t * read_ihex_file(const char * fname, uint32_t * dsize, uint32_t * start); -- 2.20.1