4 Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
6 This file is part of simavr.
8 simavr is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 simavr is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with simavr. If not, see <http://www.gnu.org/licenses/>.
28 void hdump(const char *w, uint8_t *b, size_t l)
33 for (i = 0; i < l; i++) printf("%02x",b[i]);
36 for (i = 0; i < l; i++) {
37 if (!(i & 0x1f)) printf(" ");
39 if ((i & 0x1f) == 0x1f) {
48 // decode line text hex to binary
49 int read_hex_string(const char * src, uint8_t * buffer, int maxlen)
51 uint8_t * dst = buffer;
54 while (*src && maxlen--) {
57 case 'a' ... 'f': b = (b << 4) | (c - 'a' + 0xa); break;
58 case 'A' ... 'F': b = (b << 4) | (c - 'A' + 0xa); break;
59 case '0' ... '9': b = (b << 4) | (c - '0'); break;
62 fprintf(stderr, "%s: huh '%c' (%s)\n", __FUNCTION__, c, src);
76 uint8_t * read_ihex_file(const char * fname, uint32_t * dsize, uint32_t * start)
80 FILE * f = fopen(fname, "r");
91 if (!fgets(line, sizeof(line)-1, f))
94 fprintf(stderr, "AVR: '%s' invalid ihex format (%.4s)\n", fname, line);
99 int len = read_hex_string(line + 1, bline, sizeof(bline));
104 { // calculate checksum
105 uint8_t * src = bline;
111 if (chk != bline[len-1]) {
112 fprintf(stderr, "%s: %s, invalid checksum %02x/%02x\n", __FUNCTION__, fname, chk, bline[len-1]);
117 fprintf(stderr, "%s: %s, unsupported check type %02x\n", __FUNCTION__, fname, bline[3]);
122 uint16_t addr = (bline[1] << 8) | bline[2];
124 base = addr; // start address
126 if (addr != base + size) {
127 fprintf(stderr, "%s: %s, offset out of bounds %04x expected %04x\n", __FUNCTION__, fname, addr, base+size);
130 res = realloc(res, size + bline[0]);
131 memcpy(res + size, bline + 4, bline[0]);
145 ihex_chunk_p * chunks )
147 if (!fname || !chunks)
149 FILE * f = fopen(fname, "r");
154 uint32_t segment = 0; // segment address
155 int chunk = 0, max_chunks = 0;
160 if (!fgets(line, sizeof(line)-1, f))
162 if (line[0] != ':') {
163 fprintf(stderr, "AVR: '%s' invalid ihex format (%.4s)\n", fname, line);
168 int len = read_hex_string(line + 1, bline, sizeof(bline));
173 { // calculate checksum
174 uint8_t * src = bline;
180 if (chk != bline[len-1]) {
181 fprintf(stderr, "%s: %s, invalid checksum %02x/%02x\n", __FUNCTION__, fname, chk, bline[len-1]);
186 case 0: // normal data
187 addr = segment | (bline[1] << 8) | bline[2];
189 case 1: // end of file
191 case 2: // extended address 2 bytes
192 segment = ((bline[4] << 8) | bline[5]) << 4;
195 segment = ((bline[4] << 8) | bline[5]) << 16;
198 fprintf(stderr, "%s: %s, unsupported check type %02x\n", __FUNCTION__, fname, bline[3]);
201 if (chunk < max_chunks && addr != ((*chunks)[chunk].baseaddr + (*chunks)[chunk].size)) {
202 if ((*chunks)[chunk].size)
205 if (chunk >= max_chunks) {
207 *chunks = realloc(*chunks, max_chunks * sizeof(ihex_chunk_t));
208 memset(*chunks + chunk, 0, (max_chunks - chunk) * sizeof(ihex_chunk_t));
209 (*chunks)[chunk].baseaddr = addr;
211 (*chunks)[chunk].data = realloc((*chunks)[chunk].data, (*chunks)[chunk].size + bline[0]);
212 memcpy((*chunks)[chunk].data + (*chunks)[chunk].size, bline + 4, bline[0]);
213 (*chunks)[chunk].size += bline[0];
221 // gcc -std=gnu99 -Isimavr/sim simavr/sim/sim_hex.c -o sim_hex -DIHEX_TEST -Dtest_main=main
222 int test_main(int argc, char * argv[])
224 struct ihex_chunk_t chunk[4];
226 for (int fi = 1; fi < argc; fi++) {
227 int c = read_ihex_chunks(argv[fi], chunk, 4);
232 for (int ci = 0; ci < c; ci++) {
234 sprintf(n, "%s[%d] = %08x", argv[fi], ci, chunk[ci].baseaddr);
235 hdump(n, chunk[ci].data, chunk[ci].size);