/********************************************************************** * ********************************************************************** 0 1 2 3 4 :1000100084C083C082C081C080C07FC07EC07DC0DC ~~ データ長 ~~~~ アドレス ~~ レコードタイプ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~データ ~~チェックサム. */ int read_ihex(char *s) { int c; if(s[0] == ':') { read_hex_string(s+1); c = databuf[3]; parse_ihex(c,databuf,dataidx); } return 0; }
uint8_t * read_ihex_file(const char * fname, uint32_t * dsize, uint32_t * start) { if (!fname || !dsize) return NULL; FILE * f = fopen(fname, "r"); if (!f) { perror(fname); return NULL; } uint8_t * res = NULL; uint32_t size = 0; uint32_t base = ~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; } if (bline[3] != 0) { if (bline[3] != 1) { fprintf(stderr, "%s: %s, unsupported check type %02x\n", __FUNCTION__, fname, bline[3]); break; } continue; } uint16_t addr = (bline[1] << 8) | bline[2]; if (base == ~0) { base = addr; // start address } if (addr != base + size) { fprintf(stderr, "%s: %s, offset out of bounds %04x expected %04x\n", __FUNCTION__, fname, addr, base+size); break; } res = realloc(res, size + bline[0]); memcpy(res + size, bline + 4, bline[0]); size += bline[0]; } *dsize = size; if (start) *start = base; fclose(f); return res; }
int read_ihex_chunks(ihex_chunk_p * chunks) { if(!chunks) return -1; uint32_t segment = 0; // segment address int chunk = 0, max_chunks = 0; *chunks = NULL; int current = 0; while(current < number_of_chunks) { char line[128]; memcpy(line, loaded_chunk[current], strlen(loaded_chunk[current])+1); current++; if (line[0] != ':') { 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]) { 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: continue; } if (chunk < max_chunks && addr != ((*chunks)[chunk].baseaddr + (*chunks)[chunk].size)) { if ((*chunks)[chunk].size) chunk++; } if (chunk >= max_chunks) { max_chunks++; *chunks = realloc(*chunks, max_chunks * sizeof(ihex_chunk_t)); memset(*chunks + chunk, 0, (max_chunks - chunk) * sizeof(ihex_chunk_t)); (*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]; } return max_chunks; }
int read_ihex_chunks (const char *fname, ihex_chunk_p * chunks) { if (!fname || !chunks) return -1; FILE *f = fopen (fname, "r"); if (!f) { perror (fname); return -1; } uint32_t segment = 0; // segment address int chunk = 0, max_chunks = 0; *chunks = NULL; 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 (chunk < max_chunks && addr != ((*chunks)[chunk].baseaddr + (*chunks)[chunk].size)) { if ((*chunks)[chunk].size) chunk++; } if (chunk >= max_chunks) { max_chunks++; *chunks = realloc (*chunks, max_chunks * sizeof (ihex_chunk_t)); memset (*chunks + chunk, 0, (max_chunks - chunk) * sizeof (ihex_chunk_t)); (*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]; } fclose (f); return max_chunks; }