summaryrefslogtreecommitdiff
path: root/avr
diff options
context:
space:
mode:
authorLeo C2015-04-18 02:10:01 +0200
committerLeo C2015-04-18 02:10:01 +0200
commit179bc6099854fc3772517d781052b0d9aabc7329 (patch)
tree30459a27e7b2f0f390aac0d3cbd0a7bf31999f72 /avr
parentcb52e1e0dbfdf6c6defe20b3711e0c50285748f5 (diff)
downloadz180-stamp-179bc6099854fc3772517d781052b0d9aabc7329.zip
Add command loadi (load intel hex file)
Diffstat (limited to 'avr')
-rw-r--r--avr/Tupfile2
-rw-r--r--avr/command_tbl.c6
-rw-r--r--avr/ihex.c199
3 files changed, 206 insertions, 1 deletions
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 []);
@@ -126,6 +127,11 @@ CMD_TBL_ITEM(
""
),
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'",
"addr\n"
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. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include "common.h"
+#include <stdlib.h>
+#include <ctype.h>
+#include <stdbool.h>
+
+#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;
+}