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/nuttx.git

commit 8ba084329d59920d865130d5e31a43091b61798c
Author: Bowen Wang <[email protected]>
AuthorDate: Wed Dec 4 23:27:04 2024 +0800

    rpmsg/rpmsg_port_uart: add wakeup feauture for rpmsg_port_uart
    
    Wakeup peer when peer is in low power mode
    
    Signed-off-by: Bowen Wang <[email protected]>
---
 drivers/rpmsg/rpmsg_port_uart.c | 143 ++++++++++++++++++++++++++++------------
 1 file changed, 102 insertions(+), 41 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_port_uart.c b/drivers/rpmsg/rpmsg_port_uart.c
index cf49e05ab2f..1556ab71a58 100644
--- a/drivers/rpmsg/rpmsg_port_uart.c
+++ b/drivers/rpmsg/rpmsg_port_uart.c
@@ -31,10 +31,11 @@
 #include <stdio.h>
 
 #include <nuttx/crc16.h>
+#include <nuttx/fs/fs.h>
 #include <nuttx/kmalloc.h>
 #include <nuttx/kthread.h>
 #include <nuttx/mutex.h>
-#include <nuttx/fs/fs.h>
+#include <nuttx/semaphore.h>
 
 #include "rpmsg_port.h"
 
@@ -43,10 +44,13 @@
  ****************************************************************************/
 
 #define RPMSG_PORT_UART_START              0x7f
-#define RPMSG_PORT_UART_END                0x7e
-#define RPMSG_PORT_UART_CONNREQ            0x7d
-#define RPMSG_PORT_UART_CONNACK            0x7c
-#define RPMSG_PORT_UART_ESCAPE             0x7b
+#define RPMSG_PORT_UART_CONNREQ            0x7e
+#define RPMSG_PORT_UART_CONNACK            0x7d
+#define RPMSG_PORT_UART_ESCAPE             0x7c
+#define RPMSG_PORT_UART_SUSPEND            0x7b
+#define RPMSG_PORT_UART_RESUME             0x7a
+#define RPMSG_PORT_UART_WAKEUP             0x79
+#define RPMSG_PORT_UART_END                0x78
 #define RPMSG_PORT_UART_ESCAPE_MASK        0x20
 
 #define RPMSG_PORT_UART_BUFLEN             256
@@ -55,6 +59,8 @@
 #define RPMSG_PORT_UART_RX_RECV_NORMAL     2
 #define RPMSG_PORT_UART_RX_RECV_ESCAPE     3
 
+#define RPMSG_PORT_UART_WAKEUP_TIMEOUT     MSEC2TICK(100)
+
 #ifdef CONFIG_RPMSG_PORT_UART_CRC
 #  define rpmsg_port_uart_crc16(hdr)       \
   crc16ibm((FAR uint8_t *)&(hdr)->cmd, (hdr)->len - sizeof((hdr)->crc))
@@ -64,7 +70,7 @@
 
 #ifdef CONFIG_RPMSG_PORT_UART_DEBUG
 #  define rpmsgdump                        lib_dumpbuffer
-#  define rpmsgdbg                         rpmsginfo
+#  define rpmsgdbg                         rpmsgerr
 #else
 #  define rpmsgdump(m,b,s)
 #  define rpmsgdbg(fmt,...)
@@ -80,6 +86,7 @@ struct rpmsg_port_uart_s
   struct file            file;     /* Indicate uart device */
   char                   localcpu[RPMSG_NAME_SIZE];
   rpmsg_port_rx_cb_t     rx_cb;
+  sem_t                  wake;
   bool                   connected;
 };
 
@@ -108,6 +115,75 @@ static const struct rpmsg_port_ops_s g_rpmsg_port_uart_ops 
=
  * Private Functions
  ****************************************************************************/
 
