*/
#include "cmd_cpu.h"
-//#include <ctype.h>
#include <util/atomic.h>
#include "z80-if.h"
#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 <count> ms...
*/
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<<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) {
- if ((TIFR4 & _BV(OCF4B)) != 0) {
- TIFR4 = _BV(OCF4B);
- ++ref_ovfl;
- }
- if ((TIFR3 & _BV(TOV3)) != 0) {
- TIFR3 = _BV(TOV3);
- ++x_ovfl;
- }
- }
-
- 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++;
- }
-
- 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 x_freq;
-}
-
+static const FLASH char * const FLASH cpu_strings[] = {
+ FSTR("Unknown"),
+ FSTR("8080"),
+ FSTR("8085"),
+ FSTR("Z80"),
+ FSTR("x180"),
+ FSTR("HD64180"),
+ FSTR("Z80180"),
+ FSTR("Z80S180"),
+};
#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[])
+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[])
{
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;
- uint16_t timeout = 1000;
+ uint_fast8_t freq_cmd = 0;
+// uint16_t timeout = 1000;
uint8_t eimsk_save;
ERRNUM err = ESUCCESS;
+ if (argv[0][0] == 'f')
+ freq_cmd = 1;
+
int opt;
- while ((opt = getopt(argc, argv, PSTR("swnuc:t:"))) != -1) {
+ while ((opt = getopt(argc, argv, opt_strings[freq_cmd])) != -1) {
switch (opt) {
case 's':
options |= O_SILENT;
case 'c':
lcycles = eval_arg(optarg, NULL);
break;
- case 't':
- timeout = eval_arg(optarg, NULL);
- break;
+// case 't':
+// timeout = eval_arg(optarg, NULL);
+// break;
default: /* '?' */
return CMD_RET_USAGE;
}
}
} 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);
+ if (freq_cmd) {
+ if (lcycles == 0) {
+ z80_bus_cmd(Request);
+ if (z80_read(3) == 0xFF)
+ lcycles = z80_read(5);
+ z80_bus_cmd(Release);
+ }
+ if (!err)
+ cpu_freq = z80_measure_phi(lcycles);
}
- uint32_t cpu_freq = 0;
- if (!err)
- cpu_freq = z80_measure_phi(lcycles);
-
z80_bus_cmd(Reset);
/* Restore INT5/INT6 */
Stat &= ~S_MSG_PENDING;
Stat &= ~S_CON_PENDING;
-
-
-
-
-
+ if (freq_cmd == 0) {
+ 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);
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"),
- FSTR("8080"),
- FSTR("8085"),
- FSTR("Z80"),
- FSTR("x180"),
- FSTR("HD64180"),
- FSTR("Z80180"),
- FSTR("Z80S180"),
-};
-
-command_ret_t do_cpuchk(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED)
-{
- uint_fast8_t options = O_LOAD_LOOP | O_UNLOAD_LOOP;
- uint_fast8_t cputype = 0;
- ERRNUM err = ESUCCESS;
- 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);
- }
+ char result_str[11];
- /* Save state and disable INT5/INT6 */
- ATOMIC_BLOCK(ATOMIC_FORCEON) {
- eimsk_save = EIMSK;
- EIMSK &= ~_BV(INT6);
- EIMSK &= ~_BV(INT5);
+ if (freq_cmd) {
+ ultoa(cpu_freq, result_str, 10);
+ } else {
+ if (cputype >= ARRAY_SIZE(cpu_strings))
+ cputype = 0;
+ strcpy_P(result_str, cpu_strings[cputype]);
}
- EIFR = _BV(INTF5); /* Reset pending int */
- z80_bus_cmd(Run);
+ if (!(options & O_SILENT))
+ printf_P(PSTR("%s\n"), result_str);
- clear_ctrlc(); /* forget any previous Control C */
- do {
- /* check for ctrl-c to abort... */
- if (had_ctrlc() || ctrlc()) {
- err = EINTR;
- break;
+ 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 ((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(mem_save, 0, cpuinfo_length);
- z80_bus_cmd(Release);
- }
- free(mem_save);
-
- if (err)
- cmd_error(CMD_RET_FAILURE, err, NULL);
-
- if (cputype >= ARRAY_SIZE(cpu_strings))
- cputype = 0;
- printf_P(PSTR("Detected CPU: %S\n"), cpu_strings[cputype]);
return CMD_RET_SUCCESS;
}
/*
* command table for subcommands
*/
-
cmd_tbl_t cmd_tbl_cpu[] = {
CMD_TBL_ITEM(
- chkcpu, CONFIG_SYS_MAXARGS, CTBL_RPT|CTBL_SUBCMDAUTO, do_cpuchk,
+ 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"
+ " -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"
+ " -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,
""
),
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",
""
),
-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,
),
/* 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(""),