Add first simple protocol command (version request).
authormarco <marco@38d2e660-2303-0410-9eaa-f027e97ec537>
Thu, 1 Jun 2006 12:29:21 +0000 (12:29 +0000)
committermarco <marco@38d2e660-2303-0410-9eaa-f027e97ec537>
Thu, 1 Jun 2006 12:29:21 +0000 (12:29 +0000)
git-svn-id: https://src.develer.com/svnoss/bertos/trunk@654 38d2e660-2303-0410-9eaa-f027e97ec537

app/triface/appconfig.h
app/triface/protocol.c [new file with mode: 0755]
app/triface/protocol.h [new file with mode: 0755]
app/triface/triface.c
app/triface/triface.mk
app/triface/verstag.h [new file with mode: 0755]

index 9bbd99636c7b1d0174ea84f8e9af0f6f15171302..31ee1e854c51f9b588e9a67cc4f0a270c4875533 100755 (executable)
@@ -46,6 +46,9 @@
 
 /*#*
  *#* $Log$
+ *#* Revision 1.2  2006/06/01 12:29:21  marco
+ *#* Add first simple protocol command (version request).
+ *#*
  *#* Revision 1.1  2006/05/18 00:41:47  bernie
  *#* New triface devlib application.
  *#*
 /** Baud-rate for the kdebug console */
 #define CONFIG_KDEBUG_BAUDRATE  38400
 
+/** Serial port number for kdebug console */
+#define CONFIG_KDEBUG_PORT  0
+
+
 /**
  * printf()-style formatter configuration.
  *
        #define CONFIG_SER_DEFBAUDRATE   0
 
        /** Enable ser_gets() and ser_gets_echo() */
-       #define CONFIG_SER_GETS          0
+       #define CONFIG_SER_GETS          1
 
        /** Enable second serial port in emulator. */
        #define CONFIG_EMUL_UART1        0
 /// Enable watchdog timer.
 #define CONFIG_WATCHDOG  0
 
+/// Enable internal parser commands.
+#define CONFIG_INTERNAL_COMMANDS  0
+
 #endif /* APPCONFIG_TRIFACE_H */
