]> cloudbase.mooo.com Git - z180-stamp.git/blame - avr/cmd_cpu.c
add fat commands: rm, mkdir
[z180-stamp.git] / avr / cmd_cpu.c
CommitLineData
226d3221
L
1/*
2 * (C) Copyright 2018 Leo C. <erbl259-lmu@yahoo.de>
3 *
4 * SPDX-License-Identifier: GPL-2.0
5 */
6
7#include "cmd_cpu.h"
dbc1de70 8#include <util/atomic.h>
226d3221
L
9
10#include "z80-if.h"
11#include "con-utils.h"
2c60e1dc 12#include "env.h"
51dd0948
L
13#include "eval_arg.h"
14#include "timer.h"
15#include "getopt-min.h"
2c60e1dc 16#include "debug.h"
226d3221
L
17
18/* hack to get Z180 loadfile into flash memory */
19#define const const FLASH
20#include "../z180/cpuinfo.h"
21#undef const
22
aea51b6c
L
23#define DEBUG_CPU 1 /* set to 1 to debug */
24
25#define debug_cpu(fmt, args...) \
26 debug_cond(DEBUG_CPU, fmt, ##args)
27
dbc1de70
L
28/*
29 * delay for <count> ms...
30 */
31static void test_delay(uint32_t count)
32{
33 uint32_t ts = get_timer(0);
34
35 while (get_timer(ts) <= count);
36}
37
1f12ca6c
L
38static const FLASH char * const FLASH cpu_strings[] = {
39 FSTR("Unknown"),
40 FSTR("8080"),
41 FSTR("8085"),
42 FSTR("Z80"),
43 FSTR("x180"),
44 FSTR("HD64180"),
45 FSTR("Z80180"),
46 FSTR("Z80S180"),
47};
24ba732a 48
aea51b6c
L
49#define O_SILENT (1<<0)
50#define O_WENV (1<<1)
51#define O_LOAD_LOOP (1<<2)
52#define O_UNLOAD_LOOP (1<<3)
24ba732a 53
1f12ca6c
L
54static const FLASH char * const FLASH opt_strings[] = {
55 FSTR("swnu"), /* Options for chkcpu */
6dbf5891
L
56 FSTR("swnuc:"), /* Oprions for cpufreq */
57};
58
59static const FLASH char * const FLASH env_names[] = {
60 FSTR(ENV_CPU), /* Env var for chkcpu result */
61 FSTR(ENV_CPU_FREQ), /* Env var for cpufreq result */
1f12ca6c
L
62};
63
64command_ret_t do_cpu_freq_chk(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, char * const argv[])
7535ca1b 65{
aea51b6c 66 uint_fast8_t options = O_LOAD_LOOP | O_UNLOAD_LOOP;
1f12ca6c
L
67 uint_fast8_t cputype = 0;
68 uint32_t cpu_freq = 0;
7535ca1b 69 uint_fast8_t lcycles = 0;
1f12ca6c 70 uint_fast8_t freq_cmd = 0;
6dbf5891 71// uint16_t timeout = 1000;
aea51b6c 72 uint8_t eimsk_save;
7535ca1b 73 ERRNUM err = ESUCCESS;
24ba732a 74
1f12ca6c
L
75 if (argv[0][0] == 'f')
76 freq_cmd = 1;
77
aea51b6c 78 int opt;
1f12ca6c 79 while ((opt = getopt(argc, argv, opt_strings[freq_cmd])) != -1) {
aea51b6c
L
80 switch (opt) {
81 case 's':
82 options |= O_SILENT;
83 break;
84 case 'w':
85 options |= O_WENV;
86 break;
87 case 'n':
88 options &= ~O_LOAD_LOOP;
89 break;
90 case 'u':
91 options &= ~O_UNLOAD_LOOP;
92 break;
93 case 'c':
94 lcycles = eval_arg(optarg, NULL);
95 break;
6dbf5891
L
96// case 't':
97// timeout = eval_arg(optarg, NULL);
98// break;
aea51b6c
L
99 default: /* '?' */
100 return CMD_RET_USAGE;
24ba732a
L
101 }
102 }
aea51b6c
L
103 if (argc - optind != 0)
104 return CMD_RET_USAGE;
24ba732a 105
7535ca1b
L
106 if (z80_bus_state() & ZST_RUNNING)
107 cmd_error(CMD_RET_FAILURE, ERUNNING, NULL);
108
109 uint8_t *mem_save = NULL;
110 if (options & O_LOAD_LOOP) {
111 mem_save = (uint8_t *) malloc(cpuinfo_length);
112 if (mem_save == NULL)
113 cmd_error(CMD_RET_FAILURE, ENOMEM, NULL);
114 z80_bus_cmd(Request);
115 z80_read_block(mem_save, 0, cpuinfo_length);
116 z80_load_mem(0, cpuinfo, &cpuinfo_sections, cpuinfo_address,
117 cpuinfo_length_of_sections);
118 z80_bus_cmd(Release);
24ba732a
L
119 }
120
7535ca1b 121 /* Save state and disable INT5/INT6 */
24ba732a 122 ATOMIC_BLOCK(ATOMIC_FORCEON) {
f6154a39
L
123 eimsk_save = EIMSK;
124 EIMSK &= ~_BV(INT6);
aea51b6c 125 EIMSK &= ~_BV(INT5);
f6154a39 126 }
aea51b6c 127 EIFR = _BV(INTF5); /* Reset pending int */
7535ca1b 128
aea51b6c 129 z80_bus_cmd(Run);
24ba732a 130
aea51b6c 131 clear_ctrlc(); /* forget any previous Control C */
aea51b6c
L
132 /* Wait for falling edge */
133 do {
134 /* check for ctrl-c to abort... */
135 if (had_ctrlc() || ctrlc()) {
136 err = EINTR;
137 break;
dbc1de70 138 }
aea51b6c 139 } while ((EIFR & _BV(INTF5)) == 0);
dbc1de70 140
1f12ca6c
L
141 if (freq_cmd) {
142 if (lcycles == 0) {
143 z80_bus_cmd(Request);
144 if (z80_read(3) == 0xFF)
145 lcycles = z80_read(5);
146 z80_bus_cmd(Release);
147 }
148 if (!err)
149 cpu_freq = z80_measure_phi(lcycles);
7535ca1b 150 }
aea51b6c 151 z80_bus_cmd(Reset);
7535ca1b
L
152
153 /* Restore INT5/INT6 */
f6154a39 154 ATOMIC_BLOCK(ATOMIC_FORCEON) {
aea51b6c
L
155 if ((eimsk_save & _BV(INT5)) != 0)
156 EIMSK |= _BV(INT5);
f6154a39
L
157 if ((eimsk_save & _BV(INT6)) != 0)
158 EIMSK |= _BV(INT6);
159 /* Reset pending int */
aea51b6c 160 EIFR = _BV(INTF5);
f6154a39
L
161 EIFR = _BV(INTF6);
162 }
aea51b6c
L
163 Stat &= ~S_MSG_PENDING;
164 Stat &= ~S_CON_PENDING;
165
1f12ca6c
L
166 if (freq_cmd == 0) {
167 z80_bus_cmd(Request);
168 if (z80_read(3) == 0xFF)
169 cputype = z80_read(4);
170 z80_bus_cmd(Release);
171 }
7535ca1b
L
172
173 if ((mem_save != NULL) && options & O_UNLOAD_LOOP) {
174 z80_bus_cmd(Request);
175 z80_write_block(mem_save, 0, cpuinfo_length);
176 z80_bus_cmd(Release);
177 }
178 free(mem_save);
179
aea51b6c
L
180 if (err)
181 cmd_error(CMD_RET_FAILURE, err, NULL);
182
6dbf5891
L
183 char result_str[11];
184
1f12ca6c 185 if (freq_cmd) {
6dbf5891
L
186 ultoa(cpu_freq, result_str, 10);
187 } else {
188 if (cputype >= ARRAY_SIZE(cpu_strings))
189 cputype = 0;
190 strcpy_P(result_str, cpu_strings[cputype]);
191 }
1f12ca6c 192
6dbf5891
L
193 if (!(options & O_SILENT))
194 printf_P(PSTR("%s\n"), result_str);
7535ca1b 195
6dbf5891
L
196 if (options & O_WENV) {
197 if (setenv(env_names[freq_cmd], result_str)) {
198 if (!(options & O_SILENT)) {
199 printf_P(PSTR("'setenv %S %s' failed!\n"), env_names[freq_cmd], result_str);
200 //cmd_error(CMD_RET_FAILURE, ENOMEM, PSTR("'setenv (%S, %s)' failed"), env_names[freq_cmd], result_str);
1f12ca6c 201 }
6dbf5891 202 return CMD_RET_FAILURE;
aea51b6c 203 }
7535ca1b 204 }
226d3221
L
205
206 return CMD_RET_SUCCESS;
207}
51dd0948 208
51dd0948
L
209command_ret_t do_cpu_test(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, char * const argv[])
210{
211
212 uint32_t pulsewidth = 10; /* ms */
213
51dd0948
L
214 int opt;
215 while ((opt = getopt(argc, argv, PSTR("t:"))) != -1) {
216 switch (opt) {
217 case 't':
218 pulsewidth = eval_arg(optarg, NULL);
219 break;
220 default: /* '?' */
221 return CMD_RET_USAGE;
222 }
223 }
224
225 if ((z80_bus_state() & ZST_ACQUIRED) != RESET)
226 cmd_error(CMD_RET_FAILURE, ERUNNING, NULL);
227
228 clear_ctrlc(); /* forget any previous Control C */
229 do {
230 z80_bus_cmd(Request);
231 test_delay(pulsewidth);
232 z80_bus_cmd(Release);
233 test_delay(pulsewidth);
234 } while (!(had_ctrlc() || ctrlc()));
235
236 return CMD_RET_SUCCESS;
237}
238
dbc1de70
L
239command_ret_t do_bus_test(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED)
240{
f1e16f88 241 int ch;
dbc1de70
L
242
243#if 0
dbc1de70
L
244 int opt;
245 while ((opt = getopt(argc, argv, PSTR("t:"))) != -1) {
246 switch (opt) {
247 case 't':
248 pulsewidth = eval_arg(optarg, NULL);
249 break;
250 default: /* '?' */
251 return CMD_RET_USAGE;
252 }
253 }
254#endif
255
256 my_puts_P(PSTR(
257 " 1: RESET 4: RUN r: Toggle /RESET\n"
258 " 2: REQUEST 5: RESTART b: Toggle /BUSREQ\n"
259 " 3: RELEASE 6: M_CYCLE\n"
260 "\n"
261 //"Bus state: "
262 ));
263
264 do {
265 ch = my_getchar(1);
266 if (ch >= 0) {
267 switch (ch) {
268 case '1': /* bus_cmd RESET */
269 case '2': /* bus_cmd REQUEST */
270 case '3': /* bus_cmd RELEASE */
271 case '4': /* bus_cmd RUN */
272 case '5': /* bus_cmd RESTART */
273 case '6': /* bus_cmd M_CYCLE */
274 z80_bus_cmd(ch - '1' + Reset);
275 break;
276 case 'r': /* Toggle RESET */
277 z80_toggle_reset();
278 break;
279 case 'b': /* Toggle BUSREQ */
280 z80_toggle_busreq();
281 break;
282 }
283 test_delay(10);
284 uint32_t cycles = z80_get_busreq_cycles();
285 printf_P(PSTR("\rState: %.2x, cycles: %lu, time: %luus "),
286 z80_bus_state(), cycles, (uint32_t) (cycles * 1000000LL / F_CPU));
287 }
288 } while (ch != 0x03);
289
290 putchar('\n');
291 return CMD_RET_SUCCESS;
292}
293
d66348b4
L
294command_ret_t do_busack_test(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED)
295{
296
297 if ((z80_bus_state() & ZST_ACQUIRED) != RESET)
298 cmd_error(CMD_RET_FAILURE, ERUNNING, NULL);
299
300 z80_bus_cmd(Request);
301 uint32_t result = z80_get_busreq_cycles();
302 test_delay(20);
303 z80_bus_cmd(Release);
304
305#if 0
306 long div;
307
308 pinconf = gpio_config_get(pin);
309 if (pinconf == OUTPUT_TIMER) {
310 div = gpio_clockdiv_get(pin);
dbc1de70 311 }
d66348b4
L
312#endif
313
314
315 printf_P(PSTR("cycles: %lu, time: %luus\n"), result, (uint32_t) (result * 1000000LL / F_CPU));
316
317 return CMD_RET_SUCCESS;
318}
319
51dd0948
L
320
321/*
aea51b6c 322 * command table for subcommands
51dd0948 323 */
51dd0948
L
324cmd_tbl_t cmd_tbl_cpu[] = {
325CMD_TBL_ITEM(
1f12ca6c
L
326 freq, CONFIG_SYS_MAXARGS, CTBL_RPT, do_cpu_freq_chk,
327 "Measure cpu frequency",
6dbf5891
L
328// "[-swnu] [-c loopcycles] [-t timeout]\n"
329 "[-swnu] [-c loopcycles]\n"
330 " -s Be silent\n"
e8fda1c0 331 " -w Write result to environment variable '"ENV_CPU_FREQ"'\n"
6dbf5891
L
332 " -n Don't load code snippet. \n"
333 " -u Don't unload. Leave code snippet in ram.\n"
334 " -c Overwrite cycles per lopp for in \"l: a,(50h)/jp l\" loop."
335// " -t Timeout (ms)\n"
1f12ca6c
L
336),
337CMD_TBL_ITEM(
338 chkcpu, CONFIG_SYS_MAXARGS, CTBL_RPT|CTBL_SUBCMDAUTO, do_cpu_freq_chk,
aea51b6c 339 "Check/Identify CPU",
6dbf5891
L
340// "[-swnu] [-c loopcycles] [-t timeout]\n"
341 "[-swnu] [-c loopcycles]\n"
342 " -s Be silent\n"
e8fda1c0 343 " -w Write result to environment variable '"ENV_CPU"'\n"
6dbf5891
L
344 " -n Don't load code snippet. \n"
345 " -u Don't unload. Leave code snippet in ram."
346// " -t Timeout (ms)\n"
51dd0948 347),
dbc1de70
L
348CMD_TBL_ITEM(
349 buscmd, CONFIG_SYS_MAXARGS, CTBL_RPT, do_bus_test,
350 "Bus commands",
351 ""
352),
51dd0948 353CMD_TBL_ITEM(
1f12ca6c 354 test, CONFIG_SYS_MAXARGS, CTBL_RPT, do_cpu_test,
51dd0948
L
355 "Do bus request/release cycles",
356 "[-t pulsewidth]"
357),
d66348b4 358CMD_TBL_ITEM(
1f12ca6c 359 busack, 2, CTBL_RPT, do_busack_test,
d66348b4
L
360 "Get time from /Reset high to /BUSACK low",
361 ""
362),
dbc1de70 363
51dd0948
L
364CMD_TBL_ITEM(
365 help, CONFIG_SYS_MAXARGS, CTBL_RPT, do_help,
366 "Print sub command description/usage",
367 "\n"
368 " - print brief description of all sub commands\n"
369 "fat help command ...\n"
370 " - print detailed usage of sub cmd 'command'"
371),
372
373/* This does not use the CMD_TBL_ITEM macro as ? can't be used in symbol names */
1f12ca6c 374 {FSTR("?"), CONFIG_SYS_MAXARGS, CTBL_RPT, do_help,
51dd0948
L
375 NULL,
376#ifdef CONFIG_SYS_LONGHELP
377 FSTR(""),
378#endif /* CONFIG_SYS_LONGHELP */
379 NULL,
380#ifdef CONFIG_AUTO_COMPLETE
381 NULL,
382#endif
383},
384/* Mark end of table */
385CMD_TBL_END(cmd_tbl_cpu)
386};
387
388
389command_ret_t do_cpu(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED)
390{
391 //puts_P(PSTR("Huch?"));
392
393 return CMD_RET_USAGE;
394}
395
396
dbc1de70 397#if 0 /* Z180 Single Step Functions */
51dd0948
L
398/*
399 * Z180 Single Step Functions
400 *
401 */
402
403
404#define P_RUN PORTG
405#define RUN 1
406#define DDR_RUN DDRG
407#define P_STEP PORTG
408#define STEP 0
409#define DDR_STEP DDRG
410#define P_WAIT PORTG
411#define WAIT 2
412#define DDR_WAIT DDRG
413/* All three signals are on the same Port (PortG) */
414#define PORT_SS PORTG
415#define DDR_SS DDRG
416#define PIN_SS PING
417
418static bool ss_available;
419
420int single_step_setup(void)
421{
422 ss_available = false;
423
424#if 0
425 if (z80_bus_state() & ZST_RUNNING ||
426 !(z80_bus_cmd(Request) & ZST_ACQUIRED))
427 return -1;
428#endif
429
430 /* STEP, RUN output, WAIT input */
431
432 PORT_SS |= _BV(RUN) | _BV(STEP);
433 DDR_SS |= _BV(RUN) | _BV(STEP);
434 DDR_SS &= ~_BV(WAIT);
435
436 /* RUN high, MREQ pulse --> WAIT should be low */
437 z80_mreq_pulse();
438
439 if ((PIN_SS & _BV(WAIT)) == 0) {
440
441 /* RUN high, STEP pulse --> WAIT should be high */
442 PIN_SS = _BV(STEP);
443 PIN_SS = _BV(STEP);
444 if ((PIN_SS & _BV(WAIT)) != 0) {
445
446 /* RUN high, MREQ pulse --> WAIT should be low */
447 z80_mreq_pulse();
448 if ((PIN_SS & _BV(WAIT)) == 0) {
449
450 /* RUN low --> WAIT should be high */
451 PIN_SS = _BV(RUN);
452 if ((PIN_SS & _BV(WAIT)) != 0) {
453
454 /* RUN low, STEP pulse --> WAIT should be high */
455 PIN_SS = _BV(STEP);
456 PIN_SS = _BV(STEP);
457 if ((PIN_SS & _BV(WAIT)) != 0) {
458
459 /* all tests passed */
460 ss_available = true;
461 }
462 }
463 }
464 }
465 }
466
467 if (!ss_available) {
468 DDR_SS &= ~(_BV(STEP) | _BV(RUN));
469 PORT_SS |= _BV(RUN) | _BV(STEP);
470 }
471
472 return ss_available ? 0 : -1;
473}
474#endif