]> cloudbase.mooo.com Git - z180-stamp.git/commitdiff
New command cpuchk
authorLeo C <erbl259-lmu@yahoo.de>
Sat, 8 Sep 2018 07:39:06 +0000 (09:39 +0200)
committerLeo C <erbl259-lmu@yahoo.de>
Sat, 8 Sep 2018 07:39:06 +0000 (09:39 +0200)
move z80_load_mem() to z80-if.c

avr/Tupfile
avr/cmd_boot.c
avr/cmd_cpu.c [new file with mode: 0644]
avr/command_tbl.c
avr/z80-if.c
include/cmd_cpu.h [new file with mode: 0644]
include/z80-if.h
z180/Tupfile
z180/cpuinfo.180 [new file with mode: 0644]

index b74b30575bce57a0400cd32c251950a8c02b9b30..68a6ae0e93c6239514b23e0d4ea4c34252ceabaa 100644 (file)
@@ -7,7 +7,7 @@ FATFS   = $(FATFSD)/ff.c $(FATFSD)/ffunicode.c
 
 SRC            = main.c
 SRC            += cli.c cli_readline.c command.c command_tbl.c
-SRC            += cmd_run.c cmd_boot.c cmd_misc.c
+SRC            += cmd_run.c cmd_boot.c cmd_misc.c cmd_cpu.c
 SRC            += cmd_date.c cmd_mem.c cmd_gpio.c cmd_attach.c
 SRC            += cmd_loadihex.c cmd_loadcpm3.c cmd_sd.c cmd_fat.c
 SRC            += env.c con-utils.c print-utils.c getopt-min.c eval_arg.c
@@ -23,7 +23,7 @@ SRC           += ../time/system_time.c ../time/set_system_time.c
 
 ASRC   += ../time/system_tick.S
 
-SRC_Z          = ../z180/hdrom.c ../z180/cfboot.c
+SRC_Z          = ../z180/hdrom.c ../z180/cfboot.c ../z180/cpuinfo.c
 
 #TARGETS       = $(PROG).elf
 
@@ -112,7 +112,7 @@ LDFLAGS     += -Wl,--cref
 !SIZE = |> ^ SIZE^ $(SIZE) %f |>
 
 : foreach $(ASRC) |> !as |>  {objs}
-: foreach $(SRC) | ../z180/hdrom.h ../z180/cfboot.h |> !cc |>  {objs}
+: foreach $(SRC) | ../z180/hdrom.h ../z180/cfboot.h ../z180/cpuinfo.h |> !cc |>  {objs}
 : foreach $(SRC_Z) |> !cc -D'const=const __flash' |> {objs}
 
 : {objs} |> !LINK |> $(PROG).elf
index 600bad3fffcf20fa144c80ca61e7624ea2c3617a..2159608e4055bcc600a54cdf6670f1bc49051cd2 100644 (file)
 #undef const
 
 
-
-static void z80_load_mem(int_fast8_t verbosity,
-                               const FLASH unsigned char data[],
-                               const FLASH unsigned long *sections,
-                               const FLASH unsigned long address[],
-                               const FLASH unsigned long length_of_sections[])
-{
-       uint32_t sec_base = 0;
-
-       if (verbosity > 1)
-               printf_P(PSTR("Loading Z180 memory... \n"));
-
-       for (unsigned sec = 0; sec < *sections; sec++) {
-               if (verbosity > 0) {
-                       printf_P(PSTR("   From: 0x%.5lX to: 0x%.5lX    (%5li bytes)\n"),
-                                       address[sec],
-                                       address[sec]+length_of_sections[sec] - 1,
-                                       length_of_sections[sec]);
-               }
-
-               z80_write_block_P((const FLASH unsigned char *) &data[sec_base],  /* src */
-                               address[sec],                  /* dest */
-                               length_of_sections[sec]);      /* len */
-               sec_base += length_of_sections[sec];
-       }
-}
-
 command_ret_t do_loadf(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED)
 {
        if (z80_bus_state() & ZST_RUNNING)
diff --git a/avr/cmd_cpu.c b/avr/cmd_cpu.c
new file mode 100644 (file)
index 0000000..de627c6
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * (C) Copyright 2018 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#include "cmd_cpu.h"
+//#include <ctype.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"
+
+/* hack to get Z180 loadfile into flash memory */
+#define const const FLASH
+#include "../z180/cpuinfo.h"
+#undef const
+
+
+static const FLASH char * const FLASH cpu_strings[] = {
+       FSTR("Unknown CPU"),
+       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)
+{
+       uint8_t done = 0;
+       uint8_t cputype;
+       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);
+               z80_bus_cmd(Release);
+
+               if (argv[1] && (argv[1][0] == 'n'))
+                       goto donot;
+
+               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);
+               }
+               z80_bus_cmd(Reset);
+               z80_bus_cmd(Request);
+//             z80_write_block(ram_save, 0, cpuinfo_length);
+               z80_bus_cmd(Release);
+       }
+
+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]);
+       }
+
+       return CMD_RET_SUCCESS;
+}
index 5d185ba995ad865ec60da679111acffde5f50eb7..9968dc0dfe0950e2bc457eb1dd262dc6586d065a 100644 (file)
@@ -8,6 +8,7 @@
 #include "command.h"
 #include "cmd_mem.h"
 #include "cmd_boot.h"
