You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by lu...@apache.org on 2024/10/10 09:58:44 UTC

(nuttx) 01/06: can: Merge cd_error and rx_overflow into rx_error so the error could dispath to each client without interference

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

lupyuen pushed a commit to branch releases/12.7
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 4324970980edbddf60080c1d248da71c38d66d8e
Author: Xiang Xiao <xi...@xiaomi.com>
AuthorDate: Sat Apr 6 13:19:50 2024 +0800

    can: Merge cd_error and rx_overflow into rx_error so the error could dispath to each client without interference
    
    Signed-off-by: Xiang Xiao <xi...@xiaomi.com>
---
 drivers/can/can.c       | 102 ++++++++++++++++--------------------------------
 include/nuttx/can/can.h |   5 +--
 2 files changed, 35 insertions(+), 72 deletions(-)

diff --git a/drivers/can/can.c b/drivers/can/can.c
index dea1d0fa67..be8165f441 100644
--- a/drivers/can/can.c
+++ b/drivers/can/can.c
@@ -365,10 +365,6 @@ static ssize_t can_read(FAR struct file *filep, FAR char *buffer,
   FAR struct can_rxfifo_s *fifo;
   irqstate_t               flags;
   int                      ret = 0;
-#ifdef CONFIG_CAN_ERRORS
-  FAR struct inode        *inode = filep->f_inode;
-  FAR struct can_dev_s    *dev = inode->i_private;
-#endif
 
   caninfo("buflen: %zu\n", buflen);
 
@@ -388,18 +384,9 @@ static ssize_t can_read(FAR struct file *filep, FAR char *buffer,
       flags = enter_critical_section();
 
 #ifdef CONFIG_CAN_ERRORS
-
-      /* Check for reader fifo overflow */
-
-      if (fifo->rx_overflow)
-        {
-          dev->cd_error |= CAN_ERROR5_RXOVERFLOW;
-          fifo->rx_overflow = false;
-        }
-
       /* Check for internal errors */
 
-      if (dev->cd_error != 0)
+      if (fifo->rx_error != 0)
         {
           FAR struct can_msg_s *msg;
 
@@ -422,11 +409,11 @@ static ssize_t can_read(FAR struct file *filep, FAR char *buffer,
 #endif
           msg->cm_hdr.ch_unused = 0;
           memset(&(msg->cm_data), 0, CAN_ERROR_DLC);
-          msg->cm_data[5]       = dev->cd_error;
+          msg->cm_data[5]       = fifo->rx_error;
 
           /* Reset the error flag */
 
-          dev->cd_error         = 0;
+          fifo->rx_error        = 0;
 
           ret = CAN_MSGLEN(CAN_ERROR_DLC);
           goto return_with_irqdisabled;
@@ -572,6 +559,7 @@ static int can_xmit(FAR struct can_dev_s *dev)
       if (ret < 0)
         {
           canerr("dev_send failed: %d\n", ret);
+          dev->cd_xmit.tx_queue = tmpndx;
           break;
         }
     }
@@ -893,19 +881,24 @@ static int can_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
         }
         break;
 
-      /* FIONWRITE: Return the number of CAN messages in the send queue     */
+      /* FIONWRITE: Return the number of CAN messages in the send queue */
 
       case FIONWRITE:
         {
-          *(FAR uint8_t *)arg = dev->cd_xmit.tx_tail;
+          *(FAR uint8_t *)arg = CONFIG_CAN_FIFOSIZE - 1 -
+                            (dev->cd_xmit.tx_tail - dev->cd_xmit.tx_head);
         }
         break;
 
-      /* FIONREAD: Return the number of CAN messages in the receive FIFO    */
+      /* FIONREAD: Return the number of CAN messages in the receive FIFO */
 
       case FIONREAD:
         {
-          *(FAR uint8_t *)arg = reader->fifo.rx_tail;
+          *(FAR uint8_t *)arg =
+#ifdef CONFIG_CAN_ERRORS
+                            (reader->fifo.rx_error != 0) +
+#endif
+                            reader->fifo.rx_tail - reader->fifo.rx_head;
         }
         break;
 
@@ -934,9 +927,8 @@ static int can_poll(FAR struct file *filep, FAR struct pollfd *fds,
   FAR struct can_dev_s *dev = inode->i_private;
   FAR struct can_reader_s *reader = NULL;
   pollevent_t eventset = 0;
-  int ndx;
-  int sval;
   irqstate_t flags;
+  int ndx;
   int ret;
   int i;
 
@@ -1001,21 +993,8 @@ static int can_poll(FAR struct file *filep, FAR struct pollfd *fds,
 
       /* Should we immediately notify on any of the requested events?
        * First, check if the xmit buffer is full.
-       *
-       * Get exclusive access to the cd_xmit buffer indices.  NOTE: that
-       * we do not let this wait be interrupted by a signal (we probably
-       * should, but that would be a little awkward).
        */
 
-      DEBUGASSERT(dev->cd_ntxwaiters < 255);
-      dev->cd_ntxwaiters++;
-      do
-        {
-          ret = nxsem_wait(&dev->cd_xmit.tx_sem);
-        }
-      while (ret < 0);
-      dev->cd_ntxwaiters--;
-
       ndx = dev->cd_xmit.tx_tail + 1;
       if (ndx >= CONFIG_CAN_FIFOSIZE)
         {
@@ -1027,29 +1006,17 @@ static int can_poll(FAR struct file *filep, FAR struct pollfd *fds,
           eventset |= POLLOUT;
         }
 
-      nxsem_post(&dev->cd_xmit.tx_sem);
-
       /* Check whether there are messages in the RX FIFO. */
 
-      ret = nxsem_get_value(&reader->fifo.rx_sem, &sval);
-
-      if (ret < 0)
-        {
-          DEBUGPANIC();
-          goto return_with_irqdisabled;
-        }
-      else if (sval > 0)
+      if (reader->fifo.rx_head != reader->fifo.rx_tail
+#ifdef CONFIG_CAN_ERRORS
+          || reader->fifo.rx_error != 0
+#endif
+         )
         {
-          if (reader->fifo.rx_head != reader->fifo.rx_tail)
-            {
-              /* No need to wait, just notify the application immediately */
+          /* No need to wait, just notify the application immediately */
 
-              eventset |= POLLIN;
-            }
-          else
-            {
-              canerr("RX FIFO sem not locked but FIFO is empty.\n");
-            }
+          eventset |= POLLIN;
         }
 
       poll_notify(&fds, 1, eventset);
@@ -1102,14 +1069,11 @@ int can_register(FAR const char *path, FAR struct can_dev_s *dev)
   dev->cd_crefs      = 0;
   dev->cd_npendrtr   = 0;
   dev->cd_ntxwaiters = 0;
-#ifdef CONFIG_CAN_ERRORS
-  dev->cd_error      = 0;
-#endif
   list_initialize(&dev->cd_readers);
 
   /* Initialize semaphores */
 
-  nxsem_init(&dev->cd_xmit.tx_sem, 0, 1);
+  nxsem_init(&dev->cd_xmit.tx_sem, 0, 0);
   nxmutex_init(&dev->cd_closelock);
   nxmutex_init(&dev->cd_polllock);
 
@@ -1251,21 +1215,14 @@ int can_receive(FAR struct can_dev_s *dev, FAR struct can_hdr_s *hdr,
 
           fifo->rx_tail = nexttail;
 
-          /* Notify all poll/select waiters that they can read from the
-           * cd_recv buffer
-           */
-
-          poll_notify(dev->cd_fds, CONFIG_CAN_NPOLLWAITERS, POLLIN);
-
           if (nxsem_get_value(&fifo->rx_sem, &sval) < 0)
             {
-              DEBUGPANIC();
 #ifdef CONFIG_CAN_ERRORS
               /* Report unspecified error */
 
-              dev->cd_error |= CAN_ERROR5_UNSPEC;
+              fifo->rx_error |= CAN_ERROR5_UNSPEC;
 #endif
-              return -EINVAL;
+              continue;
             }
 
           /* Unlock the binary semaphore, waking up can_read if it is
@@ -1285,11 +1242,20 @@ int can_receive(FAR struct can_dev_s *dev, FAR struct can_hdr_s *hdr,
         {
           /* Report rx overflow error */
 
-          fifo->rx_overflow = true;
+          fifo->rx_error |= CAN_ERROR5_RXOVERFLOW;
         }
 #endif
     }
 
+  /* Notify all poll/select waiters that they can read from the
+   * cd_recv buffer
+   */
+
+  if (ret == OK)
+    {
+      poll_notify(dev->cd_fds, CONFIG_CAN_NPOLLWAITERS, POLLIN);
+    }
+
   return ret;
 }
 
diff --git a/include/nuttx/can/can.h b/include/nuttx/can/can.h
index 054876418f..1d53e8442b 100644
--- a/include/nuttx/can/can.h
+++ b/include/nuttx/can/can.h
@@ -549,7 +549,7 @@ struct can_rxfifo_s
   sem_t         rx_sem;
 
 #ifdef CONFIG_CAN_ERRORS
-  bool          rx_overflow;             /* Indicates the RX FIFO overflow event */
+  uint8_t       rx_error;                /* Flags to indicate internal device errors */
 #endif
   uint8_t       rx_head;                 /* Index to the head [IN] in the circular buffer */
   uint8_t       rx_tail;                 /* Index to the tail [OUT] in the circular buffer */
@@ -666,9 +666,6 @@ struct can_dev_s
   uint8_t              cd_crefs;         /* References counts on number of opens */
   uint8_t              cd_npendrtr;      /* Number of pending RTR messages */
   volatile uint8_t     cd_ntxwaiters;    /* Number of threads waiting to enqueue a message */
-#ifdef CONFIG_CAN_ERRORS
-  uint8_t              cd_error;         /* Flags to indicate internal device errors */
-#endif
   struct list_node     cd_readers;       /* List of readers */
   mutex_t              cd_closelock;     /* Locks out new opens while close is in progress */
   mutex_t              cd_polllock;      /* Manages exclusive access to cd_fds[] */