diff options
Diffstat (limited to 'avr')
-rw-r--r-- | avr/Tupfile | 32 | ||||
-rw-r--r-- | avr/background.c | 16 | ||||
-rw-r--r-- | avr/bcd.c | 21 | ||||
-rw-r--r-- | avr/cli.c | 133 | ||||
-rw-r--r-- | avr/cli_readline.c | 13 | ||||
-rw-r--r-- | avr/cmd_boot.c | 69 | ||||
-rw-r--r-- | avr/cmd_date.c | 136 | ||||
-rw-r--r-- | avr/cmd_fat.c | 419 | ||||
-rw-r--r-- | avr/cmd_gpio.c | 8 | ||||
-rw-r--r-- | avr/cmd_help.c | 8 | ||||
-rw-r--r-- | avr/cmd_loadcpm3.c | 172 | ||||
-rw-r--r-- | avr/cmd_loadihex.c | 261 | ||||
-rw-r--r-- | avr/cmd_mem.c | 377 | ||||
-rw-r--r-- | avr/cmd_misc.c | 48 | ||||
-rw-r--r-- | avr/cmd_sd.c | 81 | ||||
-rw-r--r-- | avr/command.c | 15 | ||||
-rw-r--r-- | avr/command_tbl.c | 105 | ||||
-rw-r--r-- | avr/con-utils.c | 34 | ||||
-rw-r--r-- | avr/date.c | 139 | ||||
-rw-r--r-- | avr/debug.c | 108 | ||||
-rw-r--r-- | avr/env.c | 46 | ||||
-rw-r--r-- | avr/getopt-min.c | 9 | ||||
-rw-r--r-- | avr/gpio.c | 62 | ||||
-rw-r--r-- | avr/i2c.c | 8 | ||||
-rw-r--r-- | avr/main.c | 80 | ||||
-rw-r--r-- | avr/mmc.c | 218 | ||||
-rw-r--r-- | avr/pcf8583.c | 27 | ||||
-rw-r--r-- | avr/print-utils.c | 13 | ||||
-rw-r--r-- | avr/serial.c | 9 | ||||
-rw-r--r-- | avr/timer.c | 23 | ||||
-rw-r--r-- | avr/xmalloc.c | 11 | ||||
-rw-r--r-- | avr/z180-serv.c | 455 | ||||
-rw-r--r-- | avr/z180-stamp-avr.c | 591 | ||||
-rw-r--r-- | avr/z80-if.c | 12 |
34 files changed, 2189 insertions, 1570 deletions
diff --git a/avr/Tupfile b/avr/Tupfile index 11b5802..d73db12 100644 --- a/avr/Tupfile +++ b/avr/Tupfile @@ -1,14 +1,25 @@ include_rules PROG = stamp-monitor + +FATFS = $(TOP)/fatfs/src/ff.c + SRC = main.c SRC += cli.c cli_readline.c command.c command_tbl.c SRC += cmd_help.c cmd_date.c cmd_mem.c cmd_boot.c cmd_gpio.c cmd_misc.c -SRC += cmd_sd.c cmd_fat.c -SRC += env.c xmalloc.c date.c con-utils.c print-utils.c getopt-min.c -SRC += timer.c serial.c i2c.c pcf8583.c mmc.c +SRC += cmd_loadihex.c cmd_loadcpm3.c cmd_sd.c cmd_fat.c +SRC += env.c xmalloc.c con-utils.c print-utils.c getopt-min.c +SRC += timer.c serial.c i2c.c bcd.c pcf8583.c mmc.c SRC += background.c z180-serv.c z80-if.c gpio.c -SRC += $(TOP)/fatfs/src/ff.c +SRC += $(FATFS) $(TOP)/fatfs/src/option/unicode.c + +#TODO: time lib +SRC += ../time/asctime_r.c ../time/gmtime_r.c ../time/mk_gmtime.c +SRC += ../time/print_lz.c ../time/isLeap.c +SRC += ../time/time.c ../time/fatfs_time.c +SRC += ../time/system_time.c ../time/set_system_time.c + +ASRC += ../time/system_tick.S SRC_Z = ../z180/hdrom.c @@ -59,25 +70,34 @@ CFLAGS += -fno-split-wide-types CFLAGS += -fshort-enums #CFLAGS += -fdiagnostics-color=always - #CFLAGS += -save-temps +CFLAGS_$(FATFS) = -fno-strict-aliasing CFLAGS += $(INCLUDES) CPPFLAGS += $(DEFS) +#ASFLAGS += -Wa,-adhlns=$(<:.S=.lst),-gstabs +ASFLAGS += -mmcu=$(MCU_TARGET) -x assembler-with-cpp $(ASFLAGS) + # Linker flags LDFLAGS += -Wl,--gc-sections LDFLAGS += -Wl,--cref +# Assemble: create object files from assembler source files. +#.S.o: +# $(CC) -c $(ALL_ASFLAGS) $< -o $@ + -!cc = |> ^ CC %f^ $(CC) $(CFLAGS) $(CPPFLAGS) -c %f -o %o |> %B.o +!as = |> ^ AS %f^ $(CC) $(ASFLAGS) -c %f -o %o |> %B.o +!cc = |> ^ CC %f^ $(CC) $(CFLAGS) $(CPPFLAGS) $(CFLAGS_%f) -c %f -o %o |> %B.o !LINK = |> ^ LINK %o^ $(LD) $(CFLAGS) $(LDFLAGS) -Wl,-Map=%O.map %f $(LDLIBS) -o %o |> | %O.map !OBJCOPY= |> ^ OBJCOPY %o^ $(OBJCOPY) -Oihex %f %o |> !OBJDUMP= |> ^ OBJDUMP %o^ $(OBJDUMP) -h -S %f > %o |> %O.lss !SIZE = |> ^ SIZE^ $(SIZE) %f |> +: foreach $(ASRC) |> !as |> {objs} : foreach $(SRC) | ../z180/hdrom.h |> !cc |> {objs} : $(SRC_Z) |> !cc -D'const=const __flash' |> {objs} diff --git a/avr/background.c b/avr/background.c index 0e1ca40..9c8b5a6 100644 --- a/avr/background.c +++ b/avr/background.c @@ -1,10 +1,16 @@ +/* + * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + #include "common.h" #include "background.h" #define BG_FUNC_MAX 5 -static struct { +static struct { bg_func fct; int param; } func_tab[BG_FUNC_MAX]; @@ -13,7 +19,7 @@ static int_fast8_t fcount; int bg_register(bg_func f, int initval) { - if (fcount < BG_FUNC_MAX) { + if (fcount < BG_FUNC_MAX) { func_tab[fcount].fct = f; func_tab[fcount].param = initval; return ++fcount - 1; @@ -27,7 +33,7 @@ int bg_setstat(int handle, int val) func_tab[handle].param = val; return 1; } - + return 0; } @@ -44,7 +50,7 @@ int bg_getstat(int handle) void bg_shed(void) { static int_fast8_t current; - + if (func_tab[current].fct) { int v = func_tab[current].fct(func_tab[current].param); func_tab[current].param = v; @@ -52,5 +58,3 @@ void bg_shed(void) if (++current >= fcount) current = 0; } - - diff --git a/avr/bcd.c b/avr/bcd.c new file mode 100644 index 0000000..5154852 --- /dev/null +++ b/avr/bcd.c @@ -0,0 +1,21 @@ +/* + * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "stdlib.h" +#include "stdint.h" +#include "bcd.h" + +uint_fast8_t bcd2bin(uint8_t val) +{ + return (val >> 4) * 10 + (val & 0x0f); +} + +uint8_t bin2bcd (uint_fast8_t val) +{ + div_t d = div(val, 10); + + return (d.quot << 4) | d.rem; +} @@ -1,3 +1,16 @@ +/* + * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de> + * + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Add to readline cmdline-editing by + * (C) Copyright 2005 + * JinHua Luo, GuangDong Linux Center, <luo.jinhua@gd-linux.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + #include "common.h" #include <string.h> @@ -14,6 +27,9 @@ #include "con-utils.h" #include "cli.h" + +/* FIXME: Quoting problems */ + #define DEBUG_PARSER 0 /* set to 1 to debug */ #define debug_parser(fmt, args...) \ @@ -21,26 +37,75 @@ static int cli_parse_line(char *line, char *argv[]) { - static const FLASH char delim[] = {" \t"}; - - char *ptr; + uint_fast8_t state = 0; uint_fast8_t nargs = 0; + char *inp, *outp; + char c, quote; - debug_parser("parse_line: \"%s\"\n", line); + debug_parser("%s: \"%s\"\n", __func__, line); + + for (outp = inp = line, quote = '\0' ; + nargs < CONFIG_SYS_MAXARGS && (c = *inp) != '\0'; + inp++) { + + switch (state) { + case 0: /* before arg string, waiting for arg start */ + if (isblank(c)) + continue; + + argv[nargs++] = inp; /* begin of argument string */ + outp = inp; + state = 1; + /* fall thru */ + + case 1: /* in arg string, waiting for end of arg string */ + if (c == '\\') { + ++state; + continue; + } + if (c == '\"' || c == '\'') { + quote = c; + state = 3; + continue; + } + if (isblank(c)) { + c = '\0'; + state = 0; + } + break; - ptr = strtok_P(line, delim); - while(nargs < CONFIG_SYS_MAXARGS && ptr != NULL) { - argv[nargs++] = ptr; - ptr = strtok_P(NULL, delim); + case 3: /* in quote */ + if (c == '\\' && quote == '\"') { + ++state; + continue; + } + if (c == quote) { + state = 1; + continue; + } + break; + + case 2: /* waiting for next char */ + case 4: + --state; + break; + + } + *outp++ = c; } - if (ptr != NULL) + if (*inp != '\0') printf_P(PSTR("** Too many args (max. %d) **\n"), CONFIG_SYS_MAXARGS); + *outp = '\0'; argv[nargs] = NULL; - debug_parser("parse_line: nargs=%d\n", nargs); - + debug_parser("%s: nargs=%d\n", __func__, nargs); +#if 0 + for (int i = 0; i < nargs; i++) + debug_parser("%s: arg %d: >%s<\n", __func__, i, argv[i]); +#endif return nargs; + } static @@ -61,7 +126,8 @@ char *process_macros(char *input, char *output) for(uint_fast8_t pass = 0; pass < 2; pass++) { - uint_fast8_t state = 0; /* 0 = waiting for '$' */ + uint_fast8_t state = 0; + /* 0 = waiting for '$' */ /* 1 = waiting for '{' */ /* 2 = waiting for '}' */ /* 3 = waiting for ''' */ @@ -75,22 +141,13 @@ char *process_macros(char *input, char *output) } inp = input; - prev = '\0'; /* previous character */ - debug_parser("[PROCESS_MACROS] INPUT len %d: \"%s\"\n", strlen(inp), - inp); + debug_parser("[PROCESS_MACROS] INPUT len %d: \"%s\"\n", + strlen(inp), inp); + + for (prev = '\0'; (c = *inp++) != '\0'; prev = c) { - while ((c = *inp++) != '\0') { - if (state != 3) { - /* remove one level of escape characters */ - if ((c == '\\') && (prev != '\\')) { - if (*inp == '\0') - break; - prev = c; - c = *inp++; - } - } switch (state) { case 0: /* Waiting for (unescaped) $ */ @@ -98,19 +155,19 @@ char *process_macros(char *input, char *output) state = 3; break; } - if ((c == '$') && (prev != '\\')) + if ((c == '$') && (prev != '\\')) { state++; - else - append_char(pass, &outp, c); + continue; + } break; case 1: /* Waiting for { */ if (c == '{') { state++; varname = inp; + continue; } else { state = 0; append_char(pass, &outp, '$'); - append_char(pass, &outp, c); } break; case 2: /* Waiting for } */ @@ -126,15 +183,13 @@ char *process_macros(char *input, char *output) /* Look for another '$' */ state = 0; } - break; + continue; case 3: /* Waiting for ' */ - if ((c == '\'') && (prev != '\\')) + if (c == '\'') state = 0; - else - append_char(pass, &outp, c); break; } - prev = c; + append_char(pass, &outp, c); } append_char(pass, &outp, 0); @@ -200,12 +255,13 @@ static int cli_run_command(const char *cmd, int flag) */ for (inquotes = 0, sep = str; *sep; sep++) { if ((*sep == '\'') && - (*(sep - 1) != '\\')) + (sep != str) && /* past string start */ + (*(sep - 1) != '\\')) /* and NOT escaped */ inquotes = !inquotes; if (!inquotes && - (*sep == ';' || *sep == '\n') && /* separator */ - (sep != str) && /* past string start */ + (*sep == ';' || *sep == '\n') && /* separator */ + (sep != str) && /* past string start */ (*(sep - 1) != '\\')) /* and NOT escaped */ break; } @@ -257,7 +313,7 @@ static int cli_run_command_list(const char *cmd) /* - * Run a command using the selected parser. + * Run a command. * * @param cmd Command to run * @param flag Execution flags (CMD_FLAG_...) @@ -350,4 +406,3 @@ command_ret_t do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } return CMD_RET_SUCCESS; } - diff --git a/avr/cli_readline.c b/avr/cli_readline.c index 8795a97..ff83a3a 100644 --- a/avr/cli_readline.c +++ b/avr/cli_readline.c @@ -1,4 +1,6 @@ /* + * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de> + * * (C) Copyright 2000 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * @@ -10,7 +12,6 @@ */ #include "common.h" - #include <string.h> #include <stdio.h> #include <ctype.h> @@ -666,16 +667,8 @@ static int cli_readline_into_buffer(const FLASH char *const prompt, char *buffer my_puts_P(tab_seq + (col & 07)); col += 8 - (col & 07); } else { - char buf[2]; - - /* - * Echo input using puts() to force an - * LCD flush if we are using an LCD - */ ++col; - buf[0] = c; - buf[1] = '\0'; - my_puts(buf); + putchar(c); } *p++ = c; ++n; diff --git a/avr/cmd_boot.c b/avr/cmd_boot.c index 4775b6e..b8799aa 100644 --- a/avr/cmd_boot.c +++ b/avr/cmd_boot.c @@ -1,3 +1,11 @@ +/* + * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de> + * + * (C) Copyright 2000-2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ /* * Misc boot support @@ -8,6 +16,9 @@ #include <util/atomic.h> #include "command.h" +#include "cli_readline.h" +#include "cli.h" +#include "env.h" #include "con-utils.h" #include "z80-if.h" #include "z180-serv.h" @@ -33,11 +44,9 @@ static void z80_load_mem(void) hdrom_address[sec]+hdrom_length_of_sections[sec] - 1, hdrom_length_of_sections[sec]); - z80_bus_cmd(Request); z80_write_block_P((const FLASH unsigned char *) &hdrom[sec_base], /* src */ hdrom_address[sec], /* dest */ hdrom_length_of_sections[sec]); /* len */ - z80_bus_cmd(Release); sec_base+=hdrom_length_of_sections[sec]; sec++; } @@ -48,11 +57,15 @@ command_ret_t do_loadf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[] (void) cmdtp; (void) flag; (void) argc; (void) argv; if (z80_bus_state() & ZST_RUNNING) { - printf_P(PSTR("## Can't load while CPU is running!\n")); + my_puts_P(PSTR("Can't load while CPU is running!\n")); return CMD_RET_FAILURE; } - + if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) { + my_puts_P(PSTR("Bus timeout\n")); + return CMD_RET_FAILURE; + } z80_load_mem(); + z80_bus_cmd(Release); return CMD_RET_SUCCESS; } @@ -139,7 +152,7 @@ command_ret_t do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[] { (void) cmdtp; (void) flag; (void) argc; (void) argv; - printf_P(PSTR("## CPU now in reset state.\n")); + printf_P(PSTR("CPU now in reset state.\n")); reset_cpu(Reset); return CMD_RET_SUCCESS; @@ -159,12 +172,13 @@ void print_con_usage(char esc) { printf_P(PSTR("\n" "------------------------------------------------\n" " ?,H - This Help\n" - " R - Reset (Restart) CPU\n" " Q,X - Return to command line\n" - " \\ - code input:\n" - " \\nnn 3 decimal digits character code\n" - " \\Xhh 2 hexadecimal digits character code\n" - " ^%c - (Escape char) Type again to send itself\n" + " R - Reset (Restart) CPU\n" + " : - Execute monitor command\n" + " \\ - code input:\n" + " \\nnn 3 decimal digits character code\n" + " \\Xhh 2 hexadecimal digits character code\n" + " ^%c - (Escape char) Type again to send itself\n" "key>" ), esc + 0x40); } @@ -176,9 +190,12 @@ command_ret_t do_console(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv // uint8_t help_prompt = 0; uint8_t code = 0; uint8_t state = 0; + char esc_char = (char) getenv_ulong(PSTR(ENV_ESC_CHAR), 16, CONFIG_ESC_CHAR); (void) cmdtp; (void) flag; (void) argc; (void) argv; + printf_P(PSTR("Connecting to CPU. Escape character is '^%c'.\n"), + esc_char + 0x40); while (1) { @@ -186,14 +203,16 @@ command_ret_t do_console(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv pending = (Stat & S_CON_PENDING) != 0; Stat &= ~S_CON_PENDING; } - if (pending) - while ((ch = z80_memfifo_getc(fifo_conout)) >= 0) + if (pending) { + uint8_t count = 100; + while ((ch = z80_memfifo_getc(fifo_conout)) >= 0 && --count) putchar(ch); + } if ((ch = my_getchar(0)) >= 0) { switch (state) { case 0: - if (ch == CONFIG_ESC_CHAR) { + if (ch == esc_char) { state = 1; /* TODO: Timer starten */ } else { @@ -209,7 +228,7 @@ command_ret_t do_console(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv case '?': case 'H': - print_con_usage(CONFIG_ESC_CHAR); + print_con_usage(esc_char); state = 2; break; @@ -223,15 +242,21 @@ command_ret_t do_console(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv goto quit; break; + case ':': + putchar('\n'); + int cmdlen = cli_readline(PSTR(": ")); + if (cmdlen > 0) + run_command(console_buffer, 0); + break; + case '\\': code = 0; state = 3; break; - case CONFIG_ESC_CHAR: - z80_memfifo_putc(fifo_conin, ch); - break; default: + if (ch == esc_char) + z80_memfifo_putc(fifo_conin, ch); break; } break; @@ -246,6 +271,11 @@ command_ret_t do_console(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv if (isdigit(ch)) { code = code * 10 + ch - '0'; state++; + } else { + if (state > 3) + z80_memfifo_putc(fifo_conin, code); + z80_memfifo_putc(fifo_conin, ch); + state = 0; } if (state > 5) { z80_memfifo_putc(fifo_conin, code); @@ -260,6 +290,11 @@ command_ret_t do_console(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv ch -= 'A' - 10; code = code * 16 + ch - '0'; state++; + }else { + if (state > 6) + z80_memfifo_putc(fifo_conin, code); + z80_memfifo_putc(fifo_conin, ch); + state = 0; } if (state > 7) { z80_memfifo_putc(fifo_conin, code); diff --git a/avr/cmd_date.c b/avr/cmd_date.c index ad0d3ac..efba858 100644 --- a/avr/cmd_date.c +++ b/avr/cmd_date.c @@ -1,4 +1,6 @@ /* + * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de> + * * (C) Copyright 2001 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * @@ -8,66 +10,12 @@ /* * RTC, Date & Time support: get and set date & time */ -#include <common.h> +#include "common.h" #include <string.h> -#include <command.h> -#include <rtc.h> -#include <i2c.h> - - -static const char * const weekdays[] = { - "Sun", "Mon", "Tues", "Wednes", "Thurs", "Fri", "Satur", -}; - -int mk_date (const char *, struct rtc_time *); - -command_ret_t do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - struct rtc_time tm; - int rcode = CMD_RET_SUCCESS; - - (void) cmdtp; (void) flag; - - switch (argc) { - case 2: /* set date & time */ - /* initialize tm with current time */ - rcode = rtc_get (&tm); - - if(!rcode) { - /* insert new date & time */ - if (mk_date (argv[1], &tm) != 0) { - my_puts_P(PSTR("## Bad date format\n")); - break; - } - /* and write to RTC */ - rcode = rtc_set (&tm); - if(rcode) - my_puts_P(PSTR("## Set date failed\n")); - } else { - my_puts_P(PSTR("## Get date failed\n")); - } - /* FALL TROUGH */ - case 1: /* get date & time */ - rcode = rtc_get (&tm); +#include "time.h" +#include "rtc.h" +#include "command.h" - if (rcode) { - my_puts_P(PSTR("## Get date failed\n")); - break; - } - /* TODO: put weekdays[] in flash */ - printf_P(PSTR("Date: %4d-%02d-%02d (%sday) Time: %2d:%02d:%02d\n"), - tm.tm_year, tm.tm_mon, tm.tm_mday, - (tm.tm_wday<0 || tm.tm_wday>6) ? - "unknown " : weekdays[tm.tm_wday], - tm.tm_hour, tm.tm_min, tm.tm_sec); - - break; - default: - rcode = CMD_RET_USAGE; - } - - return rcode; -} /* * simple conversion of two-digit string with error checking @@ -97,7 +45,7 @@ static int cnvrt2 (const char *str, int *valp) * Some basic checking for valid values is done, but this will not catch * all possible error conditions. */ -int mk_date (const char *datestr, struct rtc_time *tmp) +int mk_date (const char *datestr, struct tm *tmp) { int len, val; char *ptr; @@ -123,36 +71,36 @@ int mk_date (const char *datestr, struct rtc_time *tmp) tmp->tm_sec = 0; } - if (len == 12) { /* MMDDhhmmCCYY */ + if (len == 12) { /* MMDDhhmmCCYY */ int year, century; if (cnvrt2 (datestr+ 8, ¢ury) || cnvrt2 (datestr+10, &year) ) { return (-1); } - tmp->tm_year = 100 * century + year; + tmp->tm_year = 100 * century + year - 1900; } else if (len == 10) { /* MMDDhhmmYY */ int year, century; - century = tmp->tm_year / 100; + century = (tmp->tm_year + 1900) / 100; if (cnvrt2 (datestr+ 8, &year)) return (-1); - tmp->tm_year = 100 * century + year; + tmp->tm_year = 100 * century + year -1900; } switch (len) { - case 8: /* MMDDhhmm */ + case 8: /* MMDDhhmm */ /* fall thru */ - case 10: /* MMDDhhmmYY */ + case 10: /* MMDDhhmmYY */ /* fall thru */ - case 12: /* MMDDhhmmCCYY */ + case 12: /* MMDDhhmmCCYY */ if (cnvrt2 (datestr+0, &val) || val > 12) { break; } - tmp->tm_mon = val; + tmp->tm_mon = val - 1; if (cnvrt2 (datestr+2, &val) || - val > ((tmp->tm_mon==2) ? 29 : 31)) { + val > ((tmp->tm_mon==2-1) ? 29 : 31)) { break; } tmp->tm_mday = val; @@ -169,9 +117,6 @@ int mk_date (const char *datestr, struct rtc_time *tmp) } tmp->tm_min = val; - /* calculate day of week */ - GregorianDay (tmp); - return (0); default: break; @@ -180,3 +125,52 @@ int mk_date (const char *datestr, struct rtc_time *tmp) return (-1); } +command_ret_t do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct tm t; + char buf[30]; + int rcode = CMD_RET_SUCCESS; + + (void) cmdtp; (void) flag; + + switch (argc) { + case 2: /* set date & time */ + /* initialize t with current time */ + rcode = rtc_get (&t); + + if(!rcode) { + /* insert new date & time */ + if (mk_date (argv[1], &t) != 0) { + my_puts_P(PSTR("## Bad date format\n")); + break; + } + + time_t time; + time = mk_gmtime(&t); + gmtime_r(&time, &t); + + /* and write to RTC */ + rcode = rtc_set (&t); + if(rcode) + my_puts_P(PSTR("## Set date failed\n")); + } else { + my_puts_P(PSTR("## Get date failed\n")); + } + /* FALL TROUGH */ + case 1: /* get date & time */ + rcode = rtc_get (&t); + + if (rcode) { + my_puts_P(PSTR("## Get date failed\n")); + break; + } + asctime_r(&t, buf); + printf_P(PSTR("%s\n"), buf); + break; + + default: + rcode = CMD_RET_USAGE; + } + + return rcode; +} diff --git a/avr/cmd_fat.c b/avr/cmd_fat.c index 9222c1b..af2f772 100644 --- a/avr/cmd_fat.c +++ b/avr/cmd_fat.c @@ -1,3 +1,13 @@ +/* + * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * FAT filesystem commands + */ + #include "common.h" #include <stdlib.h> #include <string.h> @@ -6,13 +16,37 @@ #include "command.h" #include "ff.h" #include "z80-if.h" +#include "con-utils.h" #include "print-utils.h" +#include "time.h" #include "timer.h" +#include "debug.h" + +/* TODO: use memory size test function (cmd_mem.c) */ +#define MAX_MEMORY (1ul << 19) +#define BUFFER_SIZE 512 DWORD get_fattime (void) { - return 0; + time_t timer; + struct tm tm_timer; + + time(&timer); + gmtime_r(&timer, &tm_timer); + + return fatfs_time(&tm_timer); +} + + +static bool check_abort(void) +{ + bool ret = ctrlc(); + + if (ret) + printf_P(PSTR("Abort\n")); + + return ret; } @@ -41,23 +75,42 @@ static const FLASH char * const FLASH rc_names[] = { static void put_rc (FRESULT rc) { + if (rc < ARRAY_SIZE(rc_names)) { #if GCC_BUG_61443 - printf_P(PSTR("rc=%u FR_"), rc); - my_puts_P(rc_names[rc]); - my_puts_P(PSTR("\n")); + printf_P(PSTR("rc=%u FR_"), rc); + my_puts_P(rc_names[rc]); + my_puts_P(PSTR("\n")); #else - printf_P(PSTR("rc=%u FR_%S\n"), rc, rc_names[rc]); + printf_P(PSTR("rc=%u FR_%S\n"), rc, rc_names[rc]); #endif + } +} + + +static void swirl(void) +{ + static const FLASH char swirlchar[] = { '-','\\','|','/' }; + static uint_fast8_t cnt; + static uint32_t tstamp; + + if (get_timer(0) > tstamp) { + printf_P(PSTR("\b%c"), swirlchar[cnt]); + cnt = (cnt+1) % ARRAY_SIZE(swirlchar); + tstamp = get_timer(0) + 250; + } } /* Work register for fs command */ -static DWORD AccSize; -static WORD AccFiles, AccDirs; -FILINFO Finfo; +struct stat_dat_s { + DWORD AccSize; + WORD AccFiles, AccDirs; + FILINFO Finfo; +}; static FRESULT scan_files ( - char* path /* Pointer to the working buffer with start path */ + char *path, /* Pointer to the working buffer with start path */ + struct stat_dat_s *statp ) { DIR dirs; @@ -66,25 +119,30 @@ FRESULT scan_files ( char *fn; res = f_opendir(&dirs, path); + swirl(); if (res == FR_OK) { i = strlen(path); - while (((res = f_readdir(&dirs, &Finfo)) == FR_OK) && Finfo.fname[0]) { - if (_FS_RPATH && Finfo.fname[0] == '.') continue; -#if _USE_LFN - fn = *Finfo.lfname ? Finfo.lfname : Finfo.fname; -#else - fn = Finfo.fname; -#endif - if (Finfo.fattrib & AM_DIR) { - AccDirs++; - path[i] = '/'; strcpy(path+i+1, fn); - res = scan_files(path); + while (((res = f_readdir(&dirs, &statp->Finfo)) == FR_OK) && + statp->Finfo.fname[0]) { + if (_FS_RPATH && statp->Finfo.fname[0] == '.') + continue; + fn = statp->Finfo.fname; + if (statp->Finfo.fattrib & AM_DIR) { + statp->AccDirs++; + path[i] = '/'; + strcpy(path+i+1, fn); + res = scan_files(path, statp); path[i] = '\0'; - if (res != FR_OK) break; + if (res != FR_OK) + break; } else { -// printf_P(PSTR("%s/%s\n"), path, fn); - AccFiles++; - AccSize += Finfo.fsize; + //printf_P(PSTR("%s/%s\n"), path, fn); + statp->AccFiles++; + statp->AccSize += statp->Finfo.fsize; + } + if (check_abort()) { + res = 255; + break; } } } @@ -99,64 +157,65 @@ FRESULT scan_files ( */ command_ret_t do_fat_stat(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - FATFS FatFs, *fs; - DWORD p1, p2; + FATFS *fs; + DWORD nfreeclst; FRESULT res; - char buffer[512]; + char *path; + struct stat_dat_s statp; (void) cmdtp; (void) flag; (void) argc; - res = f_mount(&FatFs, argv[1], 0); - if (!res) - res = f_getfree(argv[1], &p2, &fs); - if (res) { - put_rc(res); + path = (char *) malloc(BUFFER_SIZE); + if (path == NULL) { + printf_P(PSTR("fatstat: Out of Memory!\n")); + free(path); return CMD_RET_FAILURE; } - printf_P(PSTR( - "FAT type: %u\n" - "Bytes/Cluster: %lu\n" - "Number of FATs: %u\n" - "Root DIR entries: %u\n" - "Sectors/FAT: %lu\n" - "Number of clusters: %lu\n" - "FAT start (lba): %lu\n" - "DIR start (lba,cluster): %lu\n" - "Data start (lba): %lu\n"), - fs->fs_type, (DWORD)fs->csize * 512, fs->n_fats, - fs->n_rootdir, fs->fsize, fs->n_fatent - 2, - fs->fatbase, fs->dirbase, fs->database); + res = f_getfree(argv[1], &nfreeclst, &fs); + if (!res) { + printf_P(PSTR( + "FAT type: %u\n" + "Bytes/Cluster: %lu\n" + "Number of FATs: %u\n" + "Root DIR entries: %u\n" + "Sectors/FAT: %lu\n" + "Number of clusters: %lu\n" + "FAT start (lba): %lu\n" + "DIR start (lba,cluster): %lu\n" + "Data start (lba): %lu\n"), + fs->fs_type, (DWORD)fs->csize * 512, fs->n_fats, + fs->n_rootdir, fs->fsize, fs->n_fatent - 2, + fs->fatbase, fs->dirbase, fs->database); #if _USE_LABEL - TCHAR label[12]; - res = f_getlabel(argv[1], label, &p1); - if (res) { - put_rc(res); - return CMD_RET_FAILURE; - } - printf_P(PSTR( - "Volume name: %s\n" - "Volume S/N: %04X-%04X\n"), - label, (WORD)((DWORD)p1 >> 16), (WORD)(p1 & 0xFFFF)); + TCHAR label[12]; + DWORD serial; + res = f_getlabel(argv[1], label, &serial); + if (!res) { + printf_P(PSTR( + "Volume name: %s\n" + "Volume S/N: %04X-%04X\n"), + label, (WORD)(serial >> 16), (WORD)(serial & 0xFFFF)); + } #endif - my_puts_P(PSTR("\n...")); - AccSize = AccFiles = AccDirs = 0; - - strcpy(buffer, argv[1]); + if (!res) { + my_puts_P(PSTR("\nCounting... ")); + statp.AccSize = statp.AccFiles = statp.AccDirs = 0; + strcpy(path, argv[1]); - res = scan_files(buffer); - if (res) { - put_rc(res); - return CMD_RET_FAILURE; + res = scan_files(path, &statp); + } + if (!res) { + printf_P(PSTR("\r%u files, %lu bytes.\n%u folders.\n" + "%lu KB total disk space.\n%lu KB available.\n"), + statp.AccFiles, statp.AccSize, statp.AccDirs, + (fs->n_fatent - 2) * (fs->csize / 2), nfreeclst * (fs->csize / 2) + ); + } } - printf_P(PSTR("\r%u files, %lu bytes.\n%u folders.\n" - "%lu KB total disk space.\n%lu KB available.\n"), - AccFiles, AccSize, AccDirs, - (fs->n_fatent - 2) * (fs->csize / 2), p2 * (fs->csize / 2) - ); - res = f_mount(NULL, argv[1], 0); + free(path); if (res) { put_rc(res); return CMD_RET_FAILURE; @@ -171,7 +230,7 @@ command_ret_t do_fat_stat(cmd_tbl_t *cmdtp, int flag, int argc, char * const arg */ command_ret_t do_fat_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - FATFS FatFs, *fs; + FATFS *fs; DIR Dir; /* Directory object */ FILINFO Finfo; unsigned long p1; @@ -185,9 +244,7 @@ command_ret_t do_fat_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[ (void) cmdtp; (void) flag; (void) argc; - res = f_mount(&FatFs, argv[1], 0); - if (!res) - res = f_opendir(&Dir, argv[1]); + res = f_opendir(&Dir, argv[1]); if (res) { put_rc(res); return CMD_RET_FAILURE; @@ -203,22 +260,21 @@ command_ret_t do_fat_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[ } else { s1++; p1 += Finfo.fsize; } - printf_P(PSTR("%c%c%c%c%c %u/%02u/%02u %02u:%02u %9lu %s"), + printf_P(PSTR("%c%c%c%c%c %u/%02u/%02u %02u:%02u %9lu "), (Finfo.fattrib & AM_DIR) ? 'D' : '-', (Finfo.fattrib & AM_RDO) ? 'R' : '-', (Finfo.fattrib & AM_HID) ? 'H' : '-', (Finfo.fattrib & AM_SYS) ? 'S' : '-', (Finfo.fattrib & AM_ARC) ? 'A' : '-', (Finfo.fdate >> 9) + 1980, (Finfo.fdate >> 5) & 15, Finfo.fdate & 31, - (Finfo.ftime >> 11), (Finfo.ftime >> 5) & 63, - Finfo.fsize, &(Finfo.fname[0])); + (Finfo.ftime >> 11), (Finfo.ftime >> 5) & 63, Finfo.fsize); #if _USE_LFN - for (int i = strlen(Finfo.fname); i < 14; i++) - putchar(' '); - printf_P(PSTR("%s\n"), Lfname); + printf_P(PSTR("%s\n"), *Lfname ? Lfname : Finfo.fname); #else - putchar('\n'); + printf_P(PSTR("%s\n"), Finfo.fname); #endif + if (check_abort()) + break; } if (res == FR_OK) { @@ -235,146 +291,153 @@ command_ret_t do_fat_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[ return CMD_RET_SUCCESS; } +static +FRESULT mkpath(TCHAR *path) +{ + /* TODO: */ + (void) path; +#if 0 + FILINFO fd + TCHAR *p, *q; + FRESULT ret; + +#if _USE_LFN + fd.lfname = 0; +#endif + + + res = f_stat (path, &fd) + + p = strchr(path, ':'); + if (p == NULL || *++p == '\0' || *p++ != '/') + return FR_OK; + + while ((q = strchr(p, '/')) != NULL) { + *q = '\0'; + ret = f_mkdir(path); + *q = '/'; + if (ret != FR_OK && ret != FR_EXIST) + return ret; + p = q + 1; + } +#endif + + return FR_OK; +} /* - * fatread - load binary file from a dos filesystem - * <d:/path/filename> <addr> [bytes [pos]] + * fatread/write - load binary file to/from a dos filesystem + * read <d:/path/filename> <addr> [bytes [pos]] + * write <d:/path/filename> <addr> <bytes> */ -command_ret_t do_fat_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +command_ret_t do_fat_rw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - FATFS FatFs; FIL File; - unsigned long bytes = 0x80000; - unsigned long pos= 0; - unsigned long bytes_read; uint32_t addr; + unsigned long bytes; + unsigned long pos; + unsigned long bytes_rw; + + bool dowrite = (argv[0][3] == 'w'); FRESULT res; bool buserr = 0; uint32_t timer; - uint8_t buffer[512]; + uint8_t *buffer; (void) cmdtp; (void) flag; - if (argc < 3) + if (argc < (dowrite ? 4 : 3)) return CMD_RET_USAGE; addr = strtoul(argv[2], 0, 16); + if (addr >= MAX_MEMORY) { + printf_P(PSTR("address too high: 0x%0lx\n"), addr); + return CMD_RET_FAILURE; + } if (argc > 3) bytes = strtoul(argv[3], 0, 16); + else + bytes = MAX_MEMORY; if (argc > 4) pos = strtoul(argv[4], 0, 16); + else + pos = 0; + + if (addr + bytes > MAX_MEMORY) + bytes = MAX_MEMORY - addr; - res = f_mount(&FatFs, argv[1], 0); + buffer = (uint8_t *) malloc(BUFFER_SIZE); + if (buffer == NULL) { + printf_P(PSTR("fatstat: Out of Memory!\n")); + free(buffer); + return CMD_RET_FAILURE; + } + + if (dowrite) { + res = mkpath(argv[1]); + } if (!res) { - res = f_open(&File, argv[1], FA_READ); + res = f_open(&File, argv[1], dowrite ? FA_WRITE | FA_CREATE_ALWAYS + : FA_READ ); if (!res) { res = f_lseek(&File, pos); if (!res) { - bytes_read = 0; + bytes_rw = 0; timer = get_timer(0); while (bytes) { unsigned int cnt, br; - if (bytes >= sizeof buffer) { - cnt = sizeof buffer; - bytes -= sizeof buffer; + if (bytes >= BUFFER_SIZE) { + cnt = BUFFER_SIZE; + bytes -= BUFFER_SIZE; } else { cnt = bytes; bytes = 0; } - res = f_read(&File, buffer, cnt, &br); - if (res != FR_OK) - break; - if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) { - buserr = 1; - break; + if (dowrite) { + if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) { + buserr = 1; + break; + } + z80_read_block(buffer, addr, cnt); + z80_bus_cmd(Release); + res = f_write(&File, buffer, cnt, &br); + if (res != FR_OK) + break; + } else { + res = f_read(&File, buffer, cnt, &br); + if (res != FR_OK) + break; + if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) { + buserr = 1; + break; + } + z80_write_block(buffer, addr, br); + z80_bus_cmd(Release); } - z80_write_block(buffer, addr, br); - z80_bus_cmd(Release); addr += br; - bytes_read += br; - if (cnt != br) + bytes_rw += br; + if (cnt != br) { + if (dowrite) + printf_P(PSTR("Disk full?\n")); + break; + } + if (check_abort()) break; } + + FRESULT fr = f_close(&File); + if (!res) + res = fr; timer = get_timer(timer); - printf_P(PSTR("%lu bytes read with %lu bytes/sec.\n"), - bytes_read, timer ? (bytes_read * 1000 / timer) : 0); + printf_P(PSTR("%lu (0x%lx) bytes read/written with %lu bytes/sec.\n"), + bytes_rw, bytes_rw, timer ? (bytes_rw * 1000 / timer) : 0); } } - f_mount(NULL, argv[1], 0); } - if (buserr) - my_puts_P(PSTR("Bus timeout\n")); - if (res) - put_rc(res); - if (buserr || res) - return CMD_RET_FAILURE; - - return CMD_RET_SUCCESS; -} - -/* - * fatwrite - write file into a dos filesystem - * <d:/path/filename> <addr> <bytes> - */ -command_ret_t do_fat_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - FATFS FatFs; - FIL File; - unsigned long bytes; - unsigned long bytes_written; - uint32_t addr; - FRESULT res; - bool buserr = 0; - uint32_t timer; - uint8_t buffer[512]; - - (void) cmdtp; (void) flag; - - if (argc < 4) - return CMD_RET_USAGE; - - addr = strtoul(argv[2], 0, 16); - bytes = strtoul(argv[3], 0, 16); - - res = f_mount(&FatFs, argv[1], 0); - if (!res) { - res = f_open(&File, argv[1], FA_CREATE_ALWAYS | FA_WRITE); - if (!res) { - bytes_written = 0; - timer = get_timer(0); - while (bytes) { - unsigned int cnt, br; - - if (bytes >= sizeof buffer) { - cnt = sizeof buffer; - bytes -= sizeof buffer; - } else { - cnt = bytes; bytes = 0; - } - if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) { - buserr = 1; - break; - } - z80_read_block(buffer, addr, cnt); - z80_bus_cmd(Release); - res = f_write(&File, buffer, cnt, &br); - if (res != FR_OK) - break; - addr += br; - bytes_written += br; - if (cnt != br) - break; - } - res = f_close(&File); - timer = get_timer(timer); - printf_P(PSTR("%lu bytes written with %lu bytes/sec.\n"), - bytes_written, timer ? (bytes_written * 1000 / timer) : 0); - } - f_mount(NULL, argv[1], 0); - } + free(buffer); if (buserr) my_puts_P(PSTR("Bus timeout\n")); diff --git a/avr/cmd_gpio.c b/avr/cmd_gpio.c index 84723d2..5589381 100644 --- a/avr/cmd_gpio.c +++ b/avr/cmd_gpio.c @@ -1,3 +1,9 @@ +/* + * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + #include "common.h" #include <stdlib.h> #include <string.h> @@ -29,6 +35,8 @@ static void pinnames_get(void) memset(pin_names, 0, sizeof(pin_names)); pin_names_width = 0; +/* TODO: enters endless loop on wrong parameters */ + if ((lp = getenv(PSTR(ENV_PINALIAS))) != NULL) { pin_names[namestr] = strdup(lp); ptr = strtok_P(pin_names[namestr], delim1); diff --git a/avr/cmd_help.c b/avr/cmd_help.c index 8f81b2d..010339d 100644 --- a/avr/cmd_help.c +++ b/avr/cmd_help.c @@ -1,3 +1,11 @@ +/* + * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de> + * + * Copyright 2000-2009 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ #include "common.h" #include "command.h" diff --git a/avr/cmd_loadcpm3.c b/avr/cmd_loadcpm3.c new file mode 100644 index 0000000..da1be37 --- /dev/null +++ b/avr/cmd_loadcpm3.c @@ -0,0 +1,172 @@ +/* + * (C) Copyright 2015 Leo C. <erbl259-lmu@yahoo.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "common.h" +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <stdbool.h> + +#include "command.h" +#include "env.h" +#include "ff.h" +#include "con-utils.h" +#include "z80-if.h" +#include "debug.h" + + +#define RS 128 /* CP/M record size */ + +/* + * Load Routine + * + * Input: addr = Page Address of load top + * len = Length in pages of module to read + * + */ +int load(FIL *File, uint32_t addr, uint8_t len) +{ + uint8_t buffer[RS]; + unsigned int br; /* bytes read */ + int res; + + len *= 2; /* length in records of module */ + //debug("## load: addr: 0x%.4X, records: 0x%.4X, (%u)\n", addr, len, len); + + for (; len; len--) { + addr -= RS; + res = f_read(File, buffer, RS, &br); + if (res || br != RS) { + return 1; + } + + if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) { + my_puts_P(PSTR("Bus timeout\n")); + return 2; + } + z80_write_block(buffer, addr, RS); + z80_bus_cmd(Release); + //debug("## written: 0x%.4X\n", addr); + } + + return 0; +} + +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" + +command_ret_t do_loadcpm3(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + uint16_t mem_top; + uint8_t res_len; + uint16_t bank_top; + uint8_t bank_len; + uint16_t osentry_addr = 0; + uint32_t common_base, banked_base; + char *fname; + FIL File; + /* TODO: put CONFIG_CPM3_SYSFILE in flash */ + char default_fname[] = CONFIG_CPM3_SYSFILE; + unsigned int br; /* bytes read */ + uint8_t buffer[RS]; + int res; + + (void) cmdtp; (void) flag; + + + common_base = getenv_ulong(PSTR(ENV_CPM3_COMMON_BASE), 16, + CONFIG_CPM3_COMMON_BASE); + banked_base = getenv_ulong(PSTR(ENV_CPM3_BANKED_BASE), 16, + CONFIG_CPM3_BANKED_BASE); + + if (argc > 3) + banked_base = strtoul(argv[3], NULL, 16); + if (argc > 2) + banked_base = strtoul(argv[2], NULL, 16); + + fname = getenv(PSTR(ENV_CPM3_SYSFILE)); + if (argc > 2) { + fname = argv[2]; + } + if (fname == NULL || *fname == '\0') + fname = default_fname; + + res = f_open(&File, fname, FA_READ ); + if (res) { + printf_P(PSTR("Error: failed to open '%s'\n"), fname); + return CMD_RET_FAILURE; + } + + printf_P(PSTR("Loading: '%s'...\n"), fname); + + /* read the load record */ + res = f_read(&File, buffer, RS, &br); + if (res || br != RS) + goto out; + + mem_top = buffer[0] << 8; + res_len = buffer[1]; + bank_top = buffer[2] << 8; + bank_len = buffer[3]; + osentry_addr = buffer[4] + (buffer[5] << 8); + + /* read display info */ + res = f_read(&File, buffer, RS, &br); + if (res || br != RS) + goto out; + + /* print the info */ + buffer[RS-1] = '$'; + uint8_t *p = memchr(buffer, '$', RS); + *p = '\0'; + my_puts((char *)buffer); + + /* Main System Load */ + + /* Load Common Portion of System */ + if ((res = load(&File, common_base + mem_top, res_len)) != 0) + goto out; + + /* Load Banked Portion of System */ + res = load(&File, banked_base + bank_top, bank_len); + +out: + f_close(&File); + + if (res) { + printf_P(PSTR("Error: failed to read '%s'\n"), fname); + return CMD_RET_FAILURE; + } else { + if (res_len != 0) { + if (osentry_addr + common_base > 0xffff) { + z80_bus_cmd(Request); + if (z80_read(osentry_addr + common_base) == 0xc3) { + osentry_addr = z80_read(osentry_addr+common_base+1) + + (z80_read(osentry_addr + common_base+2) << 8); + } + z80_bus_cmd(Release); + if (banked_base + osentry_addr > 0xffff) + osentry_addr = 0; + } + setenv_hex(PSTR(ENV_STARTADDRESS), osentry_addr); + } + printf_P(PSTR("Loaded: Resident: ")); + if (res_len != 0) + printf_P(PSTR("0x%.5lX-0x%.5lX, "), + (common_base + mem_top) - res_len*256, + (common_base + mem_top) - 1); + else + printf_P(PSTR(" - ")); + printf_P(PSTR("Banked: ")); + if (bank_len != 0) + printf_P(PSTR("0x%.5lX-0x%.5lX\n"), + (banked_base + bank_top) - bank_len*256, + (banked_base + bank_top) - 1); + else + printf_P(PSTR(" - \n")); + + return CMD_RET_SUCCESS; + } +} diff --git a/avr/cmd_loadihex.c b/avr/cmd_loadihex.c new file mode 100644 index 0000000..18d5331 --- /dev/null +++ b/avr/cmd_loadihex.c @@ -0,0 +1,261 @@ +/* + * (C) Copyright 2015 Leo C. <erbl259-lmu@yahoo.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "common.h" +#include <stdlib.h> +#include <ctype.h> +#include <stdbool.h> + +#include "command.h" +#include "con-utils.h" +#include "z80-if.h" +#include "debug.h" + + +uint32_t detect_ramsize(void) +{ + uint32_t addr; + uint8_t save_addr, save_0; + const uint8_t PATTERN_1 = 0x55; + const uint8_t PATTERN_2 = ~PATTERN_1; + + if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) { + my_puts_P(PSTR("Bus timeout\n")); + return 0; + } + + save_0 = z80_read(0); + z80_write(0, PATTERN_1); + + for (addr=1; addr < CONFIG_SYS_RAMSIZE_MAX; addr <<= 1) { + save_addr = z80_read(addr); + z80_write(addr, PATTERN_2); + if (z80_read(0) != PATTERN_1 || z80_read(addr) != PATTERN_2) + break; + z80_write(addr, save_addr); + } + z80_write(0, save_0); + z80_bus_cmd(Release); + + return addr; +} + +typedef enum { + IHX_OK, + IHX_BROKEN, + IHX_CHKSUMERR +} ihx_rstat_t; + +typedef struct { + ihx_rstat_t status; + int8_t type; + uint8_t len; + uint16_t address; + uint8_t data[256]; +} ihex_t; + + +static +int get_hexdigit(void) { + + int c; + c = toupper(my_getchar(1)); + if (isxdigit(c)) { + c -= '0'; + if (c > 9) + c -= ('A' - '0' - 10); + return c; + } else + return -1; +} + +static +int get_hexbyte(void) { + + uint8_t i,j; + + if ((i = (uint8_t) get_hexdigit()) < 0x10) + if ((j = (uint8_t) get_hexdigit()) < 0x10) { + return (i<<4) + j; + } + + return -1; +} + + +static +int ihex_get_record(ihex_t *rec) { + + int c; + uint8_t sum; + + rec->status = IHX_BROKEN; + rec->len = 0; + rec->type = 0xff; + + while ((c = my_getchar(0)) != ':') { + if (c == 0x03) + return -1; /* Control-C */ + if (c == 0x04) { + rec->status = IHX_OK; + return 0; /*Control-D, EOF */ + } + } + + if ((c = get_hexbyte()) < 0) /* Start code */ + return -1; + sum = c; + rec->len = c; + if ((c = get_hexbyte()) < 0) /* Byte Count */ + return -1; + sum += c; + rec->address = c * 256; + if ((c = get_hexbyte()) < 0) /* Address */ + return -1; + sum += c; + rec->address += c; + if ((c = get_hexbyte()) < 0) /* Record type */ + return -1; + sum += c; + rec->type = c; + + if (rec->len) { /* Record Data */ + uint8_t n; + + for (n = 0; n < rec->len; n++) { + if ((c = get_hexbyte()) < 0) + break; + sum += c; + rec->data[n] = c; + } + + if (n < rec->len) { + return -1; + } + } + + c = get_hexbyte(); /* Check sum */ + + if (c >= 0) { + sum += c; + if (sum == 0) + rec->status = IHX_OK; + else + rec->status = IHX_CHKSUMERR; + } + + return rec->len; +} + + +command_ret_t do_loadihex(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + long offset = 0; + uint32_t base_address = 0; + uint32_t address_max = detect_ramsize(); + uint32_t address_high = 0; + uint32_t address_low = address_max; + command_ret_t rcode = CMD_RET_FAILURE; + ihex_t rec; + bool firstrec = true; + + (void) cmdtp; (void) flag; + + + if (argc > 1) + offset = strtol(argv[1], NULL, 16); + + printf_P(PSTR("Waiting for Intel Hex Records...\n")); + + while (ihex_get_record(&rec) > 0 && + rec.status == IHX_OK && + rec.type != 1 ) { + + switch (rec.type) { + case 0: /* Data record */ + if (firstrec) { + printf_P(PSTR("Loading: 0x.....")); + firstrec = false; + } + if (rec.len) { + uint32_t addr = base_address + rec.address + offset; + if (addr < address_low) + address_low = addr; + if (addr+rec.len > address_high) + address_high = addr + rec.len; + +// debug("low: 0x%.5lX, high: 0x%.5lX, max: 0x%.5lX, addr: 0x%.5lX, len: %d\n", +// address_low, address_high, address_max, addr, rec.len); + printf_P(PSTR("\b\b\b\b\b%.5lX"), addr); + if (addr < address_max) { + uint32_t tmplen = address_max - addr; + if (rec.len > tmplen) + rec.len = tmplen; + + if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) { + my_puts_P(PSTR("Bus timeout\n")); + return CMD_RET_FAILURE; + } + z80_write_block(rec.data, /* src */ + addr, /* dest */ + rec.len); /* len */ + z80_bus_cmd(Release); + } + } + break; + +#if 0 + case 1: /* EOF record */ + break; +#endif + case 2: /* Extended Segment Address Record */ + base_address = (uint32_t)((rec.data[0] << 8) + rec.data[1]) << 4; + break; + + case 4: /* Extended Linear Address Record */ + base_address = (uint32_t)((rec.data[0] << 8) + rec.data[1]) << 16; + break; + + case 3: /* Start Segment Address Record (ignored)*/ + case 5: /* Start Linear Address Record (ignored)*/ + break; + + } + } + + switch (rec.status) { + case IHX_OK: + rcode = CMD_RET_SUCCESS; + break; + + case IHX_BROKEN: + case IHX_CHKSUMERR: + printf_P(PSTR("Broken Hex Record or loading interrupted!\n")); + break; + } + + + for (uint_fast8_t i=0; i<100; ++i) { + /* flush input buffer */ + while (my_getchar(0) > 0) + ; + udelay(1000); + } + + + printf_P(PSTR("\nData loaded: ")); + if (address_low >= MIN(address_high, address_max)) + printf_P(PSTR("None.\n")); + else + printf_P(PSTR("low: 0x%.5lX high: 0x%.5lX\n"), address_low, + MIN(address_high, address_max) - 1); + + if (address_high > address_max) + printf_P(PSTR("Data above highest RAM address " + "(in range 0x%.5lX - 0x%.5lX) ignored!\n"), address_max, address_high - 1); + + return rcode; +} diff --git a/avr/cmd_mem.c b/avr/cmd_mem.c index 0bc5742..101b912 100644 --- a/avr/cmd_mem.c +++ b/avr/cmd_mem.c @@ -1,4 +1,6 @@ /* + * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de> + * * (C) Copyright 2000 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * @@ -14,13 +16,15 @@ #include "common.h" #include <stdlib.h> #include <ctype.h> +#include <avr/interrupt.h> #include "command.h" #include "cli_readline.h" #include "print-utils.h" #include "con-utils.h" +#include "timer.h" #include "z80-if.h" -//#include "debug.h" +#include "debug.h" #ifndef CONFIG_SYS_MEMTEST_SCRATCH @@ -148,8 +152,8 @@ mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[]) if (incrflag) addr += nbytes ? -1 : 1; nbytes = 1; - } - else { + + } else { char *endp; data = strtoul(console_buffer, &endp, 16); nbytes = endp - console_buffer; @@ -220,55 +224,35 @@ command_ret_t do_mem_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[ #ifdef CONFIG_MX_CYCLIC command_ret_t do_mem_mdc ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - int i; uint32_t count; + uint32_t ts; + + (void) cmdtp; + (void) flag; if (argc < 4) return CMD_RET_USAGE; count = strtoul(argv[3], NULL, 10); + clear_ctrlc(); /* forget any previous Control C */ for (;;) { - do_mem_md (NULL, 0, 3, argv); - - /* delay for <count> ms... */ -/* TODO: use timer */ - for (i=0; i<count; i++) - udelay (1000); - - /* check for ctrl-c to abort... */ - if (ctrlc()) { - my_puts_P(PSTR("Abort\n")); - return CMD_RET_SUCCESS; - } - } - - return CMD_RET_SUCCESS; -} - -command_ret_t do_mem_mwc ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - int i; - uint32_t count; - if (argc < 4) - return CMD_RET_USAGE; - - count = strtoul(argv[3], NULL, 10); + if (argv[0][1] == 'd') + do_mem_md (NULL, 0, 3, argv); + else + do_mem_mw (NULL, 0, 3, argv); - for (;;) { - do_mem_mw (NULL, 0, 3, argv); /* delay for <count> ms... */ -/* TODO: use timer */ - for (i=0; i<count; i++) - udelay (1000); - - /* check for ctrl-c to abort... */ - if (ctrlc()) { - my_puts_P(PSTR("Abort\n")); - return CMD_RET_SUCCESS; - } + ts = get_timer(0); + do { + /* check for ctrl-c to abort... */ + if (had_ctrlc() || ctrlc()) { + my_puts_P(PSTR("Abort\n")); + return CMD_RET_SUCCESS; + } + } while (get_timer(ts) < count); } return CMD_RET_SUCCESS; @@ -415,27 +399,26 @@ command_ret_t do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc, my_puts_P(PSTR("Bus timeout\n")); return CMD_RET_FAILURE; } + cli(); for (;;) z80_read(addr); - z80_bus_cmd(Release); } if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) { my_puts_P(PSTR("Bus timeout\n")); return CMD_RET_FAILURE; } + cli(); for (;;) { uint32_t i = length; uint32_t p = addr; while (i-- > 0) z80_read(p++); } - z80_bus_cmd(Release); return CMD_RET_SUCCESS; } -#ifdef CONFIG_LOOPW command_ret_t do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { uint32_t addr, length; @@ -455,7 +438,8 @@ command_ret_t do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const a data = strtoul(argv[3], NULL, 16); - /* We want to optimize the loops to run as fast as possible. + /* + * We want to optimize the loops to run as fast as possible. * If we have only one object, just run infinite loops. */ if (length == 1) { @@ -463,6 +447,7 @@ command_ret_t do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const a my_puts_P(PSTR("Bus timeout\n")); return CMD_RET_FAILURE; } + cli(); for (;;) z80_write(addr, data); } @@ -471,6 +456,7 @@ command_ret_t do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const a my_puts_P(PSTR("Bus timeout\n")); return CMD_RET_FAILURE; } + cli(); for (;;) { uint32_t i = length; uint32_t p = addr; @@ -478,35 +464,33 @@ command_ret_t do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const a z80_write(p++, data); } } -#endif /* CONFIG_LOOPW */ + +//#define CONFIG_SYS_ALT_MEMTEST #ifdef CONFIG_CMD_MEMTEST -static uint32_t mem_test_alt(vu_long *buf, uint32_t start_addr, uint32_t end_addr, - vu_long *dummy) +static uint32_t mem_test_alt(uint32_t start_addr, uint32_t end_addr) { - vu_long *addr; + uint32_t addr; + uint32_t dummy; uint32_t errs = 0; - uint32_t val, readback; - int j; - vu_long offset; - vu_long test_offset; - vu_long pattern; - vu_long temp; - vu_long anti_pattern; - vu_long num_words; - static const FLASH uint32_t bitpattern[] = { - 0x00000001, /* single bit */ - 0x00000003, /* two adjacent bits */ - 0x00000007, /* three adjacent bits */ - 0x0000000F, /* four adjacent bits */ - 0x00000005, /* two non-adjacent bits */ - 0x00000015, /* three non-adjacent bits */ - 0x00000055, /* four non-adjacent bits */ - 0xaaaaaaaa, /* alternating 1/0 */ + uint32_t offset; + uint32_t test_offset; + uint8_t pattern; + uint8_t anti_pattern; + uint8_t temp; + uint32_t num_bytes; + + static const FLASH uint8_t bitpattern[] = { + 0x01, /* single bit */ + 0x03, /* two adjacent bits */ + 0x07, /* three adjacent bits */ + 0x0F, /* four adjacent bits */ + 0x05, /* two non-adjacent bits */ + 0x15, /* three non-adjacent bits */ + 0x55, /* four non-adjacent bits */ + 0xaa, /* alternating 1/0 */ }; - num_words = (end_addr - start_addr) / sizeof(vu_long); - /* * Data line test: write a pattern to the first * location, write the 1's complement to a 'parking' @@ -524,35 +508,39 @@ static uint32_t mem_test_alt(vu_long *buf, uint32_t start_addr, uint32_t end_add * '0's and '0' bits through a field of '1's (i.e. * pattern and ~pattern). */ - addr = buf; - for (j = 0; j < sizeof(bitpattern) / sizeof(bitpattern[0]); j++) { - val = bitpattern[j]; - for (; val != 0; val <<= 1) { - *addr = val; - *dummy = ~val; /* clear the test data off the bus */ - readback = *addr; - if (readback != val) { + addr = start_addr; + dummy = start_addr+1; + for (unsigned int j = 0; j < ARRAY_SIZE(bitpattern); j++) { + pattern = bitpattern[j]; + for (; pattern != 0; pattern <<= 1) { + anti_pattern = ~pattern; + z80_write(addr, pattern); + z80_write(dummy, anti_pattern); /* clear the test data off the bus */ + temp = z80_read(addr); + if (temp != pattern) { printf_P(PSTR("FAILURE (data line): " - "expected %05lx, actual %05lx\n"), - val, readback); + "expected %02x, actual %02x\n"), + pattern, temp); errs++; - if (ctrlc()) - return -1; } - *addr = ~val; - *dummy = val; - readback = *addr; - if (readback != ~val) { + z80_write(addr, anti_pattern); + z80_write(dummy, pattern); /* clear the test data off the bus */ + temp = z80_read(addr); + if (temp != anti_pattern) { printf_P(PSTR("FAILURE (data line): " - "Is %05lx, should be %05lx\n"), - readback, ~val); + "Is %02x, should be %02x\n"), + temp, anti_pattern); errs++; - if (ctrlc()) - return -1; } } + + if (ctrlc()) + return -1; } + if (errs) + return errs; + /* * Based on code whose Original Author and Copyright * information follows: Copyright (c) 1998 by Michael @@ -587,59 +575,61 @@ static uint32_t mem_test_alt(vu_long *buf, uint32_t start_addr, uint32_t end_add * * Returns: 0 if the test succeeds, 1 if the test fails. */ - pattern = (vu_long) 0xaaaaaaaa; - anti_pattern = (vu_long) 0x55555555; - debug("%s:%d: length = 0x%.5lx\n", __func__, __LINE__, num_words); + num_bytes = (end_addr - start_addr) / sizeof(uint8_t); + + pattern = 0xaa; + anti_pattern = 0x55; + +// debug("## %s:%d: length = 0x%.5lx\n", __func__, __LINE__, num_bytes); /* * Write the default pattern at each of the * power-of-two offsets. */ - for (offset = 1; offset < num_words; offset <<= 1) - addr[offset] = pattern; + for (offset = 1; offset < num_bytes; offset <<= 1) + z80_write(addr+offset, pattern); /* * Check for address bits stuck high. */ - test_offset = 0; - addr[test_offset] = anti_pattern; + z80_write(start_addr, anti_pattern); - for (offset = 1; offset < num_words; offset <<= 1) { - temp = addr[offset]; + for (offset = 1; offset < num_bytes; offset <<= 1) { + temp = z80_read(start_addr + offset); if (temp != pattern) { - printf_P(PSTR("\nFAILURE: Address bit stuck high @ 0x%.5lx:" - " expected 0x%.5lx, actual 0x%.5lx\n"), - start_addr + offset*sizeof(vu_long), - pattern, temp); + printf_P(PSTR("FAILURE: Address bit stuck high @ 0x%.5lx:" + " expected 0x%.2x, actual 0x%.2x\n"), + start_addr + offset, pattern, temp); errs++; if (ctrlc()) return -1; } } - addr[test_offset] = pattern; + z80_write(start_addr, pattern); /* * Check for addr bits stuck low or shorted. */ - for (test_offset = 1; test_offset < num_words; test_offset <<= 1) { - addr[test_offset] = anti_pattern; + for (test_offset = 1; test_offset < num_bytes; test_offset <<= 1) { + z80_write(start_addr + test_offset, anti_pattern); - for (offset = 1; offset < num_words; offset <<= 1) { - temp = addr[offset]; + for (offset = 1; offset < num_bytes; offset <<= 1) { + temp = z80_read(start_addr + offset); if ((temp != pattern) && (offset != test_offset)) { - printf_P(PSTR("\nFAILURE: Address bit stuck low or" - " shorted @ 0x%.5lx: expected 0x%.5lx," - " actual 0x%.5lx\n"), - start_addr + offset*sizeof(vu_long), - pattern, temp); + printf_P(PSTR("FAILURE: Address bit stuck low or shorted" + " @ 0x%.5lx: expected 0x%.2x, actual 0x%.2x\n"), + start_addr + offset, pattern, temp); errs++; if (ctrlc()) return -1; } } - addr[test_offset] = pattern; + z80_write(start_addr + test_offset, pattern); } + if (errs) + return errs; + /* * Description: Test the integrity of a physical * memory device by performing an @@ -652,111 +642,50 @@ static uint32_t mem_test_alt(vu_long *buf, uint32_t start_addr, uint32_t end_add * * Returns: 0 if the test succeeds, 1 if the test fails. */ - num_words++; + num_bytes++; /* * Fill memory with a known pattern. */ - for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) { - addr[offset] = pattern; - } + for (pattern = 1, addr = start_addr; addr <= end_addr; pattern++, addr++) + z80_write(addr, pattern); /* * Check each location and invert it for the second pass. */ - for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) { - temp = addr[offset]; + for (pattern = 1, addr = start_addr; addr <= end_addr; pattern++, addr++) { + temp = z80_read(addr); if (temp != pattern) { - printf_P(PSTR("\nFAILURE (read/write) @ 0x%.5lx:" - " expected 0x%.5lx, actual 0x%.5lx)\n"), - start_addr + offset*sizeof(vu_long), - pattern, temp); + printf_P(PSTR("FAILURE (read/write) @ 0x%.5lx:" + " expected 0x%.2x, actual 0x%.2x)\n"), + addr, pattern, temp); errs++; if (ctrlc()) return -1; } anti_pattern = ~pattern; - addr[offset] = anti_pattern; + z80_write(addr, anti_pattern); } /* * Check each location for the inverted pattern and zero it. */ - for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) { - WATCHDOG_RESET(); + for (pattern = 1, addr = start_addr; addr <= end_addr; pattern++, addr++) { anti_pattern = ~pattern; - temp = addr[offset]; + temp = z80_read(addr); if (temp != anti_pattern) { - printf_P(PSTR("\nFAILURE (read/write): @ 0x%.5lx:" - " expected 0x%.5lx, actual 0x%.5lx)\n"), - start_addr + offset*sizeof(vu_long), - anti_pattern, temp); + printf_P(PSTR("FAILURE (read/write) @ 0x%.5lx:" + " expected 0x%.2x, actual 0x%.2x)\n"), + start_addr, anti_pattern, temp); errs++; if (ctrlc()) return -1; } - addr[offset] = 0; + z80_write(addr, 0); } - return 0; -} - -static uint32_t mem_test_quick(vu_long *buf, uint32_t start_addr, uint32_t end_addr, - vu_long pattern, int iteration) -{ - vu_long *end; - vu_long *addr; - uint32_t errs = 0; - uint32_t incr, length; - uint32_t val, readback; - - /* Alternate the pattern */ - incr = 1; - if (iteration & 1) { - incr = -incr; - /* - * Flip the pattern each time to make lots of zeros and - * then, the next time, lots of ones. We decrement - * the "negative" patterns and increment the "positive" - * patterns to preserve this feature. - */ - if (pattern & 0x80000000) - pattern = -pattern; /* complement & increment */ - else - pattern = ~pattern; - } - length = (end_addr - start_addr) / sizeof(uint32_t); - end = buf + length; - printf_P(PSTR("\rPattern %08lX Writing..." - "%12s" - "\b\b\b\b\b\b\b\b\b\b"), - pattern, ""); - - for (addr = buf, val = pattern; addr < end; addr++) { - *addr = val; - val += incr; - } - - my_puts_P(PSTR("Reading...")); - - for (addr = buf, val = pattern; addr < end; addr++) { - readback = *addr; - if (readback != val) { - uint32_t offset = addr - buf; - - printf_P(PSTR("\nMem error @ 0x%08X: " - "found %08lX, expected %08lX\n"), - (unsigned int)(uintptr_t)(start_addr + offset*sizeof(vu_long)), - readback, val); - errs++; - if (ctrlc()) - return -1; - } - val += incr; - } - - return 0; + return errs; } /* @@ -767,77 +696,61 @@ static uint32_t mem_test_quick(vu_long *buf, uint32_t start_addr, uint32_t end_a command_ret_t do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - uint32_t start, end; - vu_long *buf, *dummy; - int iteration_limit; -/* TODO: command_ret_t */ + uint32_t start = 0; + uint32_t end; + unsigned int iteration_limit = 0; + unsigned int iteration; + uint32_t errs = 0; /* number of errors */ int ret; - uint32_t errs = 0; /* number of errors, or -1 if interrupted */ - uint32_t pattern; - int iteration; -#if defined(CONFIG_SYS_ALT_MEMTEST) - const int alt_test = 1; -#else - const int alt_test = 0; -#endif + + (void) cmdtp; + (void) flag; if (argc > 1) start = strtoul(argv[1], NULL, 16); - else - start = CONFIG_SYS_MEMTEST_START; if (argc > 2) end = strtoul(argv[2], NULL, 16); else - end = CONFIG_SYS_MEMTEST_END; + end = CONFIG_SYS_RAMSIZE_MAX - 1; if (argc > 3) - pattern = (uint32_t)strtoul(argv[3], NULL, 16); - else - pattern = 0; + iteration_limit = (unsigned int) strtoul(argv[3], NULL, 16); - if (argc > 4) - iteration_limit = (uint32_t)strtoul(argv[4], NULL, 16); - else - iteration_limit = 0; + printf_P(PSTR("Testing %05lx ... %05lx:\n"), start, end); +// debug("## %s:%d: start %#05lx end %#05lx\n", __func__, __LINE__, start, end); - printf_P(PSTR("Testing %08x ... %08x:\n"), (unsigned int)start, (unsigned int)end); - debug("%s:%d: start %#05lx end %#05lx\n", __func__, __LINE__, - start, end); + clear_ctrlc(); /* forget any previous Control C */ -/* TODO: */ -// buf = map_sysmem(start, end - start); -// dummy = map_sysmem(CONFIG_SYS_MEMTEST_SCRATCH, sizeof(vu_long)); for (iteration = 0; !iteration_limit || iteration < iteration_limit; iteration++) { - if (ctrlc()) { - errs = -1UL; - break; - } printf_P(PSTR("Iteration: %6d\r"), iteration + 1); - debug("\n"); - if (alt_test) { - errs = mem_test_alt(buf, start, end, dummy); - } else { - errs = mem_test_quick(buf, start, end, pattern, - iteration); +// debug("\n"); + + if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) { + my_puts_P(PSTR("Bus timeout\n")); + return CMD_RET_FAILURE; } - if (errs == -1UL) + errs += mem_test_alt(start, end); + z80_bus_cmd(Release); + + if (had_ctrlc() || ctrlc()) { break; + } } - if (errs == -1UL) { + if (had_ctrlc()) { /* Memory test was aborted - write a newline to finish off */ - putc('\n'); - ret = 1; + putchar('\n'); + ret = CMD_RET_FAILURE; } else { printf_P(PSTR("Tested %d iteration(s) with %lu errors.\n"), iteration, errs); - ret = errs != 0; + ret = errs ? CMD_RET_FAILURE : CMD_RET_SUCCESS; } - return ret; /* not reached */ + return ret; } #endif /* CONFIG_CMD_MEMTEST */ diff --git a/avr/cmd_misc.c b/avr/cmd_misc.c index 315b959..c9a3c45 100644 --- a/avr/cmd_misc.c +++ b/avr/cmd_misc.c @@ -1,4 +1,6 @@ /* + * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de> + * * Copyright 2000-2009 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * @@ -7,46 +9,43 @@ #include "common.h" #include <stdlib.h> +#include <stdbool.h> #include "command.h" #include "timer.h" #include "con-utils.h" +#include "getopt-min.h" command_ret_t do_echo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - uint_fast8_t putnl = 1; + bool put_newline = true; (void) cmdtp; (void) flag; - for (uint_fast8_t i = 1; i < argc; i++) { + /* reset getopt() */ + optind = 1; + + int opt; + while ((opt = getopt(argc, argv, PSTR("n"))) != -1) { + switch (opt) { + case 'n': + put_newline = false; + break; + default: /* '?' */ + return CMD_RET_USAGE; + } + } - uint_fast8_t backslash = 0; - char *p = argv[i]; - char c; + for (uint_fast8_t i = optind; i < argc; i++) { - if (i != 1) + if (i != optind) putchar(' '); - while ((c = *p++) != '\0') { - - if(backslash) { - backslash = 0; - if (c == 'c') { - putnl = 0; - continue; - } else - putchar('\\'); - } else { - if (c == '\\') { - backslash = 1; - continue; - } - } - putchar(c); - } + + my_puts(argv[i]); } - if (putnl) + if (put_newline) putchar('\n'); return CMD_RET_SUCCESS; @@ -88,4 +87,3 @@ command_ret_t do_sleep(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[] return CMD_RET_SUCCESS; } - diff --git a/avr/cmd_sd.c b/avr/cmd_sd.c index 5494a13..6b75d6e 100644 --- a/avr/cmd_sd.c +++ b/avr/cmd_sd.c @@ -1,3 +1,9 @@ +/* + * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + #include "common.h" #include <stdlib.h> @@ -9,11 +15,11 @@ /* - * di <pd#> - Initialize disk + * status <pd#> - Show socket status * */ static -command_ret_t do_init(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +command_ret_t do_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { DSTATUS res; BYTE dev; @@ -25,26 +31,50 @@ command_ret_t do_init(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) dev = (BYTE) strtoul(argv[1], 0, 10); res = disk_status(dev); - printf_P(PSTR("disk_status=%.2x\n"), res); + printf_P(PSTR("Socket status: %02x\n"), res); + + return CMD_RET_SUCCESS; +} + +/* + * init <pd#> - Initialize disk + * + */ +static +command_ret_t do_init(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + DSTATUS res; + BYTE dev; + + (void) cmdtp; (void) flag; - if ((res & STA_NODISK) == 0) { - res = disk_initialize(dev); + if (argc < 2) + return CMD_RET_USAGE; + + dev = (BYTE) strtoul(argv[1], 0, 10); + + if (disk_status(dev) & STA_NODISK) { + printf_P(PSTR("No Disk\n")); + return CMD_RET_FAILURE; } + + res = disk_initialize(dev); printf_P(PSTR("rc=%.2x\n"), res); - if (res) { + + if (res & (STA_NODISK | STA_NOINIT)) return CMD_RET_FAILURE; - } return CMD_RET_SUCCESS; } /* - * ds <pd#> - Show disk status + * info <pd#> - Show disk info * */ static -command_ret_t do_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +command_ret_t do_info(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { + DSTATUS res; BYTE dev; union { @@ -60,6 +90,12 @@ command_ret_t do_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[ dev = (BYTE) strtoul(argv[1], 0, 10); + res = disk_status(dev); + if (res & (STA_NODISK | STA_NOINIT)) { + printf_P(res & STA_NODISK ? + PSTR("No disk\n") : PSTR("Not initialized\n")); + return CMD_RET_FAILURE; + } if (disk_ioctl(dev, GET_SECTOR_COUNT, &dat.ul) == RES_OK) printf_P(PSTR("Drive size: %lu sectors\n"), dat.ul); @@ -259,7 +295,7 @@ command_ret_t do_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[] /* * Disk ioctl - * dcs <pd#> - CTRL_SYNC + * sync <pd#> - CTRL_SYNC * */ static @@ -284,29 +320,34 @@ command_ret_t do_help(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) cmd_tbl_t cmd_sd_sub[] = { CMD_TBL_ITEM( + status, 2, 1, do_status, + "Socket staus", + "" +), +CMD_TBL_ITEM( init, 2, 1, do_init, "Initialize disk", "" ), CMD_TBL_ITEM( - status, 2, 1, do_status, - "Disk status", + info, 2, 1, do_info, + "Disk info", "" ), CMD_TBL_ITEM( dump, CONFIG_SYS_MAXARGS, 1, do_dump, - "Dump sector", - "" + "Dump sector(s)", + "<drive> [sector [count ]]" ), CMD_TBL_ITEM( read, 2, 1, do_read, - "read disk sector(s) into meomory", - "drive [sector [count [memaddr]]]" + "Read disk sector(s) into meomory", + "<drive> [sector [count [memaddr]]]" ), CMD_TBL_ITEM( write, 2, 1, do_write, - "write sector(s) from meomory to disk", - "drive [sector [count [memaddr]]]" + "Write sector(s) from meomory to disk", + "<drive> [sector [count [memaddr]]]" ), CMD_TBL_ITEM( sync, 2, 1, do_ioctl_sync, @@ -316,7 +357,7 @@ CMD_TBL_ITEM( CMD_TBL_ITEM( help, CONFIG_SYS_MAXARGS, 1, do_help, - "print sub command description/usage", + "Print sub command description/usage", "\n" " - print brief description of all sub commands\n" "sd help command ...\n" @@ -325,7 +366,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("alias for 'help'"), + FSTR("Alias for 'help'"), #ifdef CONFIG_SYS_LONGHELP FSTR(""), #endif /* CONFIG_SYS_LONGHELP */ diff --git a/avr/command.c b/avr/command.c index c080527..ed25dee 100644 --- a/avr/command.c +++ b/avr/command.c @@ -1,4 +1,13 @@ /* + * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de> + * + * (C) Copyright 2000-2009 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* * Command Processor Table */ @@ -111,7 +120,7 @@ command_ret_t _do_help(cmd_tbl_t *cmd_start, int cmd_items, cmd_tbl_t * cmdtp, */ for (i = 1; i < argc; ++i) { if ((cmdtp = find_cmd_tbl (argv[i], cmd_start, cmd_items )) != NULL) { - rcode = cmd_usage(cmdtp); + cmd_usage(cmdtp); } else { printf_P(PSTR("Unknown command '%s' - try 'help'" " without arguments.\n\n"), argv[i] @@ -140,8 +149,8 @@ cmd_tbl_t *find_cmd_tbl (const char *cmd, cmd_tbl_t *table, int table_len) for (cmdtp = table; cmdtp != table + table_len; cmdtp++) { - if (strncmp_P (cmd, cmdtp->name, len) == 0) { - if (len == strlen (cmdtp->name)) + if (strncmp_P(cmd, cmdtp->name, len) == 0) { + if (len == strlen_P(cmdtp->name)) return cmdtp; /* full match */ cmdtp_temp = cmdtp; /* abbreviated command ? */ diff --git a/avr/command_tbl.c b/avr/command_tbl.c index 02d8ac8..72a87b9 100644 --- a/avr/command_tbl.c +++ b/avr/command_tbl.c @@ -1,10 +1,13 @@ +/* + * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ #include "common.h" - #include "command.h" #include "cmd_mem.h" - extern command_ret_t do_help(cmd_tbl_t *, int, int, char * const []); extern command_ret_t do_echo(cmd_tbl_t *, int, int, char * const []); extern command_ret_t do_sleep(cmd_tbl_t *, int, int, char * const []); @@ -13,10 +16,17 @@ extern command_ret_t do_env_default(cmd_tbl_t *, int, int, char * const []); extern command_ret_t do_env_set(cmd_tbl_t *, int, int, char * const []); extern command_ret_t do_env_save(cmd_tbl_t *, int, int, char * const []); extern command_ret_t do_loadf(cmd_tbl_t *, int, int, char * const []); +extern command_ret_t do_loadcpm3(cmd_tbl_t *, int, int, char * const []); +extern command_ret_t do_loadihex(cmd_tbl_t *, int, int, char * const []); +#if defined(CONFIG_CMD_LOADB) +extern command_ret_t do_load_serial_bin(cmd_tbl_t *, int, int, char * const []); +#endif extern command_ret_t do_go(cmd_tbl_t *, int, int, char * const []); extern command_ret_t do_restart(cmd_tbl_t *, int, int, char * const []); extern command_ret_t do_console(cmd_tbl_t *, int, int, char * const []); extern command_ret_t do_dump_mem(cmd_tbl_t *, int, int, char * const []); +extern command_ret_t do_mem_mm_avr(cmd_tbl_t *, int, int, char * const []); +extern command_ret_t do_mem_nm_avr(cmd_tbl_t *, int, int, char * const []); extern command_ret_t do_eep_cp(cmd_tbl_t *, int, int, char * const []); extern command_ret_t do_busreq_pulse(cmd_tbl_t *, int, int, char * const []); extern command_ret_t do_date(cmd_tbl_t *, int, int, char * const []); @@ -24,8 +34,9 @@ extern command_ret_t do_gpio(cmd_tbl_t *, int, int, char * const []); extern command_ret_t do_sd(cmd_tbl_t *, int, int, char * const []); extern command_ret_t do_fat_stat(cmd_tbl_t *, int, int, char * const []); extern command_ret_t do_fat_ls(cmd_tbl_t *, int, int, char * const []); -extern command_ret_t do_fat_read(cmd_tbl_t *, int, int, char * const []); -extern command_ret_t do_fat_write(cmd_tbl_t *, int, int, char * const []); +//extern command_ret_t do_fat_read(cmd_tbl_t *, int, int, char * const []); +//extern command_ret_t do_fat_write(cmd_tbl_t *, int, int, char * const []); +extern command_ret_t do_fat_rw(cmd_tbl_t *, int, int, char * const []); #ifdef CONFIG_SYS_LONGHELP const FLASH char sd_help_text[] = @@ -38,14 +49,14 @@ cmd_tbl_t cmd_tbl[] = { CMD_TBL_ITEM( date, 2, 1, do_date, - "get/set/reset date & time", + "get/set date & time", "[MMDDhhmm[[CC]YY][.ss]]\ndate reset\n" " - without arguments: print date & time\n" " - with numeric argument: set the system date & time\n" - " - with 'reset' argument: reset the RTC" ), #ifdef DEBUG + CMD_TBL_ITEM( !mdr, 3, 1, do_dump_mem, "RAM dump", @@ -57,10 +68,25 @@ CMD_TBL_ITEM( "address [count]" ), CMD_TBL_ITEM( + !mdf, 3, 1, do_dump_mem, + "FLASH dump", + "address [count]" +), +CMD_TBL_ITEM( !cpe, 4, 0, do_eep_cp, "EEPROM copy", "source target count" ), +CMD_TBL_ITEM( + !mm, 2, 1, do_mem_mm_avr, + "avr memory modify (auto-incrementing address)", + "address" +), +CMD_TBL_ITEM( + !nm, 2, 1, do_mem_nm_avr, + "avr memory modify (constant address)", + "address" +), #endif CMD_TBL_ITEM( mstep, 2, 1, do_busreq_pulse, @@ -70,9 +96,10 @@ CMD_TBL_ITEM( ), CMD_TBL_ITEM( echo, CONFIG_SYS_MAXARGS, 1, do_echo, - "echo args to console", - "[args..]\n" - " - echo args to console; \\c suppresses newline" + "display a line of text", + "[-n] [argument ...]\n" + " - echo the argument(s) to console.\n" + " -n do not output the trailing newline" ), CMD_TBL_ITEM( sleep , 2, 1, do_sleep, @@ -122,6 +149,43 @@ CMD_TBL_ITEM( "" ), CMD_TBL_ITEM( + loadcpm3, 3, 0, do_loadcpm3, + "load CPM3.SYS file", + "[filename] [common base] [banked base]] \n" + " Load CP/M 3 system file from FAT filesystem. This command makes\n" + " CPMLDR superfluous. Uses the following environment variable if set:\n" + " '"ENV_CPM3_SYSFILE"' File to load. Default is '"CONFIG_CPM3_SYSFILE"'.\n" + " '"ENV_CPM3_COMMON_BASE"' Default is '"CONFIG_CPM3_COMMON_BASE_STR"'.\n" + " '"ENV_CPM3_BANKED_BASE"' Default is '"CONFIG_CPM3_BANKED_BASE_STR"'.\n" +), +CMD_TBL_ITEM( + loadi, 2, 0, do_loadihex, + "load intel hex file over serial line", + "[[-]offset]\n" + " - load Intel-Hex-Record file over serial line with offset 'offset'" +), + +#if defined(CONFIG_CMD_LOADB) +CMD_TBL_ITEM( + loadb, 1, 0, do_load_serial_bin, + "load binary file over serial line (kermit mode)", + " - load binary file over serial line" +), + +CMD_TBL_ITEM( + loadx, 1, 0, do_load_serial_bin, + "load binary file over serial line (xmodem mode)", + " - load binary file over serial line" +), + +CMD_TBL_ITEM( + loady, 1, 0, do_load_serial_bin, + "load binary file over serial line (ymodem mode)", + " - load binary file over serial line" +), +#endif /* CONFIG_CMD_LOADB */ + +CMD_TBL_ITEM( go, 2, 0, do_go, "start application at address 'addr'", "addr\n" @@ -140,7 +204,7 @@ CMD_TBL_ITEM( "" ), CMD_TBL_ITEM( - connect, 1, 1, do_console, + connect, 1, 0, do_console, "Connect to CPU console i/o", "" ), @@ -202,23 +266,21 @@ CMD_TBL_ITEM( " - set address offset for memory commands to 'offset'" ), CMD_TBL_ITEM( - loop, 3, 1, do_mem_loop, + mloop, 3, 1, do_mem_loop, "infinite loop on address range", "address number_of_bytes" ), -#ifdef CONFIG_LOOPW CMD_TBL_ITEM( - loopw, 4, 1, do_mem_loopw, + mloopw, 4, 1, do_mem_loopw, "infinite write loop on address range", "address number_of_bytes data_to_write" ), -#endif /* CONFIG_LOOPW */ #ifdef CONFIG_CMD_MEMTEST CMD_TBL_ITEM( - mtest, 5, 1, do_mem_mtest, + mtest, 4, 1, do_mem_mtest, "simple RAM read/write test", - "[start [end [pattern [iterations]]]]" + "[start [end [iterations]]]" ), #endif /* CONFIG_CMD_MEMTEST */ @@ -229,7 +291,7 @@ CMD_TBL_ITEM( "address count delay(ms)" ), CMD_TBL_ITEM( - mwc, 4, 1, do_mem_mwc, + mwc, 4, 1, do_mem_mdc, "memory write cyclic", "address value delay(ms)" ), @@ -254,7 +316,7 @@ CMD_TBL_ITEM( "path" ), CMD_TBL_ITEM( - fatload, 5, 0, do_fat_read, + fatload, 5, 0, do_fat_rw, "load binary file from a dos filesystem", "<d:/path/filename> <addr> [bytes [pos]]\n" " - Load binary file 'path/filename' on logical drive 'd'\n" @@ -265,11 +327,12 @@ CMD_TBL_ITEM( " the load stops on end of file." ), CMD_TBL_ITEM( - fatwrite, 4, 0, do_fat_write, + fatwrite, 4, 0, do_fat_rw, "write file into a dos filesystem", "<d:/path/filename> <addr> <bytes>\n" - " - write file 'filename' from the address 'addr' in RAM\n" - " to 'dev' on 'interface'" + " - Write file to 'path/filename' on logical drive 'd' from RAM\n" + " starting at address 'addr'. 'bytes' gives the size to load.\n" + " If 'bytes' is 0 or omitted, the load stops on end of file." ), CMD_TBL_ITEM( diff --git a/avr/con-utils.c b/avr/con-utils.c index f4023ff..5ee1ff1 100644 --- a/avr/con-utils.c +++ b/avr/con-utils.c @@ -1,7 +1,14 @@ +/* + * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ -#include <string.h> #include "common.h" +#include <string.h> +#include <avr/wdt.h> +#include "config.h" #include "serial.h" #include "background.h" #include "con-utils.h" @@ -21,6 +28,31 @@ int my_getchar(uint_fast8_t waitforchar) c = serial_getc(); } while ((c < 0) && waitforchar); +#ifdef CONFIG_SYS_FBOOTSIG + if (c < 0) + return c; + + static const FLASH unsigned char bootsig[] = {CONFIG_SYS_FBOOTSIG}; + static uint8_t pb; + unsigned char uc = c; + + + if (bootsig[pb] == 0) { + if (uc == 0xff) { + wdt_enable(WDTO_15MS); + for(;;) + ; + } else + pb = 0; + + } else { + if (bootsig[pb] == uc) + pb++; + else + pb = 0; + } +#endif + return c; } diff --git a/avr/date.c b/avr/date.c deleted file mode 100644 index c85361f..0000000 --- a/avr/date.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * (C) Copyright 2001 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * Date & Time support for RTC - */ - -#include <common.h> -#include <command.h> -#include <rtc.h> - - -#define FEBRUARY 2 -#define STARTOFTIME 1970 -#define SECDAY 86400L -#define SECYR (SECDAY * 365) -#define leapyear(year) ((year) % 4 == 0) -#define days_in_year(a) (leapyear(a) ? 366 : 365) -#define days_in_month(a) (month_days[(a) - 1]) - - -static const FLASH int MonthOffset[] = { - 0,31,59,90,120,151,181,212,243,273,304,334 -}; - -/* - * This only works for the Gregorian calendar - i.e. after 1752 (in the UK) - */ -void GregorianDay(struct rtc_time * tm) -{ - int leapsToDate; - int lastYear; - int day; - - lastYear=tm->tm_year-1; - - /* - * Number of leap corrections to apply up to end of last year - */ - leapsToDate = lastYear/4 - lastYear/100 + lastYear/400; - - /* - * This year is a leap year if it is divisible by 4 except when it is - * divisible by 100 unless it is divisible by 400 - * - * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 will be - */ - if((tm->tm_year%4==0) && - ((tm->tm_year%100!=0) || (tm->tm_year%400==0)) && - (tm->tm_mon>2)) { - /* - * We are past Feb. 29 in a leap year - */ - day=1; - } else { - day=0; - } - - day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + tm->tm_mday; - - tm->tm_wday=day%7; -} - -void to_tm(unsigned long tim, struct rtc_time * tm) -{ - char month_days[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; - register int i; - register long hms, day; - - day = tim / SECDAY; - hms = tim % SECDAY; - - /* Hours, minutes, seconds are easy */ - tm->tm_hour = hms / 3600; - tm->tm_min = (hms % 3600) / 60; - tm->tm_sec = (hms % 3600) % 60; - - /* Number of years in days */ - for (i = STARTOFTIME; day >= days_in_year(i); i++) { - day -= days_in_year(i); - } - tm->tm_year = i; - - /* Number of months in days left */ - if (leapyear(tm->tm_year)) { - days_in_month(FEBRUARY) = 29; - } - for (i = 1; day >= days_in_month(i); i++) { - day -= days_in_month(i); - } - days_in_month(FEBRUARY) = 28; - tm->tm_mon = i; - - /* Days are what is left over (+1) from all that. */ - tm->tm_mday = day + 1; - - /* - * Determine the day of week - */ - GregorianDay(tm); -} - -/* Converts Gregorian date to seconds since 1970-01-01 00:00:00. - * Assumes input in normal date format, i.e. 1980-12-31 23:59:59 - * => year=1980, mon=12, day=31, hour=23, min=59, sec=59. - * - * [For the Julian calendar (which was used in Russia before 1917, - * Britain & colonies before 1752, anywhere else before 1582, - * and is still in use by some communities) leave out the - * -year/100+year/400 terms, and add 10.] - * - * This algorithm was first published by Gauss (I think). - * - * WARNING: this function will overflow on 2106-02-07 06:28:16 on - * machines were long is 32-bit! (However, as time_t is signed, we - * will already get problems at other places on 2038-01-19 03:14:08) - */ -unsigned long -mktime (unsigned int year, unsigned int mon, - unsigned int day, unsigned int hour, - unsigned int min, unsigned int sec) -{ - if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */ - mon += 12; /* Puts Feb last since it has leap day */ - year -= 1; - } - - return ((( - (unsigned long) (year/4 - year/100 + year/400 + 367*mon/12 + day) + - year*365 - 719499 - )*24 + hour /* now have hours */ - )*60 + min /* now have minutes */ - )*60 + sec; /* finally seconds */ -} - diff --git a/avr/debug.c b/avr/debug.c index 27b5329..f3632c2 100644 --- a/avr/debug.c +++ b/avr/debug.c @@ -1,3 +1,9 @@ +/* + * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + #include "common.h" #include <stdlib.h> #include <string.h> @@ -5,8 +11,10 @@ #include <avr/eeprom.h> #include "command.h" +#include "cli_readline.h" #include "print-utils.h" #include "debug.h" + /* * Debugging */ @@ -32,7 +40,7 @@ void dump_heap(void) */ command_ret_t do_dump_mem(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - void (*readhow)(uint8_t *buf, uint32_t addr, uint8_t count); + void (*readwhat)(uint8_t *buf, uint32_t addr, uint8_t count); (void) cmdtp; (void) flag; @@ -42,12 +50,19 @@ command_ret_t do_dump_mem(cmd_tbl_t *cmdtp, int flag, int argc, char * const arg uint32_t addr; uint32_t length = 128; - if (strchr(argv[0],'r') != NULL) - readhow = ram_read_buf; - else if (strchr(argv[0],'e') != NULL) - readhow = eeprom_read_buf; - else + switch (argv[0][3]) { + case 'r': + readwhat = ram_read_buf; + break; + case 'e': + readwhat = eeprom_read_buf; + break; + case 'f': + readwhat = flash_read_buf; + break; + default: return CMD_RET_USAGE; + } /* Address is specified since argc > 1 */ addr = strtoul(argv[1], NULL, 16); @@ -57,7 +72,7 @@ command_ret_t do_dump_mem(cmd_tbl_t *cmdtp, int flag, int argc, char * const arg length = (uint16_t) strtoul(argv[2], NULL, 16); /* Print the lines. */ - dump_mem(addr, addr, length, readhow, NULL); + dump_mem(addr, addr, length, readwhat, NULL); return CMD_RET_SUCCESS; } @@ -112,8 +127,85 @@ command_ret_t do_eep_cp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[ return CMD_RET_SUCCESS; } -/*------------------------------------------------------------------------------*/ +/* Modify memory. + * + * Syntax: + * !mm {addr} + * !nm {addr} + */ + + static uint8_t *mm_last_addr; + +static command_ret_t +mod_mem_avr(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[]) +{ + uint8_t *addr; + uint8_t data; + int nbytes; + + (void) cmdtp; + + if (argc != 2) + return CMD_RET_USAGE; + + /* We use the last specified parameters, unless new ones are + * entered. + */ + addr = mm_last_addr; + + if ((flag & CMD_FLAG_REPEAT) == 0) { + /* New command specified. + */ + + /* Address is specified since argc > 1 + */ + addr = (uint8_t *) (size_t) strtoul(argv[1], NULL, 16); + } + + /* Print the address, followed by value. Then accept input for + * the next value. A non-converted value exits. + */ + do { + data = *addr; + printf_P(PSTR("%04x: %02x"), addr, data); + + nbytes = cli_readline(PSTR(" ? ")); + if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) { + /* <CR> pressed as only input, don't modify current + * location and move to next. "-" pressed will go back. + */ + if (incrflag) + addr += nbytes ? -1 : 1; + nbytes = 1; + + } else { + char *endp; + data = strtoul(console_buffer, &endp, 16); + nbytes = endp - console_buffer; + if (nbytes) { + *addr = data; + if (incrflag) + addr++; + } + } + } while (nbytes); + + mm_last_addr = addr; + return CMD_RET_SUCCESS; +} + + +command_ret_t do_mem_mm_avr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + return mod_mem_avr (cmdtp, 1, flag, argc, argv); +} +command_ret_t do_mem_nm_avr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + return mod_mem_avr (cmdtp, 0, flag, argc, argv); +} + +/*------------------------------------------------------------------------------*/ #if 1 @@ -1,3 +1,9 @@ +/* + * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + #include "common.h" #include <string.h> #include <stdlib.h> @@ -8,7 +14,6 @@ #include "xmalloc.h" #include "crc.h" #include "command.h" - #include "env.h" @@ -26,13 +31,17 @@ #define DELIM "\0" const FLASH char default_env[] = { - "bootdelay=" "3" DELIM - "bootcmd=" "reset; loadf; go ${startaddr}" DELIM - "baudrate=" "115200" DELIM - "startaddr=" "0" DELIM + ENV_BAUDRATE "=" "115200" DELIM + ENV_BOOTDELAY "=" "3" DELIM + ENV_BOOTCMD "=" "reset; loadf; go ${startaddr}" DELIM + ENV_CPM3_SYSFILE "=" CONFIG_CPM3_SYSFILE DELIM + ENV_PINALIAS "=" "0:PG5,1:PG4,2:PB4,3:PB5,4:PB6,5:PB7," + "6:PG3,7:PG2,8:PG1,9:PG0,10:PE7" DELIM + ENV_STARTADDRESS "=" "0" DELIM DELIM }; + /* EEPROM storage */ typedef struct environment_s { uint16_t crc; /* CRC16 over data bytes */ @@ -447,7 +456,6 @@ command_ret_t _do_env_set(int flag, int argc, char * const argv[]) env_item_t e, *ep; (void) flag; - debug("Initial value for argc=%d\n", argc); name = argv[1]; value = argv[2]; @@ -514,15 +522,35 @@ command_ret_t _do_env_set(int flag, int argc, char * const argv[]) * @return 0 if ok, 1 on error */ static -int setenv(const char *varname, const char *varvalue) +int setenv(const MEMX char *varname, const char *varvalue) { - const char * const argv[3] = { NULL, varname, varvalue }; + int rc; + +#ifdef __MEMX + char *tmpname = NULL; + if (__builtin_avr_flash_segment(varname) != -1) { + tmpname = malloc(strlen_P(varname)+1); + if (tmpname == NULL) { + printf_P(PSTR("setenv: Out of Memory!\n")); + return 1; + } + strcpy_P(tmpname, varname); + } else + tmpname = (char *) varname; +#endif + + const char * const argv[3] = { NULL, tmpname, varvalue }; int argc = 3; if (varvalue == NULL || varvalue[0] == '\0') --argc; - return (int) _do_env_set(0, argc, (char * const *)argv); + rc = (int) _do_env_set(0, argc, (char * const *)argv); + +#ifdef __MEMX + free(tmpname); +#endif + return rc; } /** diff --git a/avr/getopt-min.c b/avr/getopt-min.c index 8e5dd6c..f5ad912 100644 --- a/avr/getopt-min.c +++ b/avr/getopt-min.c @@ -1,6 +1,3 @@ -#include "common.h" - - /* * Minimum getopt, original version was: */ @@ -13,7 +10,8 @@ */ /* $Id: getopt.c,v 1.2 1992/12/07 11:12:52 nickc Exp $ */ -#include <string.h> +#include "common.h" /* definition of FLASH */ +#include <string.h> int optind = 1; /* next argv[] index */ char *optarg; /* option parameter if any */ @@ -40,7 +38,7 @@ getopt( /* returns letter, '?', EOF */ ) return -1; } - + c = argv[optind][sp]; /* option letter */ osp = sp++; /* get ready for next letter */ @@ -72,4 +70,3 @@ getopt( /* returns letter, '?', EOF */ return c; } - @@ -1,42 +1,46 @@ +/* + * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + #include "common.h" #include <util/atomic.h> #include <limits.h> #include "debug.h" #include "gpio.h" - /* -Pin Name Port Timer Mode max div max div min f [Hz] ----------------------------------------------------------------------------------- -0 PG5 OC0B PWM (2**8)*1024 262144 70.31 -1 PG4 -2 CLK2 PB4 OC2A Toggle (2**8)*1024*2 524288 35.16 -3 ZCLK PB5 OC1A PWM (2**16)*1024 67108864 0.2746 -4 PB6 OC1B PWM (2**16)*1024 67108864 0.2746 -5 PB7 OC0A Toggle (2**8)*1024*2 524288 35.16 -6 PG3 -7 PG2 -8 PG1 -9 PG0 -10 CLKO PE7 - - -pre Timer0 Timer1 Timer2 +Pin Name Port Timer Mode max div max div min f [Hz] +-------------------------------------------------------------------------------- +0 PG5 OC0B PWM (2**8)*1024 262144 70.31 +1 PG4 +2 CLK2 PB4 OC2A Toggle (2**8)*1024*2 524288 35.16 +3 ZCLK PB5 OC1A PWM (2**16)*1024 67108864 0.2746 +4 PB6 OC1B PWM (2**16)*1024 67108864 0.2746 +5 PB7 OC0A Toggle (2**8)*1024*2 524288 35.16 +6 PG3 +7 PG2 +8 PG1 +9 PG0 +10 CLKO PE7 +-------------------------------------------------------------------------------- + + +pre Timer0 Timer1 Timer2 -------------------------------------------------- -0 0 0 0 -1 1 1 1 -2 8 x8 8 x8 8 x8 -3 64 x8 64 x8 32 x4 -4 256 x4 256 x4 64 x2 -5 1024 x4 1024 x4 128 x2 -6 256 x2 -7 1024 x4 +0 0 0 0 +1 1 1 1 +2 8 x8 8 x8 8 x8 +3 64 x8 64 x8 32 x4 +4 256 x4 256 x4 64 x2 +5 1024 x4 1024 x4 128 x2 +6 256 x2 +7 1024 x4 -------------------------------------------------- - */ - #define PWMTOGGLE 0b01 #define PWMPOS 0b10 #define PWMNEG 0b11 @@ -312,7 +316,7 @@ int gpio_clockdiv_set(int pin, unsigned long divider) top = ltop - 1; - PING |= _BV(0); /* Debug */ +// PING |= _BV(0); /* Debug */ switch (timertype & TIMER) { case TIMER0: @@ -363,7 +367,7 @@ int gpio_clockdiv_set(int pin, unsigned long divider) break; } - PING |= _BV(0); /* Debug */ +// PING |= _BV(0); /* Debug */ gpio_config(pin, OUTPUT_TIMER); @@ -1,3 +1,8 @@ +/* + * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ /* * I2C (TWI) master interface. @@ -371,6 +376,3 @@ int i2c_read(uint8_t chip, unsigned int addr, uint_fast8_t alen, return !((rc & (XMIT_DONE|DATA_ACK)) == (XMIT_DONE|DATA_ACK)); } - - - @@ -1,15 +1,18 @@ /* + * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de> + * + * SPDX-License-Identifier: GPL-2.0+ */ #include "common.h" - #include <avr/interrupt.h> +#include <avr/wdt.h> #include <stdlib.h> #include <stdio.h> #include "config.h" -#include "debug.h" +#include "ff.h" #include "z80-if.h" #include "i2c.h" #include "con-utils.h" @@ -18,14 +21,14 @@ #include "cli.h" #include "env.h" #include "z180-serv.h" -#include "spi.h" #include "gpio.h" +#include "time.h" +#include "rtc.h" +#include "debug.h" -static uint8_t mcusr; +uint8_t mcusr __attribute__ ((section (".noinit"))); -/*--------------------------------------------------------------------------*/ #if DEBUG - __attribute__ ((naked)) __attribute__ ((section (".init3"))) void preset_ram (void) { @@ -33,6 +36,21 @@ void preset_ram (void) *p = 0xdd; } +#endif + +__attribute__ ((naked)) __attribute__ ((section (".init3"))) +void get_mcusr (void) +{ + /* save and clear reset reason(s) */ + /* TODO: move to init section? */ + mcusr = MCUSR; + MCUSR = 0; + + wdt_disable(); +} + +/*--------------------------------------------------------------------------*/ +#if DEBUG static const FLASH char * const FLASH rreasons[] = { FSTR("Power on"), @@ -74,13 +92,6 @@ ISR(INT6_vect) static void setup_avr(void) { - /* save and clear reset reason(s) */ - /* TODO: move to init section? */ - mcusr = MCUSR; - MCUSR = 0; - - /* WD */ - /* CPU */ /* Disable JTAG Interface regardless of the JTAGEN fuse setting. */ @@ -110,13 +121,6 @@ void setup_avr(void) TCCR3B = (0b01<<WGM32)|(0b001<<CS30); /* CTC Mode, Prescaler 1 */ TIMSK3 = _BV(OCIE3A); /* Enable TC2.oca interrupt */ - /* SPI as master */ - PRR0 &= ~_BV(PRSPI); - SPI_DDR = (SPI_DDR & ~_BV(SPI_MISO)) - | _BV(SPI_MOSI) | _BV(SPI_SCK) | _BV(SPI_SS); - SPI_PORT = (SPI_PORT & ~(_BV(SPI_MOSI) | _BV(SPI_SCK))) - | _BV(SPI_SS); - /* INT5, INT6: falling edge */ EICRB = (EICRB & ~((0b11 << ISC50) | (0b11 << ISC60))) | (0b10 << ISC50) | (0b10 << ISC60); @@ -132,6 +136,27 @@ int reset_reason_is_power_on(void) return (mcusr & _BV(PORF)) != 0; } +static +void setup_system_time(void) +{ + struct tm rtc_time; + + rtc_get(&rtc_time); + rtc_time.tm_isdst = 0; + set_system_time(mk_gmtime(&rtc_time) ); +} + + + +static void setup_fatfs(void) +{ + static FATFS FatFs0; + static FATFS FatFs1; + + f_mount(&FatFs0, "0:", 0); + f_mount(&FatFs1, "1:", 0); +} + /*--------------------------------------------------------------------------*/ /* Stored value of bootdelay, used by autoboot_command() */ @@ -228,10 +253,13 @@ void main_loop(void) int main(void) { - setup_avr(); - z80_setup_bus(); + extern void setup_mmc(void); + for (int i = 0; i < GPIO_MAX; i++) gpio_config(i, INPUT_PULLUP); + setup_avr(); + setup_mmc(); + z80_setup_bus(); env_init(); if (reset_reason_is_power_on()) @@ -245,13 +273,9 @@ int main(void) print_reset_reason(); #endif -#if DEBUG - unsigned long i_speed = getenv_ulong(PSTR("i2c_clock"), 10, CONFIG_SYS_I2C_CLOCK); - debug("### Setting I2C clock Frequency to %lu Hz.\n", i_speed); - i2c_init(i_speed); -#else i2c_init(CONFIG_SYS_I2C_CLOCK); -#endif + setup_system_time(); + setup_fatfs(); printf_P(PSTR("\nATMEGA1281+Z8S180 Stamp Monitor\n\n")); @@ -10,41 +10,43 @@ #include "timer.h" #include "spi.h" #include "diskio.h" -//#include "debug.h" +#include "debug.h" #define MAX_DRV 2 /* Port Controls (Platform dependent) */ /* SD card socket connections */ -//#define SD_CD_0 SBIT(PORT,) /* Card detect switch */ +/* TODO: config.h cofig macros */ + +//#define SD_CD_0 SBIT(PORT,) /* Card detect switch */ //#define SD_CD_0_IN SBIT(PIN,) //#define SD_CD_0_DDR SBIT(DDR,) -//#define SD_WP_0 SBIT(PORT,) /* Write protect switch */ +//#define SD_WP_0 SBIT(PORT,) /* Write protect switch */ //#define SD_WP_0_IN SBIT(PIN,) //#define SD_WP_0_DDR SBIT(DDR,) -#define SD_CS_0 SBIT(PORTB,0) /* Chip select pin */ +#define SD_CS_0 SBIT(PORTB,0) /* Chip select pin */ #define SD_CS_0_IN SBIT(PINB,0) #define SD_CS_0_DDR SBIT(DDRB,0) -#define SD_CD_1 SBIT(PORTG,3) /* Card detect switch */ -#define SD_CD_1_IN SBIT(PING,3) -#define SD_CD_1_DDR SBIT(DDRG,3) -//#define SD_WP_1 SBIT(PORTG,5) /* Write protect switch */ -#define SD_WP_1_IN SBIT(PING,5) -#define SD_WP_1_DDR SBIT(DDRG,5) +//#define SD_CD_1 SBIT(PORTG,3) /* Card detect switch */ +//#define SD_CD_1_IN SBIT(PING,3) +//#define SD_CD_1_DDR SBIT(DDRG,3) + +//#define SD_WP_1 SBIT(PORTG,5) /* Write protect switch */ +//#define SD_WP_1_IN SBIT(PING,5) +//#define SD_WP_1_DDR SBIT(DDRG,5) #define SD_CS_1 SBIT(PORTG,4) /* Chip select pin */ #define SD_CS_1_IN SBIT(PING,4) #define SD_CS_1_DDR SBIT(DDRG,4) -#define FCLK_SLOW() SPISetMMCInitClock() /* Set slow clock (100k-400k) */ -#define FCLK_FAST() SPISetFastClock() /* Set fast clock (depends on the CSD) */ - +#define SPI_CLK_SLOW() SPISetMMCInitClock() /* Set slow clock (100k-400k) */ +#define SPI_CLK_FAST() SPISetFastClock() /* Set fast clock (depends on the CSD) */ /*-------------------------------------------------------------------------- Definitions for MMC/SDC command @@ -113,14 +115,33 @@ int wait_ready (void) /* 1:OK, 0:Timeout */ static void deselect(BYTE drv) { -// debug("*** enter deselect()\n"); + //debug("*** enter deselect()\n"); if (drv == 0) SD_CS_0 = 1; - else + else { SD_CS_1 = 1; + } + /* Dummy clock (TODO: force DO hi-z for multiple slave SPI) */ + if (socket[drv].stat & STA_FAST) + SPI_CLK_FAST(); + else + SPI_CLK_SLOW(); spi_rcvr(); -// debug("*** exit deselect()\n"); + SPI_OFF(); + + if (drv == 0) { +#ifdef SD_CS_0_IN + SD_CS_0_DDR = 0; + SD_CS_0 = 0; +#endif + } else { +#ifdef SD_CS_1_IN + SD_CS_1_DDR = 0; + SD_CS_1 = 0; +#endif + } + //debug("*** exit deselect()\n"); } /*-----------------------------------------------------------------------*/ @@ -130,20 +151,35 @@ void deselect(BYTE drv) static int select(BYTE drv) /* 1:Successful, 0:Timeout */ { -// debug("*** enter select()\n"); - if (drv == 0) + //debug("*** enter select()\n"); + if (drv == 0) { +#ifdef SD_CS_0_IN + SD_CS_0 = 1; + SD_CS_0_DDR = 1; +#endif SD_CS_0 = 0; - else + } else { +#ifdef SD_CS_1_IN + SD_CS_1 = 1; + SD_CS_1_DDR = 1; +#endif SD_CS_1 = 0; + } + + if (socket[drv].stat & STA_FAST) + SPI_CLK_FAST(); + else + SPI_CLK_SLOW(); + /* Dummy clock (force DO enabled) */ spi_rcvr(); if (wait_ready()) { -// debug("*** exit select() == 1\n"); + //debug("*** exit select() == 1\n"); return 1; /* OK */ } deselect(drv); -// debug("*** exit select() == 0\n"); + //debug("*** exit select() == 0\n"); return 0; /* Timeout */ } @@ -157,57 +193,29 @@ int select(BYTE drv) /* 1:Successful, 0:Timeout */ static void power_on(BYTE drv) { -// debug("*** enter power_on()\n"); + //debug("*** enter power_on()\n"); if (drv == 0) { #ifdef SD_PWR_0 - SD_PWR_0_DDR = 1; /* Turns on PWR pin as output */ SD_PWR_0 = 0; /* Drives PWR pin high */ - - for (uint32_t to = get_timer(0); get_timer(to) < 30;) - ; /* Wait for 30ms */ #endif -#ifdef SD_CD_0 - /* Card detect, input with pullup */ - SD_CD_0_DDR = 0; - SD_CD_0 = 1; -#endif -#ifdef SD_WP_0 - SD_WP_0_DDR = 0; - SD_WP_0 = 1; -#endif - SD_CS_0 = 1; - SD_CS_0_DDR = 1; } else { #ifdef SD_PWR_1 - SD_PWR_1_DDR = 1; /* Turns on PWR pin as output */ SD_PWR_1 = 0; /* Drives PWR pin high */ - +#endif + } +#if defined SD_PWR_0 || defined SD_PWR_1 for (uint32_t to = get_timer(0); get_timer(to) < 30;) ; /* Wait for 30ms */ #endif - -#ifdef SD_CD_1 - /* Card detect, input with pullup */ - SD_CD_1_DDR = 0; - SD_CD_1 = 1; -#endif -#ifdef SD_WP_1 - SD_WP_1_DDR = 0; - SD_WP_1 = 1; -#endif - SD_CS_1 = 1; - SD_CS_1_DDR = 1; - } - -// debug("*** exit power_on()\n"); + //debug("*** exit power_on()\n"); } static void power_off(BYTE drv) { -// debug("*** enter power_off()\n"); + //debug("*** enter power_off()\n"); select(drv); /* Wait for card ready */ deselect(drv); @@ -221,7 +229,7 @@ void power_off(BYTE drv) #endif } socket[drv].stat |= STA_NOINIT; -// debug("*** exit power_off()\n"); + //debug("*** exit power_off()\n"); } #if 0 @@ -330,7 +338,7 @@ BYTE send_cmd ( /* Returns R1 resp (bit7==1:Send failed) */ } argtmp; BYTE n, res; -// debug("*** send_cmd( %.2x )\n", cmd); + //debug("*** send_cmd( %.2x )\n", cmd); if (cmd & 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */ cmd &= 0x7F; @@ -378,6 +386,55 @@ BYTE send_cmd ( /* Returns R1 resp (bit7==1:Send failed) */ ---------------------------------------------------------------------------*/ +void setup_mmc(void) +{ +#ifdef SD_PWR_0 + SD_PWR_1 = 1; /* Drives PWR pin low */ + SD_PWR_0_DDR = 1; /* Turns on PWR pin as output */ +#endif +#ifdef SD_WP_0 + SD_WP_0_DDR = 0; + SD_WP_0 = 1; /* Pullup */ +#endif + +#ifdef SD_PWR_1 + SD_PWR_1 = 1; /* Drives PWR pin low */ + SD_PWR_1_DDR = 1; /* Turns on PWR pin as output */ +#endif +#ifdef SD_WP_1 + SD_WP_1_DDR = 0; + SD_WP_1 = 1; /* Pullup */ +#endif + + /* SPI as master */ + PRR0 &= ~_BV(PRSPI); + SPI_DDR = (SPI_DDR & ~(_BV(SPI_MISO) | _BV(SPI_SS))) + | _BV(SPI_MOSI) | _BV(SPI_SCK); + SPI_PORT = SPI_PORT & ~(_BV(SPI_MOSI) | _BV(SPI_SCK)); + +#if defined SD_CD_0 + SD_CD_0_DDR = 0; + SD_CD_0 = 1; +#elif defined SD_CS_0_IN + SD_CS_0_DDR = 0; + SD_CS_0 = 0; +#else + SD_CS_0_DDR = 1; + SD_CS_0 = 1; +#endif + +#if defined SD_CD_1 + SD_CD_1_DDR = 0; + SD_CD_1 = 1; +#elif defined SD_CS_1_IN + SD_CS_1_DDR = 0; + SD_CS_1 = 0; +#else + SD_CS_1_DDR = 1; + SD_CS_1 = 1; +#endif +} + /*-----------------------------------------------------------------------*/ /* Initialize Disk Drive */ /*-----------------------------------------------------------------------*/ @@ -393,10 +450,11 @@ DSTATUS disk_initialize ( if (drv >= MAX_DRV) return STA_NOINIT; /* Supports only single drive */ if (socket[drv].stat & STA_NODISK) - return socket[drv].stat; /* No card in the socket */ + return socket[drv].stat & STAT_MASK; /* No card in the socket */ power_on(drv); /* Force socket power on */ - FCLK_SLOW(); + socket[drv].stat &= ~STA_FAST; + SPI_CLK_SLOW(); for (n = 10; n; n--) spi_rcvr(); /* 80 dummy clocks */ @@ -441,12 +499,13 @@ DSTATUS disk_initialize ( deselect(drv); if (ty) { /* Initialization succeded */ - socket[drv].stat &= ~STA_NOINIT; /* Clear STA_NOINIT */ + /* Clear STA_NOINIT */ + socket[drv].stat = (socket[drv].stat & ~STA_NOINIT) | STA_FAST; } else { /* Initialization failed */ power_off(drv); } - return socket[drv].stat; + return socket[drv].stat & STAT_MASK; } /*-----------------------------------------------------------------------*/ @@ -459,7 +518,7 @@ DSTATUS disk_status ( { if (drv >= MAX_DRV) return STA_NOINIT; - return socket[drv].stat; + return socket[drv].stat & STAT_MASK; } /*-----------------------------------------------------------------------*/ @@ -483,7 +542,6 @@ DRESULT disk_read ( /* Convert to byte address if needed */ if (!(socket[drv].CardType & CT_BLOCK)) sector *= 512; - FCLK_FAST(); /* READ_MULTIPLE_BLOCK : READ_SINGLE_BLOCK */ cmd = count > 1 ? CMD18 : CMD17; @@ -523,7 +581,6 @@ DRESULT disk_write ( /* Convert to byte address if needed */ if (!(socket[drv].CardType & CT_BLOCK)) sector *= 512; - FCLK_FAST(); if (count == 1) { /* Single block write */ @@ -574,7 +631,8 @@ DRESULT disk_ioctl ( if (socket[drv].stat & STA_NOINIT) return RES_NOTRDY; - FCLK_FAST(); + /* TODO: SPI clock? */ + switch (cmd) { case CTRL_SYNC : /* Make sure that no pending write process. Do not remove this or written sector might not left updated. */ if (select(drv)) @@ -682,29 +740,45 @@ void disk_timerproc (void) #ifdef SD_WP_0 if (SD_WP_0_IN == 0) /* Write protected */ s |= STA_PROTECT; - else /* Write enabled */ + else /* Write enabled */ s &= ~STA_PROTECT; #endif -#ifdef SD_CD_0 + +#if defined SD_CD_0 if (SD_CD_0_IN == 0) /* Card inserted */ s &= ~STA_NODISK; - else /* Socket empty */ + else /* Socket empty */ s |= (STA_NODISK | STA_NOINIT); +#elif defined SD_CS_0_IN + if (SD_CS_0_DDR == 0) { + if (SD_CS_0_IN == 1) /* Card inserted */ + s &= ~STA_NODISK; + else /* Socket empty */ + s |= (STA_NODISK | STA_NOINIT); + } #endif - socket[0].stat = s; /* Update MMC status */ + socket[0].stat = s; /* Update MMC status */ s = socket[1].stat; #ifdef SD_WP_1 if (SD_WP_1_IN == 0) /* Write protected */ s |= STA_PROTECT; - else /* Write enabled */ + else /* Write enabled */ s &= ~STA_PROTECT; #endif -#ifdef SD_CD_1 + +#if defined SD_CD_1 if (SD_CD_1_IN == 0) /* Card inserted */ s &= ~STA_NODISK; - else /* Socket empty */ + else /* Socket empty */ s |= (STA_NODISK | STA_NOINIT); +#elif defined SD_CS_1_IN + if (SD_CS_1_DDR == 0) { + if (SD_CS_1_IN == 1) /* Card inserted */ + s &= ~STA_NODISK; + else /* Socket empty */ + s |= (STA_NODISK | STA_NOINIT); + } #endif socket[1].stat = s; /* Update MMC status */ } diff --git a/avr/pcf8583.c b/avr/pcf8583.c index af1331d..169e4e9 100644 --- a/avr/pcf8583.c +++ b/avr/pcf8583.c @@ -1,13 +1,20 @@ /* + * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* * Date & Time support for Philips PCF8583 RTC */ #include "common.h" #include <stdlib.h> -#include "debug.h" -#include "command.h" +#include "time.h" #include "rtc.h" #include "i2c.h" +#include "command.h" +#include "debug.h" #define DEBUG_RTC 0 @@ -34,17 +41,17 @@ static uint_fast8_t bcd2bin(uint8_t val) static uint8_t bin2bcd (uint_fast8_t val) { div_t d = div(val, 10); - + return (d.quot << 4) | d.rem; } -int rtc_get (struct rtc_time *tmp) +int rtc_get (struct tm *tmp) { int rel = 0; uint8_t rtcbuf[NR_OF_REGS]; - uint16_t year; - + int16_t year; + i2c_read(CONFIG_SYS_I2C_RTC_ADDR, 0, 1, rtcbuf, NR_OF_REGS); i2c_read(CONFIG_SYS_I2C_RTC_ADDR, 0x10, 1, (uint8_t *) &year, 2); @@ -56,12 +63,12 @@ int rtc_get (struct rtc_time *tmp) tmp->tm_min = bcd2bin (rtcbuf[REG_MIN] & 0x7F); tmp->tm_hour = bcd2bin (rtcbuf[REG_HOUR] & 0x3F); tmp->tm_mday = bcd2bin (rtcbuf[REG_YRDATE] & 0x3F); - tmp->tm_mon = bcd2bin (rtcbuf[REG_WDMON] & 0x1F); + tmp->tm_mon = bcd2bin (rtcbuf[REG_WDMON] & 0x1F) - 1; while (year%4 < (rtcbuf[REG_YRDATE]>>6)) { year++; /* TODO: update RTC ram */ } - tmp->tm_year = year; + tmp->tm_year = year; tmp->tm_wday = rtcbuf[REG_WDMON] >> 5; tmp->tm_yday = 0; tmp->tm_isdst= 0; @@ -74,7 +81,7 @@ int rtc_get (struct rtc_time *tmp) return rel; } -int rtc_set (struct rtc_time *tmp) +int rtc_set (struct tm *tmp) { uint8_t rtcbuf[NR_OF_REGS]; @@ -84,7 +91,7 @@ int rtc_set (struct rtc_time *tmp) rtcbuf[REG_CS] = 0x84; rtcbuf[REG_CSEC] = 0x00; - rtcbuf[REG_WDMON ] = bin2bcd(tmp->tm_mon) | ((tmp->tm_wday) << 5); + rtcbuf[REG_WDMON ] = (bin2bcd(tmp->tm_mon) + 1) | ((tmp->tm_wday) << 5); rtcbuf[REG_YRDATE] = ((tmp->tm_year % 4) << 6) | bin2bcd(tmp->tm_mday); rtcbuf[REG_HOUR ] = bin2bcd(tmp->tm_hour); rtcbuf[REG_MIN ] = bin2bcd(tmp->tm_min); diff --git a/avr/print-utils.c b/avr/print-utils.c index 4205a90..9ce3e50 100644 --- a/avr/print-utils.c +++ b/avr/print-utils.c @@ -1,4 +1,11 @@ +/* + * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + #include "common.h" +#include <stdint.h> #include <stdio.h> #include <ctype.h> #include "con-utils.h" @@ -22,6 +29,12 @@ void ram_read_buf(uint8_t *buf, uint32_t addr, uint8_t count) *buf++ = *(uint8_t *) (size_t) addr++; } +void flash_read_buf(uint8_t *buf, uint32_t addr, uint8_t count) +{ + while (count--) + *buf++ = *(const __memx uint8_t *) (__uint24) addr++; +} + int dump_mem(uint32_t address, uint32_t offset, uint32_t len, void (*readfkt)(uint8_t *, uint32_t, uint8_t), char *title) { diff --git a/avr/serial.c b/avr/serial.c index e897c84..adbc3c4 100644 --- a/avr/serial.c +++ b/avr/serial.c @@ -1,4 +1,7 @@ /* + * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de> + * + * SPDX-License-Identifier: GPL-2.0+ */ #include <avr/io.h> @@ -12,7 +15,7 @@ static int _write(char c, FILE *stream); -static FILE mystdout = FDEV_SETUP_STREAM(_write, +static FILE mystdout = FDEV_SETUP_STREAM(_write, NULL, _FDEV_SETUP_WRITE); @@ -24,7 +27,7 @@ static FILE mystdout = FDEV_SETUP_STREAM(_write, #endif #if ((BUFFER_SIZE) > 256) -# error: BUFFER_SIZE +# error: BUFFER_SIZE #endif struct ring rx_ring; @@ -119,5 +122,3 @@ uint_fast8_t serial_tstc(void) { return !ring_is_empty(&rx_ring); } - - diff --git a/avr/timer.c b/avr/timer.c index 7907bba..f45f267 100644 --- a/avr/timer.c +++ b/avr/timer.c @@ -1,9 +1,13 @@ /* + * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de> + * + * SPDX-License-Identifier: GPL-2.0+ */ #include "common.h" #include <avr/interrupt.h> #include <util/atomic.h> +#include "time.h" #include "timer.h" /* timer interrupt/overflow counter */ @@ -11,14 +15,14 @@ static volatile uint32_t timestamp; -/*---------------------------------------------------------*/ -/* 1000Hz timer interrupt generated by OC3A */ -/*---------------------------------------------------------*/ - +/* + * 1000Hz timer interrupt generated by OC3A + */ ISR(TIMER3_COMPA_vect) { static int_fast8_t tick_10ms; - int_fast8_t i; + static int_fast8_t tick_1s; + int_fast8_t i, j; extern void disk_timerproc(void); @@ -26,11 +30,18 @@ ISR(TIMER3_COMPA_vect) i = tick_10ms + 1; if (i == 10) { - i = 0; Stat |= S_10MS_TO; /* Drive timer procedure of low level disk I/O module */ disk_timerproc(); + + j = tick_1s - 1; + if (j == 0) { + system_tick(); + j = 100; + } + tick_1s = j; + i = 0; } tick_10ms = i; } diff --git a/avr/xmalloc.c b/avr/xmalloc.c index 9bf2684..d42d5c9 100644 --- a/avr/xmalloc.c +++ b/avr/xmalloc.c @@ -1,5 +1,10 @@ -#include <stdlib.h> +/* + * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <stdlib.h> #include "debug.h" #include "xmalloc.h" @@ -11,7 +16,7 @@ void* xmalloc(size_t size) if (p == NULL) debug("*** Out of memory!\n"); - + return p; } @@ -22,6 +27,6 @@ void* xrealloc(void *p, size_t size) if (p == NULL) debug("*** Out of memory!\n"); - + return p; } diff --git a/avr/z180-serv.c b/avr/z180-serv.c index e3bca16..69bcd9c 100644 --- a/avr/z180-serv.c +++ b/avr/z180-serv.c @@ -1,27 +1,32 @@ +/* + * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + #include "common.h" +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> #include <util/atomic.h> #include "background.h" +#include "env.h" +#include "ff.h" #include "serial.h" #include "z80-if.h" #include "debug.h" +#include "print-utils.h" #include "z180-serv.h" +#include "timer.h" +#include "time.h" +#include "bcd.h" +#include "rtc.h" +#define DEBUG_CPM_SDIO 0 /* set to 1 to debug */ - -/*--------------------------------------------------------------------------*/ - - -uint8_t z80_get_byte(uint32_t adr) -{ - uint8_t data; - - z80_bus_cmd(Request); - data = z80_read(adr); - z80_bus_cmd(Release); - - return data; -} +#define debug_cpmsd(fmt, args...) \ + debug_cond(DEBUG_CPM_SDIO, fmt, ##args) /*--------------------------------------------------------------------------*/ @@ -48,6 +53,25 @@ uint32_t msg_to_addr(uint8_t *msg) } +static int msg_xmit_header(uint8_t func, uint8_t subf, int len) +{ + z80_memfifo_putc(fifo_msgout, 0xAE); + z80_memfifo_putc(fifo_msgout, len+2); + z80_memfifo_putc(fifo_msgout, func); + z80_memfifo_putc(fifo_msgout, subf); + + return 0; +} + +int msg_xmit(uint8_t func, uint8_t subf, int len, uint8_t *msg) +{ + msg_xmit_header(func, subf, len); + while (len--) + z80_memfifo_putc(fifo_msgout, *msg++); + + return 0; +} + void do_msg_ini_memfifo(uint8_t subf, int len, uint8_t * msg) { (void)len; @@ -64,6 +88,356 @@ void do_msg_char_out(uint8_t subf, int len, uint8_t * msg) putchar(*msg++); } +/* echo message */ +void do_msg_echo(uint8_t subf, int len, uint8_t * msg) +{ + (void)subf; + + /* send re-echo */ + msg_xmit(1, 3, len, msg); +} + +/* get timer */ +void do_msg_get_timer(uint8_t subf, int len, uint8_t * msg) +{ + uint32_t time_ms = (len >= 4) ? *(uint32_t *) msg : 0; + + time_ms = get_timer(time_ms); + msg_xmit(3, subf, sizeof(time_ms), (uint8_t *) &time_ms); +} + +/* ---------------------------------------------------------------------------*/ + +#define CPM_DAY_OFFSET ((1978-1900) * 365 + 19) /* 19 leap years */ + +/* + * Convert CP/M time stamp to a broken-down time structure + * + */ +int mk_date_time (int len, uint8_t *msg, struct tm *tmp) +{ + time_t stamp; + + if (len != 5) + return -1; + + /* days since 2000-01-01 */ + long days = msg[3] + (msg[4] << 8) - 8036; + + if (days < 0) + return -1; + + stamp = days * ONE_DAY; + stamp += bcd2bin(msg[0]); + stamp += bcd2bin(msg[1]) * 60 ; + stamp += bcd2bin(msg[2]) * 3600L; + gmtime_r(&stamp, tmp); + return 0; +} + +void mk_cpm_time(struct tm *tmp, uint8_t cpm_time[5]) +{ + uint16_t days = 1; + uint_fast8_t leap=2; + + for (int year=78; year < tmp->tm_year; year++) { + days = days + 365 + (leap == 0); + leap = (leap+1)%4; + } + days += tmp->tm_yday; + + cpm_time[0] = bin2bcd(tmp->tm_sec); + cpm_time[1] = bin2bcd(tmp->tm_min); + cpm_time[2] = bin2bcd(tmp->tm_hour); + cpm_time[3] = days; + cpm_time[4] = days >> 8; +} + +/* get/set cp/m time */ +void do_msg_get_set_time(uint8_t subf, int len, uint8_t * msg) +{ + struct tm t; + uint8_t cpm_time[5]; + int rc; + + memset(cpm_time, 0, ARRAY_SIZE(cpm_time)); + + switch (subf) { + case 3: /* set date & time */ + /* initialize t with current time */ + rc = rtc_get (&t); + + if (rc == 0) { + /* insert new date & time */ + if (mk_date_time (len, msg, &t) != 0) { + my_puts_P(PSTR("## set_time: Bad date format\n")); + break; + } + + time_t time; + time = mk_gmtime(&t); + gmtime_r(&time, &t); + + /* and write to RTC */ + rc = rtc_set (&t); + if(rc) + my_puts_P(PSTR("## set_time: Set date failed\n")); + } else { + my_puts_P(PSTR("## set_time: Get date failed\n")); + } + /* FALL TROUGH */ + case 2: /* get date & time */ + rc = rtc_get (&t); + + if (rc) { + my_puts_P(PSTR("## get_time: Get date failed\n")); + break; + } + + time_t time; + time = mk_gmtime(&t); + //mktime(&t); + gmtime_r(&time, &t); + + + mk_cpm_time(&t, cpm_time); + break; + } + + msg_xmit(3, subf, sizeof(cpm_time), cpm_time); +} + +/* ---------------------------------------------------------------------------*/ + +#define MAX_DRIVE 4 +#define BLOCK_SIZE 512 +//#define TPA_BASE 0x10000 +//#define COMMON_BASE 0xC000 + +struct cpm_drive_s { + uint8_t drv; + uint8_t device; + char *img_name; + bool dirty; + FIL fd; +}; + +static uint8_t disk_buffer[BLOCK_SIZE]; +static struct cpm_drive_s drv_table[MAX_DRIVE]; +static int handle_cpm_drv_to; + +#define f_dirty(fp) ((fp)->fs->wflag != 0) + + +int cpm_drv_to(int state) +{ + static uint32_t ts; + + switch(state) { + case 0: + break; + + case 1: + ts = get_timer(0); + state = 2; + break; + + case 2: + if (get_timer(ts) > 1000) { + for (uint_fast8_t i=0; i < MAX_DRIVE; i++) { +// if (&drv_table[i].fd && f_dirty(&drv_table[i].fd)) { + if (drv_table[i].dirty) { + f_sync(&drv_table[i].fd); + drv_table[i].dirty = false; + debug_cpmsd("## %7lu f_sync: %c:\n", get_timer(0), i+'A'); + } + } + state = 0; + } + } + return state; +} + + +void msg_cpm_result(uint8_t subf, uint8_t rc, int res) +{ + uint8_t result_msg[3]; + + if (res) + rc |= 0x80; + + result_msg[0] = rc; + result_msg[1] = res; + result_msg[2] = res >> 8; + + if (rc) { + debug_cpmsd("###%7lu error rc: %.02x, res: %d\n", get_timer(0), rc, res); + } + + msg_xmit(2, subf, sizeof(result_msg), result_msg); +} + +/* + db 2 ; disk command + ds 1 ; subcommand (login/read/write) + ds 1 ; @adrv (8 bits) +0 + ds 1 ; @rdrv (8 bits) +1 + ds 3 ; @xdph (24 bits) +2 +*/ + +void do_msg_cpm_login(uint8_t subf, int len, uint8_t * msg) +{ + + FRESULT res = 0; + uint8_t drv; + char *np; + + (void)subf; + + if (len != 5) { /* TODO: check adrv, rdrv */ + return msg_cpm_result(subf, 0x01, res); + } + + debug_cpmsd("\n## %7lu login: %c:\n", get_timer(0), msg[0]+'A'); + + + drv = msg[0]; + if ( drv>= MAX_DRIVE) { + return msg_cpm_result(subf, 0x02, res); + } + +/* + uint32_t dph = ((uint32_t)msg[4] << 16) + ((uint16_t)msg[3] << 8) + msg[2]; +*/ + + if (drv_table[drv].img_name != NULL) { + debug_cpmsd("## %7lu close: '%s'\n", get_timer(0), drv_table[drv].img_name); + f_close(&drv_table[drv].fd); + drv_table[drv].dirty = false; + free(drv_table[drv].img_name); + drv_table[drv].img_name = NULL; + } + + strcpy_P((char *)disk_buffer, PSTR("dsk0")); + disk_buffer[3] = msg[0] + '0'; + if (((np = getenv((char*)disk_buffer)) == NULL) || + ((drv_table[drv].img_name = strdup(np)) == NULL)) { + return msg_cpm_result(subf, 0x03, res); + } + + + res = f_open(&drv_table[drv].fd, drv_table[drv].img_name, + FA_WRITE | FA_READ); + + debug_cpmsd("## %7lu open: '%s', (env: '%s'), res: %d\n", get_timer(0), + drv_table[drv].img_name, disk_buffer, res); + + /* send result*/ + msg_cpm_result(subf, 0x00, res); +} + + +/* + db 2 ; disk command + ds 1 ; subcommand (login/read/write) + ds 1 ; @adrv (8 bits) +0 + ds 1 ; @rdrv (8 bits) +1 + ds 2 ; @trk (16 bits) +2 + ds 2 ; @sect(16 bits) +4 + ds 1 ; @cnt (8 bits) +6 + ds 3 ; phys. transfer addr +7 +*/ + +#define ADRV 0 +#define RDRV 1 +#define TRK 2 +#define SEC 4 +#define CNT 6 +#define ADDR 7 + +void do_msg_cpm_rw(uint8_t subf, int len, uint8_t * msg) +{ + uint8_t drv; + uint32_t addr; + uint32_t pos; + uint8_t secs; + bool dowrite = (subf == 2); + FRESULT res = 0; + uint8_t rc = 0; + bool buserr = 0; + + if (len != 10) { /* TODO: check adrv, rdrv */ + return msg_cpm_result(subf, 0x01, res); + } + + drv = msg[ADRV]; + if ( drv>= MAX_DRIVE) { + return msg_cpm_result(subf, 0x02, res); + } + + secs = msg[CNT]; + addr = ((uint32_t)msg[ADDR+2] << 16) + ((uint16_t)msg[ADDR+1] << 8) + msg[ADDR]; + + + /* TODO: tracks per sector from dpb */ + pos = (((uint16_t)(msg[TRK+1] << 8) + msg[TRK]) * 8 + + ((uint32_t)(msg[SEC+1] << 8) + msg[SEC])) * BLOCK_SIZE; + + debug_cpmsd("## %7lu cpm_rw: %s %c: trk:%4d, sec: %d, pos: %.8lx, secs: %2d, " + "addr: %.5lx\n", get_timer(0), dowrite ? "write" : " read", + msg[ADRV]+'A', ((uint16_t)(msg[TRK+1] << 8) + msg[TRK]), msg[SEC], + pos, msg[CNT], addr); + + res = f_lseek(&drv_table[drv].fd, pos); + while (!res && secs--) { + unsigned int brw; + if (dowrite) { + if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) { + buserr = 1; + break; + } else { + z80_read_block(disk_buffer, addr, BLOCK_SIZE); + z80_bus_cmd(Release); + } + res = f_write(&drv_table[drv].fd, disk_buffer, BLOCK_SIZE, &brw); + } else { + res = f_read(&drv_table[drv].fd, disk_buffer, BLOCK_SIZE, &brw); + if (res == FR_OK && brw == BLOCK_SIZE) { + if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) { + buserr = 1; + break; + } else { + z80_write_block(disk_buffer, addr, BLOCK_SIZE); + z80_bus_cmd(Release); + } + } + } + + if (brw != BLOCK_SIZE) { + debug_cpmsd("## %7lu f_read res: %d, bytes rd/wr: %u\n", get_timer(0), res, brw); + dump_ram(disk_buffer, 0, 64, "Read Data"); + res = -1; + } + + addr += BLOCK_SIZE; + } + + if (dowrite && !res) { +// res = f_sync(&drv_table[drv].fd); + drv_table[drv].dirty = true; + bg_setstat(handle_cpm_drv_to, 1); + } + + + if (buserr) { + debug_cpmsd("Bus timeout\n"); + rc = 0x03; + } + + /* send result*/ + msg_cpm_result(subf, rc, res); +} + const FLASH struct msg_item z80_messages[] = { @@ -73,6 +447,21 @@ const FLASH struct msg_item z80_messages[] = { 1, 1, 1, do_msg_char_out}, + { 1, + 2, 2, + do_msg_echo}, + { 2, + 0, 0, + do_msg_cpm_login}, + { 2, + 1, 2, + do_msg_cpm_rw}, + { 3, + 1, 1, + do_msg_get_timer}, + { 3, + 2, 3, /* 2: get, 3: set time and date */ + do_msg_get_set_time}, { 0xff, /* end mark */ 0, 0, 0}, @@ -165,7 +554,7 @@ void check_msg_fifo(void) int msg_handling(int state) { - uint8_t pending; + bool pending; ATOMIC_BLOCK(ATOMIC_FORCEON) { pending = (Stat & S_MSG_PENDING) != 0; @@ -173,21 +562,27 @@ int msg_handling(int state) } if (pending) { - switch (state) { - case 0: + uint8_t init_request; + z80_bus_cmd(Request); + init_request = z80_read(0x43); + z80_bus_cmd(Release); + if ( init_request != 0) { + /* Get address of fifo 0 */ z80_bus_cmd(Request); - uint32_t addr = z80_read(0x40) + - ((uint16_t) z80_read(0x41) << 8) + - ((uint32_t) z80_read(0x42) << 16); + uint32_t fifo_addr = z80_read(0x40) + + ((uint16_t) z80_read(0x40+1) << 8) + + ((uint32_t) z80_read(0x40+2) << 16); + z80_write(0x43, 0); z80_bus_cmd(Release); - if (addr != 0) { - z80_memfifo_init(fifo_msgin, addr); + + if (fifo_addr != 0) { + z80_memfifo_init(fifo_msgin, fifo_addr); state = 1; - } - break; - case 1: + } else + state = 0; + + } else { check_msg_fifo(); - break; } } @@ -201,21 +596,22 @@ void setup_z180_serv(void) { handle_msg_handling = bg_register(msg_handling, 0); + handle_cpm_drv_to = bg_register(cpm_drv_to, 0); } void restart_z180_serv(void) { z80_bus_cmd(Request); - z80_write(0x40, 0); - z80_write(0x41, 0); - z80_write(0x42, 0); + z80_memset(0x40, 0, 4); z80_bus_cmd(Release); for (int i = 0; i < NUM_FIFOS; i++) z80_memfifo_init(i, 0); bg_setstat(handle_msg_handling, 0); + } +#if 0 /*--------------------------------------------------------------------------*/ const FLASH uint8_t iniprog[] = { @@ -267,3 +663,4 @@ const FLASH uint8_t test1[] = { 0x00, // db 0 ;dst 0x00, 0x00, // dw 0 ;count (64k) }; +#endif diff --git a/avr/z180-stamp-avr.c b/avr/z180-stamp-avr.c deleted file mode 100644 index e6edb33..0000000 --- a/avr/z180-stamp-avr.c +++ /dev/null @@ -1,591 +0,0 @@ -/* - */ - - -#include <avr/io.h> -//#include <avr/power.h> -//#include <avr/pgmspace.h> -#include <avr/interrupt.h> -//#include <util/atomic.h> -//#include <avr/sleep.h> -//#include <string.h> - -#include <stdio.h> - - -#include "debug.h" -#include "serial.h" -#include "z80-if.h" - -#define const const __flash -#include "../z180/hdrom.h" -#undef const - -#define FLASH __flash -//#define FLASH - -#define ESCCHAR ('^'-0x40) - -#define S_10MS_TO (1<<0) - - -volatile int_fast8_t timeout_1s; -//volatile uint_least8_t Stat; -#define Stat GPIOR0 - -unsigned int to_counter; - -/****************************************************************/ - -#define P_ADL PORTA -#define P_ADH PORTC -#define P_ADB PORTE -#define PIN_ADB PINE - -#define ADB_WIDTH 3 -#define ADB_SHIFT 2 -//#define ADB_PORT GPIOE - -#define MASK(n) ((1<<(n))-1) -#define SMASK(w,s) (MASK(w) << (s)) - -typedef union { - uint32_t l; - uint16_t w[2]; - uint8_t b[4]; -} addr_t; - - - -/*--------------------------------------------------------------------------*/ - -/*---------------------------------------------------------*/ -/* 1000Hz timer interrupt generated by OC1A */ -/*---------------------------------------------------------*/ - -ISR(TIMER1_COMPA_vect) -{ - static int_fast8_t tick_10ms; -// static int_fast16_t count_ms; - - int_fast8_t i; - - - i = tick_10ms + 1; - if (i == 10) { - i = 0; - Stat |= S_10MS_TO; - - /* Drive timer procedure of low level disk I/O module */ - //disk_timerproc(); - } - tick_10ms = i; - -#if 0 - count_ms++; - if (count_ms == 1000) { - count_ms = 0; - - i = timeout_1s; - if (i) - timeout_1s = i - 1; - } -#endif -} - - -/*--------------------------------------------------------------------------*/ - -static uint32_t z80_sram_cmp(uint32_t addr, uint32_t length, uint8_t wval, int inc) -{ - uint8_t rval; - int_fast8_t errors = 0; - - DBG_P(1, "SRAM: Check 0x%.5lx byte... ", length); - while (length--) { - if ((rval = z80_read(addr)) != wval) { - if (errors == 0) { - DBG_P(1, "\nSRAM: Address W R\n" \ - " ------------------\n"); - } - errors++; - if (errors > 20) { - DBG_P(1, " ...\n"); - break; - } - DBG_P(1, " 0x%.5lx 0x%.2x 0x%.2x\n", addr, wval, rval); - } - addr++; - wval += inc; - } - DBG_P(1, "Done.\n"); - - return addr; -} - -static void z80_sram_fill(uint32_t addr, uint32_t length, uint8_t startval, int inc) -{ - printf("SRAM: Write 0x%.5lx byte... ", length); - while (length--) { - z80_write(addr, startval); - ++addr; - startval += inc; - } - printf("Done.\n"); -} - - -#if 0 -void z80_sram_fill_string(uint32_t addr, int length, const char *text) -{ - char c; - const char *p = text; - - while (length--) { - z80_write(addr++, c = *p++); - if (c == 0) - p = text; - } -} - - -uint32_t z80_sram_cmp_string(uint32_t addr, int length, const char *text) -{ - char c; - const char *p = text; - - while (length--) { - c = *p++; - if (z80_read(addr) != c) - break; - ++addr; - if (c == 0) - p = text; - } - return addr; -} - -const char * const qbfox = "Zhe quick brown fox jumps over the lazy dog!"; -const char * const qbcat = "Zhe quick brown fox jumps over the lazy cat!"; - -#endif - -uint8_t z80_get_byte(uint32_t adr) -{ - uint8_t data; - - z80_request_bus(); - data = z80_read(adr), - z80_release_bus(); - - return data; -} - - -/*--------------------------------------------------------------------------*/ - -static void do_10ms(void) -{ - if (to_counter) - to_counter--; -} - -/*--------------------------------------------------------------------------*/ - -struct msg_item { - uint8_t fct; - uint8_t sub_min, sub_max; - void (*func)(uint8_t, int, uint8_t *); -}; - -uint32_t msg_to_addr(uint8_t *msg) -{ - union { - uint32_t as32; - uint8_t as8[4]; - } addr; - - addr.as8[0] = msg[0]; - addr.as8[1] = msg[1]; - addr.as8[2] = msg[2]; - addr.as8[3] = 0; - - return addr.as32; -} - -void do_msg_ini_msgfifo(uint8_t subf, int len, uint8_t * msg) -{ - (void)subf; (void)len; - - z80_init_msg_fifo(msg_to_addr(msg)); -} - - -void do_msg_ini_memfifo(uint8_t subf, int len, uint8_t * msg) -{ - (void)len; - - z80_memfifo_init(subf - 1, msg_to_addr(msg)); -} - - -void do_msg_char_out(uint8_t subf, int len, uint8_t * msg) -{ - (void)subf; - - while (len--) - putchar(*msg++); -} - - -const FLASH struct msg_item z80_messages[] = -{ - { 0, /* fct nr. */ - 0, 0, /* sub fct nr. from, to */ - do_msg_ini_msgfifo}, - { 0, - 1, 2, - do_msg_ini_memfifo}, - { 1, - 1, 1, - do_msg_char_out}, - { 0xff, /* end mark */ - 0, 0, - 0}, - -}; - - - - -void do_message(int len, uint8_t *msg) -{ - uint8_t fct, sub_fct; - int_fast8_t i = 0; - - if (len >= 2) { - fct = *msg++; - sub_fct = *msg++; - len -= 2; - - while (fct != z80_messages[i].fct) - ++i; - - if (z80_messages[i].fct == 0xff) { - DBG_P(1, "do_message: Unknown function: %i, %i\n", - fct, sub_fct); - return; /* TODO: unknown message # */ - } - - while (fct == z80_messages[i].fct) { - if (sub_fct >= z80_messages[i].sub_min && sub_fct <= z80_messages[i].sub_max ) - break; - ++i; - } - - if (z80_messages[i].fct != fct) { - DBG_P(1, "do_message: Unknown sub function: %i, %i\n", - fct, sub_fct); - return; /* TODO: unknown message sub# */ - } - - (z80_messages[i].func)(sub_fct, len, msg); - - - } else { - /* TODO: error */ - DBG_P(1, "do_message: to few arguments (%i); this shouldn't happen!\n", len); - } -} - - - -#define CTRBUF_LEN 256 - -void check_msg_fifo(void) -{ - int ch; - static int_fast8_t state; - static int msglen,idx; - static uint8_t buffer[CTRBUF_LEN]; - - while (state != 3 && (ch = z80_msg_fifo_getc()) >= 0) { - switch (state) { - case 0: /* wait for start of message */ - if (ch == 0x81) { - msglen = 0; - idx = 0; - state = 1; - } - break; - case 1: /* get msg len */ - if (ch > 0 && ch <= CTRBUF_LEN) { - msglen = ch; - state = 2; - } else - state = 0; - break; - case 2: /* get message */ - buffer[idx++] = ch; - if (idx == msglen) - state = 3; - break; - } - } - - if (state == 3) { - do_message(msglen, buffer); - state = 0; - } -} - - -/*--------------------------------------------------------------------------*/ - -void dump_mem(const __flash uint8_t *addr, uint32_t len) -{ - DBG_P(1, "hdrom dump:"); - while (len) { - DBG_P(1, "\n %.5x:", addr); - for (unsigned i = 0; i<16; i++) - DBG_P(1, " %.2x", *addr++); - len -= len > 16 ? 16 : len; - } - DBG_P(1, "\n"); -} - -/*--------------------------------------------------------------------------*/ - -void z80_load_mem(void) -{ - unsigned sec = 0; - uint32_t sec_base = hdrom_start; - - DBG_P(1, "Loading z80 memory... \n"); - - while (sec < hdrom_sections) { - DBG_P(2, " From: 0x%.5lX to: 0x%.5lX (%5li bytes)\n", - hdrom_address[sec], - hdrom_address[sec]+hdrom_length_of_sections[sec] - 1, - hdrom_length_of_sections[sec]); - - z80_write_block((const __flash unsigned char *) &hdrom[sec_base], /* src */ - hdrom_address[sec], /* dest */ - hdrom_length_of_sections[sec]); /* len */ - sec_base+=hdrom_length_of_sections[sec]; - sec++; - } -} - -/*--------------------------------------------------------------------------*/ - -void z80_dump_mem(uint32_t addr, uint32_t len) -{ - DBG_P(1, "Memory dump:"); - while (len) { - DBG_P(1, "\n %.5lx:", addr); - for (unsigned i = 0; i<16; i++) - DBG_P(1, " %.2x", z80_read(addr++)); - len -= len > 16 ? 16 : len; - } - DBG_P(1, "\n"); -} - -/*--------------------------------------------------------------------------*/ - -void setup_rtc(void) -{ - /* TODO: */ -} - -void setup_avr(void) -{ - /* WD */ - - /* CPU */ - - /* Disable JTAG Interface regardless of the JTAGEN fuse setting. */ - MCUCR = _BV(JTD); - MCUCR = _BV(JTD); - - /* disable unused periphels */ - PRR0 = _BV(PRTIM2) | _BV(PRTIM0) | _BV(PRADC); - PRR1 = _BV(PRTIM5) | _BV(PRTIM4) | _BV(PRTIM3) | - _BV(PRUSART3) | _BV(PRUSART2) | _BV(PRUSART1); - - /* disable analog comparator */ - ACSR = _BV(ACD); - /* Ports */ - - /* Clock */ - CLKPR = _BV(CLKPCE); - CLKPR = 0; - - /* Timer */ - - OCR1A = F_CPU / 8 / 1000 - 1; // Timer1: 1000Hz interval (OC1A) - TCCR1B = 0b00001010; - TIMSK1 = _BV(OCIE1A); // Enable TC1.oca interrupt -} - -const __flash uint8_t iniprog[] = { - 0xAF, // xor a - 0xED, 0x39, 0x36, // out0 (rcr),a ;disable DRAM refresh - 0x3E, 0x30, // ld a,030h - 0xED, 0x39, 0x32 //out0 (dcntl),a ;0 mem, max i/0 wait states -}; - -const __flash uint8_t sertest[] = { - 0xAF, // xor a - 0xED, 0x39, 0x36, // out0 (rcr),a ;disable DRAM refresh - 0x3E, 0x30, // ld a,030h - 0xED, 0x39, 0x32, // out0 (dcntl),a ;0 mem, max i/0 wait states - 0x3E, 0x80, // ld a,M_MPBT ;no MP, PS=10, DR=16, SS=0 - 0xED, 0x39, 0x03, // out0 (cntlb1),a - 0x3E, 0x64, // ld a,M_RE + M_TE + M_MOD2 ; - 0xED, 0x39, 0x01, // out0 (cntla1),a - 0x3E, 0x00, // ld a,0 - 0xED, 0x39, 0x05, // out0 (stat1),a ;Enable rx interrupts - 0xED, 0x38, 0x05, //l0:in0 a,(stat1) - 0xE6, 0x80, // and 80h - 0x28, 0xF9, // jr z,l0 - 0xED, 0x00, 0x09, // in0 b,(rdr1) - 0xED, 0x38, 0x05, //l1:in0 a,(stat1) - 0xE6, 0x02, // and 02h - 0x28, 0xF9, // jr z,l1 - 0xED, 0x01, 0x07, // out0 (tdr1),b - 0x18, 0xEA, // jr l0 -}; - -const __flash uint8_t test1[] = { - 0xAF, // xor a - 0xED, 0x39, 0x36, // out0 (rcr),a ;disable DRAM refresh - 0x3E, 0x30, // ld a,030h - 0xED, 0x39, 0x32, // out0 (dcntl),a ;0 mem, max i/0 wait states - 0x21, 0x1E, 0x00, // ld hl,dmclrt ;load DMA registers - 0x06, 0x08, // ld b,dmct_e-dmclrt - 0x0E, 0x20, // ld c,sar0l - 0xED, 0x93, // otimr - 0x3E, 0xC3, // ld a,0c3h ;dst +1, src +1, burst - 0xED, 0x39, 0x31, // out0 (dmode),a ; - 0x3E, 0x62, // ld a,062h ;enable dma0, - 0xED, 0x39, 0x30, //cl_1: out0 (dstat),a ;copy 64k - 0x18, 0xFB, // jr cl_1 ; - 0x00, 0x00, //dmclrt: dw 0 ;src (inc) - 0x00, // db 0 ;src - 0x00, 0x00, // dw 0 ;dst (inc), - 0x00, // db 0 ;dst - 0x00, 0x00, // dw 0 ;count (64k) -}; - - -int main(void) -{ - int_fast8_t state = 0; - int ch; - - setup_avr(); - serial_setup(); - setup_rtc(); - sei(); - - printf_P(PSTR("\n(ATMEGA1281+HD64180)_stamp Tester\n")); - - DBG_P(1, "z80_setup_bus... "); - z80_setup_msg_fifo(); - z80_setup_bus(); - DBG_P(1, "done.\n"); - - DBG_P(1, "Get bus... "); -/* Now done via S_Z180_RUNNING - z80_busreq(LOW); - z80_reset(HIGH); -*/ - z80_request_bus(); - DBG_P(1, "got it!\n"); - -// z80_sram_fill(0, (uint32_t)512 * 1024, 0x00, 3); -// z80_sram_cmp(0, (uint32_t)512 * 1024, 0x00, 3); -// z80_dump_mem(0, 0x400); - - z80_memset(0, 0x76, 0x80000); -// z80_memset(0, 0x00, 0x80000); -// z80_write_block(test1, 0, sizeof(test1)); - -// z80_dump_mem(0, 0x100); - -// z80_sram_cmp(0, (uint32_t)512 * 1024, 0x76, 0); - - z80_load_mem(); -// z80_write(0, 0x76); -// z80_dump_mem(0, 0x200); - - -/* Now done via S_Z180_RUNNING - z80_reset(LOW); -*/ - z80_release_bus(); - DBG_P(1, "Bus released!\n"); - z80_reset(HIGH); - DBG_P(1, "Reset released!\n"); - - to_counter = 200; - - while (1) { - - if (Stat & S_10MS_TO) { - Stat &= ~S_10MS_TO; - do_10ms(); - } - - - if ((ch = serial_getc()) >= 0) { - switch (state) { - case 0: - if (ch == ESCCHAR) { - state = 1; - /* TODO: Timer starten */ - } else { -// z80_memfifo_putc(fifo_out, ch); - serial_putc(ch); - if (ch == '\r') - serial_putc('\n'); - } - break; - case 1: - switch (ch) { - - case 'r': - z80_reset_pulse(); - break; - - case 'b': - z80_request_bus(); - z80_dump_mem(0, 0x2d20); - z80_release_bus(); - break; - - case 'e': - z80_request_bus(); - z80_dump_mem(0x80000-0x4000, 0x800); - z80_dump_mem(0x80000-0x200, 0x200); - z80_release_bus(); - break; - - case ESCCHAR: - default: -// z80_memfifo_putc(fifo_out, ch); - serial_putc(ch); - if (ch == '\r') - serial_putc('\n'); - } - state = 0; - break; - } - } - -// check_msg_fifo(); - } - - return 0; -} diff --git a/avr/z80-if.c b/avr/z80-if.c index cc0bab1..21ffeac 100644 --- a/avr/z80-if.c +++ b/avr/z80-if.c @@ -1,3 +1,9 @@ +/* + * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + /** * * Pin assignments @@ -50,7 +56,6 @@ * | | P | | af1 OSC32 | * | | P | | af1 OSC32 | - */ @@ -555,10 +560,9 @@ void z80_memfifo_init(const fifo_t f, uint32_t addr) { fifo_dsc[f].base = addr; - if (addr != 0) { - DBG_P(2, "z80_memfifo_init: %i, %lx\n", f, addr); + if (addr != 0) { z80_bus_cmd(Request); fifo_dsc[f].mask = z80_read(addr + FIFO_BUFSIZE_MASK); fifo_dsc[f].idx_in = z80_read(addr + FIFO_INDEX_IN); @@ -588,7 +592,7 @@ int z80_memfifo_is_empty(const fifo_t f) int z80_memfifo_is_full(const fifo_t f) { - int rc = 1; + int rc = 0; if (fifo_dsc[f].base != 0) { z80_bus_cmd(Request); |