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

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

commit 65207ae1c53d804dd9e25b96ee564caeaeac5fee
Author: Maarten Zanders <[email protected]>
AuthorDate: Thu Feb 19 15:44:46 2026 +0100

    serial/uart_rpmsg: add _raw version of driver
    
    Mainline Linux doesn't use data encapsuation or flow control in its
    tty_rpmsg driver. Create a NuttX counterpart which matches this
    implementation.
    This driver uses the static "rpmsg-tty" name to connect with the
    remote service.
    
    Signed-off-by: Maarten Zanders <[email protected]>
---
 arch/arm/src/common/arm_internal.h         |   3 +
 arch/arm64/src/common/arm64_internal.h     |   3 +
 arch/tricore/src/common/tricore_internal.h |   3 +
 drivers/drivers_initialize.c               |   7 +-
 drivers/serial/CMakeLists.txt              |   4 +
 drivers/serial/Kconfig                     |  24 ++
 drivers/serial/Make.defs                   |   4 +
 drivers/serial/uart_rpmsg_raw.c            | 380 +++++++++++++++++++++++++++++
 include/nuttx/drivers/drivers.h            |  10 +
 include/nuttx/serial/uart_rpmsg_raw.h      |  57 +++++
 10 files changed, 494 insertions(+), 1 deletion(-)

diff --git a/arch/arm/src/common/arm_internal.h 
b/arch/arm/src/common/arm_internal.h
index a37058d332f..16c32751f5e 100644
--- a/arch/arm/src/common/arm_internal.h
+++ b/arch/arm/src/common/arm_internal.h
@@ -64,6 +64,9 @@
 #  elif defined(CONFIG_RPMSG_UART_CONSOLE)
 #    undef  USE_SERIALDRIVER
 #    undef  USE_EARLYSERIALINIT
+#  elif defined(CONFIG_RPMSG_UART_RAW_CONSOLE)
+#    undef  USE_SERIALDRIVER
+#    undef  USE_EARLYSERIALINIT
 #  else
 #    define USE_SERIALDRIVER 1
 #    define USE_EARLYSERIALINIT 1
diff --git a/arch/arm64/src/common/arm64_internal.h 
b/arch/arm64/src/common/arm64_internal.h
index a99491ab26c..52f53be16a7 100644
--- a/arch/arm64/src/common/arm64_internal.h
+++ b/arch/arm64/src/common/arm64_internal.h
@@ -64,6 +64,9 @@
 #  elif defined(CONFIG_RPMSG_UART_CONSOLE)
 #    undef  USE_SERIALDRIVER
 #    undef  USE_EARLYSERIALINIT
+#  elif defined(CONFIG_RPMSG_UART_RAW_CONSOLE)
+#    undef  USE_SERIALDRIVER
+#    undef  USE_EARLYSERIALINIT
 #  else
 #    define USE_SERIALDRIVER 1
 #    define USE_EARLYSERIALINIT 1
diff --git a/arch/tricore/src/common/tricore_internal.h 
b/arch/tricore/src/common/tricore_internal.h
index f467b32a20f..cc83ff0957a 100644
--- a/arch/tricore/src/common/tricore_internal.h
+++ b/arch/tricore/src/common/tricore_internal.h
@@ -69,6 +69,9 @@
 #  elif defined(CONFIG_RPMSG_UART_CONSOLE)
 #    undef  USE_SERIALDRIVER
 #    undef  USE_EARLYSERIALINIT
+#  elif defined(CONFIG_RPMSG_UART_RAW_CONSOLE)
+#    undef  USE_SERIALDRIVER
+#    undef  USE_EARLYSERIALINIT
 #  else
 #    define USE_SERIALDRIVER 1
 #    define USE_EARLYSERIALINIT 1
diff --git a/drivers/drivers_initialize.c b/drivers/drivers_initialize.c
index 7393f37d93d..968abaf2821 100644
--- a/drivers/drivers_initialize.c
+++ b/drivers/drivers_initialize.c
@@ -71,7 +71,8 @@
 
 #if (defined(CONFIG_LWL_CONSOLE) + defined(CONFIG_SERIAL_CONSOLE) + \
      defined(CONFIG_CDCACM_CONSOLE) + defined(CONFIG_PL2303_CONSOLE) + \
