You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/01/01 12:38:35 UTC

[incubator-nuttx] branch master updated: serial: add CONFIG_TTY_LAUNCH support

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 75aec04  serial: add CONFIG_TTY_LAUNCH support
75aec04 is described below

commit 75aec04330d0f2b8ba405e292ef34ca1d0253e37
Author: ligd <li...@xiaomi.com>
AuthorDate: Wed Dec 15 13:40:45 2021 +0800

    serial: add CONFIG_TTY_LAUNCH support
    
    this allow user start new program from tty
    
    Signed-off-by: ligd <li...@xiaomi.com>
---
 .../components/drivers/character/serial.rst        | 16 +++++
 drivers/serial/Kconfig                             | 63 ++++++++++++++++
 drivers/serial/serial.c                            | 84 ++++++++++++++++++++++
 drivers/serial/serial_dma.c                        | 14 +++-
 drivers/serial/serial_io.c                         | 11 +++
 include/nuttx/serial/serial.h                      | 13 ++++
 tools/cfgdefine.c                                  |  2 +
 7 files changed, 200 insertions(+), 3 deletions(-)

diff --git a/Documentation/components/drivers/character/serial.rst b/Documentation/components/drivers/character/serial.rst
index f45e45a..ea259fd 100644
--- a/Documentation/components/drivers/character/serial.rst
+++ b/Documentation/components/drivers/character/serial.rst
@@ -19,6 +19,22 @@ Serial Device Drivers
    ``/dev/ttyS0``, ``/dev/ttyS1``, etc. See the
    ``uart_register()`` implementation in ``drivers/serial.c``.
 
+-  **TTY_LAUNCH** this depends on ``CONFIG_TTY_LAUNCH``, this feature
+   allow user launch a new program with a special char input.
+
+   e.g. use ctrl+R to start a nuttx shell.
+   e.g. use ctrl+E to start user entry.
+
+   You can use ``TTY_LAUNCH_CHAR`` to customize which special char.
+
+   You can choose launch method:
+   ``TTY_LAUNCH_ENTRY`` or ``TTY_LAUNCH_FILE``,
+   If``TTY_LAUNCH_ENTRY`` you can set program entery by ``TTY_LAUNCH_ENTRYPOINT``.
+   If``TTY_LAUNCH_FILE`` you can set file path by ``TTY_LAUNCH_FILEPATH``.
+
+   Also, you can customize:
+   ``TTY_LAUNCH_ARGS`` ``TTY_LAUNCH_PRIORITY`` ``TTY_LAUNCH_STACKSIZE``
+
 -  **User Access**. Serial drivers are, ultimately, normal
    `character drivers <#chardrivers>`__ and are accessed as other
    character drivers.
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 0a2f7ad..6361321 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -173,6 +173,69 @@ config SERIAL_TERMIOS
 		If this is not defined, then the terminal settings (baud, parity, etc).
 		are not configurable at runtime; serial streams cannot be flushed, etc..
 
+config TTY_LAUNCH
+	bool "Enable feature TTY launch program"
+	default n
+	---help---
+		If select this, then user can launch a program with a special input.
+
+if TTY_LAUNCH
+
+config TTY_LAUNCH_CHAR
+	hex "TTY launch program characters"
+	default 0x12
+	---help---
+		Use Ctrl-R 0x12 inputs to determine whether launch a program
+
+config TTY_LAUNCH_ARGS
+	string "TTY launch argument list"
+	default INIT_ARGS
+	---help---
+		The argument list for user applications. e.g.:
+		  "\"arg1\",\"arg2\",\"arg3\""
+
+config TTY_LAUNCH_PRIORITY
+	int "TTY launch program priority"
+	default INIT_PRIORITY
+
+config TTY_LAUNCH_STACKSIZE
+	hex "TTY launch program stack size"
+	default INIT_STACKSIZE
+
+choice
+	prompt "TTY launch method"
+	default TTY_LAUNCH_ENTRY
+
+config TTY_LAUNCH_ENTRY
+	bool "TTY launch program"
+
+config TTY_LAUNCH_FILE
+	bool "TTY launch file"
+	depends on !BINFMT_DISABLE
+
+endchoice
+
+config TTY_LAUNCH_ENTRYPOINT
+	string "TTY launch program entry"
+	depends on TTY_LAUNCH_ENTRY
+	default INIT_ENTRYPOINT
+
+config TTY_LAUNCH_ENTRYNAME
+	string "TTY launch program name"
+	depends on TTY_LAUNCH_ENTRY
+	default TTY_LAUNCH_ENTRYPOINT
+
+config TTY_LAUNCH_FILEPATH
+	string "TTY launch file path"
+	depends on TTY_LAUNCH_FILE
+	default INIT_FILEPATH
+	---help---
+		The name of the entry point for user applications.  For the example
+		applications this is of the form 'app_main' where 'app' is the application
+		name. If not defined, USER_ENTRYPOINT defaults to "main".
+
+endif # TTY_LAUNCH
+
 config TTY_FORCE_PANIC
 	bool "Enable TTY force crash"
 	default n
diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c
index f02316b..84c58a7 100644
--- a/drivers/serial/serial.c
+++ b/drivers/serial/serial.c
@@ -45,6 +45,8 @@
 #include <nuttx/serial/serial.h>
 #include <nuttx/fs/ioctl.h>
 #include <nuttx/power/pm.h>
+#include <nuttx/wqueue.h>
+#include <nuttx/kthread.h>
 
 /****************************************************************************
  * Pre-processor Definitions
@@ -106,6 +108,16 @@ static int     uart_poll(FAR struct file *filep,
                          FAR struct pollfd *fds, bool setup);
 
 /****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifdef CONFIG_TTY_LAUNCH_ENTRY
+/* Lanch program entry, this must be supplied by the application. */
+
+int CONFIG_TTY_LAUNCH_ENTRYPOINT(int argc, char *argv[]);
+#endif
+
+/****************************************************************************
  * Private Data
  ****************************************************************************/
 
@@ -123,6 +135,10 @@ static const struct file_operations g_serialops =
 #endif
 };
 
+#ifdef CONFIG_TTY_LAUNCH
+static struct work_s g_serial_work;
+#endif
+
 /****************************************************************************
  * Private Functions
  ****************************************************************************/
@@ -1610,6 +1626,58 @@ errout:
 }
 
 /****************************************************************************
+ * Name: uart_nxsched_foreach_cb
+ ****************************************************************************/
+
+#ifdef CONFIG_TTY_LAUNCH
+static void uart_launch_foreach(FAR struct tcb_s *tcb, FAR void *arg)
+{
+#ifdef CONFIG_TTY_LAUNCH_ENTRY
+  if (!strcmp(tcb->name, CONFIG_TTY_LAUNCH_ENTRYNAME))
+#else
+  if (!strcmp(tcb->name, CONFIG_TTY_LAUNCH_FILEPATH))
+#endif
+    {
+      *(int *)arg = 1;
+    }
+}
+
+static void uart_launch_worker(void *arg)
+{
+#ifdef CONFIG_TTY_LAUNCH_ARGS
+  FAR char *const argv[] =
+  {
+    CONFIG_TTY_LAUNCH_ARGS,
+    NULL,
+  };
+#else
+  FAR char *const *argv = NULL;
+#endif
+  int found = 0;
+
+  nxsched_foreach(uart_launch_foreach, &found);
+  if (!found)
+    {
+#ifdef CONFIG_TTY_LAUNCH_ENTRY
+      nxtask_create(CONFIG_TTY_LAUNCH_ENTRYNAME,
+                    CONFIG_TTY_LAUNCH_PRIORITY,
+                    CONFIG_TTY_LAUNCH_STACKSIZE,
+                    (main_t)CONFIG_TTY_LAUNCH_ENTRYPOINT,
+                    argv);
+#else
+      posix_spawnattr_t attr;
+
+      posix_spawnattr_init(&attr);
+
+      attr.priority  = CONFIG_TTY_LAUNCH_PRIORITY;
+      attr.stacksize = CONFIG_TTY_LAUNCH_STACKSIZE;
+      exec_spawn(CONFIG_TTY_LAUNCH_FILEPATH, argv, NULL, 0, &attr);
+#endif
+    }
+}
+#endif
+
+/****************************************************************************
  * Public Functions
  ****************************************************************************/
 
@@ -1817,3 +1885,19 @@ void uart_reset_sem(FAR uart_dev_t *dev)
   nxsem_reset(&dev->recv.sem, 1);
   nxsem_reset(&dev->pollsem,  1);
 }
+
+/****************************************************************************
+ * Name: uart_launch
+ *
+ * Description:
+ *   This function is called when user want launch a new program by
+ *   using a special char.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_TTY_LAUNCH
+void uart_launch(void)
+{
+  work_queue(HPWORK, &g_serial_work, uart_launch_worker, NULL, 0);
+}
+#endif
diff --git a/drivers/serial/serial_dma.c b/drivers/serial/serial_dma.c
index b328c5d..4a0cbb8 100644
--- a/drivers/serial/serial_dma.c
+++ b/drivers/serial/serial_dma.c
@@ -57,7 +57,7 @@
  ****************************************************************************/
 
 #if defined(CONFIG_TTY_SIGINT) || defined(CONFIG_TTY_SIGTSTP) || \
