aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2019-02-24 22:51:09 +0100
committerKévin Redon <kredon@sysmocom.de>2019-02-27 13:42:27 +0000
commitff9f4ceca9500eb23bb1def8d67ff31bc99d0dae (patch)
tree552ed5aa26f17f7ca16f567a37d76fdc5a50025e
parent3c045b29ce191f68184e463a4505ad473823af63 (diff)
Add mnimalistic command line interface "command.c"
This is a very simplistic command line interface parser which various parts of the code can use to register textual commands on the debug UART. Change-Id: I2d289228fb97ecde5602e9756f3d7c51fa65a3b7
-rw-r--r--sysmoOCTSIM/command.c101
-rw-r--r--sysmoOCTSIM/command.h20
-rw-r--r--sysmoOCTSIM/gcc/Makefile3
-rw-r--r--sysmoOCTSIM/main.c16
4 files changed, 135 insertions, 5 deletions
diff --git a/sysmoOCTSIM/command.c b/sysmoOCTSIM/command.c
new file mode 100644
index 0000000..9502f05
--- /dev/null
+++ b/sysmoOCTSIM/command.c
@@ -0,0 +1,101 @@
+#include <string.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include <utils.h>
+
+#include "atmel_start.h"
+#include "command.h"
+
+struct cmd_state {
+ const char *prompt;
+ char buf[128];
+ unsigned int buf_idx;
+ const struct command_fn *cmd[32];
+ unsigned int cmd_idx;
+};
+
+static struct cmd_state g_cmds;
+
+int command_register(const struct command_fn *cmd)
+{
+ if (g_cmds.cmd_idx >= ARRAY_SIZE(g_cmds.cmd))
+ return -1;
+ g_cmds.cmd[g_cmds.cmd_idx++] = cmd;
+ return 0;
+}
+
+DEFUN(help, help_cmd, "help", "Print command reference")
+{
+ unsigned int i;
+ printf("Help:\r\n");
+ printf(" Command Help\r\n");
+ printf(" ---------------- ----\r\n");
+ for (i = 0; i < g_cmds.cmd_idx; i++)
+ printf(" %-16s %s\r\n", g_cmds.cmd[i]->command, g_cmds.cmd[i]->help);
+}
+
+static void cmd_execute()
+{
+ char *argv[16];
+ unsigned int i;
+ int argc = 0;
+ char *cur;
+
+ printf("\r\n");
+ memset(argv, 0, sizeof(argv));
+
+ for (cur = strtok(g_cmds.buf, " "); cur; cur = strtok(NULL, " ")) {
+ if (argc >= ARRAY_SIZE(argv))
+ break;
+ argv[argc++] = cur;
+ }
+
+ for (i = 0; i < g_cmds.cmd_idx; i++) {
+ if (!strcmp(g_cmds.cmd[i]->command, argv[0])) {
+ g_cmds.cmd[i]->fn(argc, argv);
+ return;
+ }
+ }
+ printf("Unknown command: '%s'\r\n", argv[0]);
+}
+
+static void cmd_buf_reset(void)
+{
+ memset(g_cmds.buf, 0, sizeof(g_cmds.buf));
+ g_cmds.buf_idx = 0;
+}
+
+static void cmd_buf_append(char c)
+{
+ g_cmds.buf[g_cmds.buf_idx++] = c;
+}
+
+void command_try_recv(void)
+{
+ unsigned int i = 0;
+
+ /* yield CPU after maximum of 10 received characters */
+ while (usart_sync_is_rx_not_empty(&UART_debug) && (i < 10)) {
+ int c = getchar();
+ if (c < 0)
+ return;
+ putchar(c);
+ if (c == '\r' || c == '\n' || g_cmds.buf_idx >= sizeof(g_cmds.buf)-1) {
+ cmd_execute();
+ cmd_buf_reset();
+ printf(g_cmds.prompt);
+ return;
+ }
+ /* append character */
+ cmd_buf_append(c);
+
+ i++;
+ }
+}
+
+void command_init(const char *prompt)
+{
+ g_cmds.prompt = prompt;
+ command_register(&help_cmd);
+}
diff --git a/sysmoOCTSIM/command.h b/sysmoOCTSIM/command.h
new file mode 100644
index 0000000..cdf256d
--- /dev/null
+++ b/sysmoOCTSIM/command.h
@@ -0,0 +1,20 @@
+#pragma once
+
+struct command_fn {
+ const char *command;
+ const char *help;
+ void (*fn)(int argc, char **argv);
+};
+
+#define DEFUN(funcname, cmdname, cmdstr, helpstr) \
+ static void funcname(int argc, char **argv); \
+ static struct command_fn cmdname = { \
+ .command = cmdstr, \
+ .help = helpstr, \
+ .fn = funcname, \
+ }; \
+ static void funcname(int argc, char **argv)
+
+void command_init(const char *prompt);
+int command_register(const struct command_fn *cmd);
+void command_try_recv(void);
diff --git a/sysmoOCTSIM/gcc/Makefile b/sysmoOCTSIM/gcc/Makefile
index 1c90257..7496377 100644
--- a/sysmoOCTSIM/gcc/Makefile
+++ b/sysmoOCTSIM/gcc/Makefile
@@ -80,6 +80,7 @@ main.o \
i2c_bitbang.o \
octsim_i2c.o \
ncn8025.o \
+command.o \
hpl/osc32kctrl/hpl_osc32kctrl.o \
examples/driver_examples.o \
driver_init.o \
@@ -126,6 +127,7 @@ OBJS_AS_ARGS += \
"i2c_bitbang.o" \
"octsim_i2c.o" \
"ncn8025.o" \
+"command.o" \
"hpl/osc32kctrl/hpl_osc32kctrl.o" \
"examples/driver_examples.o" \
"driver_init.o" \
@@ -178,6 +180,7 @@ DEPS_AS_ARGS += \
"i2c_bitbang.d" \
"octsim_i2c.d" \
"ncn8025.d" \
+"command.d" \
"examples/driver_examples.d" \
"hal/src/hal_cache.d" \
"hal/src/hal_sleep.d" \
diff --git a/sysmoOCTSIM/main.c b/sysmoOCTSIM/main.c
index c79d5aa..ef87162 100644
--- a/sysmoOCTSIM/main.c
+++ b/sysmoOCTSIM/main.c
@@ -27,6 +27,8 @@
#include "octsim_i2c.h"
#include "ncn8025.h"
+#include "command.h"
+
static void board_init()
{
@@ -47,6 +49,12 @@ static void board_init()
hri_port_set_PINCFG_DRVSTR_bit(PORT, 0, 11);
}
+DEFUN(hello_fn, cmd_hello,
+ "hello", "Hello World example command")
+{
+ printf("Hello World!\r\n");
+}
+
int main(void)
{
atmel_start_init();
@@ -56,13 +64,11 @@ int main(void)
usb_start();
board_init();
+ command_init("sysmoOCTSIM> ");
+ command_register(&cmd_hello);
printf("\r\n\r\nsysmocom sysmoOCTSIM\r\n");
while (true) { // main loop
- if (usart_sync_is_rx_not_empty(&UART_debug)) {
- gpio_toggle_pin_level(USER_LED);
- int c = getchar();
- putchar(c);
- }
+ command_try_recv();
}
}