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