summaryrefslogtreecommitdiff
path: root/avr/ihex.c
diff options
context:
space:
mode:
Diffstat (limited to 'avr/ihex.c')
-rw-r--r--avr/ihex.c202
1 files changed, 155 insertions, 47 deletions
diff --git a/avr/ihex.c b/avr/ihex.c
index 4e7b1a8..01fb6b0 100644
--- a/avr/ihex.c
+++ b/avr/ihex.c
@@ -15,6 +15,42 @@
//#include "debug.h"
+uint32_t detect_ramsize(void)
+{
+ uint32_t addr;
+ uint8_t save_addr, save_0;
+ const uint8_t PATTERN_1 = 0x55;
+ const uint8_t PATTERN_2 = ~PATTERN_1;
+
+ if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
+ my_puts_P(PSTR("Bus timeout\n"));
+ return 0;
+ }
+
+ save_0 = z80_read(0);
+ z80_write(0, PATTERN_1);
+
+ for (addr=1; addr < CONFIG_SYS_RAMSIZE_MAX; addr <<= 1) {
+ save_addr = z80_read(addr);
+ z80_write(addr, PATTERN_2);
+ if (z80_read(0) != PATTERN_1 || z80_read(addr) != PATTERN_2)
+ break;
+ z80_write(addr, save_addr);
+ }
+ z80_write(0, save_0);
+ z80_bus_cmd(Release);
+
+ return addr;
+}
+
+static uint32_t min(uint32_t a, uint32_t b)
+{
+ if (a < b)
+ return a;
+ return b;
+}
+
+
typedef enum {
IHX_OK,
IHX_BROKEN,
@@ -26,7 +62,7 @@ typedef struct {
int8_t type;
uint8_t len;
uint16_t address;
- uint8_t *data;
+ uint8_t data[256];
} ihex_t;
@@ -57,6 +93,8 @@ int get_hexbyte(void) {
return -1;
}
+#if 0
+
static
ihex_t ihex_get_record() {
@@ -122,73 +160,138 @@ ihex_t ihex_get_record() {
return rec;
}
+#else
+
+static
+int ihex_get_record(ihex_t *rec) {
+
+ int c;
+ uint8_t sum;
+
+ rec->status = IHX_BROKEN;
+
+
+ while ((c = my_getchar(0)) != ':')
+ if (c == 0x03)
+ return -1;
+
+ if ((c = get_hexbyte()) < 0) /* Start code */
+ return -1;
+ sum = c;
+ rec->len = c;
+ if ((c = get_hexbyte()) < 0) /* Byte Count */
+ return -1;
+ sum += c;
+ rec->address = c * 256;
+ if ((c = get_hexbyte()) < 0) /* Address */
+ return -1;
+ sum += c;
+ rec->address += c;
+ if ((c = get_hexbyte()) < 0) /* Record type */
+ return -1;
+ sum += c;
+ rec->type = c;
+
+ if (rec->len) { /* Record Data */
+ uint8_t n;
+
+ for (n = 0; n < rec->len; n++) {
+ if ((c = get_hexbyte()) < 0)
+ break;
+ sum += c;
+ rec->data[n] = c;
+ }
+
+ if (n < rec->len) {
+ return -1;
+ }
+ }
+
+ c = get_hexbyte(); /* Check sum */
+
+ if (c >= 0) {
+ sum += c;
+ if (sum == 0)
+ rec->status = IHX_OK;
+ else
+ rec->status = IHX_CHKSUMERR;
+ }
+
+ return rec->len;
+}
+
+#endif
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_max = detect_ramsize();
uint32_t address_high = 0;
- bool done = false;
+ uint32_t address_low = address_max;
command_ret_t rcode = CMD_RET_FAILURE;
ihex_t rec;
- (void) cmdtp;
- (void) flag;
+ (void) cmdtp; (void) flag;
+
+
+ printf_P(PSTR("RAM Size: 0x%.5lX\n"), address_max);
+
if (argc > 1)
offset = strtol(argv[1], NULL, 16);
- while (!done) {
- rec = ihex_get_record();
+ while (ihex_get_record(&rec) > 0 &&
+ rec.status == IHX_OK &&
+ rec.type != 1 ) {
+
+ 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;
- 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);
+printf_P(PSTR("low: 0x%.5lX, high: 0x%.5lX, max: 0x%.5lX, addr: 0x%.5lX, len: %d\n"),
+ address_low, address_high, address_max, addr, rec.len);
+
+ if (addr < address_max) {
+ uint32_t tmplen = address_max - addr;
+ if (rec.len > tmplen)
+ rec.len = tmplen;
+
+ if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
+ my_puts_P(PSTR("Bus timeout\n"));
+ return CMD_RET_FAILURE;
+ }
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;
-
}
+ break;
- } else
- done = true;
+#if 0
+ case 1: /* EOF record */
+ break;
+#endif
+ case 2: /* Extended Segment Address Record */
+ base_address = ((rec.data[0] << 8) + rec.data[1]) << 4;
+ break;
- free(rec.data);
- rec.data = 0;
+ case 4: /* Extended Linear Address Record */
+ base_address = (uint32_t)((rec.data[0] << 8) + rec.data[1]) << 16;
+ break;
+ case 3: /* Start Segment Address Record (ignored)*/
+ case 5: /* Start Linear Address Record (ignored)*/
+ break;
+
+ }
}
switch (rec.status) {
@@ -202,11 +305,16 @@ command_ret_t do_loadihex(cmd_tbl_t *cmdtp, int flag, int argc, char * const arg
break;
}
- printf_P(PSTR("Data loaded - "));
- if (address_low >= address_high)
+ printf_P(PSTR("Data loaded: "));
+ if (address_low >= min(address_high, address_max))
printf_P(PSTR("None.\n"));
else
- printf_P(PSTR("low: 0x%.5lX high: 0x%.5lX\n"), address_low, address_high);
+ printf_P(PSTR("low: 0x%.5lX high: 0x%.5lX\n"), address_low,
+ min(address_high, address_max) - 1);
+
+ if (address_high > address_max)
+ printf_P(PSTR("Data above highest RAM address "
+ "(Range 0x%.5lX...0x%.5lX) ignored!\n"), address_max, address_high - 1);
return rcode;
}