-     defined(CONFIG_SERIAL_RTT_CONSOLE) + defined(CONFIG_RPMSG_UART_CONSOLE)) 
> 1
+     defined(CONFIG_SERIAL_RTT_CONSOLE) + defined(CONFIG_RPMSG_UART_CONSOLE) + 
\
+     defined(CONFIG_RPMSG_UART_RAW_CONSOLE) ) > 1
 #  error More than one console driver selected. Check your configuration !
 #endif
 
@@ -174,6 +175,10 @@ void drivers_initialize(void)
   rpmsg_serialinit();
 #endif
 
+#ifdef CONFIG_RPMSG_UART_RAW
+  rpmsg_serialrawinit();
+#endif
+
 #ifdef CONFIG_RAM_UART
   ram_serialinit();
 #endif
diff --git a/drivers/serial/CMakeLists.txt b/drivers/serial/CMakeLists.txt
index 3dbd4bc9d3e..74f9f9d6415 100644
--- a/drivers/serial/CMakeLists.txt
+++ b/drivers/serial/CMakeLists.txt
@@ -50,6 +50,10 @@ if(CONFIG_RPMSG_UART)
   list(APPEND SRCS uart_rpmsg.c)
 endif()
 
+if(CONFIG_RPMSG_UART_RAW)
+  list(APPEND SRCS uart_rpmsg_raw.c)
+endif()
+
 if(CONFIG_UART_HOSTFS)
   list(APPEND SRCS uart_hostfs.c)
 endif()
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index ebc4b1dee28..def241f7934 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -169,6 +169,30 @@ config RPMSG_UART_CONSOLE
                NOTE: support for this option must be implemented in the board 
logic by
                setting the \"isconsole\" argument in the uart_rpmsg_init() 
function to true.
 
+config RPMSG_UART_RAW
+       bool "UART RPMSG RAW support"
+       default n
+       depends on RPMSG
+       select ARCH_HAVE_SERIAL_TERMIOS
+       select SERIAL_RXDMA
+       select SERIAL_TXDMA
+       select SERIAL_REMOVABLE
+       ---help---
+               Similar to RPMSG_UART but using data transfer without 
encapsulation or
+               flow control. This implementation is compatible with the 
upstream linux
+               implementation of tty_rpmsg. This connects to a static service 
name
+               (rpmsg-tty), independent from the local name.
+
+config RPMSG_UART_RAW_CONSOLE
+       bool "UART RPMSG RAW console support"
+       default n
+       depends on RPMSG_UART_RAW
+       ---help---
+               Register the RAW UART RPMSG device as /dev/console so that is 
will be used
+               as the console device.
+               NOTE: support for this option must be implemented in the board 
logic by
+               setting the \"isconsole\" argument in the uart_rpmsg_raw_init() 
function to true.
+
 #
 # Standard serial driver configuration
 #
diff --git a/drivers/serial/Make.defs b/drivers/serial/Make.defs
index 8843bde2c92..b9ca98dbff8 100644
--- a/drivers/serial/Make.defs
+++ b/drivers/serial/Make.defs
@@ -50,6 +50,10 @@ ifeq ($(CONFIG_RPMSG_UART),y)
   CSRCS += uart_rpmsg.c
 endif
 
+ifeq ($(CONFIG_RPMSG_UART_RAW),y)
+  CSRCS += uart_rpmsg_raw.c
+endif
+
 ifeq ($(CONFIG_UART_HOSTFS),y)
   CSRCS += uart_hostfs.c
 endif
