X-Git-Url: http://cloudbase.mooo.com/gitweb/z180-stamp.git/blobdiff_plain/dbc1de70e1824cf1a649d892db5746b86b34b4e7..7535ca1b43f9320f0de3c49fc7a12560a5022a7c:/avr/cmd_cpu.c diff --git a/avr/cmd_cpu.c b/avr/cmd_cpu.c index 6f50a2a..e77b901 100644 --- a/avr/cmd_cpu.c +++ b/avr/cmd_cpu.c @@ -10,17 +10,36 @@ #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) + + +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... @@ -32,10 +51,11 @@ static void test_delay(uint32_t count) while (get_timer(ts) <= count); } -static int32_t z80_measure_phi(uint8_t cycles, bool input_clk, uint16_t wait_ms) +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; @@ -43,96 +63,219 @@ static int32_t z80_measure_phi(uint8_t cycles, bool input_clk, uint16_t wait_ms) TCCR3A = 0; TCCR3B = 0b000<= 100000UL) { - x_freq = (x_freq + 5)/10; - ++sc; - } - while (sc--) - x_freq *= 10; + if ((TIFR3 & _BV(TOV3)) != 0) { + TIFR3 = _BV(TOV3); + x_ovfl++; + } + + 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); + +// char x_tmp_str[21]; +// +// debug_cpu("TCNT3: %6u, ref_cnt: %9lu\n", TCNT3, ref_cnt); +// ulltoa(x_tmp, x_tmp_str); +// debug_cpu("x_tmp: %s\n", x_tmp_str); + + x_tmp = (x_tmp * getenv_ulong(PSTR(ENV_FMON), 10, F_CPU) + (ref_cnt / 2)) / ref_cnt; + +// ulltoa(x_tmp, x_tmp_str); +// debug_cpu("x_tmp: %s\n", x_tmp_str); + + /* round to 5 decimal digits */ + int_fast8_t sc = 5; + while (sc > 0 || x_tmp >= 100000) { + x_tmp = (x_tmp + 5)/10; + sc--; + } + x_freq = x_tmp; + while (sc < 0) { + x_freq *= 10; + sc++; } /* Stop Timer */ TCCR3B = 0; PRR1 |= _BV(PRTIM3); - return (int32_t) x_freq; + return x_freq; } +#define O_SILENT (1<<0) +#define O_WENV (1<<1) +#define O_LOAD_LOOP (1<<2) +#define O_UNLOAD_LOOP (1<<3) + +command_ret_t do_cpu_freq(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, char * const argv[]) +{ + uint_fast8_t options = O_LOAD_LOOP | O_UNLOAD_LOOP; + uint_fast8_t lcycles = 0; + uint16_t timeout = 1000; + uint8_t eimsk_save; + ERRNUM err = ESUCCESS; + + 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) + 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); + } + + /* 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); + + 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 (lcycles == 0) { + z80_bus_cmd(Request); + if (z80_read(3) == 0xFF) + lcycles = z80_read(5); + z80_bus_cmd(Release); + } + uint32_t cpu_freq = 0; + 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 ((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 (!(options & O_SILENT)) + printf_P(PSTR("%lu\n"), cpu_freq); + +#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; +} + static const FLASH char * const FLASH cpu_strings[] = { - FSTR("Unknown CPU"), + FSTR("Unknown"), FSTR("8080"), FSTR("8085"), FSTR("Z80"), @@ -144,57 +287,111 @@ 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 options = O_LOAD_LOOP | O_UNLOAD_LOOP; + uint_fast8_t cputype = 0; 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); + uint8_t eimsk_save; + + int opt; + while ((opt = getopt(argc, argv, PSTR("swnu"))) != -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; + 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; - } - z80_bus_cmd(Request); - done = z80_read(3); - if (done == 0xFF) - cputype = z80_read(4); - z80_bus_cmd(Release); + clear_ctrlc(); /* forget any previous Control C */ + do { + /* check for ctrl-c to abort... */ + if (had_ctrlc() || ctrlc()) { + err = EINTR; + break; } - z80_bus_cmd(Reset); + } while ((EIFR & _BV(INTF5)) == 0); + + + + + + + + + + + + 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; + + z80_bus_cmd(Request); + if (z80_read(3) == 0xFF) { + cputype = z80_read(4); + } + z80_bus_cmd(Release); + + if ((mem_save != NULL) && options & O_UNLOAD_LOOP) { z80_bus_cmd(Request); -// z80_write_block(ram_save, 0, cpuinfo_length); + z80_write_block(mem_save, 0, cpuinfo_length); z80_bus_cmd(Release); } - -donot: + free(mem_save); 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; } @@ -204,9 +401,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) { @@ -234,11 +428,9 @@ command_ret_t do_cpu_test(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int command_ret_t do_bus_test(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED) { - char ch; + int ch; #if 0 - /* reset getopt() */ - optind = 0; int opt; while ((opt = getopt(argc, argv, PSTR("t:"))) != -1) { switch (opt) { @@ -315,142 +507,15 @@ command_ret_t do_busack_test(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, return CMD_RET_SUCCESS; } -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; - 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("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; - } - - 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); - } - - z80_bus_cmd(Request); - if (options & O_LOAD_LOOP) { - z80_read_block(mem_save, 0, cpuinfo_length); - z80_load_mem(0, cpuinfo, - &cpuinfo_sections, - cpuinfo_address, - cpuinfo_length_of_sections); - } - 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); - - int32_t cpu_freq; - if (!err) - cpu_freq = z80_measure_phi(lcycles, false, timeout); - - z80_bus_cmd(Reset); - if (options & O_UNLOAD_LOOP) { - z80_bus_cmd(Request); - z80_write_block(mem_save, 0, cpuinfo_length); - 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 (err) - cmd_error(CMD_RET_FAILURE, err, NULL); - - if (!(options & O_SILENT)) { - printf_P(PSTR("%ld%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 + * command table for subcommands */ cmd_tbl_t cmd_tbl_cpu[] = { CMD_TBL_ITEM( - chkcpu, CONFIG_SYS_MAXARGS, CTBL_RPT, do_cpuchk, - "Check CPU", + chkcpu, CONFIG_SYS_MAXARGS, CTBL_RPT|CTBL_SUBCMDAUTO, do_cpuchk, + "Check/Identify CPU", "" ), CMD_TBL_ITEM(