diff --git a/app/triface/protocol.c b/app/triface/protocol.c
new file mode 100755 (executable)
index 0000000..1b66c99
--- /dev/null
@@ -0,0 +1,193 @@
+/**
+ * \file
+ * <!--
+ * Copyright 2006 Develer S.r.l. (http://www.develer.com/)
+ * -->
+ *
+ * \brief Implementation of the command protocol between the board and the host
+ *
+ *
+ * \version $Id$
+ *
+ * \author Giovanni Bajo <rasky@develer.com>
+ * \author Marco Benelli <marco@develer.com>
+ * \author Bernardo Innocenti <bernie@develer.com>
+ */
+
+/*#*
+ *#* $Log$
+ *#* Revision 1.1  2006/06/01 12:29:21  marco
+ *#* Add first simple protocol command (version request).
+ *#*
+ *#*/
+
+#include "protocol.h"
+
+#include <drv/ser.h>
+#include <mware/readline.h>
+#include <mware/parser.h>
+#include <cfg/compiler.h>
+#include <cfg/debug.h>
+#include <verstag.h>
+
+#include <string.h>
+
+
+// DEBUG: set to 1 to force interactive mode
+#define FORCE_INTERACTIVE         1
+
+/**
+ * True if we are in interactive mode, false if we are in protocol mode.
+ * In interactive mode, commands are read through readline() (prompt, completion,
+ * history) without IDs, and replies/errors are sent to the serial output.
+ * In protocol mode, we implement the default protocol
+ */
+static bool interactive;
+
+/// Readline context, used for interactive mode.
+static struct RLContext rl_ctx;
+
+
+/**
+ * Send a NAK asking the host to send the current message again.
+ *
+ * \param err  human-readable description of the error for debug purposes.
+ */
+INLINE void NAK(Serial *ser, const char *err)
+{
+#ifdef _DEBUG
+       ser_printf(ser, "NAK \"%s\"\r\n", err);
+#else
+       ser_printf(ser, "NAK\r\n");
+#endif
+}
+
+static void protocol_parse(Serial *ser, const char *buf)
+{
+       const struct CmdTemplate *templ;
+       parms args[8]; // FIXME FIXME!!
+
+       templ = parser_get_cmd_template(buf);
+
+       if (!templ)
+       {
+               NAK(ser, "invalid command");
+               return;
+       }
+
+       // Extract the arguments for the command
+       if (!parser_get_cmd_arguments(buf, templ, args))
+       {
+               NAK(ser, "invalid arguments");
+               return;
+       }
+
+       // EXEC!
+}
+
+void protocol_run(Serial *ser)
+{
+       // \todo to be removed, we could probably access the serial FIFO directly
+       static char linebuf[80];
+
+       if (!interactive)
+       {
+               ser_gets(ser, linebuf, sizeof(linebuf));
+
+               // reset serial port error anyway
+               ser_setstatus(ser, 0);
+
+               // check message minimum length
+               if (linebuf[0])
+               {
+                       if (linebuf[0] == 0x1B && linebuf[1] == 0x1B)  // ESC
+                       {
+                               interactive = true;
+                               ser_printf(ser, "Entering interactive mode\r\n");
+                       }
+                       else
+                               protocol_parse(ser, linebuf);
+               }
+       }
+       else
+       {
+               const char *buf;
+
+               /*
+                * Read a line from serial. We use a temporary buffer
+                * because otherwise we would have to extract a message
+                * from the port immediately: there might not be any
+                * available, and one might get free while we read
+                * the line. We also add a fake ID at the start to
+                * fool the parser.
+                */
+               buf = rl_readline(&rl_ctx);
+
+               if (buf && buf[0] != '\0')
+               {
+                       // exit special case to immediately change serial input
+                       if (!strcmp(buf, "exit") || !strcmp(buf, "quit"))
+                       {
+                               rl_clear_history(&rl_ctx);
+                               ser_printf(ser, "Leaving interactive mode...\r\n");
+                               interactive = FORCE_INTERACTIVE;
+                       }
+                       else
+                       {
+                               //TODO: remove sequence numbers
+                               linebuf[0] = '0';
+                               linebuf[1] = ' ';
+
+                               strncpy(linebuf + 2, buf, sizeof(linebuf) - 3);
+                               linebuf[sizeof(linebuf) - 1] = '\0';
+                               protocol_parse(ser, linebuf);
+                       }
+               }
+       }
+}
+
+static ResultCode cmd_ver(const char **str)
+{
+       *str = VERS_TAG;
+kprintf("hello, version world!\nver=" VERS_TAG "\n");
+       return RC_REPLY;
+}
+static ResultCode cmd_add_hunk(parms args_results[])
+{
+       return cmd_ver(&args_results[0].s);
+}
+const struct CmdTemplate cmd_ver_template =
+{
+       "ver", "", "d", cmd_add_hunk
+};
+
+static void protocol_registerCmds(void)
+{
+//     parser_register_cmd(&CMD_HUNK_TEMPLATE(quit));
+//     parser_register_cmd(&CMD_HUNK_TEMPLATE(exit));
+//     parser_register_cmd(&CMD_HUNK_TEMPLATE(wait));
+//     parser_register_cmd(&CMD_HUNK_TEMPLATE(delay));
+//     parser_register_cmd(&CMD_HUNK_TEMPLATE(SYN));
+//     parser_register_cmd(&CMD_HUNK_TEMPLATE(RST));
+//     parser_register_cmd(&CMD_HUNK_TEMPLATE(skip_end));
+//     parser_register_cmd(&CMD_HUNK_TEMPLATE(restart));
+//     parser_register_cmd(&CMD_HUNK_TEMPLATE(ver));
+//     parser_register_cmd(&CMD_HUNK_TEMPLATE(power_off));
+
+       parser_register_cmd(&cmd_ver_template);
+}
+void protocol_init(Serial *ser)
+{
+       interactive = FORCE_INTERACTIVE;
+
+       // Initialize the readline context used for interactive mode
+       rl_init_ctx(&rl_ctx);
+       rl_setprompt(&rl_ctx, ">> ");
+       rl_sethook_get(&rl_ctx, (getc_hook)ser_getchar, ser);
+       rl_sethook_put(&rl_ctx, (putc_hook)ser_putchar, ser);
+       rl_sethook_match(&rl_ctx, parser_rl_match, NULL);
+
+       parser_init();
+
+       protocol_registerCmds();
+}
diff --git a/app/triface/protocol.h b/app/triface/protocol.h
new file mode 100755 (executable)
index 0000000..0231484
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ * \file
+ * <!--
+ * Copyright 2006 Develer S.r.l. (http://www.develer.com/)
+ * -->
+ *
+ * \brief Implementation of the command protocol between the board and the host
+ *
+ * \version $Id$
+ *
+ * \author Marco Benelli <marco@develer.com>
+ */
+
+/*#*
+ *#* $Log$
+ *#* Revision 1.1  2006/06/01 12:29:21  marco
+ *#* Add first simple protocol command (version request).
+ *#*
+ *#*/
+
+#ifndef PROTOCOL_H
+#define PROTOCOL_H
+
+// fwd decl
+struct Serial;
+
+void protocol_init(struct Serial *ser);
+void protocol_run(struct Serial *ser);
+
+#endif // PROTOOCOL_H
index c0638081b5091693c6cc636ced188a7a88e38be4..7cd01e00301cab72ec87bd4400fb916e05b9c2bf 100755 (executable)
@@ -15,6 +15,9 @@
 
 /*#*
  *#* $Log$
+ *#* Revision 1.2  2006/06/01 12:29:21  marco
+ *#* Add first simple protocol command (version request).
+ *#*
  *#* Revision 1.1  2006/05/18 00:41:47  bernie
  *#* New triface devlib application.
  *#*
@@ -24,6 +27,9 @@
 #include <drv/buzzer.h>
 #include <drv/ser.h>
 #include <cfg/macros.h>
+#include <mware/parser.h>
+
+#include "protocol.h"
 
 int main(void)
 {
@@ -36,11 +42,12 @@ int main(void)
        Serial *host_port = ser_open(0);
        ser_setbaudrate(host_port, 38400);
 
+       protocol_init(host_port);
 
        // Main loop
        for(;;)
        {
-               ser_print(host_port, "Hello, world!\r\n");
+               protocol_run(host_port);
        }
 
        return 0;
index 990a68ee21f2ae6cb50c024ad692799a1e65c168..79b5223503b8b0e2d45e4745c5304bd2d582ef0c 100755 (executable)
@@ -3,11 +3,14 @@
 # Copyright 2006 Develer S.r.l. (http://www.develer.com/)
 # All rights reserved.
 #
-# Makefile fragment for DevLib demo application.
+# Makefile fragment for DevLib triface application.
 #
 # Author: Bernardo Innocenti <bernie@develer.com>
 #
 # $Log$
+# Revision 1.2  2006/06/01 12:29:21  marco
+# Add first simple protocol command (version request).
+#
 # Revision 1.1  2006/05/18 00:41:47  bernie
 # New triface devlib application.
 #
 
 
 # Set to 1 for debug builds
-demo_DEBUG = 1
+triface_DEBUG = 1
 
 # Our target application
 TRG += triface
 
 triface_CSRC = \
        app/triface/triface.c \
+       app/triface/protocol.c \
        drv/timer.c \
        drv/ser.c \
        drv/ser_avr.c \
        mware/formatwr.c \
        mware/hex.c \
+       mware/hashtable.c \
+       mware/readline.c \
+       mware/parser.c \
 
 #      drv/buzzer.c
 
+triface_PCSRC += mware/formatwr.c
+
 triface_CFLAGS = -Os -D'ARCH=0' -Iapp/triface/hw -Iapp/triface
 triface_MCU = atmega128
 
 # Debug stuff
 ifeq ($(triface_DEBUG),1)
        triface_CFLAGS += -D_DEBUG
-#      triface_PCSRC += drv/kdebug.c
+       triface_PCSRC += drv/kdebug.c
 endif
 
diff --git a/app/triface/verstag.h b/app/triface/verstag.h
new file mode 100755 (executable)
index 0000000..86ea7c4
--- /dev/null
@@ -0,0 +1,69 @@
+/**
+ * \file
+ * <!--
+ * Copyright 2003, 2004, 2005, 2006 Develer S.r.l. (http://www.develer.com/)
+ * Copyright 2001, 2002, 2003 by Bernardo Innocenti <bernie@codewiz.org>
+ * This file is part of DevLib - See README.devlib for information.
+ * -->
+ *
+ * \version $Id$
+ *
+ * \author Bernardo Innocenti <bernie@develer.com>
+ *
+ * \brief Declare application version strings
+ */
+#ifndef DEVLIB_VERSTAG_H
+#define DEVLIB_VERSTAG_H
+
+#ifndef ARCH_CONFIG_H
+       #include "cfg/arch_config.h"
+#endif
+
+#define APP_NAME "Triface"
+#define APP_DESCRIPTION "Trinity Interface Board"
+#define APP_AUTHOR "Develer"
+#define APP_COPYRIGHT "Copyright 2006 Develer (http://www.develer.com/)"
+
+#define VERS_MAJOR 0
+#define VERS_MINOR 1
+#define VERS_REV   0
+#define VERS_LETTER ""
+
+/*!
+ * If _SNAPSHOT is defined, \c VERS_TAG contains the build date
+ * date instead of a numeric version string.
+ */
+//#define _SNAPSHOT
+
+#ifdef _DEBUG
+       #define VERS_DBG "D"
+#else
+       #define VERS_DBG ""
+#endif
+
+#define __STRINGIZE(x) #x
+#define _STRINGIZE(x) __STRINGIZE(x)
+
+/*! Build application version string (i.e.: "1.7.0") */
+#define MAKE_VERS(maj,min,rev) _STRINGIZE(maj) "." _STRINGIZE(min) "." _STRINGIZE(rev) VERS_LETTER VERS_DBG
+#ifdef _SNAPSHOT
+       #define VERS_TAG "snapshot" " " __DATE__ " " __TIME__ " " VERS_LETTER " " VERS_DBG
+#else
+       #define VERS_TAG MAKE_VERS(VERS_MAJOR,VERS_MINOR,VERS_REV)
+#endif
+
+/*! Build application version string suitable for MS windows resource files (i.e.: "1, 7, 0, 1") */
+#define MAKE_RCVERS(maj,min,rev,bld) _STRINGIZE(maj) ", " _STRINGIZE(min) ", " _STRINGIZE(rev) ", " _STRINGIZE(bld)
+#define RCVERSION_TAG MAKE_VERS(VERS_MAJOR,VERS_MINOR,VERS_REV)
+
+/*! The revision string (contains VERS_TAG) */
+extern const char vers_tag[];
+
+/*! Sequential build number (contains VERS_BUILD) */
+extern const int vers_build_nr;
+//extern const char vers_build_str[];
+
+/*! Hostname of the machine used to build this binary (contains VERS_HOST) */
+extern const char vers_host[];
+
+#endif /* DEVLIB_VERSTAG_H */