2 * (C) Copyright 2018 Leo C. <erbl259-lmu@yahoo.de>
4 * SPDX-License-Identifier: GPL-2.0
9 //#include <util/atomic.h>
12 #include "con-utils.h"
16 #include "getopt-min.h"
19 /* hack to get Z180 loadfile into flash memory */
20 #define const const FLASH
21 #include "../z180/cpuinfo.h"
25 static const FLASH
char * const FLASH cpu_strings
[] = {
36 command_ret_t
do_cpuchk(cmd_tbl_t
*cmdtp UNUSED
, uint_fast8_t flag UNUSED
, int argc UNUSED
, char * const argv
[] UNUSED
)
40 ERRNUM err
= ESUCCESS
;
41 uint8_t ram_save
[cpuinfo_length
];
43 if (z80_bus_state() & ZST_RUNNING
) {
46 z80_bus_request_or_exit();
47 z80_read_block(ram_save
, 0, cpuinfo_length
);
48 z80_load_mem(0, cpuinfo
,
51 cpuinfo_length_of_sections
);
54 if (argv
[1] && (argv
[1][0] == 'n'))
59 clear_ctrlc(); /* forget any previous Control C */
60 while (done
!= 0xFF) {
62 /* check for ctrl-c to abort... */
63 if (had_ctrlc() || ctrlc()) {
70 cputype
= z80_read(4);
75 // z80_write_block(ram_save, 0, cpuinfo_length);
82 cmd_error(CMD_RET_FAILURE
, err
, NULL
);
85 if (cputype
>= ARRAY_SIZE(cpu_strings
))
87 printf_P(PSTR("Detected CPU: %S\n"), cpu_strings
[cputype
]);
90 return CMD_RET_SUCCESS
;
94 * delay for <count> ms...
96 static void test_delay(uint32_t count
)
98 uint32_t ts
= get_timer(0);
100 while (get_timer(ts
) <= count
);
103 command_ret_t
do_cpu_test(cmd_tbl_t
*cmdtp UNUSED
, uint_fast8_t flag UNUSED
, int argc
, char * const argv
[])
106 uint32_t pulsewidth
= 10; /* ms */
112 while ((opt
= getopt(argc
, argv
, PSTR("t:"))) != -1) {
115 pulsewidth
= eval_arg(optarg
, NULL
);
118 return CMD_RET_USAGE
;
122 if ((z80_bus_state() & ZST_ACQUIRED
) != RESET
)
123 cmd_error(CMD_RET_FAILURE
, ERUNNING
, NULL
);
125 clear_ctrlc(); /* forget any previous Control C */
127 z80_bus_cmd(Request
);
128 test_delay(pulsewidth
);
129 z80_bus_cmd(Release
);
130 test_delay(pulsewidth
);
131 } while (!(had_ctrlc() || ctrlc()));
133 return CMD_RET_SUCCESS
;
136 command_ret_t
do_busack_test(cmd_tbl_t
*cmdtp UNUSED
, uint_fast8_t flag UNUSED
, int argc UNUSED
, char * const argv
[] UNUSED
)
139 if ((z80_bus_state() & ZST_ACQUIRED
) != RESET
)
140 cmd_error(CMD_RET_FAILURE
, ERUNNING
, NULL
);
142 z80_bus_cmd(Request
);
143 uint32_t result
= z80_get_busreq_cycles();
145 z80_bus_cmd(Release
);
150 pinconf
= gpio_config_get(pin
);
151 if (pinconf
== OUTPUT_TIMER
) {
152 div
= gpio_clockdiv_get(pin
);
156 printf_P(PSTR("cycles: %lu, time: %luus\n"), result
, (uint32_t) (result
* 1000000LL / F_CPU
));
158 return CMD_RET_SUCCESS
;
162 command_ret_t
do_cpu_freq(cmd_tbl_t
*cmdtp UNUSED
, int flag UNUSED
, int argc
, char * const argv
[])
165 bool write_env
= false;
166 bool load_loop
= true;
167 uint8_t lcycles
= 18;
168 uint16_t timeout
= 1000;
172 uint8_t mem_save
[cpuinfo_length
];
178 while ((opt
= getopt(argc
, argv
, PSTR("swnc:t:"))) != -1) {
190 lcycles
= eval_arg(optarg
, NULL
);
193 lcycles
= eval_arg(optarg
, NULL
);
196 return CMD_RET_USAGE
;
200 if (z80_bus_state() & ZST_RUNNING
) {
202 printf_P(PSTR("Frequency measuring failed. CPU allready running!\n"));
203 return CMD_RET_FAILURE
;
206 ATOMIC_BLOCK(ATOMIC_FORCEON
) {
207 /* Save state and disable INT6 */
210 /* Save state and set INT6 for falling edge */
212 EICRB
= (eicrb_save
& ~(0b11 << ISC60
)) | (0b10 << ISC60
);
215 z80_bus_cmd(Request
);
217 z80_read_block(mem_save
, 0, cpuinfo_length
);
218 z80_load_mem(0, cpuinfo
,
221 cpuinfo_length_of_sections
);
224 z80_bus_cmd(Release
);
226 uint32_t cpu_freq
= z80_measure_phi(lcycles
, true, timeout
);
229 z80_bus_cmd(Request
);
231 z80_write_block(mem_save
, 0, cpuinfo_length
);
232 z80_bus_cmd(Release
);
234 ATOMIC_BLOCK(ATOMIC_FORCEON
) {
237 EICRB
= (EICRB
& ~(0b11 << ISC60
)) | (eicrb_save
& (0b11 << ISC60
));
238 if ((eimsk_save
& _BV(INT6
)) != 0)
240 /* Reset pending int */
246 printf_P(PSTR("%luHz\n"), cpu_freq
);
248 printf_P(PSTR("No CPU clock or input frequency to low!\n"));
252 if (setenv_ulong(PSTR(ENV_CPU_FREQ
), cpu_freq
)) {
254 printf_P(PSTR("'SETENV (%S, %lu)' failed!\n"), PSTR(ENV_CPU_FREQ
), cpu_freq
);
255 return CMD_RET_FAILURE
;
259 return CMD_RET_SUCCESS
;
264 * command table for fat subcommands
267 cmd_tbl_t cmd_tbl_cpu
[] = {
269 chkcpu
, CONFIG_SYS_MAXARGS
, CTBL_RPT
, do_cpuchk
,
274 test
, CONFIG_SYS_MAXARGS
, 1, do_cpu_test
,
275 "Do bus request/release cycles",
279 busack
, 2, 1, do_busack_test
,
280 "Get time from /Reset high to /BUSACK low",
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
"'"
293 help
, CONFIG_SYS_MAXARGS
, CTBL_RPT
, do_help
,
294 "Print sub command description/usage",
296 " - print brief description of all sub commands\n"
297 "fat help command ...\n"
298 " - print detailed usage of sub cmd 'command'"
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
,
304 #ifdef CONFIG_SYS_LONGHELP
306 #endif /* CONFIG_SYS_LONGHELP */
308 #ifdef CONFIG_AUTO_COMPLETE
312 /* Mark end of table */
313 CMD_TBL_END(cmd_tbl_cpu
)
317 command_ret_t
do_cpu(cmd_tbl_t
*cmdtp UNUSED
, uint_fast8_t flag UNUSED
, int argc UNUSED
, char * const argv
[] UNUSED
)
319 //puts_P(PSTR("Huch?"));
321 return CMD_RET_USAGE
;
327 * Z180 Single Step Functions
337 #define DDR_STEP DDRG
340 #define DDR_WAIT DDRG
341 /* All three signals are on the same Port (PortG) */
342 #define PORT_SS PORTG
346 static bool ss_available
;
348 int single_step_setup(void)
350 ss_available
= false;
353 if (z80_bus_state() & ZST_RUNNING
||
354 !(z80_bus_cmd(Request
) & ZST_ACQUIRED
))
358 /* STEP, RUN output, WAIT input */
360 PORT_SS
|= _BV(RUN
) | _BV(STEP
);
361 DDR_SS
|= _BV(RUN
) | _BV(STEP
);
362 DDR_SS
&= ~_BV(WAIT
);
364 /* RUN high, MREQ pulse --> WAIT should be low */
367 if ((PIN_SS
& _BV(WAIT
)) == 0) {
369 /* RUN high, STEP pulse --> WAIT should be high */
372 if ((PIN_SS
& _BV(WAIT
)) != 0) {
374 /* RUN high, MREQ pulse --> WAIT should be low */
376 if ((PIN_SS
& _BV(WAIT
)) == 0) {
378 /* RUN low --> WAIT should be high */
380 if ((PIN_SS
& _BV(WAIT
)) != 0) {
382 /* RUN low, STEP pulse --> WAIT should be high */
385 if ((PIN_SS
& _BV(WAIT
)) != 0) {
387 /* all tests passed */
396 DDR_SS
&= ~(_BV(STEP
) | _BV(RUN
));
397 PORT_SS
|= _BV(RUN
) | _BV(STEP
);
400 return ss_available
? 0 : -1;