]> cloudbase.mooo.com Git - z180-stamp.git/blame - avr/cmd_loadihex.c
z80_bus_cmd(): wait for BUSACK==1 after BUSREQ=1
[z180-stamp.git] / avr / cmd_loadihex.c
CommitLineData
179bc609
L
1/*
2 * (C) Copyright 2015 Leo C. <erbl259-lmu@yahoo.de>
3 *
fcf1d5b3 4 * SPDX-License-Identifier: GPL-2.0
179bc609
L
5 */
6
7eecbdac 7#include "cmd_loadihex.h"
179bc609 8#include <ctype.h>
179bc609 9
179bc609
L
10#include "con-utils.h"
11#include "z80-if.h"
d264541a 12#include "debug.h"
179bc609
L
13
14
15typedef enum {
16 IHX_OK,
17 IHX_BROKEN,
18 IHX_CHKSUMERR
19} ihx_rstat_t;
20
21typedef struct {
22 ihx_rstat_t status;
23 int8_t type;
24 uint8_t len;
25 uint16_t address;
5480dc65 26 uint8_t data[256];
179bc609
L
27} ihex_t;
28
29
1633073f
L
30static int get_hexdigit(void)
31{
179bc609
L
32 int c;
33 c = toupper(my_getchar(1));
34 if (isxdigit(c)) {
35 c -= '0';
36 if (c > 9)
37 c -= ('A' - '0' - 10);
38 return c;
39 } else
40 return -1;
41}
42
1633073f
L
43static int get_hexbyte(void)
44{
179bc609
L
45 uint8_t i,j;
46
47 if ((i = (uint8_t) get_hexdigit()) < 0x10)
48 if ((j = (uint8_t) get_hexdigit()) < 0x10) {
49 return (i<<4) + j;
50 }
51
52 return -1;
53}
54
5480dc65 55
1633073f
L
56static int ihex_get_record(ihex_t *rec)
57{
5480dc65
L
58 int c;
59 uint8_t sum;
60
61 rec->status = IHX_BROKEN;
bf587043
L
62 rec->len = 0;
63 rec->type = 0xff;
5480dc65 64
bf587043 65 while ((c = my_getchar(0)) != ':') {
5480dc65 66 if (c == 0x03)
bf587043
L
67 return -1; /* Control-C */
68 if (c == 0x04) {
69 rec->status = IHX_OK;
70 return 0; /*Control-D, EOF */
71 }
72 }
5480dc65
L
73
74 if ((c = get_hexbyte()) < 0) /* Start code */
75 return -1;
76 sum = c;
77 rec->len = c;
78 if ((c = get_hexbyte()) < 0) /* Byte Count */
79 return -1;
80 sum += c;
81 rec->address = c * 256;
82 if ((c = get_hexbyte()) < 0) /* Address */
83 return -1;
84 sum += c;
85 rec->address += c;
86 if ((c = get_hexbyte()) < 0) /* Record type */
87 return -1;
88 sum += c;
89 rec->type = c;
90
91 if (rec->len) { /* Record Data */
92 uint8_t n;
93
94 for (n = 0; n < rec->len; n++) {
95 if ((c = get_hexbyte()) < 0)
96 break;
97 sum += c;
98 rec->data[n] = c;
99 }
100
101 if (n < rec->len) {
102 return -1;
103 }
104 }
105
106 c = get_hexbyte(); /* Check sum */
107
108 if (c >= 0) {
109 sum += c;
110 if (sum == 0)
111 rec->status = IHX_OK;
112 else
113 rec->status = IHX_CHKSUMERR;
114 }
115
116 return rec->len;
117}
118
179bc609 119
1633073f 120command_ret_t do_loadihex(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, char * const argv[])
179bc609
L
121{
122 long offset = 0;
123 uint32_t base_address = 0;
179bc609 124 uint32_t address_high = 0;
1e5609bf
L
125 uint32_t address_max;
126 uint32_t address_low;
bf587043 127 bool firstrec = true;
1633073f 128 ihex_t rec;
5480dc65 129
179bc609
L
130 if (argc > 1)
131 offset = strtol(argv[1], NULL, 16);
132
1e5609bf
L
133 int32_t ram = z80_memsize_detect();
134 if (ram < 0)
135 cmd_error(CMD_RET_FAILURE, (ERRNUM) -ram, NULL);
136
137 address_max = ram;
138 address_low = address_max;
139
1633073f 140 my_puts_P(PSTR("Waiting for Intel Hex Records...\n"));
bf587043 141
5480dc65
L
142 while (ihex_get_record(&rec) > 0 &&
143 rec.status == IHX_OK &&
144 rec.type != 1 ) {
145
146 switch (rec.type) {
147 case 0: /* Data record */
bf587043 148 if (firstrec) {
1633073f 149 my_puts_P(PSTR("Loading: 0x....."));
bf587043
L
150 firstrec = false;
151 }
5480dc65
L
152 if (rec.len) {
153 uint32_t addr = base_address + rec.address + offset;
154 if (addr < address_low)
155 address_low = addr;
156 if (addr+rec.len > address_high)
157 address_high = addr + rec.len;
179bc609 158
d264541a
L
159// debug("low: 0x%.5lX, high: 0x%.5lX, max: 0x%.5lX, addr: 0x%.5lX, len: %d\n",
160// address_low, address_high, address_max, addr, rec.len);
bf587043 161 printf_P(PSTR("\b\b\b\b\b%.5lX"), addr);
5480dc65
L
162 if (addr < address_max) {
163 uint32_t tmplen = address_max - addr;
164 if (rec.len > tmplen)
165 rec.len = tmplen;
166
e9d96859 167 z80_bus_request_or_exit();
179bc609
L
168 z80_write_block(rec.data, /* src */
169 addr, /* dest */
170 rec.len); /* len */
171 z80_bus_cmd(Release);
172 }
179bc609 173 }
5480dc65 174 break;
179bc609 175
5480dc65
L
176#if 0
177 case 1: /* EOF record */
178 break;
179#endif
180 case 2: /* Extended Segment Address Record */
d264541a 181 base_address = (uint32_t)((rec.data[0] << 8) + rec.data[1]) << 4;
5480dc65 182 break;
ae017d4c 183
5480dc65
L
184 case 4: /* Extended Linear Address Record */
185 base_address = (uint32_t)((rec.data[0] << 8) + rec.data[1]) << 16;
186 break;
ae017d4c 187
5480dc65
L
188 case 3: /* Start Segment Address Record (ignored)*/
189 case 5: /* Start Linear Address Record (ignored)*/
190 break;
191
192 }
179bc609
L
193 }
194
1633073f
L
195 if (rec.status != IHX_OK)
196 my_puts_P(PSTR("Broken Hex Record or loading interrupted!\n"));
4cbc8d3e 197
bf587043
L
198 for (uint_fast8_t i=0; i<100; ++i) {
199 /* flush input buffer */
200 while (my_getchar(0) > 0)
201 ;
202 udelay(1000);
203 }
204
1633073f 205 my_puts_P(PSTR("\nData loaded: "));
d264541a 206 if (address_low >= MIN(address_high, address_max))
1633073f 207 my_puts_P(PSTR("None.\n"));
179bc609 208 else
5480dc65 209 printf_P(PSTR("low: 0x%.5lX high: 0x%.5lX\n"), address_low,
d264541a 210 MIN(address_high, address_max) - 1);
5480dc65
L
211
212 if (address_high > address_max)
213 printf_P(PSTR("Data above highest RAM address "
d264541a 214 "(in range 0x%.5lX - 0x%.5lX) ignored!\n"), address_max, address_high - 1);
179bc609 215
1633073f 216 return rec.status == IHX_OK ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
179bc609 217}