]> cloudbase.mooo.com Git - z180-stamp.git/commitdiff
Merge branch 'fatfs-integration' into fatcommands fatcommands
authorLeo C <erbl259-lmu@yahoo.de>
Mon, 28 May 2018 11:07:24 +0000 (13:07 +0200)
committerLeo C <erbl259-lmu@yahoo.de>
Mon, 28 May 2018 11:07:24 +0000 (13:07 +0200)
# Conflicts:
# include/avr/ffconf.h

43 files changed:
.gitignore
avr/Tupfile
avr/cli.c
avr/cmd_attach.c
avr/cmd_boot.c
avr/cmd_date.c
avr/cmd_fat.c
avr/cmd_gpio.c
avr/cmd_help.c [deleted file]
avr/cmd_loadcpm3.c
avr/cmd_loadihex.c
avr/cmd_mem.c
avr/cmd_misc.c
avr/cmd_run.c
avr/cmd_sd.c
avr/command.c
avr/command_tbl.c
avr/con-utils.c
avr/debug.c
avr/env.c
avr/eval_arg.c
avr/main.c
avr/xmalloc.c [deleted file]
include/avr/ffconf.h
include/cli.h
include/cmd_attach.h [new file with mode: 0644]
include/cmd_boot.h [new file with mode: 0644]
include/cmd_date.h [new file with mode: 0644]
include/cmd_fat.h [new file with mode: 0644]
include/cmd_gpio.h [new file with mode: 0644]
include/cmd_loadcpm3.h [new file with mode: 0644]
include/cmd_loadihex.h [new file with mode: 0644]
include/cmd_mem.h
include/cmd_misc.h [new file with mode: 0644]
include/cmd_run.h [new file with mode: 0644]
include/cmd_sd.h [new file with mode: 0644]
include/command.h
include/common.h
include/con-utils.h
include/config.h
include/debug.h
include/env.h
include/xmalloc.h [deleted file]

index c2675365965858acce0072cdfb0c163904439233..55e046a64d44f98e1e999d78cf4406d1270917b3 100644 (file)
@@ -4,3 +4,5 @@
 /.tup
 /build-*
 /scratch
+*.o
+
index 05e7e69db6694c25eec355a668283b3c02ab4ac6..5e1f305229e38fddaa4c5a222a3b6e43a7ddbe21 100644 (file)
@@ -7,11 +7,10 @@ FATFS = $(FATFSD)/ff.c $(FATFSD)/ffunicode.c
 
 SRC            = main.c
 SRC            += cli.c cli_readline.c command.c command_tbl.c
-SRC            += cmd_help.c cmd_run.c cmd_boot.c cmd_misc.c
+SRC            += cmd_run.c cmd_boot.c cmd_misc.c
 SRC            += cmd_date.c cmd_mem.c cmd_gpio.c cmd_attach.c
 SRC            += cmd_loadihex.c cmd_loadcpm3.c cmd_sd.c cmd_fat.c
-SRC            += env.c xmalloc.c con-utils.c print-utils.c
-SRC            += getopt-min.c eval_arg.c
+SRC            += env.c con-utils.c print-utils.c getopt-min.c eval_arg.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            += $(FATFS)
@@ -69,7 +68,7 @@ endif
 
 CFLAGS = -g -Os
 CFLAGS += -mmcu=$(MCU_TARGET)
-CFLAGS += -std=gnu99
+CFLAGS += -std=gnu11
 CFLAGS += -Wall -Wextra
 CFLAGS += -Wredundant-decls
 CFLAGS += -mrelax
@@ -97,6 +96,7 @@ ASFLAGS += -mmcu=$(MCU_TARGET) -x assembler-with-cpp $(ASFLAGS)
 # Linker flags
 LDFLAGS        += -Wl,--gc-sections
 LDFLAGS        += -Wl,--cref
+#LDFLAGS += -flto -Os
 
 # Assemble: create object files from assembler source files.
 #.S.o:
index 922f9e1971ee7087ada1d0ab67488f358629e4ba..b96ca1bcf9ba8dfc247a47724307967283977ad8 100644 (file)
--- a/avr/cli.c
+++ b/avr/cli.c
  */
 
 #include "cli.h"
-#include "common.h"
-
-#include <string.h>
+#include "command.h"
 #include <ctype.h>
-#include <stdlib.h>
-#include <stdio.h>
 
 #include "config.h"
-#include "command.h"
-#include "xmalloc.h"
 #include "debug.h"
 #include "env.h"
 #include "cli_readline.h"
@@ -156,7 +150,12 @@ char *process_macros(char *input, char *output)
                        outp = output;
                } else {
                        int outputlen = outp - output;
-                       outp = xrealloc(output, outputlen);
+                       outp = realloc(output, outputlen);
+                       if (outp == NULL) {
+                               free(output);
+                               output = outp;
+                               break;
+                       }
                        output = outp;
                }
 
@@ -237,7 +236,7 @@ char *process_macros(char *input, char *output)
  * @returns
  *
  */
