]> cloudbase.mooo.com Git - z180-stamp.git/blob - avr/cmd_loadihex.c
Rename ihex.c to cmd_loadihex.c
[z180-stamp.git] / avr / cmd_loadihex.c
1 /*
2 * (C) Copyright 2015 Leo C. <erbl259-lmu@yahoo.de>
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7 #include "common.h"
8 #include <stdlib.h>
9 #include <ctype.h>
10 #include <stdbool.h>
11
12 #include "command.h"
13 #include "con-utils.h"
14 #include "z80-if.h"
15 //#include "debug.h"
16
17
18 uint32_t detect_ramsize(void)
19 {
20 uint32_t addr;
21 uint8_t save_addr, save_0;
22 const uint8_t PATTERN_1 = 0x55;
23 const uint8_t PATTERN_2 = ~PATTERN_1;
24
25 if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
26 my_puts_P(PSTR("Bus timeout\n"));
27 return 0;
28 }
29
30 save_0 = z80_read(0);
31 z80_write(0, PATTERN_1);
32
33 for (addr=1; addr < CONFIG_SYS_RAMSIZE_MAX; addr <<= 1) {
34 save_addr = z80_read(addr);
35 z80_write(addr, PATTERN_2);
36 if (z80_read(0) != PATTERN_1 || z80_read(addr) != PATTERN_2)
37 break;
38 z80_write(addr, save_addr);
39 }
40 z80_write(0, save_0);
41 z80_bus_cmd(Release);
42
43 return addr;
44 }
45
46 static uint32_t min(uint32_t a, uint32_t b)
47 {
48 if (a < b)
49 return a;
50 return b;
51 }
52
53
54 typedef enum {
55 IHX_OK,
56 IHX_BROKEN,
57 IHX_CHKSUMERR
58 } ihx_rstat_t;
59
60 typedef struct {
61 ihx_rstat_t status;
62 int8_t type;
63 uint8_t len;
64 uint16_t address;
65 uint8_t data[256];
66 } ihex_t;
67
68
69 static
70 int get_hexdigit(void) {
71
72 int c;
73 c = toupper(my_getchar(1));
74 if (isxdigit(c)) {
75 c -= '0';
76 if (c > 9)
77 c -= ('A' - '0' - 10);
78 return c;
79 } else
80 return -1;
81 }
82
83 static
84 int get_hexbyte(void) {
85
86 uint8_t i,j;
87
88 if ((i = (uint8_t) get_hexdigit()) < 0x10)
89 if ((j = (uint8_t) get_hexdigit()) < 0x10) {
90 return (i<<4) + j;
91 }
92
93 return -1;
94 }
95
96 #if 0
97
98 static
99 ihex_t ihex_get_record() {
100
101 int i;
102 uint8_t sum, c;
103 ihex_t rec = { IHX_BROKEN, 0, 0, 0, 0 };
104
105
106 while ((c = my_getchar(0)) != ':')
107 if (c == 0x03)
108 return rec;
109
110 if ((i = get_hexbyte()) < 0) /* Start code */
111 return rec;
112 sum = i;
113 rec.len = i;
114 if ((i = get_hexbyte()) < 0) /* Byte Count */
115 return rec;
116 sum += i;
117 rec.address = i * 256;
118 if ((i = get_hexbyte()) < 0) /* Address */
119 return rec;
120 sum += i;
121 rec.address += i;
122 if ((i = get_hexbyte()) < 0) /* Record type */
123 return rec;
124 sum += i;
125 rec.type = i;
126
127 if (rec.len) { /* Record Data */
128 uint8_t *p; int k;
129 if ((rec.data = malloc(rec.len)) == 0)
130 return rec;
131
132 for (p=rec.data, k=rec.len; k; k--) {
133 if ((i = get_hexbyte()) < 0)
134 break;
135 sum += i;
136 *p++ = i;
137 }
138
139 if (k) {
140 free(rec.data); rec.data = 0;
141 return rec;
142 }
143 }
144
145 i = get_hexbyte(); /* Check sum */
146
147 if (i >= 0) {
148 sum += i;
149 if (sum == 0)
150 rec.status = IHX_OK;
151 else
152 rec.status = IHX_CHKSUMERR;
153 }
154
155 if (rec.status != IHX_OK) {
156 free(rec.data);
157 rec.data = 0;
158 }
159
160 return rec;
161 }
162
163 #else
164
165 static
166 int ihex_get_record(ihex_t *rec) {
167
168 int c;
169 uint8_t sum;
170
171 rec->status = IHX_BROKEN;
172
173
174 while ((c = my_getchar(0)) != ':')
175 if (c == 0x03)
176 return -1;
177
178 if ((c = get_hexbyte()) < 0) /* Start code */
179 return -1;
180 sum = c;
181 rec->len = c;
182 if ((c = get_hexbyte()) < 0) /* Byte Count */
183 return -1;
184 sum += c;
185 rec->address = c * 256;
186 if ((c = get_hexbyte()) < 0) /* Address */
187 return -1;
188 sum += c;
189 rec->address += c;
190 if ((c = get_hexbyte()) < 0) /* Record type */
191 return -1;
192 sum += c;
193 rec->type = c;
194
195 if (rec->len) { /* Record Data */
196 uint8_t n;
197
198 for (n = 0; n < rec->len; n++) {
199 if ((c = get_hexbyte()) < 0)
200 break;
201 sum += c;
202 rec->data[n] = c;
203 }
204
205 if (n < rec->len) {
206 return -1;
207 }
208 }
209
210 c = get_hexbyte(); /* Check sum */
211
212 if (c >= 0) {
213 sum += c;
214 if (sum == 0)
215 rec->status = IHX_OK;
216 else
217 rec->status = IHX_CHKSUMERR;
218 }
219
220 return rec->len;
221 }
222
223 #endif
224
225 command_ret_t do_loadihex(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
226 {
227 long offset = 0;
228 uint32_t base_address = 0;
229 uint32_t address_max = detect_ramsize();
230 uint32_t address_high = 0;
231 uint32_t address_low = address_max;
232 command_ret_t rcode = CMD_RET_FAILURE;
233 ihex_t rec;
234
235 (void) cmdtp; (void) flag;
236
237
238 printf_P(PSTR("RAM Size: 0x%.5lX\n"), address_max);
239
240
241 if (argc > 1)
242 offset = strtol(argv[1], NULL, 16);
243
244 while (ihex_get_record(&rec) > 0 &&
245 rec.status == IHX_OK &&
246 rec.type != 1 ) {
247
248 switch (rec.type) {
249 case 0: /* Data record */
250 if (rec.len) {
251 uint32_t addr = base_address + rec.address + offset;
252 if (addr < address_low)
253 address_low = addr;
254 if (addr+rec.len > address_high)
255 address_high = addr + rec.len;
256
257
258 printf_P(PSTR("low: 0x%.5lX, high: 0x%.5lX, max: 0x%.5lX, addr: 0x%.5lX, len: %d\n"),
259 address_low, address_high, address_max, addr, rec.len);
260
261 if (addr < address_max) {
262 uint32_t tmplen = address_max - addr;
263 if (rec.len > tmplen)
264 rec.len = tmplen;
265
266 if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
267 my_puts_P(PSTR("Bus timeout\n"));
268 return CMD_RET_FAILURE;
269 }
270 z80_write_block(rec.data, /* src */
271 addr, /* dest */
272 rec.len); /* len */
273 z80_bus_cmd(Release);
274 }
275 }
276 break;
277
278 #if 0
279 case 1: /* EOF record */
280 break;
281 #endif
282 case 2: /* Extended Segment Address Record */
283 base_address = ((rec.data[0] << 8) + rec.data[1]) << 4;
284 break;
285
286 case 4: /* Extended Linear Address Record */
287 base_address = (uint32_t)((rec.data[0] << 8) + rec.data[1]) << 16;
288 break;
289
290 case 3: /* Start Segment Address Record (ignored)*/
291 case 5: /* Start Linear Address Record (ignored)*/
292 break;
293
294 }
295 }
296
297 switch (rec.status) {
298 case IHX_OK:
299 rcode = CMD_RET_SUCCESS;
300 break;
301
302 case IHX_BROKEN:
303 case IHX_CHKSUMERR:
304 printf_P(PSTR("Broken Hex Record or loading interrupted!\n"));
305 break;
306 }
307
308 printf_P(PSTR("Data loaded: "));
309 if (address_low >= min(address_high, address_max))
310 printf_P(PSTR("None.\n"));
311 else
312 printf_P(PSTR("low: 0x%.5lX high: 0x%.5lX\n"), address_low,
313 min(address_high, address_max) - 1);
314
315 if (address_high > address_max)
316 printf_P(PSTR("Data above highest RAM address "
317 "(Range 0x%.5lX...0x%.5lX) ignored!\n"), address_max, address_high - 1);
318
319 return rcode;
320 }