diff --git a/drivers/serial/uart_rpmsg_raw.c b/drivers/serial/uart_rpmsg_raw.c
new file mode 100644
index 00000000000..a658b3f61d3
--- /dev/null
+++ b/drivers/serial/uart_rpmsg_raw.c
@@ -0,0 +1,380 @@
+/****************************************************************************
+ * drivers/serial/uart_rpmsg_raw.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <nuttx/fs/ioctl.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/mutex.h>
+#include <nuttx/rpmsg/rpmsg.h>
+#include <nuttx/serial/serial.h>
+#include <nuttx/serial/uart_rpmsg_raw.h>
+
+/****************************************************************************
+ * Pre-processor definitions
+ ****************************************************************************/
+
+#define UART_RPMSG_DEV_CONSOLE          "/dev/console"
+#define UART_RPMSG_DEV_PREFIX           "/dev/tty"
+#define UART_RPMSG_EPT                  "rpmsg-tty"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct uart_rpmsg_priv_s
+{
+  struct rpmsg_endpoint ept;
+  mutex_t               lock;
+  FAR const char        *devname;
+  FAR const char        *cpuname;
+  FAR void              *recv_data;
+  size_t                recv_len;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int  uart_rpmsg_raw_setup(FAR struct uart_dev_s *dev);
+static void uart_rpmsg_raw_shutdown(FAR struct uart_dev_s *dev);
+static int  uart_rpmsg_raw_attach(FAR struct uart_dev_s *dev);
+static void uart_rpmsg_raw_detach(FAR struct uart_dev_s *dev);
+static void uart_rpmsg_raw_rxint(FAR struct uart_dev_s *dev, bool enable);
+static void uart_rpmsg_raw_dmasend(FAR struct uart_dev_s *dev);
+static void uart_rpmsg_raw_dmareceive(FAR struct uart_dev_s *dev);
+static void uart_rpmsg_raw_dmarxfree(FAR struct uart_dev_s *dev);
+static void uart_rpmsg_raw_dmatxavail(FAR struct uart_dev_s *dev);
+static void uart_rpmsg_raw_send(FAR struct uart_dev_s *dev, int ch);
+static void uart_rpmsg_raw_txint(FAR struct uart_dev_s *dev, bool enable);
+static bool uart_rpmsg_raw_txready(FAR struct uart_dev_s *dev);
+static bool uart_rpmsg_raw_txempty(FAR struct uart_dev_s *dev);
+static void uart_rpmsg_raw_device_created(FAR struct rpmsg_device *rdev,
+                                      FAR void *priv_);
+static void uart_rpmsg_raw_device_destroy(FAR struct rpmsg_device *rdev,
+                                      FAR void *priv_);
+static int  uart_rpmsg_raw_ept_cb(struct rpmsg_endpoint *ept, FAR void *data,
+                              size_t len, uint32_t src, FAR void *priv_);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct uart_ops_s g_uart_rpmsg_ops =
+{
+  .setup         = uart_rpmsg_raw_setup,
+  .shutdown      = uart_rpmsg_raw_shutdown,
+  .attach        = uart_rpmsg_raw_attach,
+  .detach        = uart_rpmsg_raw_detach,
+  .rxint         = uart_rpmsg_raw_rxint,
+  .dmasend       = uart_rpmsg_raw_dmasend,
+  .dmareceive    = uart_rpmsg_raw_dmareceive,
+  .dmarxfree     = uart_rpmsg_raw_dmarxfree,
+  .dmatxavail    = uart_rpmsg_raw_dmatxavail,
+  .send          = uart_rpmsg_raw_send,
+  .txint         = uart_rpmsg_raw_txint,
+  .txready       = uart_rpmsg_raw_txready,
+  .txempty       = uart_rpmsg_raw_txempty,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int uart_rpmsg_raw_setup(FAR struct uart_dev_s *dev)
+{
+  return OK;
+}
+
+static void uart_rpmsg_raw_shutdown(FAR struct uart_dev_s *dev)
+{
+}
+
+static int uart_rpmsg_raw_attach(FAR struct uart_dev_s *dev)
+{
+  return OK;
+}
+
+static void uart_rpmsg_raw_detach(FAR struct uart_dev_s *dev)
+{
+}
+
+static void uart_rpmsg_raw_rxint(FAR struct uart_dev_s *dev, bool enable)
+{
+}
+
+static void uart_rpmsg_raw_dmasend(FAR struct uart_dev_s *dev)
+{
+  FAR struct uart_rpmsg_priv_s *priv = dev->priv;
+  FAR struct uart_dmaxfer_s *xfer = &dev->dmatx;
+  size_t len = xfer->length + xfer->nlength;
+  FAR uint8_t *buf;
+  uint32_t space;
+  int ret;
+
+  buf = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true);
+  if (!buf)
+    {
+      return;
+    }
+
+  if (len > space)
+    {
+      len = space;
+    }
+
+  if (len > xfer->length)
+    {
+      memcpy(buf, xfer->buffer, xfer->length);
+      memcpy(buf + xfer->length, xfer->nbuffer, len - xfer->length);
+    }
+  else
+    {
+      memcpy(buf, xfer->buffer, len);
+    }
+
+  ret = rpmsg_send_nocopy(&priv->ept, buf, len);
+
+  if (ret < 0)
+    {
+      rpmsg_release_tx_buffer(&priv->ept, buf);
+      dev->dmatx.nbytes = 0;
+    }
+  else
+    {
+      dev->dmatx.nbytes = len;
+    }
+
+  uart_xmitchars_done(dev);
+}
+
+static void uart_rpmsg_raw_dmareceive(FAR struct uart_dev_s *dev)
+{
+  FAR struct uart_rpmsg_priv_s *priv = dev->priv;
+  FAR struct uart_dmaxfer_s *xfer = &dev->dmarx;
+  FAR char *data = priv->recv_data;
+  size_t len = priv->recv_len;
+  size_t space = xfer->length + xfer->nlength;
+
+  if (len > space)
+    {
+      len = space;
+    }
+
+  if (len > xfer->length)
+    {
+      memcpy(xfer->buffer, data, xfer->length);
+      memcpy(xfer->nbuffer, data + xfer->length, len - xfer->length);
+    }
+  else
+    {
+      memcpy(xfer->buffer, data, len);
+    }
+
+  xfer->nbytes = len;
+  uart_recvchars_done(dev);
+}
+
+static void uart_rpmsg_raw_dmarxfree(FAR struct uart_dev_s *dev)
+{
+}
+
+static void uart_rpmsg_raw_dmatxavail(FAR struct uart_dev_s *dev)
+{
+  FAR struct uart_rpmsg_priv_s *priv = dev->priv;
+
+  nxmutex_lock(&priv->lock);
+
+  if (is_rpmsg_ept_ready(&priv->ept) && dev->dmatx.length == 0)
+    {
+      uart_xmitchars_dma(dev);
+    }
+
+  nxmutex_unlock(&priv->lock);
+}
+
+static void uart_rpmsg_raw_send(FAR struct uart_dev_s *dev, int ch)
+{
+  int nexthead;
+
+  nexthead = dev->xmit.head + 1;
+  if (nexthead >= dev->xmit.size)
+    {
+      nexthead = 0;
+    }
+
+  if (nexthead != dev->xmit.tail)
+    {
+      /* No.. not full.  Add the character to the TX buffer and return. */
+
+      dev->xmit.buffer[dev->xmit.head] = ch;
+      dev->xmit.head = nexthead;
+    }
+
+  uart_rpmsg_raw_dmatxavail(dev);
+}
+
+static void uart_rpmsg_raw_txint(FAR struct uart_dev_s *dev, bool enable)
+{
+}
+
+static bool uart_rpmsg_raw_txready(FAR struct uart_dev_s *dev)
+{
+  int nexthead;
+
+  nexthead = dev->xmit.head + 1;
+  if (nexthead >= dev->xmit.size)
+    {
+      nexthead = 0;
+    }
+
+  return nexthead != dev->xmit.tail;
+}
+
+static bool uart_rpmsg_raw_txempty(FAR struct uart_dev_s *dev)
+{
+  return true;
+}
+
+static void uart_rpmsg_raw_device_created(FAR struct rpmsg_device *rdev,
+                                          FAR void *priv_)
+{
+  FAR struct uart_dev_s *dev = priv_;
+  FAR struct uart_rpmsg_priv_s *priv = dev->priv;
+
+  if (strcmp(priv->cpuname, rpmsg_get_cpuname(rdev)) == 0)
+    {
+      priv->ept.priv = dev;
+      rpmsg_create_ept(&priv->ept, rdev, UART_RPMSG_EPT,
+                       RPMSG_ADDR_ANY, RPMSG_ADDR_ANY,
+                       uart_rpmsg_raw_ept_cb, NULL);
+    }
+}
+
+static void uart_rpmsg_raw_device_destroy(FAR struct rpmsg_device *rdev,
+                                          FAR void *priv_)
+{
+  FAR struct uart_dev_s *dev = priv_;
+  FAR struct uart_rpmsg_priv_s *priv = dev->priv;
+
+  if (priv->ept.priv != NULL &&
+      strcmp(priv->cpuname, rpmsg_get_cpuname(rdev)) == 0)
+    {
+      rpmsg_destroy_ept(&priv->ept);
+    }
+
+  dev->dmatx.nbytes = dev->dmatx.length + dev->dmatx.nlength;
+  uart_xmitchars_done(dev);
+}
+
+static int uart_rpmsg_raw_ept_cb(FAR struct rpmsg_endpoint *ept,
+                                 FAR void *data, size_t len, uint32_t src,
+                                 FAR void *priv_)
+{
+  FAR struct uart_dev_s *dev = priv_;
+  FAR struct uart_rpmsg_priv_s *priv = dev->priv;
+
+  if (len > 0)
+    {
+      nxmutex_lock(&dev->recv.lock);
+
+      priv->recv_data = data;
+      priv->recv_len = len;
+
+      uart_recvchars_dma(dev);
+
+      priv->recv_data = NULL;
+      priv->recv_len = 0;
+
+      nxmutex_unlock(&dev->recv.lock);
+    }
+
+  return 0;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int uart_rpmsg_raw_init(FAR const char *cpuname, FAR const char *devname,
+                        int buf_size, bool isconsole)
+{
+  FAR struct uart_rpmsg_priv_s *priv;
+  FAR struct uart_dev_s *dev;
+  char name[32];
+  int ret;
+
+  dev = kmm_zalloc(sizeof(struct uart_dev_s) +
+                   sizeof(struct uart_rpmsg_priv_s) +
+                   buf_size * 2);
+  if (dev == NULL)
+    {
+      return -ENOMEM;
+    }
+
+  dev->ops         = &g_uart_rpmsg_ops;
+  dev->isconsole   = isconsole;
+  dev->recv.size   = buf_size;
+  dev->xmit.size   = buf_size;
+  dev->priv        = dev + 1;
+  dev->recv.buffer = (FAR char *)dev->priv +
+                     sizeof(struct uart_rpmsg_priv_s);
+  dev->xmit.buffer = dev->recv.buffer + buf_size;
+  priv             = dev->priv;
+  priv->cpuname    = cpuname;
+  priv->devname    = devname;
+
+  nxmutex_init(&priv->lock);
+
+  ret = rpmsg_register_callback(dev,
+                                uart_rpmsg_raw_device_created,
+                                uart_rpmsg_raw_device_destroy,
+                                NULL,
+                                NULL);
+  if (ret < 0)
+    {
+      nxmutex_destroy(&priv->lock);
+      kmm_free(dev);
+      return ret;
+    }
+
+  snprintf(name, sizeof(name), "%s%s",
+           UART_RPMSG_DEV_PREFIX, devname);
+  uart_register(name, dev);
+
+#ifdef CONFIG_RPMSG_UART_RAW_CONSOLE
+  if (dev->isconsole)
+    {
+      uart_register(UART_RPMSG_DEV_CONSOLE, dev);
+    }
+#endif
+
+  return 0;
+}
diff --git a/include/nuttx/drivers/drivers.h b/include/nuttx/drivers/drivers.h
index 07c9b005030..7f0c00f7ec0 100644
--- a/include/nuttx/drivers/drivers.h
+++ b/include/nuttx/drivers/drivers.h
@@ -274,6 +274,16 @@ void lwlconsole_init(void);
 
 void rpmsg_serialinit(void);
 
+/****************************************************************************
+ * Name: rpmsg_serialrawinit
+ *
+ * Description:
+ *   Register rpmsg serial driver
+ *
+ ****************************************************************************/
+
+void rpmsg_serialrawinit(void);
+
 #undef EXTERN
 #if defined(__cplusplus)
 }
diff --git a/include/nuttx/serial/uart_rpmsg_raw.h 
b/include/nuttx/serial/uart_rpmsg_raw.h
new file mode 100644
index 00000000000..f353b7b8738
--- /dev/null
+++ b/include/nuttx/serial/uart_rpmsg_raw.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+ * include/nuttx/serial/uart_rpmsg_raw.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_SERIAL_UART_RPMSG_RAW_H
+#define __INCLUDE_NUTTX_SERIAL_UART_RPMSG_RAW_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdbool.h>
+
+#ifdef CONFIG_RPMSG_UART_RAW
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+int uart_rpmsg_raw_init(FAR const char *cpuname, FAR const char *devname,
+                    int buf_size, bool isconsole);
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONFIG_RPMSG_UART_RAW */
+#endif /* __INCLUDE_NUTTX_SERIAL_UART_RPMSG_RAW_H */

Reply via email to