]> cloudbase.mooo.com Git - z180-stamp.git/blobdiff - avr/cmd_cpu.c
Remove compiler warnings
[z180-stamp.git] / avr / cmd_cpu.c
index de627c607526a9336c60e7582e6cfcf6dfefc36c..e5158fd705c11a2bc7a5ade6674f782552aca8a6 100644 (file)
@@ -6,14 +6,15 @@
 
 #include "cmd_cpu.h"
 //#include <ctype.h>
-//#include <util/atomic.h>
+#include <util/atomic.h>
 
 #include "z80-if.h"
 #include "con-utils.h"
-//#include "env.h"
-//#include "eval_arg.h"
-//#include "getopt-min.h"
-//#include "debug.h"
+#include "env.h"
+#include "eval_arg.h"
+#include "timer.h"
+#include "getopt-min.h"
+#include "debug.h"
 
 /* hack to get Z180 loadfile into flash memory */
 #define const const FLASH
 #undef const
 
 
+/*
+ * delay for <count> ms...
+ */
+static void    test_delay(uint32_t count)
+{
+       uint32_t ts = get_timer(0);
+
+       while (get_timer(ts) <= count);
+}
+
+uint32_t z80_measure_phi(uint_fast8_t cycles)
+{
+       uint16_t ref_stop;
+       uint16_t ref_ovfl;
+       uint8_t x_ovfl;
+       uint8_t eimsk_save,eicrb_save;
+       uint32_t x_freq;
+
+
+       ATOMIC_BLOCK(ATOMIC_FORCEON) {
+               /* Save state and disable INT6 */
+               eimsk_save = EIMSK;
+               EIMSK &= ~_BV(INT6);
+               /* Save state and set INT6 for falling edge */
+               eicrb_save = EICRB;
+               EICRB = (eicrb_save & ~(0b11 << ISC60)) | (0b10 << ISC60);
+       }
+
+       PRR1 &= ~_BV(PRTIM3);
+       TCCR3A = 0;
+       TCCR3B = 0b000<<CS30;   /* stop counter */
+       TCNT3 = 0;
+       x_ovfl = 0;
+       TIFR3 = _BV(TOV3);
+       ref_ovfl = 0;
+
+       ATOMIC_BLOCK(ATOMIC_FORCEON) {
+               /* Reset pending int */
+               EIFR = _BV(INTF6);
+               /* Wait for falling edge */
+               while ((EIFR & _BV(INTF6)) == 0)
+                       ;
+               TCCR3B = 0b110<<CS30;   /* Count falling edges on T3 (==INT6) */
+               OCR4B = TCNT4;
+               TIFR4 = _BV(OCF4B);             /* clear compare match flag */
+       }
+       while (ref_ovfl < 60) {
+               ATOMIC_BLOCK(ATOMIC_FORCEON) {
+                       if ((TIFR4 & _BV(OCF4B)) != 0) {
+                               TIFR4 = _BV(OCF4B);
+                               ref_ovfl++;
+                       }
+                       if ((TIFR3 & _BV(TOV3)) != 0) {
+                               TIFR3 = _BV(TOV3);
+                               x_ovfl++;
+                       }
+               }
+       }
+
+       ATOMIC_BLOCK(ATOMIC_FORCEON) {
+               EIFR = _BV(INTF6);
+               for (;;) {
+                       if (EIFR & _BV(INTF6)) {
+                               TCCR3B = 0b000<<CS30;   /* stop counter */
+                               ref_stop = TCNT4;
+                               break;
+                       }
+                       if ((TIFR4 & _BV(OCF4B)) != 0) {
+                               TIFR4 = _BV(OCF4B);
+                               ref_ovfl++;
+                       }
+               }
+       }
+
+       if ((TIFR3 & _BV(TOV3)) != 0) {
+               TIFR3 = _BV(TOV3);
+               x_ovfl++;
+       }
+
+       ATOMIC_BLOCK(ATOMIC_FORCEON) {
+               /* Restore INT6 */
+               EICRB = eicrb_save;
+               if ((eimsk_save & _BV(INT6)) != 0)
+                       EIMSK |= _BV(INT6);
+               /* Reset pending int */
+               EIFR = _BV(INTF6);
+       }
+
+       uint32_t ref_cnt = (ref_stop - OCR4B) + ((uint32_t)ref_ovfl << 16);
+       uint32_t x_cnt = TCNT3 + ((uint32_t) x_ovfl << 16);
+       uint64_t x_tmp = (uint64_t) 100000 * (x_cnt * cycles);
+
+       debug("TCNT3: %6u, ref_cnt: %9lu\n", TCNT3, ref_cnt);
+       debug("x_tmp: %lu %lu\n", (uint32_t) (x_tmp >> 32), (uint32_t) (x_tmp & 0xffffffff));
+
+       x_tmp = (x_tmp * getenv_ulong(PSTR(ENV_FMON), 10, F_CPU) + (ref_cnt / 2)) / ref_cnt;
+
+       debug("x_tmp: %lu %lu\n", (uint32_t) (x_tmp >> 32), (uint32_t) (x_tmp & 0xffffffff));
+
+       /* round to 5 decimal digits */
+       int_fast8_t sc = 5;
+       while (x_tmp >= 100000) {
+               x_tmp = (x_tmp + 5)/10;
+           sc--;
+       }
+       x_freq = x_tmp;
+       while (sc < 0) {
+               x_freq *= 10;
+           sc++;
+       }
+       x_freq += (uint32_t) sc << 28;
+
+
+       /* Stop Timer */
+       TCCR3B = 0;
+       PRR1 |= _BV(PRTIM3);
+
+       return x_freq;
+}
+
+#if 0
+float z80_measure_phi(uint_fast8_t cycles, uint16_t wait_ms)
+{
+       uint16_t ref_stop;
+       uint16_t ref_ovfl;
+       uint8_t x_ovfl;
+       uint8_t eimsk_save,eicrb_save;
+       float x_freq;
+
+
+       ATOMIC_BLOCK(ATOMIC_FORCEON) {
+               /* Save state and disable INT6 */
+               eimsk_save = EIMSK;
+               EIMSK &= ~_BV(INT6);
+               /* Save state and set INT6 for falling edge */
+               eicrb_save = EICRB;
+               EICRB = (eicrb_save & ~(0b11 << ISC60)) | (0b10 << ISC60);
+       }
+
+       PRR1 &= ~_BV(PRTIM3);
+       TCCR3A = 0;
+       TCCR3B = 0b000<<CS30;   /* stop counter */
+       TCNT3 = 0;
+       x_ovfl = 0;
+       TIFR3 = _BV(TOV3);
+       ref_ovfl = 0;
+
+       ATOMIC_BLOCK(ATOMIC_FORCEON) {
+               /* Reset pending int */
+               EIFR = _BV(INTF6);
+               /* Wait for falling edge */
+               while ((EIFR & _BV(INTF6)) == 0)
+                       ;
+               TCCR3B = 0b110<<CS30;   /* Count falling edges on T3 (==INT6) */
+               OCR4B = TCNT4;
+               TIFR4 = _BV(OCF4B);             /* clear compare match flag */
+       }
+       while (ref_ovfl < 60) {
+               ATOMIC_BLOCK(ATOMIC_FORCEON) {
+                       if ((TIFR4 & _BV(OCF4B)) != 0) {
+                               TIFR4 = _BV(OCF4B);
+                               ref_ovfl++;
+                       }
+                       if ((TIFR3 & _BV(TOV3)) != 0) {
+                               TIFR3 = _BV(TOV3);
+                               x_ovfl++;
+                       }
+               }
+       }
+
+       ATOMIC_BLOCK(ATOMIC_FORCEON) {
+               EIFR = _BV(INTF6);
+               for (;;) {
+                       if (EIFR & _BV(INTF6)) {
+                               TCCR3B = 0b000<<CS30;   /* stop counter */
+                               ref_stop = TCNT4;
+                               break;
+                       }
+                       if ((TIFR4 & _BV(OCF4B)) != 0) {
+                               TIFR4 = _BV(OCF4B);
+                               ref_ovfl++;
+                       }
+               }
+       }
+
+       if ((TIFR3 & _BV(TOV3)) != 0) {
+               TIFR3 = _BV(TOV3);
+               x_ovfl++;
+       }
+
+       ATOMIC_BLOCK(ATOMIC_FORCEON) {
+               /* Restore INT6 */
+               EICRB = eicrb_save;
+               if ((eimsk_save & _BV(INT6)) != 0)
+                       EIMSK |= _BV(INT6);
+               /* Reset pending int */
+               EIFR = _BV(INTF6);
+       }
+
+       uint32_t ref_cnt = (ref_stop - OCR4B) + ((uint32_t)ref_ovfl << 16);
+
+       uint32_t x_cnt = TCNT3 + ((uint32_t) x_ovfl << 16);
+       x_freq = x_cnt * cycles;
+
+       x_freq = (x_freq * getenv_ulong(PSTR(ENV_FMON), 10, F_CPU)) / ref_cnt;
+
+       debug("TCNT3: %6u, ref_cnt: %9lu\n", TCNT3, ref_cnt);
+#if 0
+       debug("ref_start: %6u, ref_stop: %6u, ref_ovfl: %4u, ref_cnt: %9lu\n"
+                                 "    TCNT3: %6u, x_cnt: %6lu, xfreq: %f\n",
+                               OCR4B, ref_stop, ref_ovfl, ref_cnt,
+                               TCNT3, x_cnt, x_freq);
+#endif
+
+
+       /* Stop Timer */
+       TCCR3B = 0;
+       PRR1 |= _BV(PRTIM3);
+
+       return x_freq;
+}
+#endif
+
+#if 0
+int32_t z80_measure_phi(uint_fast8_t cycles, uint16_t wait_ms)
+{
+       uint16_t ref_stop;
+       uint16_t ref_ovfl;
+       uint8_t x_ovfl;
+       uint32_t x_freq;
+       uint8_t eimsk_save,eicrb_save;
+
+
+       ATOMIC_BLOCK(ATOMIC_FORCEON) {
+               /* Save state and disable INT6 */
+               eimsk_save = EIMSK;
+               EIMSK &= ~_BV(INT6);
+               /* Save state and set INT6 for falling edge */
+               eicrb_save = EICRB;
+               EICRB = (eicrb_save & ~(0b11 << ISC60)) | (0b10 << ISC60);
+       }
+
+       PRR1 &= ~_BV(PRTIM3);
+       TCCR3A = 0;
+       TCCR3B = 0b000<<CS30;   /* stop counter */
+       TCNT3 = 0;
+       x_ovfl = 0;
+       TIFR3 = _BV(TOV3);
+       ref_ovfl = 0;
+
+       ATOMIC_BLOCK(ATOMIC_FORCEON) {
+               /* Reset pending int */
+               EIFR = _BV(INTF6);
+               /* Wait for falling edge */
+               while ((EIFR & _BV(INTF6)) == 0)
+                       ;
+               OCR4B = TCNT4;
+               TCCR3B = 0b110<<CS30;   /* Count falling edges on T3 (==INT6) */
+               TIFR4 = _BV(OCF4B);             /* clear compare match flag */
+       }
+       while (ref_ovfl < 60) {
+               ATOMIC_BLOCK(ATOMIC_FORCEON) {
+                       if ((TIFR4 & _BV(OCF4B)) != 0) {
+                               TIFR4 = _BV(OCF4B);
+                               ref_ovfl++;
+                       }
+                       if ((TIFR3 & _BV(TOV3)) != 0) {
+                               TIFR3 = _BV(TOV3);
+                               x_ovfl++;
+                       }
+               }
+       }
+
+       ATOMIC_BLOCK(ATOMIC_FORCEON) {
+               EIFR = _BV(INTF6);
+               for (;;) {
+                       if (EIFR & _BV(INTF6)) {
+                               ref_stop = TCNT4;
+                               TCCR3B = 0b000<<CS30;   /* stop counter */
+                               break;
+                       }
+                       if ((TIFR4 & _BV(OCF4B)) != 0) {
+                               TIFR4 = _BV(OCF4B);
+                               if (ref_ovfl)
+                                       ref_ovfl++;
+                       }
+               }
+       }
+
+#if 0
+       ATOMIC_BLOCK(ATOMIC_FORCEON) {
+               EIFR = _BV(INTF6);
+               for (;;) {
+                       if (EIFR & _BV(INTF6))
+                               break;
+                       if (TIFR4 & _BV(OCF4B)) {
+                               if (EIFR & _BV(INTF6))
+                                       break;
+                               TIFR4 = _BV(OCF4B);
+                               if (EIFR & _BV(INTF6))
+                                       break;
+                               ref_ovfl++;
+                               if (EIFR & _BV(INTF6))
+                                       break;
+                               if (ref_ovfl == 0)
+                                       break;
+                       }
+               }
+               ref_stop = TCNT4;
+               TCCR3B = 0b000<<CS30;   /* stop counter */
+               if ((TIFR4 & _BV(OCF4B)) != 0) {
+                       TIFR4 = _BV(OCF4B);
+                       if (ref_ovfl)
+                               ref_ovfl++;
+               }
+       }
+#endif
+       if ((TIFR3 & _BV(TOV3)) != 0) {
+               TIFR3 = _BV(TOV3);
+               x_ovfl++;
+       }
+
+       if (ref_ovfl == 0)
+               x_freq = 0xFFFFFFFE;
+       else
+       {
+               uint32_t ref_cnt = (ref_stop - OCR4B) + ((uint32_t)ref_ovfl << 16);
+
+               x_freq = TCNT3 + ((uint32_t) x_ovfl << 16);
+               uint32_t x_cnt = x_freq;
+               x_freq *= cycles;
+
+               x_freq = ((uint64_t) x_freq * getenv_ulong(PSTR(ENV_FMON), 10, F_CPU) + (ref_cnt / 2))/ ref_cnt;
+
+               debug("ref_start: %6u, ref_stop: %6u, ref_ovfl: %4u, ref_cnt: %9lu\n"
+                                         "    TCNT3: %6u, x_cnt: %6lu, xfreq: %9lu\n",
+                                       OCR4B, ref_stop, ref_ovfl, ref_cnt,
+                                       TCNT3, x_cnt, x_freq);
+
+               /* round to 5 decimal digits */
+               uint_fast8_t sc = 0;
+               while (x_freq >= 100000UL) {
+                       x_freq = (x_freq + 5)/10;
+                       ++sc;
+               }
+               while (sc--)
+                       x_freq *= 10;
+       }
+
+       /* Stop Timer */
+       TCCR3B = 0;
+       PRR1 |= _BV(PRTIM3);
+
+       ATOMIC_BLOCK(ATOMIC_FORCEON) {
+               /* Restore INT6 */
+#if 0 /* wtf? */
+               eicrb_save = EICRB;
+               EICRB = (EICRB & ~(0b11 << ISC60)) | (eicrb_save & (0b11 << ISC60));
+#endif
+               EICRB = eicrb_save;
+               if ((eimsk_save & _BV(INT6)) != 0)
+                       EIMSK |= _BV(INT6);
+               /* Reset pending int */
+               EIFR = _BV(INTF6);
+       }
+
+       return (int32_t) x_freq;
+}
+#endif
+
 static const FLASH char * const FLASH cpu_strings[] = {
        FSTR("Unknown CPU"),
        FSTR("8080"),
@@ -34,8 +405,7 @@ static const FLASH char * const FLASH cpu_strings[] = {
 
 command_ret_t do_cpuchk(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED)
 {
-       uint8_t done = 0;
-       uint8_t cputype;
+       uint_fast8_t cputype = 0;
        ERRNUM err = ESUCCESS;
        uint8_t ram_save[cpuinfo_length];
 
@@ -56,6 +426,7 @@ command_ret_t do_cpuchk(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int a
                z80_bus_cmd(Run);
 
                clear_ctrlc();          /* forget any previous Control C */
+               uint_fast8_t done = 0;
                while (done != 0xFF) {
                        _delay_ms(8);
                        /* check for ctrl-c to abort... */
@@ -80,11 +451,385 @@ donot:
        if (err)
                cmd_error(CMD_RET_FAILURE, err, NULL);
 
-       if (done == 0xFF) {
-               if (cputype >= ARRAY_SIZE(cpu_strings))
-                       cputype = 0;
-               printf_P(PSTR("Detected CPU: %S\n"), cpu_strings[cputype]);
+       if (cputype >= ARRAY_SIZE(cpu_strings))
+               cputype = 0;
+       printf_P(PSTR("Detected CPU: %S\n"), cpu_strings[cputype]);
+
+       return CMD_RET_SUCCESS;
+}
+
+command_ret_t do_cpu_test(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, char * const argv[])
+{
+
+       uint32_t pulsewidth = 10; /* ms */
+
+       int opt;
+       while ((opt = getopt(argc, argv, PSTR("t:"))) != -1) {
+               switch (opt) {
+               case 't':
+                       pulsewidth = eval_arg(optarg, NULL);
+                       break;
+               default: /* '?' */
+                       return CMD_RET_USAGE;
+               }
+       }
+
+       if ((z80_bus_state() & ZST_ACQUIRED) != RESET)
+               cmd_error(CMD_RET_FAILURE, ERUNNING, NULL);
+
+       clear_ctrlc();          /* forget any previous Control C */
+       do {
+               z80_bus_cmd(Request);
+               test_delay(pulsewidth);
+               z80_bus_cmd(Release);
+               test_delay(pulsewidth);
+       } while (!(had_ctrlc() || ctrlc()));
+
+       return CMD_RET_SUCCESS;
+}
+
+command_ret_t do_bus_test(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED)
+{
+       int ch;
+
+#if 0
+       int opt;
+       while ((opt = getopt(argc, argv, PSTR("t:"))) != -1) {
+               switch (opt) {
+               case 't':
+                       pulsewidth = eval_arg(optarg, NULL);
+                       break;
+               default: /* '?' */
+                       return CMD_RET_USAGE;
+               }
+       }
+#endif
+
+       my_puts_P(PSTR(
+               "  1:  RESET         4:  RUN           r:  Toggle /RESET\n"
+               "  2:  REQUEST       5:  RESTART       b:  Toggle /BUSREQ\n"
+               "  3:  RELEASE       6:  M_CYCLE\n"
+               "\n"
+               //"Bus state: "
+       ));
+
+       do {
+               ch = my_getchar(1);
+               if (ch >= 0) {
+                       switch (ch) {
+                               case '1':               /* bus_cmd RESET   */
+                               case '2':               /* bus_cmd REQUEST */
+                               case '3':               /* bus_cmd RELEASE */
+                               case '4':               /* bus_cmd RUN     */
+                               case '5':               /* bus_cmd RESTART */
+                               case '6':               /* bus_cmd M_CYCLE */
+                                               z80_bus_cmd(ch - '1' + Reset);
+                                               break;
+                               case 'r':               /* Toggle RESET    */
+                                               z80_toggle_reset();
+                                               break;
+                               case 'b':               /* Toggle BUSREQ   */
+                                               z80_toggle_busreq();
+                                               break;
+                       }
+                       test_delay(10);
+                       uint32_t cycles = z80_get_busreq_cycles();
+                       printf_P(PSTR("\rState: %.2x, cycles: %lu, time: %luus      "),
+                                       z80_bus_state(), cycles, (uint32_t) (cycles * 1000000LL / F_CPU));
+               }
+       } while (ch != 0x03);
+
+       putchar('\n');
+       return CMD_RET_SUCCESS;
+}
+
+command_ret_t do_busack_test(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED)
+{
+
+       if ((z80_bus_state() & ZST_ACQUIRED) != RESET)
+               cmd_error(CMD_RET_FAILURE, ERUNNING, NULL);
+
+       z80_bus_cmd(Request);
+       uint32_t result = z80_get_busreq_cycles();
+       test_delay(20);
+       z80_bus_cmd(Release);
+
+#if 0
+       long div;
+
+       pinconf = gpio_config_get(pin);
+       if (pinconf == OUTPUT_TIMER) {
+               div = gpio_clockdiv_get(pin);
        }
+#endif
+
+
+       printf_P(PSTR("cycles: %lu, time: %luus\n"), result, (uint32_t) (result * 1000000LL / F_CPU));
 
        return CMD_RET_SUCCESS;
 }
+
+static const FLASH uint8_t loop_code[] = {
+/* 0000 */  0x00,             /* nop                                        */
+/* 0001 */  0xAF,             /* xor  a                                     */
+/* 0005 */  0xD3,0x32,        /* out  (032h),a  ;DCNTL                      */
+/* 0002 */  0xD3,0x36,        /* out  (036h),a  ;RCR                        */
+/*      */                    /*                                            */
+/* 0006 */  0xD3,0x40,        /* out  (040H),a  ;Ready                      */
+/*      */                    /*                                            */
+/*      */                    /*                ;Z80    Z180(0W) Z180(MaxW) */
+/* 0008 */                    /* loop:          ;-------------------------- */
+/* 0008 */  0xDB,0x50,        /* in   a,(050h)  ;11       10     +3*3  19   */
+/* 000A */  0xC3,0x08,0x00    /* jp   loop      ;10        9     +3*3  18   */
+                              /*                ;-------------------------- */
+                              /*                ;21       19           37   */
+};
+
+command_ret_t do_cpu_freq(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, char * const argv[])
+{
+
+#define O_SILENT               (1<<0)
+#define O_WENV                 (1<<1)
+#define O_LOAD_LOOP     (1<<2)
+#define O_UNLOAD_LOOP   (1<<3)
+
+       uint_fast8_t options = O_LOAD_LOOP | O_UNLOAD_LOOP;
+       uint_fast8_t lcycles = 19;
+       uint16_t timeout = 1000;
+
+       uint8_t mem_save[ARRAY_SIZE(loop_code)];
+
+       int opt;
+       while ((opt = getopt(argc, argv, PSTR("swnuc:t:"))) != -1) {
+               switch (opt) {
+               case 's':
+                       options |= O_SILENT;
+                       break;
+               case 'w':
+                       options |= O_WENV;
+                       break;
+               case 'n':
+                       options &= ~O_LOAD_LOOP;
+                       break;
+               case 'u':
+                       options &= ~O_UNLOAD_LOOP;
+                       break;
+               case 'c':
+                       lcycles = eval_arg(optarg, NULL);
+                       break;
+               case 't':
+                       timeout = eval_arg(optarg, NULL);
+                       break;
+               default: /* '?' */
+                       return CMD_RET_USAGE;
+               }
+       }
+       if (argc - optind != 0)
+               return CMD_RET_USAGE;
+
+       if (z80_bus_state() & ZST_RUNNING) {
+               if (!(options & O_SILENT))
+                       printf_P(PSTR("Frequency measuring failed. CPU allready running!\n"));
+               return CMD_RET_FAILURE;
+       }
+
+
+       z80_bus_cmd(Request);
+       if (options & O_LOAD_LOOP) {
+               z80_read_block(mem_save, 0, ARRAY_SIZE(loop_code));
+               z80_write_block_P(loop_code, 0, ARRAY_SIZE(loop_code));
+       }
+       Stat &= ~S_IO_0X40;                             /* Reset pending int */
+       z80_bus_cmd(Release);
+       z80_bus_cmd(Run);
+
+       clear_ctrlc();                                  /* forget any previous Control C */
+       ERRNUM err = 0;
+
+       /* Wait for falling edge */
+       do {
+               /* check for ctrl-c to abort... */
+               if (had_ctrlc() || ctrlc()) {
+                       err = EINTR;
+                       break;
+               }
+       } while ((Stat & S_IO_0X40) == 0);
+
+       uint32_t cpu_freq = 0;
+       if (!err)
+               cpu_freq = z80_measure_phi(lcycles);
+
+       z80_bus_cmd(Reset);
+       if (options & O_UNLOAD_LOOP) {
+               z80_bus_cmd(Request);
+               z80_write_block(mem_save, 0, ARRAY_SIZE(loop_code));
+               z80_bus_cmd(Release);
+       }
+       if (err)
+               cmd_error(CMD_RET_FAILURE, err, NULL);
+
+       if (!(options & O_SILENT)) {
+               printf_P(PSTR("%lu %3u\n"), cpu_freq & 0x0fffffff, cpu_freq >> 28);
+
+//             printf_P(PSTR("%f%S\n"), cpu_freq, cpu_freq < 0 ? PSTR("") : PSTR("Hz"));
+//             if (cpu_freq != 0)
+//             else
+//                     printf_P(PSTR("No CPU clock or input frequency to low!\n"));
+       }
+#if 0
+       if (options & O_WENV) {
+               if (setenv_ulong(PSTR(ENV_CPU_FREQ), cpu_freq)) {
+                       if (!(options & O_SILENT))
+                               printf_P(PSTR("'SETENV (%S, %lu)' failed!\n"), PSTR(ENV_CPU_FREQ), cpu_freq);
+                       return CMD_RET_FAILURE;
+               }
+       }
+#endif
+       return CMD_RET_SUCCESS;
+}
+
+
+/*
+ * command table for fat subcommands
+ */
+
+cmd_tbl_t cmd_tbl_cpu[] = {
+CMD_TBL_ITEM(
+       chkcpu, CONFIG_SYS_MAXARGS,     CTBL_RPT,       do_cpuchk,
+       "Check CPU",
+       ""
+),
+CMD_TBL_ITEM(
+       buscmd, CONFIG_SYS_MAXARGS,     CTBL_RPT,       do_bus_test,
+       "Bus commands",
+       ""
+),
+CMD_TBL_ITEM(
+       test,   CONFIG_SYS_MAXARGS,     1,      do_cpu_test,
+       "Do bus request/release cycles",
+       "[-t pulsewidth]"
+),
+CMD_TBL_ITEM(
+       busack, 2,      1,      do_busack_test,
+       "Get time from /Reset high to /BUSACK low",
+       ""
+),
+CMD_TBL_ITEM(
+       freq,   CONFIG_SYS_MAXARGS,     1,      do_cpu_freq,
+       "Measure cpu frequency",
+       "[-qwn] [-c loopcycles] [-t timeout]\n"
+       "     -q Be quiet\n"
+//     "     -w  Write result to environment variable '"ENV_CPU_FREQ"'"
+),
+
+CMD_TBL_ITEM(
+       help,   CONFIG_SYS_MAXARGS,     CTBL_RPT,       do_help,
+       "Print sub command description/usage",
+       "\n"
+       "       - print brief description of all sub commands\n"
+       "fat help command ...\n"
+       "       - print detailed usage of sub cmd 'command'"
+),
+
+/* This does not use the CMD_TBL_ITEM macro as ? can't be used in symbol names */
+       {FSTR("?"),   CONFIG_SYS_MAXARGS, 1, do_help,
+        NULL,
+#ifdef  CONFIG_SYS_LONGHELP
+       FSTR(""),
+#endif /* CONFIG_SYS_LONGHELP */
+       NULL,
+#ifdef CONFIG_AUTO_COMPLETE
+       NULL,
+#endif
+},
+/* Mark end of table */
+CMD_TBL_END(cmd_tbl_cpu)
+};
+
+
+command_ret_t do_cpu(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED)
+{
+       //puts_P(PSTR("Huch?"));
+
+       return CMD_RET_USAGE;
+}
+
+
+#if 0          /* Z180 Single Step Functions */
+/*
+ * Z180 Single Step Functions
+ *
+ */
+
+
+#define P_RUN          PORTG
+#define RUN                    1
+#define DDR_RUN                DDRG
+#define P_STEP         PORTG
+#define STEP           0
+#define DDR_STEP       DDRG
+#define P_WAIT         PORTG
+#define WAIT           2
+#define DDR_WAIT       DDRG
+/* All three signals are on the same Port (PortG) */
+#define PORT_SS                PORTG
+#define DDR_SS         DDRG
+#define PIN_SS         PING
+
+static bool ss_available;
+
+int single_step_setup(void)
+{
+       ss_available = false;
+
+#if 0
+       if (z80_bus_state() & ZST_RUNNING ||
+                       !(z80_bus_cmd(Request) & ZST_ACQUIRED))
+               return  -1;
+#endif
+
+       /* STEP, RUN output, WAIT input */
+
+       PORT_SS |= _BV(RUN) | _BV(STEP);
+       DDR_SS |= _BV(RUN) | _BV(STEP);
+       DDR_SS &= ~_BV(WAIT);
+
+       /* RUN high, MREQ pulse --> WAIT should be low */
+       z80_mreq_pulse();
+
+       if ((PIN_SS & _BV(WAIT)) == 0) {
+
+               /* RUN high, STEP pulse --> WAIT should be high */
+               PIN_SS = _BV(STEP);
+               PIN_SS = _BV(STEP);
+               if ((PIN_SS & _BV(WAIT)) != 0) {
+
+                       /* RUN high, MREQ pulse --> WAIT should be low */
+                       z80_mreq_pulse();
+                       if ((PIN_SS & _BV(WAIT)) == 0) {
+
+                               /* RUN low --> WAIT should be high */
+                               PIN_SS = _BV(RUN);
+                               if ((PIN_SS & _BV(WAIT)) != 0) {
+
+                                       /* RUN low, STEP pulse --> WAIT should be high */
+                                       PIN_SS = _BV(STEP);
+                                       PIN_SS = _BV(STEP);
+                                       if ((PIN_SS & _BV(WAIT)) != 0) {
+
+                                               /* all tests passed */
+                                               ss_available = true;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       if (!ss_available) {
+               DDR_SS &= ~(_BV(STEP) | _BV(RUN));
+               PORT_SS |= _BV(RUN) | _BV(STEP);
+       }
+
+       return ss_available ? 0 : -1;
+}
+#endif