From f7c30da5c75281bd2dfba133529a7ac1fa31e6b1 Mon Sep 17 00:00:00 2001 From: marco Date: Thu, 1 Jun 2006 12:29:21 +0000 Subject: [PATCH] Add first simple protocol command (version request). git-svn-id: https://src.develer.com/svnoss/bertos/trunk@654 38d2e660-2303-0410-9eaa-f027e97ec537 --- app/triface/appconfig.h | 12 ++- app/triface/protocol.c | 193 ++++++++++++++++++++++++++++++++++++++++ app/triface/protocol.h | 30 +++++++ app/triface/triface.c | 9 +- app/triface/triface.mk | 15 +++- app/triface/verstag.h | 69 ++++++++++++++ 6 files changed, 323 insertions(+), 5 deletions(-) create mode 100755 app/triface/protocol.c create mode 100755 app/triface/protocol.h create mode 100755 app/triface/verstag.h diff --git a/app/triface/appconfig.h b/app/triface/appconfig.h index 9bbd9963..31ee1e85 100755 --- a/app/triface/appconfig.h +++ b/app/triface/appconfig.h @@ -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. *#* @@ -57,6 +60,10 @@ /** 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. * @@ -110,7 +117,7 @@ #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 @@ -134,4 +141,7 @@ /// 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 index 00000000..1b66c990 --- /dev/null +++ b/app/triface/protocol.c @@ -0,0 +1,193 @@ +/** + * \file + * + * + * \brief Implementation of the command protocol between the board and the host + * + * + * \version $Id$ + * + * \author Giovanni Bajo + * \author Marco Benelli + * \author Bernardo Innocenti + */ + +/*#* + *#* $Log$ + *#* Revision 1.1 2006/06/01 12:29:21 marco + *#* Add first simple protocol command (version request). + *#* + *#*/ + +#include "protocol.h" + +#include +#include +#include +#include +#include +#include + +#include + + +// 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 index 00000000..02314845 --- /dev/null +++ b/app/triface/protocol.h @@ -0,0 +1,30 @@ +/** + * \file + * + * + * \brief Implementation of the command protocol between the board and the host + * + * \version $Id$ + * + * \author Marco Benelli + */ + +/*#* + *#* $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 diff --git a/app/triface/triface.c b/app/triface/triface.c index c0638081..7cd01e00 100755 --- a/app/triface/triface.c +++ b/app/triface/triface.c @@ -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 #include #include +#include + +#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; diff --git a/app/triface/triface.mk b/app/triface/triface.mk index 990a68ee..79b52235 100755 --- a/app/triface/triface.mk +++ b/app/triface/triface.mk @@ -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 # # $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. # @@ -15,27 +18,33 @@ # 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 index 00000000..86ea7c43 --- /dev/null +++ b/app/triface/verstag.h @@ -0,0 +1,69 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \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 */ -- 2.25.1