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