From: Leo C Date: Sat, 18 Apr 2015 00:10:01 +0000 (+0200) Subject: Add command loadi (load intel hex file) X-Git-Tag: hexrel-5~4 X-Git-Url: http://cloudbase.mooo.com/gitweb/z180-stamp.git/commitdiff_plain/179bc6099854fc3772517d781052b0d9aabc7329 Add command loadi (load intel hex file) --- diff --git a/avr/Tupfile b/avr/Tupfile index 78e9744..87eca70 100644 --- a/avr/Tupfile +++ b/avr/Tupfile @@ -7,7 +7,7 @@ FATFS = $(TOP)/fatfs/src/ff.c SRC = main.c SRC += cli.c cli_readline.c command.c command_tbl.c SRC += cmd_help.c cmd_date.c cmd_mem.c cmd_boot.c cmd_gpio.c cmd_misc.c -SRC += cmd_sd.c cmd_fat.c +SRC += ihex.c cmd_sd.c cmd_fat.c SRC += env.c xmalloc.c con-utils.c print-utils.c getopt-min.c SRC += timer.c serial.c i2c.c pcf8583.c mmc.c SRC += background.c z180-serv.c z80-if.c gpio.c diff --git a/avr/command_tbl.c b/avr/command_tbl.c index d4ff6f2..2163526 100644 --- a/avr/command_tbl.c +++ b/avr/command_tbl.c @@ -16,6 +16,7 @@ extern command_ret_t do_env_default(cmd_tbl_t *, int, int, char * const []); extern command_ret_t do_env_set(cmd_tbl_t *, int, int, char * const []); extern command_ret_t do_env_save(cmd_tbl_t *, int, int, char * const []); extern command_ret_t do_loadf(cmd_tbl_t *, int, int, char * const []); +extern command_ret_t do_loadihex(cmd_tbl_t *, int, int, char * const []); extern command_ret_t do_go(cmd_tbl_t *, int, int, char * const []); extern command_ret_t do_restart(cmd_tbl_t *, int, int, char * const []); extern command_ret_t do_console(cmd_tbl_t *, int, int, char * const []); @@ -125,6 +126,11 @@ CMD_TBL_ITEM( "load srec_cat prepared image from controller flash", "" ), +CMD_TBL_ITEM( + loadi, 2, 0, do_loadihex, + "load intel hex file", + "[[-]offset]" +), CMD_TBL_ITEM( go, 2, 0, do_go, "start application at address 'addr'", diff --git a/avr/ihex.c b/avr/ihex.c new file mode 100644 index 0000000..2a9f033 --- /dev/null +++ b/avr/ihex.c @@ -0,0 +1,199 @@ +/* + * (C) Copyright 2015 Leo C. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "common.h" +#include +#include +#include + +#include "command.h" +#include "con-utils.h" +#include "z80-if.h" +//#include "debug.h" + + +typedef enum { + IHX_OK, + IHX_BROKEN, + IHX_CHKSUMERR +} ihx_rstat_t; + +typedef struct { + ihx_rstat_t status; + int8_t type; + uint8_t len; + uint16_t address; + uint8_t *data; +} ihex_t; + + +static +int get_hexdigit(void) { + + int c; + c = toupper(my_getchar(1)); + if (isxdigit(c)) { + c -= '0'; + if (c > 9) + c -= ('A' - '0' - 10); + return c; + } else + return -1; +} + +static +int get_hexbyte(void) { + + uint8_t i,j; + + if ((i = (uint8_t) get_hexdigit()) < 0x10) + if ((j = (uint8_t) get_hexdigit()) < 0x10) { + return (i<<4) + j; + } + + return -1; +} + +static +ihex_t ihex_get_record() { + + int i; + uint8_t sum, c; + ihex_t rec = { IHX_BROKEN, 0, 0, 0, 0 }; + + + while ((c = my_getchar(0)) != ':') + if (c == 0x03) + return rec; + + if ((i = get_hexbyte()) < 0) /* Start code */ + return rec; + sum = i; + rec.len = i; + if ((i = get_hexbyte()) < 0) /* Byte Count */ + return rec; + sum += i; + rec.address = i * 256; + if ((i = get_hexbyte()) < 0) /* Address */ + return rec; + sum += i; + rec.address += i; + if ((i = get_hexbyte()) < 0) /* Record type */ + return rec; + sum += i; + rec.type = i; + + if (rec.len) { /* Record Data */ + uint8_t *p; int k; + if ((rec.data = malloc(rec.len)) == 0) + return rec; + for (p=rec.data, k=rec.len; k; k--) { + if ((i = get_hexbyte()) < 0) + break; + sum += i; + *p++ = i; + } + if (k) { + free(rec.data); rec.data = 0; + return rec; + } + } + if ((i = get_hexbyte()) < 0) /* Check sum */ + return rec; + sum += i; + if (sum) { + free(rec.data); rec.data = 0; + rec.status = IHX_CHKSUMERR; + } else + rec.status = IHX_OK; + + return rec; +} + + +command_ret_t do_loadihex(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + long offset = 0; + uint32_t base_address = 0; + uint32_t address_low = 0xffffffff; + uint32_t address_high = 0; + bool done = false; + command_ret_t rcode = CMD_RET_FAILURE; + ihex_t rec; + + (void) cmdtp; + (void) flag; + + if (argc > 1) + offset = strtol(argv[1], NULL, 16); + + while (!done) { + rec = ihex_get_record(); + + if (rec.status == IHX_OK) { + switch (rec.type) { + case 0: /* Data record */ + if (rec.len) { + uint32_t addr = base_address + rec.address + offset; + if (addr < address_low) + address_low = addr; + if (addr+rec.len > address_high) + address_high = addr + rec.len; + + z80_bus_cmd(Request); + z80_write_block(rec.data, /* src */ + addr, /* dest */ + rec.len); /* len */ + z80_bus_cmd(Release); + } + continue; + break; + + case 1: /* EOF record */ + + done = true; + break; + + case 2: /* Extended Segment Address Record */ + base_address = ((rec.data[0] << 8) + rec.data[1]) << 4; + continue; + break; + + case 4: /* Extended Linear Address Record */ + base_address = (uint32_t)((rec.data[0] << 8) + rec.data[1]) << 16; + continue; + break; + + case 3: /* Start Segment Address Record (ignored)*/ + case 5: /* Start Linear Address Record (ignored)*/ + continue; + break; + + } + + } else + done = true; + } + + switch (rec.status) { + case IHX_OK: + rcode = CMD_RET_SUCCESS; + break; + + case IHX_BROKEN: + case IHX_CHKSUMERR: + printf_P(PSTR("Broken Hex Record or loading interrupted!\n")); + break; + } + + printf_P(PSTR("Data loaded - ")); + if (address_low >= address_high) + printf_P(PSTR("None.\n")); + else + printf_P(PSTR("low: 0x%.5lX high: 0x%.5lX\n"), address_low, address_high); + + return rcode; +}