-static int cli_run_command(const char *cmd, int flag)
+static int cli_run_command(const char *cmd, uint_fast8_t flag)
 {
        char *cmdbuf;                   /* working copy of cmd          */
        char *token;                    /* start of token in cmdbuf     */
@@ -315,6 +314,10 @@ static int cli_run_command(const char *cmd, int flag)
 
                /* find macros in this token and replace them */
                finaltoken = process_macros(token, finaltoken);
+               if (finaltoken == NULL) {
+                       rc = -1;        /* no command at all */
+                       break;
+               }
 
                /* Extract arguments */
                argc = cli_parse_line(finaltoken, argv);
@@ -362,7 +365,7 @@ static int cli_run_command_list(const char *cmd)
  * @param flag Execution flags (CMD_FLAG_...)
  * @return 0 on success, or != 0 on error.
  */
-int run_command(const char *cmd, int flag)
+int run_command(const char *cmd, uint_fast8_t flag)
 {
        /*
         * cli_run_command can return 0 or 1 for success, so clean up
@@ -381,7 +384,7 @@ int run_command(const char *cmd, int flag)
  * @param flag Execution flags (CMD_FLAG_...)
  * @return 0 (not repeatable) or 1 (repeatable) on success, -1 on error.
  */
-static int run_command_repeatable(const char *cmd, int flag)
+static int run_command_repeatable(const char *cmd, uint_fast8_t flag)
 {
        return cli_run_command(cmd, flag);
 }
@@ -400,7 +403,7 @@ void cli_loop(void)
 {
        char *lastcommand = NULL;
        int len;
-       int flag;
+       uint_fast8_t flag;
        int rc = 1;
 
        for (;;) {
index e9b5ccdc0968186cd8e98cfb42f13b1b858e3cf4..fcc4f4951e02ae07249f4e6104b3253d756c2dbf 100644 (file)
@@ -8,9 +8,7 @@
  * attach channels to devices
  */
 
-#include "common.h"
-#include <string.h>
-#include <stdbool.h>
+#include "cmd_attach.h"
 
 #include "command.h"
 #include "z180-serv.h"
@@ -58,7 +56,7 @@ void printerror(int rc, uint8_t unit, char *fn)
  *
  */
 
-command_ret_t do_attach(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_attach(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        uint8_t unit;
        char *filename = NULL;
index a83968f3ee4be7da08982cb4e406849a31240044..b4aa5c027c8e75f66ec1d68c7ecf4b4f9e499118 100644 (file)
 /*
  * Misc boot support
  */
-#include "common.h"
+#include "cmd_boot.h"
 #include <ctype.h>
 #include <util/atomic.h>
 
-#include "command.h"
 #include "cli_readline.h"      /* console_buffer[] */
 #include "cli.h"                       /* run_command() */
 #include "env.h"
@@ -59,7 +58,7 @@ static void z80_load_mem(int_fast8_t verbosity,
        }
 }
 
-command_ret_t do_loadf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_loadf(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        (void) cmdtp; (void) flag; (void) argc; (void) argv;
 
@@ -112,7 +111,7 @@ void print_vars(char *title)
  *             -v      verbose
  */
 
-command_ret_t do_bootcf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_bootcf(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        struct {
                uint8_t  jr[2];
@@ -274,7 +273,7 @@ command_ret_t do_bootcf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
        return CMD_RET_SUCCESS;
 }
 
-command_ret_t do_busreq_pulse(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_busreq_pulse(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        uint16_t count=1;
 
@@ -296,7 +295,7 @@ command_ret_t do_busreq_pulse(cmd_tbl_t *cmdtp, int flag, int argc, char * const
 }
 
 
-command_ret_t do_go(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_go(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        uint32_t addr;
 
@@ -348,7 +347,7 @@ void reset_cpu(bus_cmd_t mode)
 }
 
 
-command_ret_t do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_reset(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        (void) cmdtp; (void) flag; (void) argc; (void) argv;
 
@@ -358,7 +357,7 @@ command_ret_t do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
        return CMD_RET_SUCCESS;
 }
 
-command_ret_t do_restart(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_restart(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        (void) cmdtp; (void) flag; (void) argc; (void) argv;
 
@@ -383,7 +382,7 @@ void print_con_usage(char esc)
        ), esc + 0x40);
 }
 
-command_ret_t do_console(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_console(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        int ch;
        uint8_t pending;
index 3e2e01680513df316623da108b4112761cf67a29..cbc4a32088ec2996095af7102e148a5be1f04ca1 100644 (file)
@@ -4,17 +4,15 @@
  * (C) Copyright 2001
  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  *
- * SPDX-License-Identifier:    GPL-2.0+
+ * SPDX-License-Identifier:    GPL-2.0
  */
 
 /*
  * RTC, Date & Time support: get and set date & time
  */
-#include "common.h"
-#include <string.h>
+#include "cmd_date.h"
 #include "time.h"
 #include "rtc.h"
-#include "command.h"
 
 
 /*
@@ -125,7 +123,7 @@ int mk_date (const char *datestr, struct tm *tmp)
        return (-1);
 }
 
-command_ret_t do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_date(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        struct tm t;
        char buf[30];
index 20d1da9f01e921c26425c65c6d26d0a69746127b..33d60510b575e84ff95983cef5d78a2ce874d971 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2014,2016 Leo C. <erbl259-lmu@yahoo.de>
+ * (C) Copyright 2014,2016,2018 Leo C. <erbl259-lmu@yahoo.de>
  *
  * SPDX-License-Identifier:    GPL-2.0
  */
@@ -8,11 +8,9 @@
  * FAT filesystem commands
  */
 
-#include "common.h"
-#include <string.h>
-#include <stdbool.h>
+#include "cmd_fat.h"
+#include <util/delay.h>
 
-#include "command.h"
 #include "ff.h"
 #include "z80-if.h"
 #include "eval_arg.h"
 #include "time.h"
 #include "timer.h"
 #include "debug.h"
+#include "env.h"
+#include "getopt-min.h"
 
-/* TODO: use memory size test function (cmd_mem.c) */
-#define MAX_MEMORY     (1ul << 19)
+
+#define DEBUG_CP               1       /* set to 1 to debug */
+#define DEBUG_LS               1       /* set to 1 to debug */
+#define DEBUG_RM               1       /* set to 1 to debug */
+#define DEBUG_FA               1       /* set to 1 to debug */
+
+#define debug_cp(fmt, args...)                                                        \
+       debug_cond(DEBUG_CP, fmt, ##args)
+#define debug_ls(fmt, args...)                                                        \
+       debug_cond(DEBUG_LS, fmt, ##args)
+#define debug_rm(fmt, args...)                                                        \
+       debug_cond(DEBUG_RM, fmt, ##args)
+#define debug_fa(fmt, args...)                                                        \
+       debug_cond(DEBUG_FA, fmt, ##args)
+
+
+
+/* TODO: use memory size test function (detect_ramsize() in cmd_loadihex.c) */
+/* TODO: detect_ramsize() should be moved to z80-if.c */
+#define MAX_MEMORY     CONFIG_SYS_RAMSIZE_MAX
 #define BUFFER_SIZE    512
+#define MAX_PATHLEN CONFIG_SYS_MAX_PATHLEN
+
+
+typedef struct {
+       char *p_end;                    /* pointer to NULL at end of path */
+       char p_path[MAX_PATHLEN + 1];   /* pointer to the start of a path */
+} PATH_T;
+
+/*
+ * Multible (fat) partitions per physical drive are not supported,
+ * but we have up to 2 sdcard slots.
+ */
+FATFS FatFs0;
+FATFS FatFs1;
+
+uint8_t *blockbuf;
+int blockbuf_size;
+PATH_T from;
+PATH_T to;
+command_ret_t command_ret;
+char *cmdname;
+
+static uint8_t flags;
+#define F_FLAG (1<<3)  // overwrite existing file ignoring write protection
+#define I_FLAG (1<<1)  // prompt before overwrite (overrides a previous -n option)
+#define N_FLAG (1<<2)  // do not overwrite an existing file (overrides a previous -i option)
+#define P_FLAG (1<<4)  // preserve attributes and timestamps
+#define R_FLAG (1<<0)  // copy directories recursively
+#define V_FLAG (1<<5)  // explain what is being done
+
+
 
+void setup_fatfs(void)
+{
+       f_mount(&FatFs0, "0:", 0);
+       f_mount(&FatFs1, "1:", 0);
+}
 
 DWORD get_fattime (void)
 {
@@ -50,6 +104,29 @@ static bool check_abort(void)
 }
 
 
+static const FLASH char * const FLASH rc_strings[] = {
+                       FSTR("OK"),
+                       FSTR("disk error"),
+                       FSTR("internal error"),
+                       FSTR("not ready"),
+                       FSTR("no file"),
+                       FSTR("no path"),
+                       FSTR("invalid name"),
+                       FSTR("denied"),
+                       FSTR("exist"),
+                       FSTR("invalid object"),
+                       FSTR("write protected"),
+                       FSTR("invalid drive"),
+                       FSTR("not enabled"),
+                       FSTR("no file system"),
+                       FSTR("mkfs aborted"),
+                       FSTR("timeout"),
+                       FSTR("locked"),
+                       FSTR("not enough core"),
+                       FSTR("too many open files"),
+                       FSTR("invalid parameter")
+               };
+
 static const FLASH char * const FLASH rc_names[] = {
                        FSTR("OK"),
                        FSTR("DISK_ERR"),
@@ -86,6 +163,217 @@ void put_rc (FRESULT rc)
 #endif
 }
 
+const FLASH char * rctostr(FRESULT rc)
+{
+       return  rc < ARRAY_SIZE(rc_strings) ? rc_strings[rc] : PSTR(" Unknown Error");
+}
+
+void err(const char *fmt, ...)
+{
+       va_list ap;
+       va_start(ap, fmt);
+       printf_P(PSTR("fat %s: "), cmdname);
+       vfprintf_P(stdout, fmt, ap);
+       va_end(ap);
+       printf_P(PSTR("\n"));
+       _delay_ms(20);
+       command_ret = CMD_RET_FAILURE;
+}
+
+/******************************************************************************/
+
+/*
+ * These functions manipulate paths in PATH_T structures.
+ *
+ * They eliminate multiple slashes in paths when they notice them,
+ * and keep the path non-slash terminated.
+ *
+ * Both path_set() and path_append() return 0 if the requested name
+ * would be too long.
+ */
+
+
+static void path_init(void)
+{
+       from.p_path[0] = '\0'; from.p_end = from.p_path;
+       to.p_path[0] = '\0';   to.p_end = to.p_path;
+}
+
+static char *path_skip_heading(char *p)
+{
+       if ((p[0] & 0x38) == '0' &&  p[1] == ':') {
+               p += 2;
+       } else {
+               char *q = p;
+               if (*q++ == '.') {
+                       if (*q == '.')
+                               ++q;
+                       if (*q == '\0' || *q == '/')
+                               p = q;
+               }
+               return p;
+       }
+       if (*p == '/')
+               ++p;
+
+       return p;
+}
+
+static void strip_trailing_slash(PATH_T *p)
+{
+       char *beg = path_skip_heading(p->p_path);
+       char *end = p->p_end;
+
+       while (end > beg && end[-1] == '/')
+               *--end = '\0';
+
+       p->p_end =end;
+}
+
+/*
+ * Move specified string into path.  Convert "" to "." to handle BSD
+ * semantics for a null path.  Strip trailing slashes.
+ */
+int
+path_set(PATH_T *p, char *string)
+{
+       if (strlen(string) > MAX_PATHLEN) {
+               err(PSTR("set: '%s': name too long"), string);
+               return 0;
+       }
+
+       (void)strcpy(p->p_path, string);
+       p->p_end = p->p_path + strlen(p->p_path);
+
+       if (p->p_path == p->p_end) {
+               *p->p_end++ = '.';
+               *p->p_end = '\0';
+       }
+
+       strip_trailing_slash(p);
+       return 1;
+}
+
+/*
+ * Append specified string to path, inserting '/' if necessary.  Return a
+ * pointer to the old end of path for restoration.
+ */
+char *
+path_append(PATH_T *p, char *name)
+{
+       char *old = p->p_end;
+       int len = strlen(name);
+
+       /* The "+ 1" accounts for the '/' between old path and name. */
+       if ((len + p->p_end - p->p_path + 1) > MAX_PATHLEN) {
+               err(PSTR("append: '%s/%s': name too long"), p->p_path, name);
+               return NULL;
+       }
+
+       /*
+        * This code should always be executed, since paths shouldn't
+        * end in '/'.
+        */
+       if (p->p_end[-1] != '/') {
+               *p->p_end++ = '/';
+               *p->p_end = '\0';
+       }
+
+       strncat(p->p_end, name, len);
+       p->p_end += len;
+       *p->p_end = '\0';
+
+       strip_trailing_slash(p);
+       return old;
+}
+
+/*
+ * Restore path to previous value.  (As returned by path_append.)
+ */
+void
+path_restore(PATH_T *p, char *old)
+{
+       p->p_end = old;
+       *p->p_end = '\0';
+}
+
+/*
+ * Return basename of path.
+ */
+char *path_basename(PATH_T *p)
+{
+       char *basename = strrchr(p->p_path, '/');
+
+       if (basename) {
+               ++basename;
+       } else {
+               basename = p->p_path;
+               if ((basename[0] & 0x38) == '0' &&  basename[1] == ':')
+                       basename += 2;
+       }
+
+       return basename;
+}
+
+#if 0
+char *path_basename_pattern(PATH_T *p)
+{
+       char *pattern = path_basename(p);
+       if (strpbrk_P(pattern, PSTR("*?"))) {
+               memmove(pattern+1, pattern, strlen(pattern)+1);
+               *pattern++ = '\0';
+       } else {
+               //p->p_pattern = p->p_end + 1;
+               pattern = p->p_end + 1;
+               pattern[0] = '*';
+               pattern[1] = '\0';
+       }
+       return pattern;
+}
+#endif
+
+/*
+ * Split path
+ * Return basename/pattern of path.
+ */
+
+char *path_split_pattern(PATH_T *p)
+{
+       char *pp = path_skip_heading(p->p_path);
+       char *pattern = strrchr(pp, '/');
+
+       if (pattern == NULL) {
+               pattern = pp;
+               p->p_end = pattern;
+       } else {
+               p->p_end = pattern;
+               pattern++;
+       }
+       memmove(pattern+2, pattern, strlen(pattern)+1);
+       pattern += 2;
+       *p->p_end = '\0' ;
+
+       return pattern;
+}
+
+void path_fix(PATH_T *p)
+{
+       char *pp = path_skip_heading(p->p_path);
+
+       if (pp != p->p_end) {
+               *p->p_end++ = '/';
+               *p->p_end = '\0' ;
+       }
+}
+
+void path_unfix(PATH_T *p)
+{
+       char *pp = path_skip_heading(p->p_path);
+
+       if (pp != p->p_end) {
+               *--p->p_end = '\0' ;
+       }
+}
 
 static void swirl(void)
 {
@@ -100,7 +388,744 @@ static void swirl(void)
        }
 }
 
-/* Work register for fs command */
+/*
+ * pwd - Print current directory of the current drive.
+ *
+ */
+command_ret_t do_pwd(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED)
+{
+       FRESULT res;
+
+       cmdname = argv[0];
+       command_ret = CMD_RET_SUCCESS;
+
+       res = f_getcwd(from.p_path, MAX_PATHLEN);  /* Get current directory path */
+
+       if (res == FR_OK)
+               puts(from.p_path);
+       else
+               err(PSTR("Error: %S"), rctostr(res));
+
+       return command_ret;
+}
+
+
+/*
+ * cd - Change the current/working directory.
+ *
+ */
+command_ret_t do_cd(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, char * const argv[])
+{
+       char *arg;
+       FRESULT res = FR_OK;
+
+       cmdname = argv[0];
+       command_ret = CMD_RET_SUCCESS;
+
+       if (argc < 2) {
+               arg = getenv_str(PSTR(ENV_HOME));
+               if (arg == NULL) {
+                       err(PSTR("'%S' is not set"), PSTR(ENV_HOME));
+                       return command_ret;
+               }
+       } else
+               arg = argv[1];
+
+       if (arg[1] == ':')
+               res = f_chdrive(arg);
+       if (res == FR_OK)
+               res = f_chdir(arg);
+       if (res != FR_OK)
+               err(PSTR("'%s': %S"), arg, rctostr(res));
+
+       return command_ret;
+}
+
+
+static int decode_arg(const char *arg)
+{
+       BYTE attr = 0;
+       char c;
+
+       while ((c = *++arg) != '\0') {
+               switch (c) {
+                       case 'a':
+                               attr |= AM_ARC;         /* Archive   */
+                               break;
+                       case 'h':
+                               attr |= AM_HID;         /* Hidden    */
+                               break;
+                       case 'r':
+                               attr |= AM_RDO;         /* Read only */
+                               break;
+                       case 's':
+                               attr |= AM_SYS;         /* System    */
+                               break;
+                       default:
+                               err(PSTR("unknown attribute: '%c'"), c);
+                               return -1;
+               }
+       }
+       return attr;
+}
+
+static void print_attrib(char *path, FILINFO *f)
+{
+       printf_P(PSTR("%c%c%c%c%c %s%s\n"),
+                               (f->fattrib & AM_DIR) ? 'D' : '-',
+                               (f->fattrib & AM_RDO) ? 'R' : '-',
+                               (f->fattrib & AM_HID) ? 'H' : '-',
+                               (f->fattrib & AM_SYS) ? 'S' : '-',
+                               (f->fattrib & AM_ARC) ? 'A' : '-',
+                               path, f->fname);
+}
+
+command_ret_t do_attrib(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, UNUSED char * const argv[])
+{
+       DIR Dir;                                        /* Directory object */
+       FILINFO Finfo;
+       FRESULT res;
+       BYTE set_mask = 0;
+       BYTE clear_mask = 0;
+
+       cmdname = argv[0];
+       command_ret = CMD_RET_SUCCESS;
+
+
+       for (;;) {
+               int attr;
+               char *arg = *++argv;
+
+               if (!arg)
+                       return CMD_RET_USAGE;
+               if (arg[0] != '-' && arg[0] != '+')
+                       break;
+               attr = decode_arg(arg);
+               if (attr < 0)
+                       return CMD_RET_FAILURE;
+               if (arg[0] == '+')
+                       set_mask |= attr;
+               else
+                       clear_mask |= attr;
+       }
+
+       do {
+               if (!path_set(&from, *argv)) {
+                       /* TODO: error out*/
+               }
+               char *pattern = path_split_pattern(&from);
+               if (*pattern == '\0')
+                       pattern = "*";
+               debug_fa("==== path: '%s', pattern: '%s'\n", from.p_path ? from.p_path : "<NULL>", pattern ? pattern : "<NULL>");
+               res = f_findfirst(&Dir, &Finfo, from.p_path, pattern);
+               debug_fa("==== findfirst %d\n", res);
+               if (res != FR_OK || !Finfo.fname[0]) {
+                       path_fix(&from);
+                       err(PSTR("'%s%s': No such file or directory"), from.p_path, pattern);
+               } else {
+                       do {
+                               if (set_mask | clear_mask) {
+                                       if ((res = f_chmod(Finfo.fname, set_mask, set_mask | clear_mask)) != FR_OK) {
+                                               path_fix(&from);
+                                               err(PSTR("'%s%s': %S"), from.p_path, Finfo.fname, rctostr(res));
+                                               path_unfix(&from);
+                                       }
+                               } else {
+                                       path_fix(&from);
+                                       print_attrib(from.p_path, &Finfo);
+                                       path_unfix(&from);
+                               }
+
+                               res = f_findnext(&Dir, &Finfo);
+                               //debug_fa("==== findnext %d\n", res);
+                       } while (res == FR_OK && Finfo.fname[0]);
+               }
+               f_closedir(&Dir);
+       } while (*++argv);
+
+       return command_ret;
+}
+
+command_ret_t do_rm(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, char * const argv[])
+{
+       DIR Dir;                                        /* Directory object */
+       FILINFO Finfo;
+       FRESULT res;
+
+       cmdname = argv[0];
+       command_ret = CMD_RET_SUCCESS;
+
+       /* reset getopt() */
+       optind = 0;
+       flags = 0;
+
+       int opt;
+       while ((opt = getopt(argc, argv, PSTR("nv"))) != -1) {
+               switch (opt) {
+                       case 'n':
+                               flags |=  N_FLAG;
+                               break;
+                       case 'v':
+                               flags |=  V_FLAG;
+                               break;
+                       default:
+                               return CMD_RET_USAGE;
+                               break;
+               }
+       }
+       argc -= optind;
+       argv += optind;
+
+       if (argc < 1) {
+               err(PSTR("missing operand"));
+       } else {
+               for (int i = 0; i < argc; i++) {
+                       if (!path_set(&from, argv[i])) {
+                               /* TODO: error out*/
+                       }
+                       char *pattern = path_split_pattern(&from);
+
+                       debug_rm("==== path: '%s', pattern: '%s'\n", from.p_path ? from.p_path : "<NULL>", pattern ? pattern : "<NULL>");
+
+                       res = f_findfirst(&Dir, &Finfo, from.p_path, pattern);
+                       debug_rm("==== findfirst %d\n", res);
+
+                       if (res != FR_OK || !Finfo.fname[0]) {
+                               path_fix(&from);
+                               err(PSTR("cannot remove '%s%s': No such file or directory"), from.p_path, pattern);
+                       } else {
+                               do {
+                                       if (Finfo.fattrib & AM_DIR) {
+                                               path_fix(&from);
+                                               err(PSTR("cannot remove '%s%s': Is a directory"), from.p_path, Finfo.fname);
+                                       } else {
+                                               if (!(flags & N_FLAG)) {
+                                                       if ((res = f_unlink(Finfo.fname)) == FR_OK) {
+                                                               if (flags & V_FLAG)
+                                                                       path_fix(&from);
+                                                                       printf_P(PSTR("removed '%s%s'\n"), from.p_path, Finfo.fname);
+                                                                       path_unfix(&from);
+                                                       } else {
+                                                               path_fix(&from);
+                                                               err(PSTR("cannot remove '%s%s': %S"), from.p_path, Finfo.fname, rctostr(res));
+                                                       }
+                                               } else {
+                                                       path_fix(&from);
+                                                       printf_P(PSTR("not removed '%s%s'\n"), from.p_path, Finfo.fname);
+                                                       path_unfix(&from);
+                                               }
+                                       }
+                                       res = f_findnext(&Dir, &Finfo);
+                                       //debug_rm("==== findnext %d\n", res);
+                               } while (res == FR_OK && Finfo.fname[0]);
+                       }
+                       f_closedir(&Dir);
+               }
+
+               /* TODO */
+               if (res) {
+                       put_rc(res);
+                       return CMD_RET_FAILURE;
+               }
+       }
+       return command_ret;
+}
+
+command_ret_t do_rmdir(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, char * const argv[])
+{
+       cmdname = argv[0];
+       command_ret = CMD_RET_SUCCESS;
+
+       return command_ret;
+}
+
+command_ret_t do_mkdir(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, char * const argv[])
+{
+       cmdname = argv[0];
+       command_ret = CMD_RET_SUCCESS;
+
+       return command_ret;
+}
+
+
+static void print_dirent(FILINFO *f)
+{
+       printf_P(PSTR("%c%c%c%c%c %u/%02u/%02u %02u:%02u %9lu  %s\n"),
+                               (f->fattrib & AM_DIR) ? 'D' : '-',
+                               (f->fattrib & AM_RDO) ? 'R' : '-',
+                               (f->fattrib & AM_HID) ? 'H' : '-',
+                               (f->fattrib & AM_SYS) ? 'S' : '-',
+                               (f->fattrib & AM_ARC) ? 'A' : '-',
+                               (f->fdate >> 9) + 1980, (f->fdate >> 5) & 15, f->fdate & 31,
+                               (f->ftime >> 11), (f->ftime >> 5) & 63,
+                               f->fsize, f->fname);
+}
+
+/*
+ * ls path - Directory listing
+ *
+ */
+command_ret_t do_ls(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, char * const argv[])
+{
+       FATFS *fs;
+       DIR Dir;                                        /* Directory object */
+       FILINFO Finfo;
+       unsigned long p1;
+       unsigned int s1, s2;
+       FRESULT res;
+
+       cmdname = argv[0];
+       command_ret = CMD_RET_SUCCESS;
+
+       path_init();
+       if (argc > 1)
+               if (!path_set(&from, argv[1])) {
+                       /* TODO: error out*/
+               }
+
+#if 0
+       char *pattern = path_basename_pattern(&from);
+#else
+       char *pattern = path_split_pattern(&from);
+       if (*pattern == '\0')
+               pattern = "*";
+#endif
+       debug_ls("==== path: '%s', pattern: '%s'\n", from.p_path ? from.p_path : "<NULL>", pattern ? pattern : "<NULL>");
+
+       p1 = s1 = s2 = 0;
+       res = f_findfirst(&Dir, &Finfo, from.p_path, pattern);  /* Start to search for files */
+       if (res != FR_OK || !Finfo.fname[0]) {
+               path_fix(&from);
+               err(PSTR("'%s%s': No such file or directory"), from.p_path, pattern);
+       } else {
+               do {
+                       if (Finfo.fattrib & AM_DIR) {
+                               s2++;
+                       } else {
+                               s1++; p1 += Finfo.fsize;
+                       }
+                       print_dirent(&Finfo);
+                       if (check_abort())
+                               break;
+                       res = f_findnext(&Dir, &Finfo);
+               } while (res == FR_OK && Finfo.fname[0]);
+       }
+       f_closedir(&Dir);
+
+       if (res == FR_OK && command_ret == CMD_RET_SUCCESS) {
+               printf_P(PSTR("%4u File(s),%10lu bytes total\n%4u Dir(s)"), s1, p1, s2);
+               if (f_getfree(from.p_path, (DWORD*)&p1, &fs) == FR_OK)
+                       printf_P(PSTR(", %10luK bytes free\n"), p1 * fs->csize / 2);
+       }
+
+       if (res && command_ret == CMD_RET_SUCCESS) {
+               put_rc(res);
+               return CMD_RET_FAILURE;
+       }
+
+       return command_ret;
+}
+
+/*
+ * tst path - for debugging: test access with different functions
+ *
+ */
+command_ret_t do_tst(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, char * const argv[])
+{
+       DIR Dir;                                        /* Directory object */
+       FILINFO Finfo;
+       FRESULT res = FR_OK;
+       char *path = "";
+       char *pattern = "*";
+
+       printf_P(PSTR("sizeof DIR: %u, sizeof FIL: %u\n"), sizeof (DIR), sizeof (FILINFO));
+
+       char * buf = (char *) malloc(BUFFER_SIZE);
+       if (buf == NULL) {
+               printf_P(PSTR("tst: Out of Memory!\n"));
+               return CMD_RET_FAILURE;
+       }
+       res = f_getcwd(buf, BUFFER_SIZE);  /* Get current directory path */
+
+       if (!res) {
+               printf_P(PSTR("cwd: '%s'\n"), buf);
+       }
+       free(buf);
+       if (res) {
+               put_rc(res);
+               return CMD_RET_FAILURE;
+       }
+
+       if (argc > 1)
+               path = argv[1];
+       if (argc > 2)
+               pattern = argv[2];
+
+       printf_P(PSTR("arg: '%s' '%s'\n"), path, pattern);
+       printf_P(PSTR("==== f_stat:      "));
+       res = f_stat(path, &Finfo);
+       put_rc(res);
+       if (res == FR_OK) {
+               print_dirent(&Finfo);
+       }
+
+       printf_P(PSTR("==== f_findfirst: "));
+       res = f_findfirst(&Dir, &Finfo, path, pattern);  /* Start to search for files */
+       put_rc(res);
+       if (res == FR_OK) {
+               print_dirent(&Finfo);
+       }
+       f_closedir(&Dir);
+
+       printf_P(PSTR("==== f_opendir:   "));
+       res = f_opendir(&Dir, path);
+       put_rc(res);
+       f_closedir(&Dir);
+
+       return CMD_RET_SUCCESS;
+}
+
+/******************************************************************************/
+
+static void
+setfile(FILINFO *fs)
+{
+       FRESULT fr;
+
+       fr = f_utime(to.p_path, fs);
+       if (fr != FR_OK)
+               err(PSTR("f_utime: %s: %S"), to.p_path, rctostr(fr));
+       fr = f_chmod(to.p_path, fs->fattrib, AM_RDO|AM_ARC|AM_SYS|AM_HID);
+       if (fr != FR_OK)
+               err(PSTR("f_chmod: %s: %S"), to.p_path, rctostr(fr));
+
+}
+
+void copy_file(FILINFO *fs, uint_fast8_t dne)
+{
+       FIL from_fd, to_fd;
+       UINT rcount, wcount;
+       FRESULT fr;
+       BYTE open_mode;
+
+       if (blockbuf == NULL) {
+               blockbuf_size = get_freemem() / 512 * 512;
+               if (blockbuf_size != 0)
+                       blockbuf = (uint8_t *) malloc(blockbuf_size);
+               if (blockbuf == NULL) {
+                       err(PSTR("Not enough memory!\n"));
+                       return;
+               }
+       }
+
+debug_cp("==== copy_file(): dne: %u, blockbuf_size: %d, freemem: %u\n", dne, blockbuf_size, get_freemem());
+debug_cp("     from:'%s'  to:'%s'\n", from.p_path, to.p_path);
+
+
+       if ((fr = f_open(&from_fd, from.p_path, FA_READ)) != FR_OK) {
+               err(PSTR("%s: %S"), from.p_path, rctostr(fr));
+               return;
+       }
+
+       /*
+        * If the file exists and we're interactive, verify with the user.
+        */
+       if (!dne) {
+               if (flags & N_FLAG) {
+                       if (flags & V_FLAG)
+                               printf_P(PSTR("%s not overwritten\n"), to.p_path);
+                       f_close(&from_fd);
+                       return;
+               } if (flags & I_FLAG) {
+                       printf_P(PSTR("overwrite '%s'? "), to.p_path);
+                       if (!confirm_yes()) {
+                               f_close(&from_fd);
+                               return;
+                       }
+               }
+               if (flags & F_FLAG) {
+                       /* Remove existing destination file name create a new file. */
+                       f_chmod(to.p_path,0, AM_RDO);
+                       f_unlink(to.p_path);
+                       open_mode = FA_WRITE|FA_CREATE_NEW;
+               } else {
+                       /* Overwrite existing destination file name. */
+                       open_mode = FA_WRITE|FA_CREATE_ALWAYS;
+               }
+       } else {
+               open_mode = FA_WRITE|FA_CREATE_NEW;
+       }
+       fr = f_open(&to_fd, to.p_path, open_mode);
+
+       if (fr != FR_OK) {
+               err(PSTR("%s: %S"), to.p_path, rctostr(fr));
+               f_close(&from_fd);
+               return;
+       }
+
+       while ((fr = f_read(&from_fd, blockbuf, blockbuf_size, &rcount)) == FR_OK &&
+                                                                                       rcount > 0) {
+               fr = f_write(&to_fd, blockbuf, rcount, &wcount);
+               if (fr || wcount < rcount) {
+                       err(PSTR("%s: %S"), to.p_path, rctostr(fr));
+                       break;
+               }
+       }
+       if (fr != FR_OK)
+               err(PSTR("%s: S"), from.p_path, rctostr(fr));
+
+       f_close(&from_fd);
+       if ((fr = f_close(&to_fd)) != FR_OK)
+               err(PSTR("%s: %S"), to.p_path, rctostr(fr));
+
+       if (flags & P_FLAG)
+               setfile(fs);
+}
+
+static void copy();
+
+static void copy_dir(void)
+{
+       DIR Dir;                                        /* Directory object */
+       FILINFO Finfo;
+       char *old_from, *old_to;
+       FRESULT res;
+       char *pattern = {"*"};
+
+debug_cp("==== copy_dir(): freemem: %u\n", get_freemem());
+debug_cp("     from:'%s'  to:'%s'\n", from.p_path, to.p_path);
+
+#if 0
+
+       printf_P(PSTR("directory copy not supported, ommitting dir '%s'\n"),
+               from->p_path);
+       command_ret = CMD_RET_FAILURE;
+
+#else
+
+       for (res = f_findfirst(&Dir, &Finfo, from.p_path, pattern);
+                res == FR_OK && Finfo.fname[0];
+                res = f_findnext(&Dir, &Finfo)) {
+
+               if (!(Finfo.fattrib & AM_DIR) &&
+                               (old_from = path_append(&from, Finfo.fname))) {
+                       if ((old_to = path_append(&to, Finfo.fname))) {
+                               copy();
+                               path_restore(&to, old_to);
+                       }
+                       path_restore(&from, old_from);
+               }
+       }
+
+       for (res = f_findfirst(&Dir, &Finfo, from.p_path, pattern);
+                res == FR_OK && Finfo.fname[0];
+                res = f_findnext(&Dir, &Finfo)) {
+
+               if ((Finfo.fattrib & AM_DIR) &&
+                               (old_from = path_append(&from, Finfo.fname))) {
+                       if ((old_to = path_append(&to, Finfo.fname))) {
+                               copy();
+                               path_restore(&to, old_to);
+                       }
+                       path_restore(&from, old_from);
+               }
+       }
+}
+#endif
+
+/*
+ * copy file or directory at "from" to "to".
+ */
+static void copy()
+{
+       FILINFO from_stat, to_stat;
+       uint_fast8_t dne;
+       FRESULT fr;
+
+debug_cp("==== copy(); freemem: %u\n", get_freemem());
+debug_cp("     from:'%s'  to:'%s'\n", from.p_path, to.p_path);
+
+       fr = f_stat(from.p_path, &from_stat);
+       if (fr != FR_OK) {
+               err(PSTR("%s: %S"), from.p_path, rctostr(fr));
+               return;
+       }
+
+       /* not an error, but need to remember it happened */
+       if (f_stat(to.p_path, &to_stat) != FR_OK)
+               dne = 1;
+       else {
+               if (strcmp(to.p_path, from.p_path) == 0) {
+                       (void)printf_P(PSTR("%s and %s are identical (not copied).\n"),
+                                       to.p_path, from.p_path);
+                       command_ret = CMD_RET_FAILURE;
+                       return;
+               }
+               dne = 0;
+       }
+
+       if(from_stat.fattrib & AM_DIR) {
+               if (!(flags & R_FLAG)) {
+                       (void)printf_P(PSTR("-r not specified; ommitting dir '%s'\n"),
+                           from.p_path);
+                       command_ret = CMD_RET_FAILURE;
+                       return;
+               }
+               if (dne) {
+                       /*
+                        * If the directory doesn't exist, create the new one.
+                        */
+                       if ((fr = f_mkdir(to.p_path)) != FR_OK) {
+                               err(PSTR("%s: %S"), to.p_path, rctostr(fr));
+                               return;
+                       }
+               } else if (!(to_stat.fattrib & AM_DIR)) {
+                       (void)printf_P(PSTR("%s: not a directory.\n"), to.p_path);
+                       return;
+               }
+               copy_dir();
+               if (flags & P_FLAG)
+                       setfile(&from_stat);
+
+               return;
+       }
+       copy_file(&from_stat, dne);
+}
+
+command_ret_t do_cp(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, char * const argv[])
+{
+
+    FRESULT fr;        /* Return value */
+    //DIR dj;                  /* Directory search object */
+    FILINFO to_stat;    /* File information */
+    char *old_to;
+
+
+       cmdname = argv[0];
+       uint8_t tflags = 0;
+       command_ret = CMD_RET_SUCCESS;
+
+       /* reset getopt() */
+       optind = 0;
+
+       int opt;
+       while ((opt = getopt(argc, argv, PSTR("finprv"))) != -1) {
+               switch (opt) {
+                       case 'f':
+                               tflags &= ~(I_FLAG | N_FLAG);
+                               tflags |=  F_FLAG;
+                               break;
+                       case 'i':
+                               tflags &= ~(F_FLAG | N_FLAG);
+                               tflags |=  I_FLAG;
+                               break;
+                       case 'n':
+                               tflags &= ~(F_FLAG | I_FLAG);
+                               tflags |=  N_FLAG;
+                               break;
+                       case 'p':
+                               tflags |= P_FLAG;
+                               break;
+                       case 'r':
+                               tflags |= R_FLAG;
+                               break;
+                       case 'v':
+                               tflags |= V_FLAG;
+                               break;
+                       default:
+                               return CMD_RET_USAGE;
+                               break;
+               }
+       }
+       flags = tflags;
+       argc -= optind;
+       argv += optind;
+
+       if (argc < 2)
+               return CMD_RET_USAGE;
+
+       path_init();
+
+       /* last argument is destination */
+       if (!path_set(&to, argv[--argc]))
+               goto cleanup;
+
+       /*
+        * Cp has two distinct cases:
+        *
+        * % cp [-rip] source target
+        * % cp [-rip] source1 ... directory
+        *
+        * In both cases, source can be either a file or a directory.
+        *
+        * In (1), the target becomes a copy of the source. That is, if the
+        * source is a file, the target will be a file, and likewise for
+        * directories.
+        *
+        * In (2), the real target is not directory, but "directory/source".
+        */
+
+       fr = f_stat(to.p_path, &to_stat);
+debug_cp("==== main, stat to: fr: %d, attr: %02x, flags:%02x, freemem: %u\n",
+                                               fr, to_stat.fattrib, flags, get_freemem());
+debug_cp("     from:'%s'  to:'%s'\n", from.p_path, to.p_path);
+
+       if (fr != FR_OK && fr != FR_NO_FILE && fr != FR_NO_PATH) {
+               err(PSTR("Test1: %s: %S"), to.p_path, rctostr(fr));
+               command_ret = CMD_RET_FAILURE;
+               goto cleanup;
+       }
+       if (!(fr == FR_OK && (to_stat.fattrib & AM_DIR))) {
+               /*
+                * Case (1).  Target is not a directory.
+                */
+               if (argc > 1) {
+                       err(PSTR("target '%s' is not a directory"), to.p_path);
+                       //command_ret = CMD_RET_USAGE;
+                       goto cleanup;
+               }
+               if (!path_set(&from, *argv)) {
+                       command_ret = CMD_RET_FAILURE;
+                       goto cleanup;
+               }
+               copy();
+       }
+       else {
+               /*
+                * Case (2).  Target is a directory.
+                */
+               for (;; ++argv) {
+                       if (!path_set(&from, *argv))
+                               continue;
+                       if (!(old_to = path_append(&to, path_basename(&from))))
+                               continue;
+                       copy();
+                       if (!--argc)
+                               break;
+                       path_restore(&to, old_to);
+               }
+       }
+
+cleanup:
+       free(blockbuf);
+       blockbuf = NULL;
+       blockbuf_size = 0;
+
+       return command_ret;
+}
+
+#if 0
+               if (flags & V_FLAG)
+                       printf_P((PSTR("%s  %s -> %s\n", badcp ? : "ERR:" : "    ", curr->fts_path, to.p_path)));
+
+#endif
+
+
+/******************************************************************************/
+
+/*
+ * Work register for stat command
+ */
 struct stat_dat_s {
        DWORD AccSize;
        WORD  AccFiles, AccDirs;
@@ -155,24 +1180,24 @@ FRESULT scan_files (
  * fatstat path - Show logical drive status
  *
  */
-command_ret_t do_fat_stat(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_stat(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, char * const argv[])
 {
        FATFS *fs;
        DWORD nfreeclst;
        FRESULT res;
-       char *path;
+       char *buf;
+       char *path = "";
        struct stat_dat_s statp;
 
-       (void) cmdtp; (void) flag; (void) argc;
-
-       path = (char *) malloc(BUFFER_SIZE);
-       if (path == NULL) {
-               printf_P(PSTR("fatstat: Out of Memory!\n"));
-               free(path);
+       buf = (char *) malloc(BUFFER_SIZE);
+       if (buf == NULL) {
+               printf_P(PSTR("fat stat: Out of Memory!\n"));
                return CMD_RET_FAILURE;
        }
 
-       res = f_getfree(argv[1], &nfreeclst, &fs);
+       if (argc > 1)
+               path = argv[1];
+       res = f_getfree(path, &nfreeclst, &fs);
        if (!res) {
                printf_P(PSTR(
                                        "FAT type:                %u\n"
@@ -189,22 +1214,21 @@ command_ret_t do_fat_stat(cmd_tbl_t *cmdtp, int flag, int argc, char * const arg
                                fs->fatbase, fs->dirbase, fs->database);
 
 #if _USE_LABEL
-               TCHAR label[12];
                DWORD serial;
-               res = f_getlabel(argv[1], label, &serial);
+               res = f_getlabel(path, buf, &serial);
                if (!res) {
                        printf_P(PSTR(
                                                "Volume name:             %s\n"
                                                "Volume S/N:              %04X-%04X\n"),
-                                       label, (WORD)(serial >> 16), (WORD)(serial & 0xFFFF));
+                                       buf, (WORD)(serial >> 16), (WORD)(serial & 0xFFFF));
                }
 #endif
                if (!res) {
                        my_puts_P(PSTR("\nCounting...  "));
                        statp.AccSize = statp.AccFiles = statp.AccDirs = 0;
-                       strcpy(path, argv[1]);
+                       strcpy(buf, path);
 
-                       res = scan_files(path, &statp);
+                       res = scan_files(buf, &statp);
                }
                if (!res) {
                        printf_P(PSTR("\r%u files, %lu bytes.\n%u folders.\n"
@@ -215,108 +1239,20 @@ command_ret_t do_fat_stat(cmd_tbl_t *cmdtp, int flag, int argc, char * const arg
                }
        }
 
-       free(path);
-       if (res) {
-               put_rc(res);
-               return CMD_RET_FAILURE;
-       }
-       return CMD_RET_SUCCESS;
-}
-
-
-/*
- * fatls path - Directory listing
- *
- */
-command_ret_t do_fat_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
-       FATFS *fs;
-       DIR Dir;                                        /* Directory object */
-       FILINFO Finfo;
-       unsigned long p1;
-       unsigned int s1, s2;
-       FRESULT res;
-
-       (void) cmdtp; (void) flag; (void) argc;
-
-       res = f_opendir(&Dir, argv[1]);
-       if (res) {
-               put_rc(res);
-               return CMD_RET_FAILURE;
-       }
-
-       p1 = s1 = s2 = 0;
-       for(;;) {
-               res = f_readdir(&Dir, &Finfo);
-               if ((res != FR_OK) || !Finfo.fname[0])
-                       break;
-               if (Finfo.fattrib & AM_DIR) {
-                       s2++;
-               } else {
-                       s1++; p1 += Finfo.fsize;
-               }
-               printf_P(PSTR("%c%c%c%c%c %u/%02u/%02u %02u:%02u %9lu  %s\n"),
-                                       (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);
-               if (check_abort())
-                       break;
-       }
-
-       if (res == FR_OK) {
-               printf_P(PSTR("%4u File(s),%10lu bytes total\n%4u Dir(s)"), s1, p1, s2);
-               if (f_getfree(argv[1], (DWORD*)&p1, &fs) == FR_OK)
-                       printf_P(PSTR(", %10luK bytes free\n"), p1 * fs->csize / 2);
-       }
-
+       free(buf);
        if (res) {
                put_rc(res);
                return CMD_RET_FAILURE;
        }
-
        return CMD_RET_SUCCESS;
 }
 
-static
-FRESULT mkpath(TCHAR *path)
-{
-       /* TODO: */
-       (void) path;
-#if 0
-       FILINFO fd
-       TCHAR *p, *q;
-       FRESULT ret;
-
-       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/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_rw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_rw(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, char * const argv[])
 {
        FIL File;
        uint32_t addr;
@@ -324,14 +1260,12 @@ command_ret_t do_fat_rw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
        unsigned long pos;
        unsigned long bytes_rw;
 
-       bool dowrite = (argv[0][3] == 'w');
+       bool dowrite = (argv[0][0] == 'w');
        FRESULT res = FR_OK;
        bool buserr = 0;
        uint32_t timer;
        uint8_t *buffer;
 
-       (void) cmdtp; (void) flag;
-
        if (argc < (dowrite ? 4 : 3))
                return CMD_RET_USAGE;
 
@@ -359,9 +1293,6 @@ command_ret_t do_fat_rw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
                return CMD_RET_FAILURE;
        }
 
-       if (dowrite) {
-               res = mkpath(argv[1]);
-       }
        if (!res) {
                res = f_open(&File, argv[1], dowrite ? FA_WRITE | FA_CREATE_ALWAYS
                                                                                         : FA_READ );
@@ -434,3 +1365,133 @@ command_ret_t do_fat_rw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
 
        return CMD_RET_SUCCESS;
 }
+
+/*
+ * command table for fat subcommands
+ */
+
+cmd_tbl_t cmd_tbl_fat[] = {
+CMD_TBL_ITEM(
+       stat,   2,      CTBL_RPT,       do_stat,
+       "Show logical drive status",
+       "dev"
+),
+CMD_TBL_ITEM(
+       pwd,    1,      CTBL_RPT,       do_pwd,
+       "Print name of current/working directory",
+       ""
+),
+CMD_TBL_ITEM(
+       attrib, CONFIG_SYS_MAXARGS,     0,                      do_attrib,
+    "Display or change attributes on a FAT filesystem",
+    "[+-ahrs] files...\n"
+    "\n"
+    "    -    Clear attributes\n"
+    "    +    Set attributes\n"
+    "    a    Archive\n"
+    "    h    Hidden\n"
+    "    r    Read only\n"
+    "    s    System\n"
+    "Display only:\n"
+    "    v    Volume label\n"
+    "    d    Directory\n"
+),
+CMD_TBL_ITEM(
+       cd,             2,      0,                      do_cd,
+       "Change the current/working directory.",
+       "path"
+),
+CMD_TBL_ITEM(
+       rm,             CONFIG_SYS_MAXARGS,     0,                      do_rm,
+       "Remove FILE(s)",
+       "[OPTION]... [FILE]...\n"
+       //"    -i prompt before removal\n"
+       "    -v explain what is being done\n"
+       "\n"
+       "rm does not remove directories."
+),
+CMD_TBL_ITEM(
+       rmdir,          CONFIG_SYS_MAXARGS,     0,                      do_rmdir,
+       "Remove the DIRECTORY(ies), if they are empty",
+       "[OPTION]... DIRECTORY..."
+),
+CMD_TBL_ITEM(
+       mkdir,          CONFIG_SYS_MAXARGS,     0,                      do_mkdir,
+       "Create the DIRECTORY(ies), if they do not already exist.",
+       "[OPTION]... DIRECTORY..."
+),
+CMD_TBL_ITEM(
+       ls,             2,      CTBL_RPT,       do_ls,
+       "Directory listing",
+       "path"
+),
+CMD_TBL_ITEM(
+       tst,    3,      CTBL_DBG|CTBL_RPT,      do_tst,
+       "FatFS test function",
+       "path"
+),
+CMD_TBL_ITEM(
+       load,   5,      0,                      do_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"
+       "      to address 'addr' from dos filesystem.\n"
+       "      'pos' gives the file position to start loading from.\n"
+       "      If 'pos' is omitted, 0 is used. 'pos' requires 'bytes'.\n"
+       "      'bytes' gives the size to load. If 'bytes' is 0 or omitted,\n"
+       "      the load stops on end of file."
+),
+CMD_TBL_ITEM(
+       write,  4,      0,                      do_rw,
+       "write file into a dos filesystem",
+       "<d:/path/filename> <addr> <bytes>\n"
+       "    - Write file to 'path/filename' on logical drive 'd' from RAM\n"
+       "      starting at address 'addr'.\n"
+),
+
+CMD_TBL_ITEM(
+       cp,     CONFIG_SYS_MAXARGS,     CTBL_DBG,       do_cp,
+       "copy files",
+       "[-f | -i | -n] [-prv] source_file target_file\n"
+//     "[-f | -i | -n] [-prv] source_file target_file\n"
+//     "cp [-f | -i | -n] [-prv] source_file ... target_dir\n"
+       "    -f overwrite existing file ignoring write protection\n"
+       "       this option is ignored when the -n option is also used\n"
+       "    -i prompt before overwrite (overrides a previous -n option)\n"
+       "    -n do not overwrite an existing file (overrides a previous -i option)\n"
+       "    -p preserve attributes and timestamps\n"
+       "    -r copy directories recursively\n"
+       "    -v explain what is being done\n"
+),
+
+CMD_TBL_ITEM(
+       help,   CONFIG_SYS_MAXARGS,     CTBL_RPT,       do_help,
+       "Print sub command description/usage",
+       "\n"
+       "       - print brief description of all sub commands\n"
+       "fat help command ...\n"
+       "       - print detailed usage of sub cmd 'command'"
+),
+
+/* 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'"),
+#ifdef  CONFIG_SYS_LONGHELP
+       FSTR(""),
+#endif /* CONFIG_SYS_LONGHELP */
+       NULL,
+#ifdef CONFIG_AUTO_COMPLETE
+       NULL,
+#endif
+},
+/* Mark end of table */
+CMD_TBL_END(cmd_tbl_fat)
+};
+
+
+command_ret_t do_fat(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED)
+{
+       puts_P(PSTR("Huch?"));
+
+       return CMD_RET_USAGE;
+}
index 5cc02d0d46bc1d3ebb1bf331f29206fb8ac9a8ac..8f50ca3a2cfd9c59fd2a4bd86e9e93534e0ec599 100644 (file)
@@ -1,15 +1,12 @@
 /*
  * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
  *
- * SPDX-License-Identifier:    GPL-2.0+
+ * SPDX-License-Identifier:    GPL-2.0
  */
 
-#include "common.h"
-#include <stdlib.h>
-#include <string.h>
+#include "cmd_gpio.h"
 #include <ctype.h>
 
-#include "command.h"
 #include "print-utils.h"
 #include "getopt-min.h"
 #include "env.h"
@@ -176,7 +173,7 @@ static uint_fast8_t pinarg_get(char * arg, uint_fast8_t pinarg[])
 }
 
 
-command_ret_t do_gpio(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+command_ret_t do_gpio(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char *const argv[])
 {
        char printheader = 1;
        uint_fast8_t pinarg[GPIO_MAX];
diff --git a/avr/cmd_help.c b/avr/cmd_help.c
deleted file mode 100644 (file)
index 010339d..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * (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"
-
-command_ret_t do_help(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
-       const int len = cmd_tbl_item_count();
-       return _do_help(cmd_tbl, len, cmdtp, flag, argc, argv);
-}
index e6e2cdce0a1f90f9a76a427ada3d2104d7445dda..39e3278eee9def269fd31e3892ee5438a70c0ae6 100644 (file)
@@ -8,12 +8,9 @@
  * See CP/M 3 System Manual, Appendix D: CPM3.SYS File Format
  */
 
-#include "common.h"
+#include "cmd_loadcpm3.h"
 #include <ctype.h>
-#include <string.h>
-#include <stdbool.h>
 
-#include "command.h"
 #include "env.h"
 #include "ff.h"
 #include "eval_arg.h"
@@ -63,7 +60,7 @@ int load(FIL *File, uint32_t addr, uint8_t len)
 
 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
 
-command_ret_t do_loadcpm3(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_loadcpm3(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        uint16_t mem_top;
        uint8_t res_len;
index 18d5331d8b2a0d9f8fc025cae787943ccf571d4b..2c0fa9e709eca2f3641fac13fa79fbc14c137236 100644 (file)
@@ -1,15 +1,12 @@
 /*
  * (C) Copyright 2015 Leo C. <erbl259-lmu@yahoo.de>
  *
- * SPDX-License-Identifier:    GPL-2.0+
+ * SPDX-License-Identifier:    GPL-2.0
  */
 
-#include "common.h"
-#include <stdlib.h>
+#include "cmd_loadihex.h"
 #include <ctype.h>
-#include <stdbool.h>
 
-#include "command.h"
 #include "con-utils.h"
 #include "z80-if.h"
 #include "debug.h"
@@ -151,7 +148,7 @@ int ihex_get_record(ihex_t *rec) {
 }
 
 
-command_ret_t do_loadihex(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_loadihex(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        long offset = 0;
        uint32_t base_address = 0;
index 315cd71e93e61dc9bf0dea6b58cc15e1baba6a9b..763b857b860bf20de2ca586f833f58f716d1766f 100644 (file)
@@ -60,7 +60,7 @@ int z180_read_buf(uint8_t *buf, uint32_t addr, uint8_t count)
  * Syntax:
  *     md {addr} {len}
  */
-command_ret_t do_mem_md(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_mem_md(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        uint32_t addr, length;
 
@@ -114,7 +114,7 @@ command_ret_t do_mem_md(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
  *     nm {addr}
  */
 static command_ret_t
-mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[])
+mod_mem(cmd_tbl_t *cmdtp, int incrflag, uint_fast8_t flag, int argc, char * const argv[])
 {
        uint32_t addr;
        uint8_t data;
@@ -183,16 +183,16 @@ mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[])
 }
 
 
-command_ret_t do_mem_mm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_mem_mm(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        return mod_mem (cmdtp, 1, flag, argc, argv);
 }
-command_ret_t do_mem_nm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_mem_nm(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        return mod_mem (cmdtp, 0, flag, argc, argv);
 }
 
-command_ret_t do_mem_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_mem_mw(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        uint32_t writeval;
        uint32_t addr;
@@ -254,7 +254,7 @@ 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[])
+command_ret_t do_mem_mdc ( cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        uint32_t count;
        uint32_t ts;
@@ -300,7 +300,7 @@ command_ret_t do_mem_mdc ( cmd_tbl_t *cmdtp, int flag, int argc, char * const ar
 }
 #endif /* CONFIG_MX_CYCLIC */
 
-command_ret_t do_mem_cmp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_mem_cmp(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        uint32_t addr1, addr2, count, ngood;
        command_ret_t rcode = CMD_RET_SUCCESS;
@@ -349,7 +349,7 @@ command_ret_t do_mem_cmp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv
        return rcode;
 }
 
-command_ret_t do_mem_cp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_mem_cp(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        uint32_t src, dest, count;
        int_fast8_t step;
@@ -399,7 +399,7 @@ command_ret_t do_mem_cp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
        return CMD_RET_SUCCESS;
 }
 
-command_ret_t do_mem_base(cmd_tbl_t *cmdtp, int flag, int argc,
+command_ret_t do_mem_base(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc,
                       char * const argv[])
 {
        (void) cmdtp;
@@ -414,7 +414,7 @@ command_ret_t do_mem_base(cmd_tbl_t *cmdtp, int flag, int argc,
        return CMD_RET_SUCCESS;
 }
 
-command_ret_t do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc,
+command_ret_t do_mem_loop(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc,
                       char * const argv[])
 {
        uint32_t addr, length;
@@ -460,7 +460,7 @@ command_ret_t do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc,
        return CMD_RET_SUCCESS;
 }
 
-command_ret_t do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_mem_loopw (cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        uint32_t addr, length;
        uint8_t data;
@@ -734,7 +734,7 @@ static uint32_t mem_test_alt(uint32_t start_addr, uint32_t end_addr)
  * configured using CONFIG_SYS_ALT_MEMTEST. The complete test loops until
  * interrupted by ctrl-c or by a failure of one of the sub-tests.
  */
-command_ret_t do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc,
+command_ret_t do_mem_mtest(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc,
                        char * const argv[])
 {
        uint32_t start = 0;
index 9061b5ad0d95cd7520093bf769352bd594142bb0..a88ba7292e57d71c541a4fa4cc2a6cb0c7f9949e 100644 (file)
@@ -7,17 +7,16 @@
  * SPDX-License-Identifier:    GPL-2.0
  */
 
-#include "common.h"
+#include "cmd_misc.h"
 #include "eval_arg.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[])
+command_ret_t do_echo(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        bool put_newline = true;
 
@@ -52,7 +51,7 @@ command_ret_t do_echo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 }
 
 
-command_ret_t do_sleep(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_sleep(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        unsigned long start = get_timer(0);
        unsigned long delay;
index 8593ef5472e2e3b0b2076cd184459c6e1e85f954..467739c6daff5c1744fc84d31f26e409bb986db4 100644 (file)
@@ -4,19 +4,15 @@
  * SPDX-License-Identifier:    GPL-2.0
  */
 
-#include "common.h"
-#include <string.h>
-#include <stdio.h>
+#include "cmd_run.h"
 
 #include "ff.h"
-#include "config.h"
-#include "command.h"
 #include "cli_readline.h"      /* console_buffer[] */
 #include "cli.h"                       /* run_command() */
 #include "env.h"
 
 
-command_ret_t do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_run(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        int i;
        (void) cmdtp;
@@ -39,7 +35,7 @@ command_ret_t do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        return CMD_RET_SUCCESS;
 }
 
-static int source(FIL *fp, int flag, int argc, char * const argv[])
+static int source(FIL *fp, uint_fast8_t flag, int argc, char * const argv[])
 {
        int lineno = 0;
        int res = 0;
@@ -66,7 +62,7 @@ static int source(FIL *fp, int flag, int argc, char * const argv[])
        return !f_eof(fp) || res;
 }
 
-command_ret_t do_source(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_source(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        FIL File;
        int res;
index 91007f994dc10e094e1bebf71fc185e5874c72a8..06c933852cb1f5df1ce8885bbcaea12a35f89ab6 100644 (file)
@@ -1,13 +1,11 @@
 /*
  * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
  *
- * SPDX-License-Identifier:    GPL-2.0+
+ * SPDX-License-Identifier:    GPL-2.0
  */
 
-#include "common.h"
-//#include <stdlib.h>
+#include "cmd_sd.h"
 
-#include "command.h"
 #include "diskio.h"
 #include "ff.h"
 #include "eval_arg.h"
@@ -20,7 +18,7 @@
  *
  */
 static
-command_ret_t do_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_status(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        DSTATUS res;
        BYTE dev;
@@ -42,7 +40,7 @@ command_ret_t do_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
  *
  */
 static
-command_ret_t do_init(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_init(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        DSTATUS res;
        BYTE dev;
@@ -73,7 +71,7 @@ command_ret_t do_init(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  *
  */
 static
-command_ret_t do_info(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_info(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        DSTATUS res;
        BYTE dev;
@@ -122,7 +120,7 @@ command_ret_t do_info(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  *
  */
 static
-command_ret_t do_dump(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_dump(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        static BYTE dev_last;
        static  DWORD sec_last;
@@ -175,7 +173,7 @@ command_ret_t do_dump(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  *
  */
 static
-command_ret_t do_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_read(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        DRESULT res;
        BYTE dev;
@@ -237,7 +235,7 @@ command_ret_t do_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  *
  */
 static
-command_ret_t do_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_write(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        DRESULT res;
        BYTE dev;
@@ -300,7 +298,7 @@ command_ret_t do_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
  *
  */
 static
-command_ret_t do_ioctl_sync(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_ioctl_sync(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        BYTE dev;
 
@@ -316,48 +314,45 @@ command_ret_t do_ioctl_sync(cmd_tbl_t *cmdtp, int flag, int argc, char * const a
 }
 
 
-static
-command_ret_t do_help(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
-
-cmd_tbl_t cmd_sd_sub[] = {
+cmd_tbl_t cmd_tbl_sd[] = {
 CMD_TBL_ITEM(
-       status, 2,                      1,      do_status,
+       status, 2,                      CTBL_RPT,       do_status,
        "Socket staus",
        "drive"
 ),
 CMD_TBL_ITEM(
-       init,   2,                      1,      do_init,
+       init,   2,                      CTBL_RPT,       do_init,
        "Initialize disk",
        "drive"
 ),
 CMD_TBL_ITEM(
-       info,   2,                      1,      do_info,
+       info,   2,                      CTBL_RPT,       do_info,
        "Disk info",
        "drive"
 ),
 CMD_TBL_ITEM(
-       dump,   CONFIG_SYS_MAXARGS,     1,      do_dump,
+       dump,   CONFIG_SYS_MAXARGS,     CTBL_RPT,       do_dump,
        "Dump sector(s)",
        "drive [sector [count ]]"
 ),
 CMD_TBL_ITEM(
-       read,   2,                      1,      do_read,
+       read,   2,                      CTBL_RPT,       do_read,
        "Read disk sector(s) into meomory",
        "drive [sector [count [memaddr]]]"
 ),
 CMD_TBL_ITEM(
-       write,  2,                      1,      do_write,
+       write,  2,                      CTBL_RPT,       do_write,
        "Write sector(s) from meomory to disk",
        "drive [sector [count [memaddr]]]"
 ),
 CMD_TBL_ITEM(
-       sync,   2,                      1,      do_ioctl_sync,
+       sync,   2,                      CTBL_RPT,       do_ioctl_sync,
        "Device control: SYNC",
        "drive"
 ),
 
 CMD_TBL_ITEM(
-       help,   CONFIG_SYS_MAXARGS,     1,      do_help,
+       help,   CONFIG_SYS_MAXARGS,     CTBL_RPT,       do_help,
        "Print sub command description/usage",
        "\n"
        "       - print brief description of all sub commands\n"
@@ -371,34 +366,18 @@ CMD_TBL_ITEM(
 #ifdef  CONFIG_SYS_LONGHELP
        FSTR(""),
 #endif /* CONFIG_SYS_LONGHELP */
+       NULL,
 #ifdef CONFIG_AUTO_COMPLETE
-       0,
+       NULL,
 #endif
 },
+/* Mark end of table */
+CMD_TBL_END(cmd_tbl_sd)
 };
 
-static
-command_ret_t do_help(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
-       return _do_help(cmd_sd_sub, ARRAY_SIZE(cmd_sd_sub), cmdtp, flag, argc, argv);
-}
-
 
-command_ret_t do_sd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_sd(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
-       cmd_tbl_t *cp;
-
-       if (argc < 2)
-               return CMD_RET_USAGE;
-
-       /* drop initial "sd" arg */
-       argc--;
-       argv++;
-
-       cp = find_cmd_tbl(argv[0], cmd_sd_sub, ARRAY_SIZE(cmd_sd_sub));
-
-       if (cp)
-               return cp->cmd(cmdtp, flag, argc, argv);
-
+       puts_P(PSTR("Huch?"));
        return CMD_RET_USAGE;
 }
index cd2ee39c81be86cc8035e4a738c4697db7174ec8..c8a73f0bea37facb1b640451e5dd30d55dedd324 100644 (file)
@@ -59,9 +59,10 @@ int cmpstring_PP(const void *p1, const void *p2)
                         (*(const FLASH cmd_tbl_t **) p2)->name);
 }
 
-int cmd_tbl_item_count(void)
+/****************************************************************************/
+
+int cmd_tbl_item_count(cmd_tbl_t *p)
 {
-       cmd_tbl_t * p = cmd_tbl;
        int count = 0;
 
        while (p->name != NULL) {
@@ -70,115 +71,155 @@ int cmd_tbl_item_count(void)
        return count;
 }
 
+
+cmd_tbl_t *get_cmd_tbl_base(cmd_tbl_t  *cmdtp)
+{
+       cmd_tbl_t *p = cmdtp;
+
+       while (p->name != NULL)
+               ++p;
+
+       return p->subcmd;
+}
+
+/*
+ * find command table entry for a command
+ */
+typedef struct {
+               size_t len;
+               uint_fast8_t level;
+               bool opt_debug;
+       } find_cmd_para_t;
+
+cmd_tbl_t *_find_cmd (const char *cmd, cmd_tbl_t *table, find_cmd_para_t *para)
+{
+       cmd_tbl_t *cmdtp_ret = NULL;
+       uint_fast8_t n_found = 0, sub_found = 0;
+
+       for (cmd_tbl_t *cmdtp = table; cmdtp->name != NULL; cmdtp++) {
+               if (strncmp_P(cmd, cmdtp->name, para->len) == 0 &&
+                                       (para->opt_debug || !(cmdtp->flags & CTBL_DBG))) {
+                       if (para->len == strlen_P(cmdtp->name))
+                               return cmdtp;   /* full match */
+
+                       cmdtp_ret = cmdtp;      /* abbreviated command ? */
+                       n_found++;
+               } else if (cmdtp->subcmd && cmdtp->flags & CTBL_SUBCMDAUTO) {
+                       cmd_tbl_t *sub = _find_cmd(cmd, cmdtp->subcmd, para);
+                       if (sub) {
+                               cmdtp_ret = sub;
+                               ++n_found;
+                       }
+               }
+       }
+       if (n_found == 1) {                     /* exactly one match */
+               if (sub_found)
+                       para->level++;
+               return cmdtp_ret;
+       }
+
+       return NULL;    /* not found or ambiguous command */
+}
+
+
+cmd_tbl_t *find_cmd (const char *cmd, cmd_tbl_t *table, uint_fast8_t *cmdlevel)
+{
+       find_cmd_para_t para;
+
+       if (!cmd)
+               return NULL;
+
+       char *optenv = getenv_str(PSTR("cmd"));
+       para.level = 0;
+       para.opt_debug = optenv && strstr_P(optenv, PSTR("debug")) != NULL;
+       para.len = strlen(cmd);
+
+       cmd_tbl_t *cmdtp = _find_cmd(cmd, table, &para);
+
+       if (cmdlevel)
+               *cmdlevel = para.level;
+       return cmdtp;
+}
+
+cmd_tbl_t *find_cmd_sub(const char *cmd, cmd_tbl_t *table)
+{
+       cmd_tbl_t *entry = NULL;
+
+       for (cmd_tbl_t *tp = get_cmd_tbl_base(table); tp->name && entry == NULL; tp++)
+               if (tp->subcmd && tp->flags & CTBL_SUBCMDAUTO)
+                       entry = find_cmd(cmd, tp->subcmd, NULL);
+
+       return entry;
+}
+
 /*
  * Use puts() instead of printf() to avoid printf buffer overflow
  * for long help messages
  */
 
-command_ret_t _do_help(cmd_tbl_t *cmd_start, int cmd_items, cmd_tbl_t * cmdtp,
-               int flag, int argc, char * const argv[])
+command_ret_t do_help(cmd_tbl_t *cmdtp, uint_fast8_t flag UNUSED, int argc, char * const argv[])
 {
-       uint_fast8_t i, max_len = 0;
-       command_ret_t rcode = CMD_RET_SUCCESS;
-
-       (void) flag;
+       cmd_tbl_t *tbl_start = get_cmd_tbl_base(cmdtp);
 
        char *optenv = getenv_str(PSTR("cmd"));
        bool opt_debug = optenv && strstr_P(optenv, PSTR("debug")) != NULL;
 
        if (argc == 1) {        /*show list of commands */
-               cmd_tbl_t *cmd_array[cmd_items];
-               int i;
-
-               /* Make array of commands from .uboot_cmd section */
-               cmdtp = cmd_start;
-               for (i = 0; i < cmd_items; i++) {
-                       cmd_array[i] = cmdtp++;
-                       uint_fast8_t l = strlen_P(cmd_array[i]->name);
-                       if (l > max_len)
-                               max_len = l;
+               int cmd_items = cmd_tbl_item_count(tbl_start);
+               cmd_tbl_t **cmd_list = (cmd_tbl_t **) malloc(cmd_items * sizeof(cmd_tbl_t *));
+               uint_fast8_t maxlen_cmd = 0;
+
+               /* Make array of commands */
+               cmd_tbl_t *tp = tbl_start;
+               for (int i = 0; i < cmd_items; i++) {
+                       uint_fast8_t l = strlen_P(tp->name);
+                       if (l > maxlen_cmd)
+                               maxlen_cmd = l;
+                       cmd_list[i] = tp++;
                }
-
                /* Sort command list */
-               qsort(cmd_array, cmd_items, sizeof (cmd_tbl_t *), cmpstring_PP);
+               qsort(cmd_list, cmd_items, sizeof (cmd_tbl_t *), cmpstring_PP);
 
                /* print short help (usage) */
-               for (i = 0; i < cmd_items; i++) {
-                       if (opt_debug || cmd_array[i]->name[0] != '!') {
-                               const FLASH char *usage = cmd_array[i]->usage;
+               for (int i = 0; i < cmd_items; i++) {
+                       if (opt_debug || !(cmd_list[i]->flags & CTBL_DBG)) {
+                               const FLASH char *usage = cmd_list[i]->usage;
 
                                /* allow user abort */
-                               if (ctrlc ())
+                               if (ctrlc ()) {
+                                       free(cmd_list);
                                        return CMD_RET_FAILURE;
+                               }
                                if (usage == NULL)
                                        continue;
-#ifdef GCC_BUG_61443
-                               print_usage_line(cmd_array[i]->name, max_len, usage);
+#if defined(GCC_BUG_61443) || 1
+                               print_usage_line(cmd_list[i]->name, maxlen_cmd, usage);
 #else
                                printf_P(PSTR("%-" stringify(8) /*FIXME*/ "S - %S\n"),
-                                               cmd_array[i]->name, usage);
+                                               cmd_list[i]->name, usage);
 #endif
                        }
                }
+               free(cmd_list);
                return CMD_RET_SUCCESS;
        }
+
        /*
         * command help (long version)
         */
-       for (i = 1; i < argc; ++i) {
-               if ((cmdtp = find_cmd_tbl (argv[i], cmd_start, cmd_items )) != NULL &&
+       for (uint8_t i = 1; i < argc; ++i) {
+               if ((cmdtp = find_cmd(argv[i], tbl_start, NULL)) != NULL &&
                                        (opt_debug || cmdtp->name[0] != '!')) {
                        cmd_usage(cmdtp);
                } else {
                        printf_P(PSTR("Unknown command '%s' - try 'help'"
                                " without arguments.\n\n"), argv[i]
                                );
-                       rcode = CMD_RET_FAILURE;
+                       return CMD_RET_FAILURE;
                }
        }
-       return rcode;
-}
-
-/***************************************************************************
- * find command table entry for a command
- */
-cmd_tbl_t *find_cmd_tbl (const char *cmd, cmd_tbl_t *table, int table_len)
-{
-       cmd_tbl_t *cmdtp;
-       cmd_tbl_t *cmdtp_temp = table;  /*Init value */
-       size_t len;
-       uint_fast8_t n_found = 0;
-
-       char *optenv = getenv_str(PSTR("cmd"));
-       bool opt_debug = optenv && strstr_P(optenv, PSTR("debug")) != NULL;
-
-       if (!cmd)
-               return NULL;
-
-       len = strlen(cmd);
-
-       for (cmdtp = table;
-            cmdtp != table + table_len;
-            cmdtp++) {
-               if (strncmp_P(cmd, cmdtp->name, len) == 0 &&
-                                       (opt_debug || cmdtp->name[0] != '!')) {
-                       if (len == strlen_P(cmdtp->name))
-                               return cmdtp;   /* full match */
 
-                       cmdtp_temp = cmdtp;     /* abbreviated command ? */
-                       n_found++;
-               }
-       }
-       if (n_found == 1)                       /* exactly one match */
-               return cmdtp_temp;
-
-       return NULL;    /* not found or ambiguous command */
-}
-
-
-cmd_tbl_t *find_cmd (const char *cmd)
-{
-       return find_cmd_tbl(cmd, cmd_tbl, cmd_tbl_item_count());
+       return CMD_RET_SUCCESS;
 }
 
 
@@ -263,7 +304,7 @@ static int complete_cmdv(int argc, char * const argv[], char last_char, int maxv
 
        /* more than one arg or one but the start of the next */
        if (argc > 1 || (last_char == '\0' || isblank(last_char))) {
-               cmdtp = find_cmd(argv[0]);
+               cmdtp = find_cmd(argv[0], cmd_tbl);
                if (cmdtp == NULL || cmdtp->complete == NULL) {
                        cmdv[0] = NULL;
                        return 0;
@@ -482,7 +523,7 @@ int cmd_auto_complete(const FLASH char *const prompt, char *buf, int *np, int *c
  * @param argv         Arguments
  * @return 0 if command succeeded, else non-zero (CMD_RET_...)
  */
-command_ret_t cmd_call(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t cmd_call(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        command_ret_t result;
 
@@ -492,22 +533,43 @@ command_ret_t cmd_call(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
        return result;
 }
 
-command_ret_t cmd_process(int flag, int argc, char * const argv[],
+#pragma GCC diagnostic ignored "-Wclobbered"
+
+command_ret_t cmd_process(uint_fast8_t flag, int argc, char * const argv[],
                               uint_fast8_t *repeatable)
 {
        command_ret_t rc = CMD_RET_SUCCESS;
        cmd_tbl_t *cmdtp;
+       uint_fast8_t cmdlevel;
 
        /* Look up command in command table */
-       cmdtp = find_cmd(argv[0]);
+       cmdtp = find_cmd(argv[0], cmd_tbl, &cmdlevel);
+       if (cmdtp != NULL) {
+               /* Check if this command has subcommands */
+               if (cmdtp->subcmd && argc > 1) {
+
+                       /* Look up subcommand in subcommand table */
+                       cmd_tbl_t *cmdtpsub = find_cmd(argv[1], cmdtp->subcmd, &cmdlevel);
+                       if (cmdtpsub == NULL) {
+                               printf_P(PSTR("Unknown '%s' subcommand '%s' - try '%s help'\n"), argv[0], argv[1], argv[0]);
+                               return CMD_RET_FAILURE;
+                       }
+                       cmdtp = cmdtpsub;
+                       --argc;
+                       ++argv;
+               }
+       }
+#if 0
+        else {
+               /* Search subcommands */
+               cmdtp = find_cmd_sub(argv[0], cmd_tbl, &cmdlevel);
+       }
+#endif
+
        if (cmdtp == NULL) {
                printf_P(PSTR("Unknown command '%s' - try 'help'\n"), argv[0]);
                return CMD_RET_FAILURE;
        }
-       if (!cmdtp->cmd) {
-               debug("### Command '%s' found, but ->cmd == NULL \n", argv[0]);
-               return CMD_RET_FAILURE;
-       }
 
        /* found - check max args */
        if (argc > cmdtp->maxargs)
@@ -531,7 +593,7 @@ command_ret_t cmd_process(int flag, int argc, char * const argv[],
        /* If OK so far, then do the command */
        if (!rc) {
                rc = cmd_call(cmdtp, flag, argc, argv);
-               *repeatable &= cmdtp->repeatable;
+               *repeatable &= (cmdtp->flags & CTBL_RPT) != 0;
        }
        if (rc == CMD_RET_USAGE)
                rc = cmd_usage(cmdtp);
index ed14db9e259ff18d48ef7460118a29781a2711f0..176971421cc2657ec19d0586512d3f6b4ac1ef8c 100644 (file)
@@ -7,44 +7,18 @@
 #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 []);
-extern command_ret_t do_env_print(cmd_tbl_t *, int, int, char * const []);
-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_bootcf(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 []);
-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_rw(cmd_tbl_t *, int, int, char * const []);
-extern command_ret_t do_run(cmd_tbl_t *, int, int, char * const []);
-extern command_ret_t do_source(cmd_tbl_t *, int, int, char * const []);
-extern command_ret_t do_attach(cmd_tbl_t *, int, int, char * const []);
-
-#ifdef CONFIG_SYS_LONGHELP
-const FLASH char sd_help_text[] =
-       "bla \t- do bla\n"
-       ;
-#endif /* CONFIG_SYS_LONGHELP */
+#include "cmd_boot.h"
+#include "cmd_misc.h"
+#include "cmd_date.h"
+#include "cmd_run.h"
+#include "cmd_loadcpm3.h"
+#include "cmd_loadihex.h"
+#include "cmd_gpio.h"
+#include "cmd_sd.h"
+#include "cmd_fat.h"
+#include "cmd_attach.h"
+#include "env.h"
+#include "debug.h"
 
 
 cmd_tbl_t cmd_tbl[] = {
@@ -60,35 +34,45 @@ CMD_TBL_ITEM(
 #ifdef DEBUG
 
 CMD_TBL_ITEM(
-       !mdr,   3,      1,      do_dump_mem,
+       !mdr,   3,      CTBL_DBG|CTBL_RPT,      do_dump_mem,
        "RAM dump",
        "address [count]"
 ),
 CMD_TBL_ITEM(
-       !mde,   3,      1,      do_dump_mem,
+       !mde,   3,      CTBL_DBG|CTBL_RPT,      do_dump_mem,
        "EEPROM dump",
        "address [count]"
 ),
 CMD_TBL_ITEM(
-       !mdf,   3,      1,      do_dump_mem,
+       !mdf,   3,      CTBL_DBG|CTBL_RPT,      do_dump_mem,
        "FLASH dump",
        "address [count]"
 ),
 CMD_TBL_ITEM(
-       !cpe,   4,      0,      do_eep_cp,
+       !cpe,   4,      CTBL_DBG,       do_eep_cp,
        "EEPROM copy",
        "source target count"
 ),
 CMD_TBL_ITEM(
-       !mm,    2,      1,      do_mem_mm_avr,
+       !mm,    2,      CTBL_DBG|CTBL_RPT,      do_mem_mm_avr,
        "avr memory modify (auto-incrementing address)",
        "address"
 ),
 CMD_TBL_ITEM(
-       !nm,    2,      1,      do_mem_nm_avr,
+       !nm,    2,      CTBL_DBG|CTBL_RPT,      do_mem_nm_avr,
        "avr memory modify (constant address)",
        "address"
 ),
+CMD_TBL_ITEM(
+       !prfree,        1,      CTBL_DBG|CTBL_RPT,      do_pr_free_avr,
+       "print avr heap free list",
+       ""
+),
+CMD_TBL_ITEM(
+       !prheap,        1,      CTBL_DBG,       do_pr_heap_avr,
+       "dump avr heap",
+       ""
+),
 #endif
 CMD_TBL_ITEM(
        mstep,  2,      1,      do_busreq_pulse,
@@ -264,22 +248,22 @@ CMD_TBL_ITEM(
 ),
 
 CMD_TBL_ITEM(
-       md,     3,      1,      do_mem_md,
+       md,     3,      CTBL_RPT,       do_mem_md,
        "memory display",
        "address [# of objects]"
 ),
 CMD_TBL_ITEM(
-       mm,     2,      1,      do_mem_mm,
+       mm,     2,      CTBL_RPT,       do_mem_mm,
        "memory modify (auto-incrementing address)",
        "address"
 ),
 CMD_TBL_ITEM(
-       nm,     2,      1,      do_mem_nm,
+       nm,     2,      CTBL_RPT,       do_mem_nm,
        "memory modify (constant address)",
        "address"
 ),
 CMD_TBL_ITEM(
-       mw,     CONFIG_SYS_MAXARGS,     1,      do_mem_mw,
+       mw,     CONFIG_SYS_MAXARGS,     CTBL_RPT,       do_mem_mw,
        "memory write (fill)",
        "[-bwl] address value [count]\n"
        "   -b  write value as byte (8 bit, default)\n"
@@ -287,12 +271,12 @@ CMD_TBL_ITEM(
        "   -l  write value as long (32 bit)"
 ),
 CMD_TBL_ITEM(
-       cp,     4,      1,      do_mem_cp,
+       cp,     4,      CTBL_RPT,       do_mem_cp,
        "memory copy",
        "source target count"
 ),
 CMD_TBL_ITEM(
-       cmp,    4,      1,      do_mem_cmp,
+       cmp,    4,      CTBL_RPT,       do_mem_cmp,
        "memory compare",
        "addr1 addr2 count"
 ),
@@ -305,19 +289,19 @@ CMD_TBL_ITEM(
        "    - set address offset for memory commands to 'offset'"
 ),
 CMD_TBL_ITEM(
-       mloop,  3,      1,      do_mem_loop,
+       mloop,  3,      CTBL_RPT,       do_mem_loop,
        "infinite loop on address range",
        "address number_of_bytes"
 ),
 CMD_TBL_ITEM(
-       mloopw, 4,      1,      do_mem_loopw,
+       mloopw, 4,      CTBL_RPT,       do_mem_loopw,
        "infinite write loop on address range",
        "address number_of_bytes data_to_write"
 ),
 
 #ifdef CONFIG_CMD_MEMTEST
 CMD_TBL_ITEM(
-       mtest,  4,      1,      do_mem_mtest,
+       mtest,  4,      CTBL_RPT,       do_mem_mtest,
        "simple RAM read/write test",
        "[start [end [iterations]]]"
 ),
@@ -325,12 +309,12 @@ CMD_TBL_ITEM(
 
 #ifdef CONFIG_MX_CYCLIC
 CMD_TBL_ITEM(
-       mdc,    4,      1,      do_mem_mdc,
+       mdc,    4,      CTBL_RPT,       do_mem_mdc,
        "memory display cyclic",
        "address count delay(ms)"
 ),
 CMD_TBL_ITEM(
-       mwc,    CONFIG_SYS_MAXARGS,     1,      do_mem_mdc,
+       mwc,    CONFIG_SYS_MAXARGS,     CTBL_RPT,       do_mem_mdc,
        "memory write cyclic",
        "[-bwl] address value delay(ms)\n"
        "   -b  write value as byte (8 bit, default)\n"
@@ -339,44 +323,25 @@ CMD_TBL_ITEM(
 ),
 #endif /* CONFIG_MX_CYCLIC */
 
-CMD_TBL_ITEM(
-       sd,   CONFIG_SYS_MAXARGS, 1, do_sd,
+CMD_TBL_ITEM_TOP(
+       sd,   CONFIG_SYS_MAXARGS, CTBL_SUBCMDAUTO, do_sd,
        "SD/MMC card handling commands",
        "<subcommand> args ...\n"
        "sd help\n"
-       "    - print help on subcommands"
-),
-
-CMD_TBL_ITEM(
-       fatstat,        2,      1,      do_fat_stat,
-       "Show logical drive status",
-       "dev"
-),
-CMD_TBL_ITEM(
-       fatls,  2,      1,      do_fat_ls,
-       "Directory listing",
-       "path"
+       "    - print help on subcommands",
+       cmd_tbl_sd
 ),
-CMD_TBL_ITEM(
-       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"
-       "      to address 'addr' from dos filesystem.\n"
-       "      'pos' gives the file position to start loading from.\n"
-       "      If 'pos' is omitted, 0 is used. 'pos' requires 'bytes'.\n"
-       "      'bytes' gives the size to load. If 'bytes' is 0 or omitted,\n"
-       "      the load stops on end of file."
-),
-CMD_TBL_ITEM(
-       fatwrite,       4,      0,      do_fat_rw,
-       "write file into a dos filesystem",
-       "<d:/path/filename> <addr> <bytes>\n"
-       "    - Write file to 'path/filename' on logical drive 'd' from RAM\n"
-       "      starting at address 'addr'.\n"
+CMD_TBL_ITEM_TOP(
+       fat,   CONFIG_SYS_MAXARGS, CTBL_SUBCMD|CTBL_SUBCMDAUTO, do_fat,
+       "fat filesystem commands",
+       "<subcommand> args ...\n"
+       "fat help\n"
+       "    - print help on subcommands",
+       cmd_tbl_fat
 ),
+
 CMD_TBL_ITEM(
-       attach, CONFIG_SYS_MAXARGS,     1,      do_attach,
+       attach, CONFIG_SYS_MAXARGS,     CTBL_RPT,       do_attach,
        "attach filesystem image file to CP/M drive",
        "[-rw] [-o options] dsk<n> diskfile\n"
        "    Attach diskfile to dsk<n>, where n in 0..7\n"
@@ -396,17 +361,17 @@ CMD_TBL_ITEM(
        "    -a      Detach all.\n"
        "\n"
        "attach\n"
-       "    Without arguments, list current assignments\n"
+       "    Without arguments, list current assignments"
 ),
 CMD_TBL_ITEM(
-       detach, 2,      1,      do_attach,
+       detach, 2,      0,      do_attach,
        "detach file from CP/M drive",
        "dsk<n>]\n"
        "    - alias for 'attach -d dsk<n>'"
 ),
 
 CMD_TBL_ITEM(
-       help,   CONFIG_SYS_MAXARGS,     1,      do_help,
+       help,   CONFIG_SYS_MAXARGS,     0,      do_help,
        "print command description/usage",
        "\n"
        "       - print brief description of all commands\n"
@@ -420,10 +385,11 @@ CMD_TBL_ITEM(
 #ifdef  CONFIG_SYS_LONGHELP
        FSTR(""),
 #endif /* CONFIG_SYS_LONGHELP */
+       NULL,
 #ifdef CONFIG_AUTO_COMPLETE
-       0,
+       NULL,
 #endif
 },
 /* Mark end of table */
-{ 0 },
+CMD_TBL_END(cmd_tbl)
 };
index 4a96771040c536123388f92657a0d1e6fe54c982..410822108b971a710c8fde7b7c29c76690a39a78 100644 (file)
@@ -80,13 +80,29 @@ uint_fast8_t ctrlc(void)
 /* Reads user's confirmation.
    Returns 1 if user's input is "y", "Y", "yes" or "YES"
 */
+uint_fast8_t confirm_yes(void)
+{
+       uint_fast8_t checkch, ch;
+
+       checkch = ch = my_getchar(1);
+       putchar(ch);
+       while (ch != '\r') {
+               ch = my_getchar(1);
+               putchar(ch);
+       }
+       putchar('\n');
+
+       return (checkch  == 'y');
+}
+
+#if 0
 uint_fast8_t confirm_yesno(void)
 {
        unsigned int i;
        char str_input[5];
 
        /* Flush input */
-       while (serial_getc())
+       while (serial_getc() < 0)
                ;
        i = 0;
        while (i < sizeof(str_input)) {
@@ -104,6 +120,7 @@ uint_fast8_t confirm_yesno(void)
                return 1;
        return 0;
 }
+#endif
 
 /* pass 1 to disable ctrlc() checking, 0 to enable.
  * returns previous state
index 1b4ecc2a60bb7930fffabdaa8c3a1323d576f235..ea4aa21a9f0dce93b8eb7db501c20e02c54cc811 100644 (file)
 
 #ifdef DEBUG
 
-
-#if 0
-void dump_heap(void)
-{
-       extern unsigned int __brkval;
-
-       dump_ram(__malloc_heap_start,
-               __brkval - (unsigned int) __malloc_heap_start,
-               "=== Heap:");
-}
-#endif
-
-
 /*
  * Memory Display
  *     md addr {len}
  */
-command_ret_t do_dump_mem(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_dump_mem(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        int (*readwhat)(uint8_t *buf, uint32_t addr, uint8_t count);
 
@@ -78,7 +65,7 @@ command_ret_t do_dump_mem(cmd_tbl_t *cmdtp, int flag, int argc, char * const arg
        return CMD_RET_SUCCESS;
 }
 
-command_ret_t do_eep_cp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_eep_cp(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        uint16_t src, dest, count;
        int_fast8_t step;
@@ -139,10 +126,9 @@ command_ret_t do_eep_cp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
  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[])
+mod_mem_avr(cmd_tbl_t *cmdtp, int incrflag, uint_fast8_t flag, int argc, char * const argv[])
 {
        uint8_t *addr;
-       uint8_t data;
        int nbytes;
 
        (void) cmdtp;
@@ -168,7 +154,7 @@ mod_mem_avr(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const arg
         * the next value.  A non-converted value exits.
         */
        do {
-               data = *addr;
+               uint8_t data = *addr;
                printf_P(PSTR("%04x: %02x"), addr, data);
 
                nbytes = cli_readline(PSTR(" ? "), 0);
@@ -197,29 +183,32 @@ mod_mem_avr(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const arg
 }
 
 
-command_ret_t do_mem_mm_avr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_mem_mm_avr(cmd_tbl_t *cmdtp, uint_fast8_t 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[])
+command_ret_t do_mem_nm_avr(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        return mod_mem_avr (cmdtp, 0, flag, argc, argv);
 }
 
 /*------------------------------------------------------------------------------*/
 
-#if 1
-
 struct __freelist {
        size_t sz;
        struct __freelist *nx;
 };
 
-extern char *__brkval;         /* first location not yet allocated */
-extern struct __freelist *__flp; /* freelist pointer (head of freelist) */
+extern char *__brkval;                         /* first location not yet allocated */
+extern struct __freelist *__flp;       /* freelist pointer (head of freelist) */
 
 #define STACK_POINTER() ((char *)AVR_STACK_POINTER_REG)
 
+size_t get_freemem(void)
+{
+       return (size_t) STACK_POINTER() - __malloc_margin - (size_t) __brkval;
+}
+
 void
 printfreelist(const char * title)
 {
@@ -227,29 +216,47 @@ printfreelist(const char * title)
        int i;
        unsigned int freesum = 0;
 
-/* TODO: printf_P */
-
        if (!__flp) {
-               printf("%s no free list\n", title ? title : "");
+               printf_P(PSTR("%s no free list\n"), title ? title : "");
        } else {
-               printf("Free list: %s\n", title ? title : "");
+               printf_P(PSTR("Free list: %s\n"), title ? title : "");
                for (i = 0, fp1 = __flp; fp1; i++, fp1 = fp1->nx) {
-                       printf("    entry %d @ %04x: size %4u, next ",
+                       printf_P(PSTR("    entry %d @ %04x: size %4u, next "),
                               i, (size_t)fp1, fp1->sz);
                        if (fp1->nx)
-                               printf("%04x\n", (size_t)fp1->nx);
+                               printf_P(PSTR("%04x\n"), (size_t)fp1->nx);
                        else
-                               printf("NULL\n");
+                               printf_P(PSTR("NULL\n"));
                        freesum += fp1->sz;
                }
        }
 
-       freesum +=  (size_t) STACK_POINTER() - __malloc_margin - (size_t) __brkval;
+       freesum += get_freemem();
 
-       printf("SP: %04x, __brkval: %04x, Total free: %04u\n",
+       printf_P(PSTR("SP: %04x, __brkval: %04x, Total free: %04u\n"),
                (size_t) STACK_POINTER(), (size_t) __brkval, freesum);
 }
 
-#endif
+command_ret_t do_pr_free_avr(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED)
+{
+       printfreelist(NULL);
+
+       return CMD_RET_SUCCESS;
+}
+
+void dump_heap(void)
+{
+       //extern unsigned int __brkval;
+
+       dump_ram((uint8_t *)__malloc_heap_start, (size_t) __malloc_heap_start,  __brkval - __malloc_heap_start,
+                                       "=== Heap:");
+}
+
+command_ret_t do_pr_heap_avr(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED)
+{
+       dump_heap();
+
+       return CMD_RET_SUCCESS;
+}
 
 #endif /* DEBUG */
index 952c88a0b9081b827d58ee6cfbe9c8ef0e41b88f..3b299c4b9cb18e99d0a828dc9ceb070b983910f2 100644 (file)
--- a/avr/env.c
+++ b/avr/env.c
@@ -4,18 +4,12 @@
  * SPDX-License-Identifier:    GPL-2.0
  */
 
-#include "common.h"
-#include <string.h>
-#include <stdlib.h>
-#include <stdbool.h>
+#include "env.h"
 #include <avr/eeprom.h>
 
 #include "config.h"
 #include "debug.h"
-#include "xmalloc.h"
 #include "crc.h"
-#include "command.h"
-#include "env.h"
 
 
 #define ENV_SIZE       (CONFIG_ENV_SIZE - sizeof(uint16_t) -1)
@@ -199,7 +193,7 @@ int envlist_import(uint8_t flags)
                                return -1;
                }
 
-               np = (char *) xmalloc(len+1);
+               np = (char *) malloc(len+1);
                if (np == NULL) {
                        printf_P(PSTR("## Can't malloc %d bytes\n"), len+1);
                        return 1;
@@ -451,7 +445,7 @@ int env_print(const MEMX char *name)
  * @return 0 if ok, 1 on error
  */
 static
-command_ret_t _do_env_set(int flag, int argc, char * const argv[])
+command_ret_t _do_env_set(uint_fast8_t flag, int argc, char * const argv[])
 {
        int i, len;
        char *name, *value, *valp, *p;
@@ -488,7 +482,7 @@ command_ret_t _do_env_set(int flag, int argc, char * const argv[])
        for (i = 2, len += 1; i < argc; ++i)
                len += strlen(argv[i]) + 1;
 
-       value = xmalloc(len);
+       value = malloc(len);
        if (value == NULL) {
                printf_P(PSTR("## Can't malloc %d bytes\n"), len);
                return CMD_RET_FAILURE;
@@ -644,7 +638,7 @@ bool getenv_yesno(const MEMX char *name)
 */
 }
 
-command_ret_t do_env_print(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_env_print(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        command_ret_t rc = CMD_RET_SUCCESS;
 
@@ -673,7 +667,7 @@ command_ret_t do_env_print(cmd_tbl_t *cmdtp, int flag, int argc, char * const ar
 }
 
 
-command_ret_t do_env_set(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_env_set(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        (void) cmdtp;
 
@@ -684,7 +678,7 @@ command_ret_t do_env_set(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv
 }
 
 
-command_ret_t do_env_default(cmd_tbl_t *cmdtp, int flag,
+command_ret_t do_env_default(cmd_tbl_t *cmdtp, uint_fast8_t flag,
                          int argc, char * const argv[])
 {
        (void) cmdtp; (void) flag; (void) argc; (void) argv;
@@ -702,7 +696,7 @@ command_ret_t do_env_default(cmd_tbl_t *cmdtp, int flag,
 }
 
 
-command_ret_t do_env_save(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_env_save(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
 {
        (void) cmdtp; (void) flag; (void) argc; (void) argv;
 
index b93150935cdb1983dabf8b66ff2ee39b3d81307d..fd8b067acf53bed4339feed7a82045cec96db2c2 100644 (file)
@@ -5,12 +5,10 @@
  */
 
 #include "eval_arg.h"
-#include "common.h"
-#include <stdlib.h>
+#include "command.h"   /* jump_buf */
 #include <ctype.h>
 #include <setjmp.h>
 #include "print-utils.h"
-#include "command.h"   /* jump_buf */
 
 static jmp_buf eval_jbuf;
 static char ch;
index 86dcc50caa6c506476e333ed06434c5bb1509552..450e2bad324b08161c55e47baed790ee4d706bca 100644 (file)
@@ -24,6 +24,8 @@
 #include "time.h"
 #include "rtc.h"
 #include "debug.h"
+#include "cmd_fat.h"
+
 
 uint8_t mcusr __attribute__ ((section (".noinit")));
 
@@ -146,16 +148,6 @@ void setup_system_time(void)
 }
 
 
-
-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() */
@@ -254,6 +246,7 @@ int main(void)
 {
        extern void setup_mmc(void);
 
+       __malloc_margin = CONFIG_SYS_MALLOC_MARGIN;
        setup_avr();
        for (int i = 0; i < GPIO_MAX; i++)
                gpio_config(i, INPUT_PULLUP);
diff --git a/avr/xmalloc.c b/avr/xmalloc.c
deleted file mode 100644 (file)
index d42d5c9..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-#include <stdlib.h>
-#include "debug.h"
-#include "xmalloc.h"
-
-void* xmalloc(size_t size)
-{
-       void *p;
-
-       p = malloc(size);
-
-       if (p == NULL)
-               debug("*** Out of memory!\n");
-
-       return p;
-}
-
-
-void* xrealloc(void *p, size_t size)
-{
-       p = realloc(p, size);
-
-       if (p == NULL)
-               debug("*** Out of memory!\n");
-
-       return p;
-}
index 51a3c23633ebe325952f16dbe591d346005509cf..336df0ae80af9ebc290da1912b78e9d57a806c03 100644 (file)
@@ -33,7 +33,7 @@
 /  2: Enable with LF-CRLF conversion. */
 
 
-#define FF_USE_FIND            0
+#define FF_USE_FIND            1
 /* This option switches filtered directory read functions, f_findfirst() and
 /  f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
 
 /* This option switches f_expand function. (0:Disable or 1:Enable) */
 
 
-#define FF_USE_CHMOD   0
+#define FF_USE_CHMOD   1
 /* This option switches attribute manipulation functions, f_chmod() and f_utime().
 /  (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */
 
 
-#define FF_USE_LABEL   0
+#define FF_USE_LABEL   1
 /* This option switches volume label functions, f_getlabel() and f_setlabel().
 /  (0:Disable or 1:Enable) */
 
index 28e92be7f6719e09ca0d7d85ec9ebd9961e3ac54..e6df4085d99172be3b8909d041994271a8a0ca24 100644 (file)
@@ -10,6 +10,8 @@
 #ifndef CLI_H
 #define CLI_H
 
+#include "common.h"
+
 /**
  * Go into the command loop
  *
@@ -30,7 +32,7 @@ void cli_loop(void);
  *           (If cmd is NULL or "" or longer than CONFIG_SYS_CBSIZE-1 it is
  *           considered unrecognized)
  */
-//int cli_simple_run_command(const char *cmd, int flag);
+//int cli_simple_run_command(const char *cmd, uint_fast8_t flag);
 
 /**
  * cli_simple_run_command_list() - Execute a list of command
@@ -45,7 +47,7 @@ void cli_loop(void);
  * @param flag Execution flags (CMD_FLAG_...)
  * @return 0 on success, or != 0 on error.
  */
-//int cli_simple_run_command_list(char *cmd, int flag);
+//int cli_simple_run_command_list(char *cmd, uint_fast8_t flag);
 
 /**
  * parse_line() - split a command line down into separate arguments
@@ -73,7 +75,7 @@ void cli_loop(void);
  * @param flag Execution flags (CMD_FLAG_...)
  * @return 0 on success, or != 0 on error.
  */
-int run_command(const char *cmd, int flag);
+int run_command(const char *cmd, uint_fast8_t flag);
 
 int run_command_list(const char *cmd, int len);
 
diff --git a/include/cmd_attach.h b/include/cmd_attach.h
new file mode 100644 (file)
index 0000000..2bd7363
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * (C) Copyright 2018 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef CMD_ATTACH_H
+#define CMD_ATTACH_H
+
+#include "command.h"
+
+command_ret_t do_attach(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+
+#endif /* CMD_ATTACH_H */
diff --git a/include/cmd_boot.h b/include/cmd_boot.h
new file mode 100644 (file)
index 0000000..015a215
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * (C) Copyright 2018 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef CMD_BOOT_H
+#define CMD_BOOT_H
+
+#include "command.h"
+
+command_ret_t do_loadf(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+command_ret_t do_bootcf(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+command_ret_t do_busreq_pulse(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+command_ret_t do_go(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+command_ret_t do_restart(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+command_ret_t do_reset(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[]);
+command_ret_t do_console(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+
+
+
+#endif /* CMD_BOOT_H */
diff --git a/include/cmd_date.h b/include/cmd_date.h
new file mode 100644 (file)
index 0000000..cd98f2a
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * (C) Copyright 2018 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef CMD_DATE_H
+#define CMD_DATE_H
+
+#include "command.h"
+
+command_ret_t do_date(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+
+#endif /* CMD_DATE_H */
diff --git a/include/cmd_fat.h b/include/cmd_fat.h
new file mode 100644 (file)
index 0000000..ed96a52
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * (C) Copyright 2014-2018 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef CMD_FAT_H
+#define CMD_FAT_H
+
+#include "command.h"
+
+extern cmd_tbl_t cmd_tbl_fat[];
+
+command_ret_t do_fat(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+
+void setup_fatfs(void);
+
+#endif /* CMD_FAT_H */
diff --git a/include/cmd_gpio.h b/include/cmd_gpio.h
new file mode 100644 (file)
index 0000000..d2f211d
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * (C) Copyright 2018 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef CMD_GPIO_H
+#define CMD_GPIO_H
+
+#include "command.h"
+
+command_ret_t do_gpio(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+
+
+#endif /* CMD_GPIO_H */
diff --git a/include/cmd_loadcpm3.h b/include/cmd_loadcpm3.h
new file mode 100644 (file)
index 0000000..5ef2a9d
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * (C) Copyright 2018 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef CMD_LOADCPM3_H
+#define CMD_LOADCPM3_H
+
+#include "command.h"
+
+command_ret_t do_loadcpm3(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+
+#endif /* CMD_LOADCPM3_H */
diff --git a/include/cmd_loadihex.h b/include/cmd_loadihex.h
new file mode 100644 (file)
index 0000000..7ca53cf
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * (C) Copyright 2018 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef CMD_LOADIHEX_H
+#define CMD_LOADIHEX_H
+
+#include "command.h"
+
+command_ret_t do_loadihex(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+
+#endif /* CMD_LOADIHEX_H */
index 782c10a94e679fa379ec35e06e7019418b930f0d..b019d27e023690deb0382209ddafafa519901efc 100644 (file)
@@ -1,30 +1,29 @@
 /*
  * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
  *
- * SPDX-License-Identifier:    GPL-2.0+
+ * SPDX-License-Identifier:    GPL-2.0
  */
 
 #ifndef CMD_MEM_H
 #define CMD_MEM_H
 
 #include "command.h"
-#include "cmd_mem.h"
 
 
-extern command_ret_t do_mem_md(cmd_tbl_t *, int, int, char * const []);
-extern command_ret_t do_mem_mm(cmd_tbl_t *, int, int, char * const []);
-extern command_ret_t do_mem_nm(cmd_tbl_t *, int, int, char * const []);
-extern command_ret_t do_mem_mw(cmd_tbl_t *, int, int, char * const []);
-extern command_ret_t do_mem_cp(cmd_tbl_t *, int, int, char * const []);
-extern command_ret_t do_mem_cmp(cmd_tbl_t *, int, int, char * const []);
-extern command_ret_t do_mem_base(cmd_tbl_t *, int, int, char * const []);
-extern command_ret_t do_mem_loop(cmd_tbl_t *, int, int, char * const []);
-extern command_ret_t do_mem_loopw(cmd_tbl_t *, int, int, char * const []);
+extern command_ret_t do_mem_md(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+extern command_ret_t do_mem_mm(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+extern command_ret_t do_mem_nm(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+extern command_ret_t do_mem_mw(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+extern command_ret_t do_mem_cp(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+extern command_ret_t do_mem_cmp(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+extern command_ret_t do_mem_base(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+extern command_ret_t do_mem_loop(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+extern command_ret_t do_mem_loopw(cmd_tbl_t *, uint_fast8_t, int, char * const []);
 #ifdef CONFIG_CMD_MEMTEST
-extern command_ret_t do_mem_mtest(cmd_tbl_t *, int, int, char * const []);
+extern command_ret_t do_mem_mtest(cmd_tbl_t *, uint_fast8_t, int, char * const []);
 #endif
 #ifdef CONFIG_MX_CYCLIC
-extern command_ret_t do_mem_mdc(cmd_tbl_t *, int, int, char * const []);
+extern command_ret_t do_mem_mdc(cmd_tbl_t *, uint_fast8_t, int, char * const []);
 #endif /* CONFIG_MX_CYCLIC */
 
 #endif /* CMD_MEM_H */
diff --git a/include/cmd_misc.h b/include/cmd_misc.h
new file mode 100644 (file)
index 0000000..f0f56a7
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * (C) Copyright 2018 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef CMD_MISC_H
+#define CMD_MISC_H
+
+#include "command.h"
+
+command_ret_t do_echo(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[]);
+command_ret_t do_sleep(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[]);
+
+#endif /* CMD_MISC_H */
diff --git a/include/cmd_run.h b/include/cmd_run.h
new file mode 100644 (file)
index 0000000..4691a55
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * (C) Copyright 2018 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef CMD_RUN_H
+#define CMD_RUN_H
+
+#include "command.h"
+
+command_ret_t do_source(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+command_ret_t do_run(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+
+
+#endif /* CMD_RUN_H */
diff --git a/include/cmd_sd.h b/include/cmd_sd.h
new file mode 100644 (file)
index 0000000..0a5f5e5
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * (C) Copyright 2018 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef CMD_SD_H
+#define CMD_SD_H
+
+#include "command.h"
+
+extern cmd_tbl_t cmd_tbl_sd[];
+
+command_ret_t do_sd(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+
+#endif /* CMD_SD_H */
index 9ca460df4284a076a5179a46fef63bde45258572..54c04727f92df4f5abbc461c5a5148de95320a7b 100644 (file)
@@ -44,24 +44,24 @@ typedef enum {
  * Monitor Command Table
  */
 
+typedef const FLASH struct cmd_tbl_s cmd_tbl_t;
 struct cmd_tbl_s {
        const FLASH char *name;         /* Command Name                 */
-       int             maxargs;                        /* maximum number of arguments  */
-       int             repeatable;                     /* autorepeat allowed?          */
+       uint8_t         maxargs;                        /* maximum number of arguments  */
+       uint8_t         flags;                  /* autorepeat allowed?          */
                                                                /* Implementation function      */
-       command_ret_t   (*cmd)(const FLASH struct cmd_tbl_s *, int, int, char * const []);
+       command_ret_t   (*cmd)(cmd_tbl_t *, uint_fast8_t, int, char * const []);
        const FLASH char *usage;        /* Usage message        (short) */
 #ifdef CONFIG_SYS_LONGHELP
        const FLASH char *help;         /* Help  message        (long)  */
 #endif
+       cmd_tbl_t *subcmd;
 #ifdef CONFIG_AUTO_COMPLETE
        /* do auto completion on the arguments */
        int             (*complete)(int argc, char * const argv[], char last_char, int maxv, char *cmdv[]);
 #endif
 };
 
-typedef const FLASH struct cmd_tbl_s cmd_tbl_t;
-
 /**
  * Process a command with arguments. We look up the command and execute it
  * if valid. Otherwise we print a usage message.
@@ -75,16 +75,13 @@ typedef const FLASH struct cmd_tbl_s cmd_tbl_t;
  * @return 0 if the command succeeded, 1 if it failed
  */
 command_ret_t
-cmd_process(int flag, int argc, char * const argv[], uint_fast8_t *repeatable);
+cmd_process(uint_fast8_t flag, int argc, char * const argv[], uint_fast8_t *repeatable);
 
 
 /* command.c */
-command_ret_t _do_help (cmd_tbl_t *cmd_start, int cmd_items, cmd_tbl_t * cmdtp, int
-             flag, int argc, char * const argv[]);
-cmd_tbl_t *find_cmd(const char *cmd);
-cmd_tbl_t *find_cmd_tbl (const char *cmd, cmd_tbl_t *table, int table_len);
+command_ret_t do_help(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[]);
 
-int cmd_tbl_item_count(void);
+int cmd_tbl_item_count(cmd_tbl_t *p);
 command_ret_t cmd_usage(cmd_tbl_t *cmdtp);
 
 #ifdef CONFIG_AUTO_COMPLETE
@@ -106,21 +103,19 @@ int cmd_process_error(cmd_tbl_t *cmdtp, int err);
  *
  * All commands use a common argument format:
  *
- * void function (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+ * void function (cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[]);
  */
 
 
 #ifdef CONFIG_CMD_BOOTD
-extern command_ret_t do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+extern command_ret_t do_bootd(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[]);
 #endif
 #ifdef CONFIG_CMD_BOOTM
-extern command_ret_t do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+extern command_ret_t do_bootm(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[]);
 extern int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd);
 #else
-static inline int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd)
+static inline int bootm_maybe_autostart(cmd_tbl_t *cmdtp UNUSED, const char *cmd UNUSED)
 {
-       (void) cmdtp; (void) cmd;
-
        return 0;
 }
 #endif
@@ -128,13 +123,19 @@ static inline int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd)
 extern int common_diskboot(cmd_tbl_t *cmdtp, const char *intf, int argc,
                           char *const argv[]);
 
-extern command_ret_t do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
-
 /*
  * Command Flags:
  */
-#define CMD_FLAG_REPEAT                0x0001  /* repeat last command          */
-#define CMD_FLAG_BOOTD         0x0002  /* command is from bootd        */
+#define CMD_FLAG_REPEAT                0x01    /* repeat last command          */
+#define CMD_FLAG_BOOTD         0x02    /* command is from bootd        */
+
+/*
+ * Flags for command table:
+ */
+#define CTBL_RPT                       0x01    /* command is repeatable        */
+#define CTBL_SUBCMD                    0x02    /* command has subcommands      */
+#define CTBL_SUBCMDAUTO                0x04    /* execute subcommands whithout prefix */
+#define CTBL_DBG                       0x08    /* command is  only for debugging */
 
 #ifdef CONFIG_AUTO_COMPLETE
 # define _CMD_COMPLETE(x) x,
@@ -148,16 +149,27 @@ extern command_ret_t do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const
 #endif
 
 
-#define CMD_TBL_ITEM_COMPLETE(_name, _maxargs, _rep, _cmd,             \
-                               _usage, _help, _comp)                   \
-               { FSTR(#_name), _maxargs, _rep, _cmd, FSTR(_usage),     \
-                       _CMD_HELP(FSTR(_help)) _CMD_COMPLETE(_comp) }
+#define CMD_TBL_ITEM_FULL(_name, _maxargs, _rep, _cmd,                         \
+                               _usage, _help, _subtbl, _comp)                                 \
+               { FSTR(#_name), _maxargs, _rep, _cmd, FSTR(_usage),                        \
+                       _CMD_HELP(FSTR(_help)) _subtbl, _CMD_COMPLETE(_comp) }
+
+#define CMD_TBL_ITEM_COMPLETE(_name, _maxargs, _rep, _cmd,                     \
+                               _usage, _help, _comp)                                          \
+               { FSTR(#_name), _maxargs, _rep, _cmd, FSTR(_usage),                        \
+                       _CMD_HELP(FSTR(_help)) NULL, _CMD_COMPLETE(_comp) }
+
+#define CMD_TBL_ITEM(_name, _maxargs, _rep, _cmd, _usage, _help)               \
+       CMD_TBL_ITEM_FULL(_name, _maxargs, _rep, _cmd,                             \
+                                       _usage, _help, NULL, NULL)
+
+#define CMD_TBL_ITEM_TOP(_name, _maxargs, _rep, _cmd, _usage, _help, _subtbl)  \
+       CMD_TBL_ITEM_FULL(_name, _maxargs, _rep, _cmd,                             \
+                                       _usage, _help, _subtbl, NULL)
 
-#define CMD_TBL_ITEM(_name, _maxargs, _rep, _cmd, _usage, _help)       \
-       CMD_TBL_ITEM_COMPLETE(_name, _maxargs, _rep, _cmd,              \
-                                       _usage, _help, NULL)
+#define CMD_TBL_END(_table_start)      { .subcmd = _table_start }
 
-typedef command_ret_t (*do_cmd_t)(cmd_tbl_t *, int, int, char * const []);
+typedef command_ret_t (*do_cmd_t)(cmd_tbl_t *, uint_fast8_t, int, char * const []);
 
 extern  cmd_tbl_t cmd_tbl[];
 
index e22b7a158316bbb9c94f39c9a5bac6da272a40ca..eb38853cbe96ad0f8870df023a1bd32691079949 100644 (file)
@@ -9,9 +9,15 @@
 
 #include <stdio.h>
 #include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdlib.h>
 
 #define GCC_VERSION (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__)
 
+#define USED __attribute__((used))
+#define UNUSED __attribute__((unused))
+
 #ifdef __AVR__
 #include <avr/io.h>
 #include <avr/pgmspace.h>
index 86c0df02369c1234b385da33abb1d2694eb5fa01..a71fdf9f3c12a49a42651b9e63b7ffb4b591a685 100644 (file)
@@ -15,16 +15,16 @@ uint_fast8_t tstc(void);
 
 int my_getchar(uint_fast8_t waitforchar);
 
-/* test if ctrl-c was pressed */
+/* Test if ctrl-c was pressed */
 uint_fast8_t ctrlc(void);
 
-
-/* pass 1 to disable ctrlc() checking, 0 to enable.
- * returns previous state
- */
+/* Pass 1 to disable ctrlc() checking, 0 to enable. Returns previous state. */
 uint_fast8_t disable_ctrlc(uint_fast8_t disable);
 
 uint_fast8_t had_ctrlc (void);
 void clear_ctrlc(void);
 
+/* Reads user's confirmation. Returns 1 if user's input is "y", "Y", "yes" or "YES" */
+uint_fast8_t confirm_yes(void);
+
 #endif /* CON_UTILS_H */
index 8d7f348028eeb6afefea6900e92474abeaf42172..29862852b057a7369806e580c834f17d5941af18 100644 (file)
@@ -8,32 +8,33 @@
 #define CONFIG_H
 
 /* Version */
-#define VERSION                 "0.6.8.2"
+#define VERSION                        "0.6.8.2"
 
 /* Environment variables */
 
-#define ENV_BAUDRATE                   "baudrate"
-#define ENV_BOOTDELAY                  "bootdelay"
-#define ENV_BOOTCMD                            "bootcmd"
+#define ENV_BAUDRATE                           "baudrate"
+#define ENV_BOOTDELAY                          "bootdelay"
+#define ENV_BOOTCMD                                    "bootcmd"
 
-#define ENV_CPM3_SYSFILE               "cpm3_file"
-#define ENV_CPM3_COMMON_BASE   "cpm3_commonbase"
-#define ENV_CPM3_BANKED_BASE   "cpm3_bankedbase"
-#define ENV_CPM3_SCB                   "cpm3_scb"
+#define ENV_CPM3_SYSFILE                       "cpm3_file"
+#define ENV_CPM3_COMMON_BASE           "cpm3_commonbase"
+#define ENV_CPM3_BANKED_BASE           "cpm3_bankedbase"
+#define ENV_CPM3_SCB                           "cpm3_scb"
 
-#define ENV_PINALIAS                   "pin_alias"
-#define ENV_STARTADDRESS               "startaddress"
-#define ENV_ESC_CHAR                   "esc_char"
+#define ENV_PINALIAS                           "pin_alias"
+#define ENV_STARTADDRESS                       "startaddress"
+#define ENV_ESC_CHAR                           "esc_char"
 
-#define ENV_SINGLESTEP                 "singlestep"
+#define ENV_HOME                                       "HOME"
+#define ENV_SINGLESTEP                         "singlestep"
 
-#define CONFIG_ENV_SIZE                        1600
-#define CONFIG_ENV_OFFSET              0
-#define CONFIG_ENVVAR_MAX              30
+#define CONFIG_ENV_SIZE                                1600
+#define CONFIG_ENV_OFFSET                      0
+#define CONFIG_ENVVAR_MAX                      40
 
-#define CONFIG_BAUDRATE                        115200L
-#define CONFIG_PWRON_DELAY             2000    /* ms to wait after power on */
-#define CONFIG_BOOTDELAY               4
+#define CONFIG_BAUDRATE                                115200L
+#define CONFIG_PWRON_DELAY                     2000    /* ms to wait after power on */
+#define CONFIG_BOOTDELAY                       4
 //#define CONFIG_ZERO_BOOTDELAY_CHECK  1
 
 #define CONFIG_CPM3_SYSFILE                    "0:/cpm3.sys"
 //#define CONFIG_CPM3_COMMON_BASE_STR  "F000"
 #define CONFIG_CPM3_BANKED_BASE_STR    "0"
 
-#define CONFIG_CPM_MAX_DRIVE   8
-#define CONFIG_CPM_BASE_DRIVE  'A'
-#define CONFIG_CPM_BLOCK_SIZE  512
+#define CONFIG_CPM_MAX_DRIVE           8
+#define CONFIG_CPM_BASE_DRIVE          'A'
+#define CONFIG_CPM_BLOCK_SIZE          512
 
 #define CONFIG_CMD_MEMTEST
 #define CONFIG_MX_CYCLIC
-#define CONFIG_SYS_RAMSIZE_MAX (1l<<19)        /* max. addressable memory */
+#define CONFIG_SYS_RAMSIZE_MAX                 (1l<<19)        /* max. addressable memory */
 
-#define CONFIG_CMD_DATE 1
+#define CONFIG_CMD_DATE                        1
 
 
 //#define CONFIG_CMD_LOADB
 
 
-#define CONFIG_SYS_I2C_RTC_ADDR        0x50
-#define CONFIG_SYS_I2C_BUFSIZE 64
-#define CONFIG_SYS_I2C_CLOCK   100000L /* SCL clock frequency in Hz */
+#define CONFIG_SYS_I2C_RTC_ADDR                0x50
+#define CONFIG_SYS_I2C_BUFSIZE         64
+#define CONFIG_SYS_I2C_CLOCK           100000L /* SCL clock frequency in Hz */
 
-#define CONFIG_SYS_CBSIZE      250
-#define CONFIG_SYS_HIST_MAX    20
-#define CONFIG_SYS_MAXARGS     20
-#define CONFIG_SYS_ENV_NAMELEN 16
+#define CONFIG_SYS_CBSIZE                      250
+#define CONFIG_SYS_HIST_MAX                    20
+#define CONFIG_SYS_MAXARGS                     20
+#define CONFIG_SYS_ENV_NAMELEN         16
+#define CONFIG_SYS_MAX_PATHLEN         127
+#define CONFIG_SYS_MALLOC_MARGIN       256
 
 #define CONFIG_SYS_PROMPT                      "-> "
 #define CONFIG_SYS_PROMPT_REPEAT       "=> "
-#define CONFIG_ESC_CHAR                ('^'-0x40)
+#define CONFIG_ESC_CHAR                                ('^'-0x40)
 
-#define CONFIG_SYS_FBOOTSIG "Peda"
+#define CONFIG_SYS_FBOOTSIG            "Peda"
 
 /* TODO: */
-//#define CONFIG_AUTO_COMPLETE 1
+//#define CONFIG_AUTO_COMPLETE         1
 
-#define CONFIG_SYS_LONGHELP    1
+#define CONFIG_SYS_LONGHELP                    1
 
 #endif /* CONFIG_H */
index 0ee0129fa45dae5ebeeb14a71f2f7f43b7c0a881..b7b6deafb5497f58206aca825e9a2334dcc9f0ea 100644 (file)
 #ifndef DEBUG_H_
 #define DEBUG_H_
 
-#include "common.h"
+#include "command.h"
+
+command_ret_t do_dump_mem(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+command_ret_t do_mem_mm_avr(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+command_ret_t do_mem_nm_avr(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+command_ret_t do_eep_cp(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+command_ret_t do_pr_free_avr(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+command_ret_t do_pr_heap_avr(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+
+void printfreelist(const char * title);
+size_t get_freemem(void);
+
 
 #ifdef DEBUG
 #define _DEBUG 1
@@ -43,8 +54,4 @@
 #endif
 #endif /* 0 */
 
-
-void printfreelist(const char * title);
-
-
 #endif /* DEBUG_H_ */
index bc4441302bc3ef18c919cfd0894bab86da4df051..1dbe30f413cf33e02c99882c5bcf2d932afed62f 100644 (file)
@@ -7,10 +7,14 @@
 #ifndef ENV_H
 #define ENV_H
 
-#include <stdbool.h>
+#include "command.h"
 
-int env_init(void);
+command_ret_t do_env_print(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+command_ret_t do_env_default(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+command_ret_t do_env_set(cmd_tbl_t *, uint_fast8_t, int, char * const []);
+command_ret_t do_env_save(cmd_tbl_t *, uint_fast8_t, int, char * const []);
 
+int env_init(void);
 char *getenv_str(const MEMX char *name);
 unsigned long getenv_ulong(const MEMX char *name, int base, unsigned long default_val);
 bool getenv_yesno(const MEMX char *name);
diff --git a/include/xmalloc.h b/include/xmalloc.h
deleted file mode 100644 (file)
index cb0019f..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-
-#ifndef XMALLOC_H
-#define XMALLOC_H
-
-void* xmalloc(size_t size);
-void* xrealloc(void *p, size_t size);
-
-#endif /* XMALLOC_H */