Fix Intel hex ELAR record generation.

This commit is contained in:
David Carne 2013-07-08 08:38:31 +12:00 committed by Daniel Beer
parent 93faabd5e5
commit 8bec81f576
1 changed files with 40 additions and 16 deletions

View File

@ -371,6 +371,15 @@ int cmd_dis(char **arg)
return 0; return 0;
} }
#define IHEX_REC_DATA 0x00
#define IHEX_REC_EOF 0x01
#define IHEX_REC_ESAR 0x02
#define IHEX_REC_SSAR 0x03
#define IHEX_REC_ELAR 0x04
#define IHEX_REC_SLAR 0x05
#define IHEX_SEG(addr) (((addr) >> 16) & 0xFFFF)
struct hexout_data { struct hexout_data {
FILE *file; FILE *file;
address_t addr; address_t addr;
@ -403,17 +412,18 @@ static int hexout_start(struct hexout_data *hexout, const char *filename)
return 0; return 0;
} }
static int hexout_write(FILE *out, int len, uint16_t addr, static int hexout_write(FILE *out, uint8_t type, int len, uint16_t addr,
const uint8_t *payload) const uint8_t *payload)
{ {
int i; int i;
int cksum = 0; int cksum = 0;
if (fprintf(out, ":%02X%04X00", len, addr) < 0) if (fprintf(out, ":%02X%04X%02X", len, addr, type) < 0)
goto fail; goto fail;
cksum += len; cksum += len;
cksum += addr & 0xff; cksum += addr & 0xff;
cksum += addr >> 8; cksum += addr >> 8;
cksum += type;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
if (fprintf(out, "%02X", payload[i]) < 0) if (fprintf(out, "%02X", payload[i]) < 0)
@ -433,29 +443,43 @@ fail:
static int hexout_flush(struct hexout_data *hexout) static int hexout_flush(struct hexout_data *hexout)
{ {
address_t addr_low = hexout->addr & 0xffff; while (hexout->len) {
address_t segoff = hexout->addr >> 16; address_t addr_low = hexout->addr & 0xffff;
address_t segoff = IHEX_SEG(hexout->addr);
if (!hexout->len) if (segoff != hexout->segoff) {
return 0; uint8_t offset_data[] = {segoff >> 8, segoff & 0xff};
if (segoff != hexout->segoff) { if (hexout_write(hexout->file, IHEX_REC_ELAR,
uint8_t offset_data[] = {segoff >> 8, segoff & 0xff}; 2, 0, offset_data) < 0)
return -1;
hexout->segoff = segoff;
}
if (hexout_write(hexout->file, 2, 0, offset_data) < 0) uint32_t writesize = hexout->len;
/* If the hexout buffer will wrap past the end of segment;
* only write until the end of the segment to allow
* emitting an ELAR record */
if (IHEX_SEG(hexout->addr + writesize) != segoff)
writesize = 0x10000 - addr_low;
if (hexout_write(hexout->file, IHEX_REC_DATA, writesize, addr_low,
hexout->buf) < 0)
return -1; return -1;
hexout->segoff = segoff;
hexout->len -= writesize;
hexout->addr += writesize;
memmove(hexout->buf, hexout->buf + writesize,
sizeof(hexout->buf) - writesize);
} }
if (hexout_write(hexout->file, hexout->len, addr_low,
hexout->buf) < 0)
return -1;
hexout->len = 0;
return 0; return 0;
} }
static int hexout_feed(struct hexout_data *hexout, static int hexout_feed(struct hexout_data *hexout,
uint16_t addr, const uint8_t *buf, int len) uint32_t addr, const uint8_t *buf, int len)
{ {
while (len) { while (len) {
int count; int count;
@ -527,7 +551,7 @@ int cmd_hexout(char **arg)
if (hexout_flush(&hexout) < 0) if (hexout_flush(&hexout) < 0)
goto fail; goto fail;
if (fprintf(hexout.file, ":00000001FF\n") < 0) { if (hexout_write(hexout.file, IHEX_REC_EOF, 0, 0, NULL) < 0) {
pr_error("hexout: failed to write terminator\n"); pr_error("hexout: failed to write terminator\n");
goto fail; goto fail;
} }