]> cloudbase.mooo.com Git - z180-stamp.git/blob - avr/cmd_cpu.c
z80_toggle_reset(), z80_toggle_busreq()
[z180-stamp.git] / avr / cmd_cpu.c
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"
8 //#include <ctype.h>
9 //#include <util/atomic.h>
10
11 #include "z80-if.h"
12 #include "con-utils.h"
13 //#include "env.h"
14 #include "eval_arg.h"
15 #include "timer.h"
16 #include "getopt-min.h"
17 //#include "debug.h"
18
19 /* hack to get Z180 loadfile into flash memory */
20 #define const const FLASH
21 #include "../z180/cpuinfo.h"
22 #undef const
23
24
25 static const FLASH char * const FLASH cpu_strings[] = {
26 FSTR("Unknown CPU"),
27 FSTR("8080"),
28 FSTR("8085"),
29 FSTR("Z80"),
30 FSTR("x180"),
31 FSTR("HD64180"),
32 FSTR("Z80180"),
33 FSTR("Z80S180"),
34 };
35
36 command_ret_t do_cpuchk(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED)
37 {
38 uint8_t done = 0;
39 uint8_t cputype;
40 ERRNUM err = ESUCCESS;
41 uint8_t ram_save[cpuinfo_length];
42
43 if (z80_bus_state() & ZST_RUNNING) {
44 err = ERUNNING;
45 } else {
46 z80_bus_request_or_exit();
47 z80_read_block(ram_save, 0, cpuinfo_length);
48 z80_load_mem(0, cpuinfo,
49 &cpuinfo_sections,
50 cpuinfo_address,
51 cpuinfo_length_of_sections);
52 z80_bus_cmd(Release);
53
54 if (argv[1] && (argv[1][0] == 'n'))
55 goto donot;
56
57 z80_bus_cmd(Run);
58
59 clear_ctrlc(); /* forget any previous Control C */
60 while (done != 0xFF) {
61 _delay_ms(8);
62 /* check for ctrl-c to abort... */
63 if (had_ctrlc() || ctrlc()) {
64 err = EINTR;
65 break;
66 }
67 z80_bus_cmd(Request);
68 done = z80_read(3);
69 if (done == 0xFF)
70 cputype = z80_read(4);
71 z80_bus_cmd(Release);
72 }
73 z80_bus_cmd(Reset);
74 z80_bus_cmd(Request);
75 // z80_write_block(ram_save, 0, cpuinfo_length);
76 z80_bus_cmd(Release);
77 }
78
79 donot:
80
81 if (err)
82 cmd_error(CMD_RET_FAILURE, err, NULL);
83
84 if (done == 0xFF) {
85 if (cputype >= ARRAY_SIZE(cpu_strings))
86 cputype = 0;
87 printf_P(PSTR("Detected CPU: %S\n"), cpu_strings[cputype]);
88 }
89
90 return CMD_RET_SUCCESS;
91 }
92
93 /*
94 * delay for <count> ms...
95 */
96 static void test_delay(uint32_t count)
97 {
98 uint32_t ts = get_timer(0);
99
100 while (get_timer(ts) <= count);
101 }
102
103 command_ret_t do_cpu_test(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, char * const argv[])
104 {
105
106 uint32_t pulsewidth = 10; /* ms */
107
108 /* reset getopt() */
109 optind = 0;
110
111 int opt;
112 while ((opt = getopt(argc, argv, PSTR("t:"))) != -1) {
113 switch (opt) {
114 case 't':
115 pulsewidth = eval_arg(optarg, NULL);
116 break;
117 default: /* '?' */
118 return CMD_RET_USAGE;
119 }
120 }
121
122 if ((z80_bus_state() & ZST_ACQUIRED) != RESET)
123 cmd_error(CMD_RET_FAILURE, ERUNNING, NULL);
124
125 clear_ctrlc(); /* forget any previous Control C */
126 do {
127 z80_bus_cmd(Request);
128 test_delay(pulsewidth);
129 z80_bus_cmd(Release);
130 test_delay(pulsewidth);
131 } while (!(had_ctrlc() || ctrlc()));
132
133 return CMD_RET_SUCCESS;
134 }
135
136 command_ret_t do_busack_test(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED)
137 {
138
139 if ((z80_bus_state() & ZST_ACQUIRED) != RESET)
140 cmd_error(CMD_RET_FAILURE, ERUNNING, NULL);
141
142 z80_bus_cmd(Request);
143 uint32_t result = z80_get_busreq_cycles();
144 test_delay(20);
145 z80_bus_cmd(Release);
146
147 #if 0
148 long div;
149
150 pinconf = gpio_config_get(pin);
151 if (pinconf == OUTPUT_TIMER) {
152 div = gpio_clockdiv_get(pin);
153 #endif
154
155
156 printf_P(PSTR("cycles: %lu, time: %luus\n"), result, (uint32_t) (result * 1000000LL / F_CPU));
157
158 return CMD_RET_SUCCESS;
159 }
160
161 #if 0
162 command_ret_t do_cpu_freq(cmd_tbl_t *cmdtp UNUSED, int flag UNUSED, int argc, char * const argv[])
163 {
164 bool silent = false;
165 bool write_env = false;
166 bool load_loop = true;
167 uint8_t lcycles = 18;
168 uint16_t timeout = 1000;
169
170 uint8_t eicrb_save;
171 uint8_t eimsk_save;
172 uint8_t mem_save[cpuinfo_length];
173
174 /* reset getopt() */
175 optind = 0;
176
177 int opt;
178 while ((opt = getopt(argc, argv, PSTR("swnc:t:"))) != -1) {
179 switch (opt) {
180 case 's':
181 silent = true;
182 break;
183 case 'w':
184 write_env = true;
185 break;
186 case 'n':
187 load_loop = false;
188 break;
189 case 'c':
190 lcycles = eval_arg(optarg, NULL);
191 break;
192 case 't':
193 lcycles = eval_arg(optarg, NULL);
194 break;
195 default: /* '?' */
196 return CMD_RET_USAGE;
197 }
198 }
199
200 if (z80_bus_state() & ZST_RUNNING) {
201 if (!silent)
202 printf_P(PSTR("Frequency measuring failed. CPU allready running!\n"));
203 return CMD_RET_FAILURE;
204 }
205
206 ATOMIC_BLOCK(ATOMIC_FORCEON) {
207 /* Save state and disable INT6 */
208 eimsk_save = EIMSK;
209 EIMSK &= ~_BV(INT6);
210 /* Save state and set INT6 for falling edge */
211 eicrb_save = EICRB;
212 EICRB = (eicrb_save & ~(0b11 << ISC60)) | (0b10 << ISC60);
213 }
214
215 z80_bus_cmd(Request);
216 if (load_loop) {
217 z80_read_block(mem_save, 0, cpuinfo_length);
218 z80_load_mem(0, cpuinfo,
219 &cpuinfo_sections,
220 cpuinfo_address,
221 cpuinfo_length_of_sections);
222 }
223 z80_bus_cmd(Run);
224 z80_bus_cmd(Release);
225
226 uint32_t cpu_freq = z80_measure_phi(lcycles, true, timeout);
227
228 z80_bus_cmd(Reset);
229 z80_bus_cmd(Request);
230 if (load_loop)
231 z80_write_block(mem_save, 0, cpuinfo_length);
232 z80_bus_cmd(Release);
233
234 ATOMIC_BLOCK(ATOMIC_FORCEON) {
235 /* Restore INT6 */
236 eicrb_save = EICRB;
237 EICRB = (EICRB & ~(0b11 << ISC60)) | (eicrb_save & (0b11 << ISC60));
238 if ((eimsk_save & _BV(INT6)) != 0)
239 EIMSK |= _BV(INT6);
240 /* Reset pending int */
241 EIFR = _BV(INTF6);
242 }
243
244 if (!silent) {
245 if (cpu_freq != 0)
246 printf_P(PSTR("%luHz\n"), cpu_freq);
247 else
248 printf_P(PSTR("No CPU clock or input frequency to low!\n"));
249 }
250
251 if (write_env) {
252 if (setenv_ulong(PSTR(ENV_CPU_FREQ), cpu_freq)) {
253 if (!silent)
254 printf_P(PSTR("'SETENV (%S, %lu)' failed!\n"), PSTR(ENV_CPU_FREQ), cpu_freq);
255 return CMD_RET_FAILURE;
256 }
257 }
258
259 return CMD_RET_SUCCESS;
260 }
261 #endif
262
263 /*
264 * command table for fat subcommands
265 */
266
267 cmd_tbl_t cmd_tbl_cpu[] = {
268 CMD_TBL_ITEM(
269 chkcpu, CONFIG_SYS_MAXARGS, CTBL_RPT, do_cpuchk,
270 "Check CPU",
271 ""
272 ),
273 CMD_TBL_ITEM(
274 test, CONFIG_SYS_MAXARGS, 1, do_cpu_test,
275 "Do bus request/release cycles",
276 "[-t pulsewidth]"
277 ),
278 CMD_TBL_ITEM(
279 busack, 2, 1, do_busack_test,
280 "Get time from /Reset high to /BUSACK low",
281 ""
282 ),
283 #if 0
284 CMD_TBL_ITEM(
285 freq, CONFIG_SYS_MAXARGS, 1, do_cpu_freq,
286 "Measure cpu frequency",
287 "[-swn] [-c loopcycles]\n"
288 " -s Supress output (silent)\n"
289 " -w Write result to environment variable '"ENV_CPU_FREQ"'"
290 ),
291 #endif
292 CMD_TBL_ITEM(
293 help, CONFIG_SYS_MAXARGS, CTBL_RPT, do_help,
294 "Print sub command description/usage",
295 "\n"
296 " - print brief description of all sub commands\n"
297 "fat help command ...\n"
298 " - print detailed usage of sub cmd 'command'"
299 ),
300
301 /* This does not use the CMD_TBL_ITEM macro as ? can't be used in symbol names */
302 {FSTR("?"), CONFIG_SYS_MAXARGS, 1, do_help,
303 NULL,
304 #ifdef CONFIG_SYS_LONGHELP
305 FSTR(""),
306 #endif /* CONFIG_SYS_LONGHELP */
307 NULL,
308 #ifdef CONFIG_AUTO_COMPLETE
309 NULL,
310 #endif
311 },
312 /* Mark end of table */
313 CMD_TBL_END(cmd_tbl_cpu)
314 };
315
316
317 command_ret_t do_cpu(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED)
318 {
319 //puts_P(PSTR("Huch?"));
320
321 return CMD_RET_USAGE;
322 }
323
324
325 #if 0
326 /*
327 * Z180 Single Step Functions
328 *
329 */
330
331
332 #define P_RUN PORTG
333 #define RUN 1
334 #define DDR_RUN DDRG
335 #define P_STEP PORTG
336 #define STEP 0
337 #define DDR_STEP DDRG
338 #define P_WAIT PORTG
339 #define WAIT 2
340 #define DDR_WAIT DDRG
341 /* All three signals are on the same Port (PortG) */
342 #define PORT_SS PORTG
343 #define DDR_SS DDRG
344 #define PIN_SS PING
345
346 static bool ss_available;
347
348 int single_step_setup(void)
349 {
350 ss_available = false;
351
352 #if 0
353 if (z80_bus_state() & ZST_RUNNING ||
354 !(z80_bus_cmd(Request) & ZST_ACQUIRED))
355 return -1;
356 #endif
357
358 /* STEP, RUN output, WAIT input */
359
360 PORT_SS |= _BV(RUN) | _BV(STEP);
361 DDR_SS |= _BV(RUN) | _BV(STEP);
362 DDR_SS &= ~_BV(WAIT);
363
364 /* RUN high, MREQ pulse --> WAIT should be low */
365 z80_mreq_pulse();
366
367 if ((PIN_SS & _BV(WAIT)) == 0) {
368
369 /* RUN high, STEP pulse --> WAIT should be high */
370 PIN_SS = _BV(STEP);
371 PIN_SS = _BV(STEP);
372 if ((PIN_SS & _BV(WAIT)) != 0) {
373
374 /* RUN high, MREQ pulse --> WAIT should be low */
375 z80_mreq_pulse();
376 if ((PIN_SS & _BV(WAIT)) == 0) {
377
378 /* RUN low --> WAIT should be high */
379 PIN_SS = _BV(RUN);
380 if ((PIN_SS & _BV(WAIT)) != 0) {
381
382 /* RUN low, STEP pulse --> WAIT should be high */
383 PIN_SS = _BV(STEP);
384 PIN_SS = _BV(STEP);
385 if ((PIN_SS & _BV(WAIT)) != 0) {
386
387 /* all tests passed */
388 ss_available = true;
389 }
390 }
391 }
392 }
393 }
394
395 if (!ss_available) {
396 DDR_SS &= ~(_BV(STEP) | _BV(RUN));
397 PORT_SS |= _BV(RUN) | _BV(STEP);
398 }
399
400 return ss_available ? 0 : -1;
401 }
402 #endif