+/****************************************************************************
+ * Name: rpmsg_port_uart_send_one
+ ****************************************************************************/
+
+static inline void
+rpmsg_port_uart_send_one(FAR struct rpmsg_port_uart_s *rpuart, uint8_t ch)
+{
+  ssize_t ret = file_write(&rpuart->file, &ch, 1);
+  if (ret != 1)
+    {
+      rpmsgerr("Send ch %u failed, ret=%zd\n", ch, ret);
+      PANIC();
+    }
+}
+
+/****************************************************************************
+ * Name: rpmsg_port_uart_send_command
+ ****************************************************************************/
+
+static inline void
+rpmsg_port_uart_send_command(FAR struct rpmsg_port_uart_s *rpuart,
+                             uint8_t cmd)
+{
+  if (cmd != RPMSG_PORT_UART_WAKEUP)
+    {
+      rpmsg_port_uart_send_one(rpuart, RPMSG_PORT_UART_WAKEUP);
+    }
+
+  rpmsg_port_uart_send_one(rpuart, cmd);
+}
+
+/****************************************************************************
+ * Name: rpmsg_port_uart_wakeup
+ *
+ * Description:
+ *   Send wakeup data to peer if peer is suspended.
+ *
+ ****************************************************************************/
+
+static inline void
+rpmsg_port_uart_wakeup(FAR struct rpmsg_port_uart_s *rpuart)
+{
+  int ret;
+
+  /* Try first, if peer is in suspend state, start send the wakeup byte */
+
+  ret = nxsem_trywait(&rpuart->wake);
+  if (ret >= 0)
+    {
+      nxsem_post(&rpuart->wake);
+      return;
+    }
+
+  for (; ; )
+    {
+      rpmsgdbg("Try to wakeup peer\n");
+      rpmsg_port_uart_send_command(rpuart, RPMSG_PORT_UART_WAKEUP);
+
+      ret = nxsem_tickwait(&rpuart->wake, RPMSG_PORT_UART_WAKEUP_TIMEOUT);
+      if (ret >= 0)
+        {
+          nxsem_post(&rpuart->wake);
+          break;
+        }
+    }
+
+  rpmsgdbg("Wakeup peer success\n");
+}
+
 /****************************************************************************
  * Name: rpmsg_port_uart_send_packet
  *
@@ -119,6 +195,8 @@ static const struct rpmsg_port_ops_s g_rpmsg_port_uart_ops =
 static void rpmsg_port_uart_send_packet(FAR struct rpmsg_port_uart_s *rpuart,
                                         FAR const void *data, size_t datalen)
 {
+  rpmsg_port_uart_wakeup(rpuart);
+
   rpmsgdump("TX Packed Data", data, datalen);
 
   while (datalen > 0)
@@ -157,7 +235,7 @@ static void rpmsg_port_uart_send_frame(FAR struct 
rpmsg_port_uart_s *rpuart,
   for (; datalen-- > 0; data = (FAR uint8_t *)data + 1)
     {
       ch = *(FAR uint8_t *)data;
-      if (ch >= RPMSG_PORT_UART_ESCAPE && ch <= RPMSG_PORT_UART_START)
+      if (ch >= RPMSG_PORT_UART_END && ch <= RPMSG_PORT_UART_START)
         {
           buf[next++] = RPMSG_PORT_UART_ESCAPE;
           buf[next++] = ch ^ RPMSG_PORT_UART_ESCAPE_MASK;
@@ -203,38 +281,6 @@ static void rpmsg_port_uart_send_data(FAR struct 
rpmsg_port_uart_s *rpuart,
   rpmsg_port_uart_send_frame(rpuart, hdr, hdr->len);
 }
 
-/****************************************************************************
- * Name: rpmsg_port_uart_send_connect_req
- ****************************************************************************/
-
-static void
-rpmsg_port_uart_send_connect_req(FAR struct rpmsg_port_uart_s *rpuart)
-{
-  uint8_t ch = RPMSG_PORT_UART_CONNREQ;
-  ssize_t ret = file_write(&rpuart->file, &ch, 1);
-  if (ret != 1)
-    {
-      rpmsgerr("Send connect request failed, ret=%zd\n", ret);
-      PANIC();
-    }
-}
-
-/****************************************************************************
- * Name: rpmsg_port_uart_send_connect_ack
- ****************************************************************************/
-
-static void
-rpmsg_port_uart_send_connect_ack(FAR struct rpmsg_port_uart_s *rpuart)
-{
-  uint8_t ch = RPMSG_PORT_UART_CONNACK;
-  ssize_t ret = file_write(&rpuart->file, &ch, 1);
-  if (ret != 1)
-    {
-      rpmsgerr("Send connect ack failed, ret=%zd\n", ret);
-      PANIC();
-    }
-}
-
 /****************************************************************************
  * Name: rpmsg_port_uart_register_callback
  ****************************************************************************/
@@ -268,7 +314,7 @@ rpmsg_port_uart_process_rx_conn(FAR struct 
rpmsg_port_uart_s *rpuart,
           rpuart->connected = true;
         }
 
-      rpmsg_port_uart_send_connect_ack(rpuart);
+      rpmsg_port_uart_send_command(rpuart, RPMSG_PORT_UART_CONNACK);
       rpmsg_port_register(&rpuart->port, rpuart->localcpu);
     }
   else if (ch == RPMSG_PORT_UART_CONNACK)
@@ -325,6 +371,18 @@ static int rpmsg_port_uart_rx_thread(int argc, FAR char 
*argv[])
               state = RPMSG_PORT_UART_RX_WAIT_START;
               continue;
             }
+          else if (buf[i] == RPMSG_PORT_UART_SUSPEND)
+            {
+              rpmsgdbg("Received suspend command\n");
+              nxsem_wait(&rpuart->wake);
+              continue;
+            }
+          else if (buf[i] == RPMSG_PORT_UART_RESUME)
+            {
+              rpmsgdbg("Received resume command\n");
+              nxsem_post(&rpuart->wake);
+              continue;
+            }
 
           if (rpuart->connected == false)
             {
@@ -403,7 +461,7 @@ static int rpmsg_port_uart_tx_thread(int argc, FAR char 
*argv[])
   FAR struct rpmsg_port_queue_s *txq = &rpuart->port.txq;
   FAR struct rpmsg_port_header_s *hdr;
 
-  rpmsg_port_uart_send_connect_req(rpuart);
+  rpmsg_port_uart_send_command(rpuart, RPMSG_PORT_UART_CONNREQ);
 
   for (; ; )
     {
@@ -456,6 +514,8 @@ int rpmsg_port_uart_initialize(FAR const struct 
rpmsg_port_config_s *cfg,
       return -ENOMEM;
     }
 
+  nxsem_init(&rpuart->wake, 0, 1);
+
   /* Hardware initialize */
 
   ret = file_open(&rpuart->file, uartpath, O_RDWR);
@@ -515,6 +575,7 @@ err_rx_thread:
 err_rpmsg_port:
   file_close(&rpuart->file);
 err_file:
+  nxsem_destroy(&rpuart->wake);
   kmm_free(rpuart);
   return ret;
 }

Reply via email to