+#include "cmd_cpu.h"
 #include "cmd_misc.h"
 #include "cmd_date.h"
 #include "cmd_run.h"
@@ -125,6 +126,11 @@ CMD_TBL_ITEM_TOP(
        cmd_tbl_env
 ),
 
+CMD_TBL_ITEM(
+       chkcpu, CONFIG_SYS_MAXARGS,     CTBL_RPT,       do_cpuchk,
+       "Check CPU",
+       ""
+),
 CMD_TBL_ITEM(
        loadf,  1,      0,      do_loadf,
        "load srec_cat prepared image from controller flash",
index 180a27fa25c88f240fafaa35960bd3232a4fb097..7a953f06e9017b384615b69b0f6cb5fd5dda7c2e 100644 (file)
@@ -506,6 +506,8 @@ int32_t z80_memsize_detect(void)
        return addr;
 }
 
+/*--------------------------------------------------------------------------*/
+
 void z80_write(uint32_t addr, uint8_t data)
 {
        z80_setaddress(addr);
@@ -605,6 +607,7 @@ void z80_read_block (uint8_t *dest, uint32_t src, size_t length)
        Z80_O_MREQ = 1;
 }
 
+/*--------------------------------------------------------------------------*/
 
 /*
   0179'                         rx.bs_mask:    ds      1               ; (buf_len - 1)
@@ -745,3 +748,31 @@ void z80_memfifo_putc(fifo_t f, uint8_t val)
        z80_write(fifo_dsc[f].base+FIFO_INDEX_IN, fifo_dsc[f].idx_in);
        z80_bus_cmd(Release);
 }
+
+/*--------------------------------------------------------------------------*/
+
+void z80_load_mem(int_fast8_t verbosity,
+                               const FLASH unsigned char data[],
+                               const FLASH unsigned long *sections,
+                               const FLASH unsigned long address[],
+                               const FLASH unsigned long length_of_sections[])
+{
+       uint32_t sec_base = 0;
+
+       if (verbosity > 1)
+               printf_P(PSTR("Loading Z180 memory... \n"));
+
+       for (unsigned sec = 0; sec < *sections; sec++) {
+               if (verbosity > 0) {
+                       printf_P(PSTR("   From: 0x%.5lX to: 0x%.5lX    (%5li bytes)\n"),
+                                       address[sec],
+                                       address[sec]+length_of_sections[sec] - 1,
+                                       length_of_sections[sec]);
+               }
+
+               z80_write_block_P((const FLASH unsigned char *) &data[sec_base],  /* src */
+                               address[sec],                  /* dest */
+                               length_of_sections[sec]);      /* len */
+               sec_base += length_of_sections[sec];
+       }
+}
diff --git a/include/cmd_cpu.h b/include/cmd_cpu.h
new file mode 100644 (file)
index 0000000..d590468
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * (C) Copyright 2018 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef CMD_CPU_H
+#define CMD_CPU_H
+
+#include "command.h"
+
+command_ret_t do_cpuchk(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+
+#endif /* CMD_CPU_H */
index 0ad14f5c170a2a779bbff3952b4a27e18c13d16b..7225cf47c8a450f74e98d9e0b5eacfa30a86d0a1 100644 (file)
@@ -58,3 +58,8 @@ int z80_memfifo_is_full(const fifo_t f);
 int z80_memfifo_getc(const fifo_t f);
 uint8_t z80_memfifo_getc_wait(const fifo_t f);
 void z80_memfifo_putc(fifo_t f, uint8_t val);
+
+void z80_load_mem(int_fast8_t verbosity, const FLASH unsigned char data[],
+                                                                                const FLASH unsigned long *sections,
+                                                                                const FLASH unsigned long address[],
+                                                                                const FLASH unsigned long length_of_sections[]);
index c7d79fbea81cfee4c8aef548fc4ebffd1d9fe6ca..0c3f95e53c06b24abef65d5a4bc9ec567f05a39a 100644 (file)
@@ -2,6 +2,7 @@ include_rules
 
 PROG   = hdrom
 CFBOOT = cfboot
+CPUINFO        = cpuinfo
 
 SRC    = init.180
 SRC    += ddtz.180
@@ -52,6 +53,9 @@ rm -f ${OUTPUT}; exit ${ERROR} \
 : $(CFBOOT).180 |> $(AS) -%B/HFS |> %B.hex | %B.lst
 : $(CFBOOT).hex |> srec_cat -o %o -c_array %B -C_COMpressed -include %f -Intel |> $(CFBOOT).c | $(CFBOOT).h
 
+: $(CPUINFO).180 |> $(AS) -%B/HFS |> %B.hex | %B.lst
+: $(CPUINFO).hex |> srec_cat -o %o -c_array %B -C_COMpressed -include %f -Intel |> $(CPUINFO).c | $(CPUINFO).h
+
 #COMMAND="$(AS) -%B/$(AS_OPT)"; \
 
 
diff --git a/z180/cpuinfo.180 b/z180/cpuinfo.180
new file mode 100644 (file)
index 0000000..8629aa5
--- /dev/null
@@ -0,0 +1,204 @@
+       .z80                            ; for M80, ignored by SLR assembler\r
+       include z180reg.inc\r
+\r
+RUN_TPA                equ     0\r
+\r
+UUNKNOWN       equ     0       ;Unknown CPU\r
+U8080          equ     1       ;8080\r
+U8085          equ     2       ;8085\r
+UZ80           equ     3       ;Z80\r
+UX180          equ     4       ;HD64180 or higher\r
+UHD64180       equ     5       ;HD64180\r
+UZ80180                equ     6       ;Z80180\r
+UZ8S180        equ     7       ;Z8S180, Z8L180\r
+\r
+\r
+;-------------------------------------------------------------------------------\r
+\r
+\r
+   if RUN_TPA\r
+base           equ     0100h\r
+   else\r
+base           equ     0\r
+   endif\r
+\r
+\r
+       aseg\r
+       org     base\r
+       jp      start\r
+\r
+done:  db      0\r
+result:        db      0\r
+\r
+;-------------------------------------------------------------------------------\r
+; Read internal register at address in L and IOBASE in H.\r
+;\r
+\r
+reg_in:\r
+       ld      a,h\r
+       add     a,l\r
+       ld      c,a\r
+       ld      b,0\r
+       in      a,(c)\r
+       ret\r
+\r
+;-------------------------------------------------------------------------------\r
+; Write internal register at address in L and IOBASE in H.\r
+;\r
+\r
+reg_out:\r
+       ld      b,a\r
+       ld      a,h\r
+       add     a,l\r
+       ld      c,a\r
+       ld      a,b\r
+       ld      b,0\r
+       out     (c),a\r
+       ret\r
+\r
+;-------------------------------------------------------------------------------\r
+; Check if register C exists. D holds mask of bit to test.\r
+;      return nz, if register exists\r
+\r
+chk_reg:\r
+       call    reg_in\r
+       cp      0ffh\r
+       ret     nz              ;\r
+\r
+       ; check, if register is changeable\r
+\r
+       xor     d               ; set bit(s) in register to 0\r
+       call    reg_out\r
+       call    reg_in          ; get it back\r
+       ex      af,af'\r
+       ld      a,0ffh          ; set to register original state\r
+       call    reg_out\r
+       ex      af,af'\r
+       cpl\r
+       and     d\r
+       ret\r
+\r
+;-------------------------------------------------------------------------------\r
+; Check CPU\r
+;\r
+;\r
+; return:\r
+;      E = 0   Unknown\r
+;      E = 1   8080\r
+;      E = 2   8085\r
+;      E = 3   Z80\r
+;      E = 4   HD64180 or higher\r
+;      E = 5   HD64180\r
+;      E = 6   Z80180\r
+;      E = 7   Z8S180, Z8L180\r
+;\r
+;-------------------------------------------------------------------------------\r
+; Registers only in Z180+, not in HD64180\r
+;      3E      OMCR\r
+;\r
+; Registers only in Z8S180/Z8L180\r
+;      12      ASEXT0\r
+;      13      ASEXT1\r
+;      1A      ASTC0L\r
+;      1B      ASTC0H\r
+;      1C      ASTC1L\r
+;      1D      ASTC1H\r
+;      1E      CMR\r
+;      1F      CCR\r
+;      2D      IAR1B\r
+;\r
+; Reserved registers\r
+;      11\r
+;      19\r
+;      35\r
+;      37\r
+;      3B - 3D\r
+\r
+check:\r
+       ld      e,U8080         ; Init return val, assume 8080\r
+       xor     a\r
+       dec     a               ; 00 --> 0FFH   8080/8085: even parity; Z80+: No overflow\r
+       jp      po,chk_z80      ; Z80+ if P/V flag reset\r
+\r
+       ; The 8085 logical AND instructions always set the auxiliary flag ON.\r
+       ; The 8080 logical AND instructions set the flag to reflect the\r
+       ; logical OR of bit 3 of the values involved in the AND operation.\r
+       ; (8080/8085 ASSEMBLY LANGUAGE PROGRAMMING MANUAL, 1977, 1978)\r
+\r
+       xor     a\r
+       and     a               ; 8085 sets, 8080 resets half carry.\r
+       daa                     ; A=06 (8085) or A=00 (8080)\r
+       ret     z\r
+       inc     e\r
+       ret\r
+\r
+chk_z80:\r
+       ld      e,UZ80          ; Assume Z80\r
+       daa                     ; Z80: 099H, x180+: 0F9H\r
+       cp      99h             ; Result on 180 type cpus is F9 here. Thanks Hitachi\r
+       ret     z\r
+       inc     e               ; x180\r
+\r
+       ; At least Hitachi HD64180\r
+       ; Test differences in certain internal registers\r
+       ; to determine the 180 variant.\r
+       ; First, search the internal register bank.\r
+\r
+       ld      h,00H           ; I/O Base\r
+find_base_loop:\r
+       ld      l,icr\r
+       call    reg_in\r
+       and     11011111b       ; mask I/O Stop bit\r
+       xor     h\r
+       cp      01FH\r
+       jr      nz,nxt_base\r
+\r
+       ;TODO: additional plausibility checks\r
+\r
+       jr      z,base_found\r
+nxt_base:\r
+       ld      a,h\r
+       add     a,040H\r
+       ld      h,a\r
+       jr      nc,find_base_loop\r
+       ret                     ;I/O registers not found\r
+\r
+       ; Register (base) found.\r
+\r
+base_found:\r
+       inc     e               ; HD64180\r
+       ld      l,omcr          ; Check, if CPU has OMCR register\r
+       ld      d,M_IOC         ;\r
+       call    chk_reg         ;\r
+       ret     z               ; Register does not exist. It's a HD64180\r
+\r
+       inc     e               ; Z80180\r
+       ld      l,cmr           ; Check, if CPU has CMR register\r
+       ld      d,M_LNC         ;\r
+       call    chk_reg         ;\r
+       ret     z               ; register does not exist. It's a Z80180\r
+\r
+       inc     e               ; S180/L180 (class) detected.\r
+\r
+       ret\r
+\r
+;-------------------------------------------------------------------------------\r
+\r
+start:\r
+       ld      sp,stack\r
+       call    check\r
+\r
+       ld      hl,result\r
+       ld      (hl),e\r
+       dec     hl\r
+       ld      (hl),0ffH\r
+       halt\r
+       jp      $-1\r
+\r
+       rept    8\r
+         dw    0\r
+       endm\r
+stack:\r
+       end\r
+\r
+; vim:set ts=8 noet nowrap\r