]> cloudbase.mooo.com Git - z180-stamp.git/blame - avr/cmd_loadihex.c
loadi seems to work now.
[z180-stamp.git] / avr / cmd_loadihex.c
CommitLineData
179bc609
L
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"
d264541a 15#include "debug.h"
179bc609
L
16
17
5480dc65
L
18uint32_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
179bc609
L
46typedef enum {
47 IHX_OK,
48 IHX_BROKEN,
49 IHX_CHKSUMERR
50} ihx_rstat_t;
51
52typedef struct {
53 ihx_rstat_t status;
54 int8_t type;
55 uint8_t len;
56 uint16_t address;
5480dc65 57 uint8_t data[256];
179bc609
L
58} ihex_t;
59
60
61static
62int get_hexdigit(void) {
63
64 int c;
65 c = toupper(my_getchar(1));
66 if (isxdigit(c)) {
67 c -= '0';
68 if (c > 9)
69 c -= ('A' - '0' - 10);
70 return c;
71 } else
72 return -1;
73}
74
75static
76int get_hexbyte(void) {
77
78 uint8_t i,j;
79
80 if ((i = (uint8_t) get_hexdigit()) < 0x10)
81 if ((j = (uint8_t) get_hexdigit()) < 0x10) {
82 return (i<<4) + j;
83 }
84
85 return -1;
86}
87
5480dc65
L
88
89static
90int ihex_get_record(ihex_t *rec) {
91
92 int c;
93 uint8_t sum;
94
95 rec->status = IHX_BROKEN;
96
97
98 while ((c = my_getchar(0)) != ':')
99 if (c == 0x03)
100 return -1;
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
L
147
148command_ret_t do_loadihex(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
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;
179bc609
L
155 command_ret_t rcode = CMD_RET_FAILURE;
156 ihex_t rec;
157
5480dc65
L
158 (void) cmdtp; (void) flag;
159
160
179bc609
L
161 if (argc > 1)
162 offset = strtol(argv[1], NULL, 16);
163
5480dc65
L
164 while (ihex_get_record(&rec) > 0 &&
165 rec.status == IHX_OK &&
166 rec.type != 1 ) {
167
168 switch (rec.type) {
169 case 0: /* Data record */
170 if (rec.len) {
171 uint32_t addr = base_address + rec.address + offset;
172 if (addr < address_low)
173 address_low = addr;
174 if (addr+rec.len > address_high)
175 address_high = addr + rec.len;
179bc609 176
d264541a
L
177// debug("low: 0x%.5lX, high: 0x%.5lX, max: 0x%.5lX, addr: 0x%.5lX, len: %d\n",
178// address_low, address_high, address_max, addr, rec.len);
5480dc65
L
179
180 if (addr < address_max) {
181 uint32_t tmplen = address_max - addr;
182 if (rec.len > tmplen)
183 rec.len = tmplen;
184
185 if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
186 my_puts_P(PSTR("Bus timeout\n"));
187 return CMD_RET_FAILURE;
188 }
179bc609
L
189 z80_write_block(rec.data, /* src */
190 addr, /* dest */
191 rec.len); /* len */
192 z80_bus_cmd(Release);
193 }
179bc609 194 }
5480dc65 195 break;
179bc609 196
5480dc65
L
197#if 0
198 case 1: /* EOF record */
199 break;
200#endif
201 case 2: /* Extended Segment Address Record */
d264541a 202 base_address = (uint32_t)((rec.data[0] << 8) + rec.data[1]) << 4;
5480dc65 203 break;
ae017d4c 204
5480dc65
L
205 case 4: /* Extended Linear Address Record */
206 base_address = (uint32_t)((rec.data[0] << 8) + rec.data[1]) << 16;
207 break;
ae017d4c 208
5480dc65
L
209 case 3: /* Start Segment Address Record (ignored)*/
210 case 5: /* Start Linear Address Record (ignored)*/
211 break;
212
213 }
179bc609
L
214 }
215
216 switch (rec.status) {
217 case IHX_OK:
218 rcode = CMD_RET_SUCCESS;
219 break;
220
221 case IHX_BROKEN:
222 case IHX_CHKSUMERR:
223 printf_P(PSTR("Broken Hex Record or loading interrupted!\n"));
224 break;
225 }
226
5480dc65 227 printf_P(PSTR("Data loaded: "));
d264541a 228 if (address_low >= MIN(address_high, address_max))
179bc609
L
229 printf_P(PSTR("None.\n"));
230 else
5480dc65 231 printf_P(PSTR("low: 0x%.5lX high: 0x%.5lX\n"), address_low,
d264541a 232 MIN(address_high, address_max) - 1);
5480dc65
L
233
234 if (address_high > address_max)
235 printf_P(PSTR("Data above highest RAM address "
d264541a 236 "(in range 0x%.5lX - 0x%.5lX) ignored!\n"), address_max, address_high - 1);
179bc609
L
237
238 return rcode;
239}