-    defined(CONFIG_TTY_FORCE_PANIC)
+    defined(CONFIG_TTY_FORCE_PANIC) || defined(CONFIG_TTY_LAUNCH)
 static int uart_check_signo(int pid, const char *buf, size_t size)
 {
   size_t i;
@@ -72,6 +72,14 @@ static int uart_check_signo(int pid, const char *buf, size_t size)
         }
 #endif
 
+#ifdef CONFIG_TTY_LAUNCH
+      if (buf[i] == CONFIG_TTY_LAUNCH_CHAR)
+        {
+          uart_launch();
+          return 0;
+        }
+#endif
+
 #ifdef CONFIG_TTY_SIGINT
       if (pid > 0 && buf[i] == CONFIG_TTY_SIGINT_CHAR)
         {
@@ -105,7 +113,7 @@ static int uart_check_signo(int pid, const char *buf, size_t size)
 
 #if defined(CONFIG_SERIAL_RXDMA) && \
    (defined(CONFIG_TTY_SIGINT) || defined(CONFIG_TTY_SIGTSTP) || \
-    defined(CONFIG_TTY_FORCE_PANIC))
+    defined(CONFIG_TTY_FORCE_PANIC) || defined(CONFIG_TTY_LAUNCH))
 static int uart_recvchars_signo(FAR uart_dev_t *dev)
 {
   FAR struct uart_dmaxfer_s *xfer = &dev->dmarx;
@@ -369,7 +377,7 @@ void uart_recvchars_done(FAR uart_dev_t *dev)
   FAR struct uart_buffer_s *rxbuf = &dev->recv;
   size_t nbytes = xfer->nbytes;
 #if defined(CONFIG_TTY_SIGINT) || defined(CONFIG_TTY_SIGTSTP) || \
-    defined(CONFIG_TTY_FORCE_PANIC)
+    defined(CONFIG_TTY_FORCE_PANIC) || defined(CONFIG_TTY_LAUNCH)
   int signo = 0;
 
   /* Check if the SIGINT character is anywhere in the newly received DMA
diff --git a/drivers/serial/serial_io.c b/drivers/serial/serial_io.c
index 3add7e9..35cf83e4 100644
--- a/drivers/serial/serial_io.c
+++ b/drivers/serial/serial_io.c
@@ -252,6 +252,17 @@ void uart_recvchars(FAR uart_dev_t *dev)
         }
       else
 #endif
+#ifdef CONFIG_TTY_LAUNCH
+      /* Is this the special character that will generate the SIGTSTP
+       * signal?
+       */
+
+      if ((dev->tc_lflag & ISIG) && ch == CONFIG_TTY_LAUNCH_CHAR)
+        {
+          uart_launch();
+        }
+      else
+#endif
 
       /* If the RX buffer becomes full, then the serial data is discarded.
        * This is necessary because on most serial hardware, you must read
diff --git a/include/nuttx/serial/serial.h b/include/nuttx/serial/serial.h
index d5aa793..293a1c9 100644
--- a/include/nuttx/serial/serial.h
+++ b/include/nuttx/serial/serial.h
@@ -495,6 +495,19 @@ void uart_recvchars_done(FAR uart_dev_t *dev);
 
 void uart_reset_sem(FAR uart_dev_t *dev);
 
+/****************************************************************************
+ * Name: uart_lanch
+ *
+ * Description:
+ *   This function is called when user want lanch a new program by
+ *   using a special char.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_TTY_LAUNCH
+void uart_launch(void);
+#endif
+
 #undef EXTERN
 #if defined(__cplusplus)
 }
diff --git a/tools/cfgdefine.c b/tools/cfgdefine.c
index 87ecb87..0405584 100644
--- a/tools/cfgdefine.c
+++ b/tools/cfgdefine.c
@@ -60,6 +60,8 @@ static const char *dequote_list[] =
   "CONFIG_PASS1_BUILDIR",                 /* Pass1 build directory */
   "CONFIG_PASS1_TARGET",                  /* Pass1 build target */
   "CONFIG_PASS1_OBJECT",                  /* Pass1 build object */
+  "CONFIG_TTY_LAUNCH_ENTRYPOINT",         /* Name of entry point from tty launch */
+  "CONFIG_TTY_LAUNCH_ARGS",               /* Argument list of entry point from tty launch */
 
   /* NxWidgets/NxWM */