]> cloudbase.mooo.com Git - z180-stamp.git/blobdiff - avr/ihex.c
New memory test commands, loadi updates. Needs testing
[z180-stamp.git] / avr / ihex.c
index 4e7b1a8ec7e90e65f746fff8de1046154e19f000..01fb6b0bea8c32a99b9bbbfb5f92e164611f826d 100644 (file)
 //#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;
 }