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

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

commit 6173b0ecbf9cedd2db42619ca8961f42c75c427a
Author: chao an <[email protected]>
AuthorDate: Tue Oct 27 13:41:37 2026 +0800

    drivers/serial: Copy RX buffers in chunks
    
    Add a fast path in uart_readv() for raw input where no newline, carriage
    return, canonical, or echo processing is enabled.
    
    The raw path copies each contiguous segment from the UART RX ring into the
    uio buffer with uio_copyfrom() instead of consuming one byte at a time.  The
    existing per-byte path is kept for termios translation, canonical editing,
    and echo handling.
    
    Signed-off-by: chao an <[email protected]>
---
 drivers/serial/serial.c | 40 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 38 insertions(+), 2 deletions(-)

diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c
index ad1ee3a102f..d8743938160 100644
--- a/drivers/serial/serial.c
+++ b/drivers/serial/serial.c
@@ -1015,12 +1015,13 @@ static ssize_t uart_readv(FAR struct file *filep, FAR 
struct uio *uio)
 #ifdef CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS
   unsigned int nbuffered;
   unsigned int watermark;
-  sbuf_size_t head;
 #endif
   irqstate_t flags;
   ssize_t recvd = 0;
   ssize_t buflen;
   bool echoed = false;
+  bool rawmode;
+  sbuf_size_t head;
   sbuf_size_t tail;
   char ch;
   int ret;
@@ -1044,6 +1045,9 @@ static ssize_t uart_readv(FAR struct file *filep, FAR 
struct uio *uio)
    */
 
   buflen = uio->uio_resid;
+  rawmode = (dev->tc_iflag & (INLCR | IGNCR | ICRNL)) == 0 &&
+            (dev->tc_lflag & (ICANON | ECHO)) == 0;
+
   while (recvd < buflen)
     {
 #ifdef CONFIG_SERIAL_REMOVABLE
@@ -1078,8 +1082,40 @@ static ssize_t uart_readv(FAR struct file *filep, FAR 
struct uio *uio)
        */
 
       tail = rxbuf->tail;
-      if (rxbuf->head != tail)
+      head = rxbuf->head;
+      if (head != tail)
         {
+          if (rawmode)
+            {
+              ssize_t ncopy;
+
+              if (head > tail)
+                {
+                  ncopy = head - tail;
+                }
+              else
+                {
+                  ncopy = rxbuf->size - tail;
+                }
+
+              if (ncopy > buflen - recvd)
+                {
+                  ncopy = buflen - recvd;
+                }
+
+              uio_copyfrom(uio, recvd, &rxbuf->buffer[tail], ncopy);
+              recvd += ncopy;
+
+              tail += ncopy;
+              if (tail >= rxbuf->size)
+                {
+                  tail = 0;
+                }
+
+              rxbuf->tail = tail;
+              continue;
+            }
+
           /* Take the next character from the tail of the buffer */
 
           ch = rxbuf->buffer[tail];

Reply via email to