X-Git-Url: http://cloudbase.mooo.com/gitweb/z180-stamp.git/blobdiff_plain/d66348b4fb147eb01c30aa9b3a8904ce6c59a4c1..6dbf5891f52b1e06f8448e2b0526214bc882c6ec:/avr/cmd_cpu.c diff --git a/avr/cmd_cpu.c b/avr/cmd_cpu.c index 1627d9f..2abf5db 100644 --- a/avr/cmd_cpu.c +++ b/avr/cmd_cpu.c @@ -5,25 +5,135 @@ */ #include "cmd_cpu.h" -//#include -//#include +#include #include "z80-if.h" #include "con-utils.h" -//#include "env.h" +#include "env.h" #include "eval_arg.h" #include "timer.h" #include "getopt-min.h" -//#include "debug.h" +#include "debug.h" /* hack to get Z180 loadfile into flash memory */ #define const const FLASH #include "../z180/cpuinfo.h" #undef const +#define DEBUG_CPU 1 /* set to 1 to debug */ + +#define debug_cpu(fmt, args...) \ + debug_cond(DEBUG_CPU, fmt, ##args) + +static +char * ulltoa (uint64_t val, char *s) +{ + char *p = s; + + while (val >= 10) { + *p++ = (val % 10) + '0'; + val = val / 10; + } + *p++ = val + '0'; + *p = '\0'; + + return strrev(s); +} + +/* + * delay for ms... + */ +static void test_delay(uint32_t count) +{ + uint32_t ts = get_timer(0); + + while (get_timer(ts) <= count); +} + +static uint32_t z80_measure_phi(uint_fast8_t cycles) +{ + uint16_t ref_stop; + uint16_t ref_ovfl; + uint8_t x_ovfl; + uint32_t x_freq; + + + PRR1 &= ~_BV(PRTIM3); + TCCR3A = 0; + TCCR3B = 0b000< 0 || x_tmp >= 100000; sc--) x_tmp = (x_tmp + 5)/10; + x_freq = x_tmp; + for ( ; sc < 0; sc++) x_freq *= 10; + + return x_freq; +} static const FLASH char * const FLASH cpu_strings[] = { - FSTR("Unknown CPU"), + FSTR("Unknown"), FSTR("8080"), FSTR("8085"), FSTR("Z80"), @@ -33,71 +143,164 @@ static const FLASH char * const FLASH cpu_strings[] = { FSTR("Z80S180"), }; -command_ret_t do_cpuchk(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED) +#define O_SILENT (1<<0) +#define O_WENV (1<<1) +#define O_LOAD_LOOP (1<<2) +#define O_UNLOAD_LOOP (1<<3) + +static const FLASH char * const FLASH opt_strings[] = { + FSTR("swnu"), /* Options for chkcpu */ + FSTR("swnuc:"), /* Oprions for cpufreq */ +}; + +static const FLASH char * const FLASH env_names[] = { + FSTR(ENV_CPU), /* Env var for chkcpu result */ + FSTR(ENV_CPU_FREQ), /* Env var for cpufreq result */ +}; + +command_ret_t do_cpu_freq_chk(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, char * const argv[]) { - uint8_t done = 0; - uint8_t cputype; + uint_fast8_t options = O_LOAD_LOOP | O_UNLOAD_LOOP; + uint_fast8_t cputype = 0; + uint32_t cpu_freq = 0; + uint_fast8_t lcycles = 0; + uint_fast8_t freq_cmd = 0; +// uint16_t timeout = 1000; + uint8_t eimsk_save; ERRNUM err = ESUCCESS; - uint8_t ram_save[cpuinfo_length]; - if (z80_bus_state() & ZST_RUNNING) { - err = ERUNNING; - } else { - z80_bus_request_or_exit(); - z80_read_block(ram_save, 0, cpuinfo_length); - z80_load_mem(0, cpuinfo, - &cpuinfo_sections, - cpuinfo_address, - cpuinfo_length_of_sections); + if (argv[0][0] == 'f') + freq_cmd = 1; + + int opt; + while ((opt = getopt(argc, argv, opt_strings[freq_cmd])) != -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) + cmd_error(CMD_RET_FAILURE, ERUNNING, NULL); + + uint8_t *mem_save = NULL; + if (options & O_LOAD_LOOP) { + mem_save = (uint8_t *) malloc(cpuinfo_length); + if (mem_save == NULL) + cmd_error(CMD_RET_FAILURE, ENOMEM, NULL); + z80_bus_cmd(Request); + z80_read_block(mem_save, 0, cpuinfo_length); + z80_load_mem(0, cpuinfo, &cpuinfo_sections, cpuinfo_address, + cpuinfo_length_of_sections); z80_bus_cmd(Release); + } - if (argv[1] && (argv[1][0] == 'n')) - goto donot; + /* Save state and disable INT5/INT6 */ + ATOMIC_BLOCK(ATOMIC_FORCEON) { + eimsk_save = EIMSK; + EIMSK &= ~_BV(INT6); + EIMSK &= ~_BV(INT5); + } + EIFR = _BV(INTF5); /* Reset pending int */ - z80_bus_cmd(Run); + z80_bus_cmd(Run); - clear_ctrlc(); /* forget any previous Control C */ - while (done != 0xFF) { - _delay_ms(8); - /* check for ctrl-c to abort... */ - if (had_ctrlc() || ctrlc()) { - err = EINTR; - break; - } + clear_ctrlc(); /* forget any previous Control C */ + /* Wait for falling edge */ + do { + /* check for ctrl-c to abort... */ + if (had_ctrlc() || ctrlc()) { + err = EINTR; + break; + } + } while ((EIFR & _BV(INTF5)) == 0); + + if (freq_cmd) { + if (lcycles == 0) { z80_bus_cmd(Request); - done = z80_read(3); - if (done == 0xFF) - cputype = z80_read(4); + if (z80_read(3) == 0xFF) + lcycles = z80_read(5); z80_bus_cmd(Release); } - z80_bus_cmd(Reset); + if (!err) + cpu_freq = z80_measure_phi(lcycles); + } + z80_bus_cmd(Reset); + + /* Restore INT5/INT6 */ + ATOMIC_BLOCK(ATOMIC_FORCEON) { + if ((eimsk_save & _BV(INT5)) != 0) + EIMSK |= _BV(INT5); + if ((eimsk_save & _BV(INT6)) != 0) + EIMSK |= _BV(INT6); + /* Reset pending int */ + EIFR = _BV(INTF5); + EIFR = _BV(INTF6); + } + Stat &= ~S_MSG_PENDING; + Stat &= ~S_CON_PENDING; + + if (freq_cmd == 0) { z80_bus_cmd(Request); -// z80_write_block(ram_save, 0, cpuinfo_length); + if (z80_read(3) == 0xFF) + cputype = z80_read(4); z80_bus_cmd(Release); } -donot: + if ((mem_save != NULL) && options & O_UNLOAD_LOOP) { + z80_bus_cmd(Request); + z80_write_block(mem_save, 0, cpuinfo_length); + z80_bus_cmd(Release); + } + free(mem_save); if (err) cmd_error(CMD_RET_FAILURE, err, NULL); - if (done == 0xFF) { + char result_str[11]; + + if (freq_cmd) { + ultoa(cpu_freq, result_str, 10); + } else { if (cputype >= ARRAY_SIZE(cpu_strings)) cputype = 0; - printf_P(PSTR("Detected CPU: %S\n"), cpu_strings[cputype]); + strcpy_P(result_str, cpu_strings[cputype]); } - return CMD_RET_SUCCESS; -} + if (!(options & O_SILENT)) + printf_P(PSTR("%s\n"), result_str); -/* - * delay for ms... - */ -static void test_delay(uint32_t count) -{ - uint32_t ts = get_timer(0); + if (options & O_WENV) { + if (setenv(env_names[freq_cmd], result_str)) { + if (!(options & O_SILENT)) { + printf_P(PSTR("'setenv %S %s' failed!\n"), env_names[freq_cmd], result_str); + //cmd_error(CMD_RET_FAILURE, ENOMEM, PSTR("'setenv (%S, %s)' failed"), env_names[freq_cmd], result_str); + } + return CMD_RET_FAILURE; + } + } - while (get_timer(ts) <= count); + 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[]) @@ -105,9 +308,6 @@ command_ret_t do_cpu_test(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int uint32_t pulsewidth = 10; /* ms */ - /* reset getopt() */ - optind = 0; - int opt; while ((opt = getopt(argc, argv, PSTR("t:"))) != -1) { switch (opt) { @@ -133,162 +333,131 @@ command_ret_t do_cpu_test(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int 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) +command_ret_t do_bus_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); + int ch; #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; -} - -#if 0 -command_ret_t do_cpu_freq(cmd_tbl_t *cmdtp UNUSED, int flag UNUSED, int argc, char * const argv[]) -{ - bool silent = false; - bool write_env = false; - bool load_loop = true; - uint8_t lcycles = 18; - uint16_t timeout = 1000; - - uint8_t eicrb_save; - uint8_t eimsk_save; - uint8_t mem_save[cpuinfo_length]; - - /* reset getopt() */ - optind = 0; - int opt; - while ((opt = getopt(argc, argv, PSTR("swnc:t:"))) != -1) { + while ((opt = getopt(argc, argv, PSTR("t:"))) != -1) { switch (opt) { - case 's': - silent = true; - break; - case 'w': - write_env = true; - break; - case 'n': - load_loop = false; - break; - case 'c': - lcycles = eval_arg(optarg, NULL); - break; case 't': - lcycles = eval_arg(optarg, NULL); + pulsewidth = eval_arg(optarg, NULL); break; default: /* '?' */ return CMD_RET_USAGE; } } +#endif - if (z80_bus_state() & ZST_RUNNING) { - if (!silent) - printf_P(PSTR("Frequency measuring failed. CPU allready running!\n")); - return CMD_RET_FAILURE; - } + 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: " + )); - 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); - } + 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); - z80_bus_cmd(Request); - if (load_loop) { - z80_read_block(mem_save, 0, cpuinfo_length); - z80_load_mem(0, cpuinfo, - &cpuinfo_sections, - cpuinfo_address, - cpuinfo_length_of_sections); - } - z80_bus_cmd(Run); - z80_bus_cmd(Release); + putchar('\n'); + return CMD_RET_SUCCESS; +} - uint32_t cpu_freq = z80_measure_phi(lcycles, true, timeout); +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(Reset); z80_bus_cmd(Request); - if (load_loop) - z80_write_block(mem_save, 0, cpuinfo_length); + uint32_t result = z80_get_busreq_cycles(); + test_delay(20); z80_bus_cmd(Release); - ATOMIC_BLOCK(ATOMIC_FORCEON) { - /* Restore INT6 */ - eicrb_save = EICRB; - EICRB = (EICRB & ~(0b11 << ISC60)) | (eicrb_save & (0b11 << ISC60)); - if ((eimsk_save & _BV(INT6)) != 0) - EIMSK |= _BV(INT6); - /* Reset pending int */ - EIFR = _BV(INTF6); - } +#if 0 + long div; - if (!silent) { - if (cpu_freq != 0) - printf_P(PSTR("%luHz\n"), cpu_freq); - else - printf_P(PSTR("No CPU clock or input frequency to low!\n")); + pinconf = gpio_config_get(pin); + if (pinconf == OUTPUT_TIMER) { + div = gpio_clockdiv_get(pin); } +#endif - if (write_env) { - if (setenv_ulong(PSTR(ENV_CPU_FREQ), cpu_freq)) { - if (!silent) - printf_P(PSTR("'SETENV (%S, %lu)' failed!\n"), PSTR(ENV_CPU_FREQ), cpu_freq); - return CMD_RET_FAILURE; - } - } + + printf_P(PSTR("cycles: %lu, time: %luus\n"), result, (uint32_t) (result * 1000000LL / F_CPU)); return CMD_RET_SUCCESS; } -#endif + /* - * command table for fat subcommands + * command table for subcommands */ - cmd_tbl_t cmd_tbl_cpu[] = { CMD_TBL_ITEM( - chkcpu, CONFIG_SYS_MAXARGS, CTBL_RPT, do_cpuchk, - "Check CPU", + freq, CONFIG_SYS_MAXARGS, CTBL_RPT, do_cpu_freq_chk, + "Measure cpu frequency", +// "[-swnu] [-c loopcycles] [-t timeout]\n" + "[-swnu] [-c loopcycles]\n" + " -s Be silent\n" + " -w Write result to environment variable '"ENV_CPU_FREQ"'" + " -n Don't load code snippet. \n" + " -u Don't unload. Leave code snippet in ram.\n" + " -c Overwrite cycles per lopp for in \"l: a,(50h)/jp l\" loop." +// " -t Timeout (ms)\n" +), +CMD_TBL_ITEM( + chkcpu, CONFIG_SYS_MAXARGS, CTBL_RPT|CTBL_SUBCMDAUTO, do_cpu_freq_chk, + "Check/Identify CPU", +// "[-swnu] [-c loopcycles] [-t timeout]\n" + "[-swnu] [-c loopcycles]\n" + " -s Be silent\n" + " -w Write result to environment variable '"ENV_CPU"'" + " -n Don't load code snippet. \n" + " -u Don't unload. Leave code snippet in ram." +// " -t Timeout (ms)\n" +), +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, + test, CONFIG_SYS_MAXARGS, CTBL_RPT, do_cpu_test, "Do bus request/release cycles", "[-t pulsewidth]" ), CMD_TBL_ITEM( - busack, 2, 1, do_busack_test, + busack, 2, CTBL_RPT, do_busack_test, "Get time from /Reset high to /BUSACK low", "" ), -#if 0 -CMD_TBL_ITEM( - freq, CONFIG_SYS_MAXARGS, 1, do_cpu_freq, - "Measure cpu frequency", - "[-swn] [-c loopcycles]\n" - " -s Supress output (silent)\n" - " -w Write result to environment variable '"ENV_CPU_FREQ"'" -), -#endif + CMD_TBL_ITEM( help, CONFIG_SYS_MAXARGS, CTBL_RPT, do_help, "Print sub command description/usage", @@ -299,7 +468,7 @@ CMD_TBL_ITEM( ), /* This does not use the CMD_TBL_ITEM macro as ? can't be used in symbol names */ - {FSTR("?"), CONFIG_SYS_MAXARGS, 1, do_help, + {FSTR("?"), CONFIG_SYS_MAXARGS, CTBL_RPT, do_help, NULL, #ifdef CONFIG_SYS_LONGHELP FSTR(""), @@ -322,7 +491,7 @@ command_ret_t do_cpu(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc } -#if 0 +#if 0 /* Z180 Single Step Functions */ /* * Z180 Single Step Functions *