]> cloudbase.mooo.com Git - z180-stamp.git/blob - avr/cmd_boot.c
26855f1e6099e7858f0c6a8136417f22d198e5e6
[z180-stamp.git] / avr / cmd_boot.c
1
2 /*
3 * Misc boot support
4 */
5 #include "common.h"
6 #include <stdlib.h>
7 #include <limits.h>
8 #include <ctype.h>
9 #include <util/delay.h>
10 #include <avr/pgmspace.h>
11
12 #include "command.h"
13 #include "getopt-min.h"
14 #include "z80-if.h"
15 #include "pin.h"
16 #include "debug.h"
17
18 /* ugly hack to get Z180 loadfile into flash memory */
19 #define const const FLASH
20 #include "../z180/hdrom.h"
21 #undef const
22
23
24
25 static void z80_load_mem(void)
26 {
27 unsigned sec = 0;
28 uint32_t sec_base = hdrom_start;
29
30 printf_P(PSTR("Loading Z180 memory... \n"));
31
32 while (sec < hdrom_sections) {
33 printf_P(PSTR(" From: 0x%.5lX to: 0x%.5lX (%5li bytes)\n"),
34 hdrom_address[sec],
35 hdrom_address[sec]+hdrom_length_of_sections[sec] - 1,
36 hdrom_length_of_sections[sec]);
37
38 z80_bus_cmd(Request);
39 z80_write_block((const FLASH unsigned char *) &hdrom[sec_base], /* src */
40 hdrom_address[sec], /* dest */
41 hdrom_length_of_sections[sec]); /* len */
42 z80_bus_cmd(Release);
43 sec_base+=hdrom_length_of_sections[sec];
44 sec++;
45 }
46 }
47
48 command_ret_t do_loadf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
49 {
50 (void) cmdtp; (void) flag; (void) argc; (void) argv;
51
52 if (z80_bus_state() & ZST_RUNNING) {
53 printf_P(PSTR("## Can't load while CPU is running!\n"));
54 return CMD_RET_FAILURE;
55 }
56
57 z80_load_mem();
58
59 return CMD_RET_SUCCESS;
60 }
61
62
63 command_ret_t do_busreq_pulse(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
64 {
65 uint16_t count=1;
66
67 (void) cmdtp; (void) flag;
68
69 if (!(z80_bus_state() & ZST_RUNNING)) {
70 printf_P(PSTR("## CPU is not running!\n"));
71 return CMD_RET_FAILURE;
72 }
73
74 if (argc > 1)
75 count = (uint16_t) strtoul(argv[2], NULL, 16);
76
77 z80_bus_cmd(Request);
78 while (count--)
79 z80_bus_cmd(M_Cycle);
80
81 return CMD_RET_SUCCESS;
82 }
83
84
85 command_ret_t do_go(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
86 {
87 uint32_t addr;
88
89 (void) cmdtp; (void) flag;
90
91 if (argc < 2)
92 return CMD_RET_USAGE;
93 addr = strtoul(argv[1], NULL, 16);
94 if (addr >= (1UL<<16)) {
95 printf_P(PSTR("## Startaddress 0x%05lx too high.\n"
96 " (Out of logical address space (0x00000-0x0ffff))\n"),
97 addr);
98 return CMD_RET_FAILURE;
99 }
100
101 if (z80_bus_state() & ZST_RUNNING) {
102 printf_P(PSTR("## CPU allready running!\n"));
103 return CMD_RET_FAILURE;
104 }
105
106 printf_P(PSTR("## Starting application at 0x%04lx ...\n"), addr);
107
108 if (addr != 0) {
109 uint8_t tmp[3];
110 uint_fast8_t i;
111
112 z80_bus_cmd(Request);
113 for (i = 0; i < 3; i++)
114 tmp[i] = z80_read(i);
115 z80_write(0, 0xc3);
116 z80_write(1, addr);
117 z80_write(2, (addr >> 8));
118
119 z80_bus_cmd(Run);
120 z80_bus_cmd(M_Cycle);
121 z80_bus_cmd(M_Cycle);
122 for (i = 0; i < 3; i++)
123 z80_write(i, tmp[i]);
124 } else
125 z80_bus_cmd(Run);
126
127 z80_bus_cmd(Release);
128
129 return CMD_RET_SUCCESS;
130 }
131
132 command_ret_t do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
133 {
134 (void) cmdtp; (void) flag; (void) argc; (void) argv;
135
136 printf_P(PSTR("## CPU now in reset state.\n"));
137
138 z80_bus_cmd(Reset);
139 return CMD_RET_SUCCESS;
140 }
141
142 command_ret_t do_restart(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
143 {
144 (void) cmdtp; (void) flag; (void) argc; (void) argv;
145
146 z80_bus_cmd(Restart);
147
148 return CMD_RET_SUCCESS;
149 }
150
151 #if 0
152 command_ret_t do_clock(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
153 {
154 long freq;
155 char *endp;
156
157 (void) cmdtp; (void) flag;
158
159 if (argc == 2) {
160 if (toupper(argv[1][0]) == 'L')
161 freq = 0;
162 else if (toupper(argv[1][0]) == 'H')
163 freq = LONG_MAX;
164 else {
165 freq = strtol(argv[1], &endp, 10);
166 switch (*endp) {
167 case 'M':
168 freq *= 1000;
169 case 'K':
170 freq *= 1000;
171 endp++;
172 case '\0':
173 if (*endp == '\0')
174 break;
175 default:
176 printf_P(PSTR("invalid value\n"));
177 return CMD_RET_USAGE;
178 }
179
180 if (freq == 0) {
181 printf_P(PSTR("CPU clock cannot be 0\n"));
182 return CMD_RET_USAGE;
183 }
184
185
186 /* if (freq > (long) F_CPU / 2) {
187 printf_P(PSTR("Max CPU clock freq. is: %luHz\n"), F_CPU/2);
188 return CMD_RET_USAGE;
189 }
190 */
191 }
192 if (z80_clock_set(freq) < 0) {
193 printf_P(PSTR("Setting CPU clock freq. to %luHz failed.\n"),
194 freq);
195 }
196 }
197
198 printf_P(PSTR("CPU clock: %luHz\n"), z80_clock_get());
199
200
201 return CMD_RET_SUCCESS;
202 }
203
204 command_ret_t do_clock2(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
205 {
206 long value;
207 char *endp;
208 uint8_t div_flag = 0;
209
210 (void) cmdtp; (void) flag;
211
212 if (argc >= 2) {
213 if (argv[1][0] == '-' && argv[1][1] == 'd') {
214 div_flag = 1;
215 argc--;
216 argv++;
217 }
218 }
219
220 if (argc == 2) {
221 if (toupper(argv[1][0]) == 'L')
222 value = 0;
223 else if (toupper(argv[1][0]) == 'H')
224 value = LONG_MAX;
225 else {
226 value = strtol(argv[1], &endp, 10);
227 switch (*endp) {
228 case 'M':
229 value *= 1000;
230 case 'K':
231 value *= 1000;
232 endp++;
233 case '\0':
234 if (*endp == '\0')
235 break;
236 default:
237 printf_P(PSTR("invalid value\n"));
238 return CMD_RET_USAGE;
239 }
240
241 if (value == 0) {
242 printf_P(PSTR("clk2 cannot be 0\n"));
243 return CMD_RET_USAGE;
244 }
245
246 if (div_flag) {
247 if (value > 256*1024L) {
248 printf_P(PSTR("Max clk2 divider is: %lu\n"), 256*1024L);
249 return CMD_RET_USAGE;
250 }
251 } else {
252 if (value > (long) F_CPU / 2) {
253 printf_P(PSTR("Max clk2 freq. is: %luHz\n"), F_CPU/2);
254 return CMD_RET_USAGE;
255 }
256 }
257 }
258 if (div_flag ? z80_clock2_divset(value) : z80_clock2_set(value) < 0) {
259 printf_P(PSTR("Setting clk2 freq. to %luHz failed.\n"),
260 value);
261 }
262 }
263
264 printf_P(PSTR("clk2: %luHz\n"), z80_clock2_get());
265
266
267 return CMD_RET_SUCCESS;
268 }
269 #endif
270
271 // {INPUT, INPUT_PULLUP, OUTPUT, OUTPUT_TIMER} pinmode_t;
272
273
274 static void print_blanks(uint_fast8_t count)
275 {
276 while(count--)
277 putchar(' ');
278 }
279
280 static const FLASH char * const FLASH pinconf_str[] = {
281 FSTR("?"),
282 FSTR("Input"),
283 FSTR("Pullup"),
284 FSTR("Output"),
285 FSTR("Clock"),
286 };
287
288 static const FLASH char * const FLASH pinlevel_str[] = {
289 FSTR("Low"),
290 FSTR("High"),
291 FSTR(""),
292 };
293
294 int print_pin(int pin, int multi)
295 {
296 int pinconf;
297 const FLASH char *levelp;
298 long div;
299
300 pinconf = pin_config_get(pin);
301 if (pinconf == OUTPUT_TIMER) {
302 div = pin_clockdiv_get(pin);
303 levelp = pinlevel_str[2];
304 } else
305 levelp = pinlevel_str[pin_read(pin)];
306
307 if (multi) {
308 printf_P(PSTR("%3d "), pin);
309 my_puts_P(pinconf_str[pinconf]);
310 print_blanks(8 - strlen_P(pinconf_str[pinconf]));
311 my_puts_P(levelp);
312 print_blanks(6 - strlen_P(levelp));
313 if (pinconf == OUTPUT_TIMER)
314 printf_P(PSTR("%7ld %8ld"),
315 div, F_CPU/div);
316 } else {
317 printf_P(PSTR("Pin %d: "), pin);
318 my_puts_P(pinconf_str[pinconf]);
319 printf_P(PSTR(", "));
320 my_puts_P(levelp);
321
322 if (pinconf == OUTPUT_TIMER)
323 printf_P(PSTR("divide by %ld (%ldHz)"),
324 div, F_CPU/div);
325 }
326 printf_P(PSTR("\n"));
327
328 return 0;
329 }
330
331 int pinarg_insert(int pin, int count, int pinarg[])
332 {
333 int pos;
334
335 if (pin < 0 || pin >= PIN_MAX)
336 return -1;
337
338 for (pos = 0; pos < count; pos++) {
339 if (pin == pinarg[pos])
340 return 0;
341 if (pin < pinarg[pos])
342 break;
343 }
344 for (int i = count-1; i == pos ; i--)
345 pinarg[i+1] = pinarg[i];
346 pinarg[pos] = pin;
347
348 return 1;
349 }
350
351 int pinarg_get(char * arg, int pinarg[])
352 {
353 int count = 0;
354 char *endp;
355 int pin1, pin2, rc;
356
357 while (1) {
358 pin1 = (int) strtoul(arg, &endp, 10);
359 if (endp != arg && *endp == '-') {
360 arg = endp+1;
361 pin2 = (int) strtoul(arg, &endp, 10);
362 if (pin1 < pin2)
363 for (; pin1 < pin2; pin1++)
364 if ((rc = pinarg_insert(pin1, count, pinarg)) >= 0)
365 count += rc;
366 else
367 return 0;
368 else
369 return 0;
370 }
371 if (endp != arg && pin1 >= 0) {
372 if ((*endp == ',' || *endp == '\0') &&
373 (rc = pinarg_insert(pin1, count, pinarg)) >= 0) {
374 count += rc;
375 if (*endp == '\0')
376 return count;
377 } else
378 return 0;
379 } else
380 return 0;
381
382 arg = endp+1;
383 }
384 }
385
386
387 command_ret_t do_pin(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
388 {
389 char printheader = 1;
390 int pinarg[PIN_MAX];
391 int pinargc;
392
393 (void) cmdtp; (void) flag;
394
395 /* reset getopt() */
396 optind = 1;
397
398 int opt;
399 while ((opt = getopt(argc, argv, PSTR("s"))) != -1) {
400 switch (opt) {
401 case 's':
402 printheader = 0;
403 break;
404 default: /* '?' */
405 return CMD_RET_USAGE;
406 }
407 }
408
409 /* remaining arguments */
410 argc -= optind;
411
412 if (argc == 0)
413 /* print cofig of all pins */
414 for (pinargc = 0; pinargc < PIN_MAX; pinargc++)
415 pinarg[pinargc] = pinargc;
416 else {
417 /* get first arg */
418 pinargc = pinarg_get(argv[optind++], pinarg);
419 if (pinargc == 0)
420 return CMD_RET_USAGE;
421 else
422 argc--;
423 }
424
425 if (argc == 0) {
426 /* no more args, print config */
427 if (pinargc == 1)
428 print_pin(pinarg[0], 0);
429 else {
430 if (printheader)
431 printf_P(PSTR("Pin Config Level Divider Frequency/Hz\n"
432 "-----------------------------------------\n"));
433 for (int i = 0; i < pinargc; i++)
434 print_pin(pinarg[i], 1);
435 }
436 return CMD_RET_SUCCESS;
437 }
438
439 /* arguments must be in pairs: pins conf */
440 if (argc % 2 != 1)
441 return CMD_RET_USAGE;
442
443 while (argc > 0) {
444 char *endp;
445 pinmode_t mode = NONE;
446 int level = 0;
447 unsigned long value = 0;
448 uint8_t hz_flag = 0;
449
450 switch (toupper(argv[optind][0])) {
451 case 'H':
452 level = 1;
453 case 'L':
454 mode = OUTPUT;
455 break;
456 case 'P':
457 mode = INPUT_PULLUP;
458 break;
459 case 'I':
460 case 'T':
461 mode = INPUT;
462 break;
463
464 default:
465 value = strtoul(argv[optind], &endp, 10);
466 switch (*endp) {
467 case 'M':
468 value *= 1000;
469 case 'K':
470 value *= 1000;
471 endp++;
472 }
473
474 if (*endp && strcmp_P(endp, PSTR("Hz")) == 0) {
475 hz_flag = 1;
476 endp += 2;
477 }
478
479 if (*endp != '\0') {
480 printf_P(PSTR("invalid parameter: '%s'\n"), argv[optind]);
481 return CMD_RET_USAGE;
482 }
483
484 if (value == 0) {
485 printf_P(PSTR("invalid value: %lu \n"));
486 return CMD_RET_USAGE;
487 }
488
489 if (hz_flag) {
490 if (value > F_CPU / 2) {
491 printf_P(PSTR("Max frequency is: %luHz\n"), F_CPU/2);
492 return CMD_RET_USAGE;
493 }
494 value = F_CPU/value;
495 }
496 mode = OUTPUT_TIMER;
497
498 }
499
500 if (mode == NONE)
501 return CMD_RET_USAGE;
502
503 for (int i = 0; i < pinargc; i++) {
504 switch (mode) {
505 case OUTPUT:
506 pin_write(pinarg[i], level);
507 /* fall thru */
508 case INPUT:
509 case INPUT_PULLUP:
510 pin_config(pinarg[i], mode);
511 break;
512 case OUTPUT_TIMER:
513 if (pin_clockdiv_set(pinarg[i], value) < 0) {
514 printf_P(PSTR("Setting pin %d to %lu failed.\n"),
515 pinarg[i], value);
516 }
517 break;
518 default:
519 break;
520 }
521 }
522
523 optind++;
524 pinargc = pinarg_get(argv[optind++], pinarg);
525 argc -= 2;
526 }
527
528 return CMD_RET_SUCCESS;
529 }
530