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 c3bae60 drivers/can: optimize can driver reader side
c3bae60 is described below
commit c3bae60c57db5f8033a9017efc2dd5f8d65bfa86
Author: Petro Karashchenko <[email protected]>
AuthorDate: Fri Mar 11 16:46:20 2022 +0100
drivers/can: optimize can driver reader side
Signed-off-by: Petro Karashchenko <[email protected]>
---
arch/arm/src/lpc43xx/lpc43_can.c | 2 +-
drivers/can/can.c | 96 ++++++++++++++++++++++------------------
include/nuttx/can/can.h | 6 ++-
3 files changed, 60 insertions(+), 44 deletions(-)
diff --git a/arch/arm/src/lpc43xx/lpc43_can.c b/arch/arm/src/lpc43xx/lpc43_can.c
index f41c0b6..249384f 100644
--- a/arch/arm/src/lpc43xx/lpc43_can.c
+++ b/arch/arm/src/lpc43xx/lpc43_can.c
@@ -184,7 +184,7 @@ static int can_bittiming(struct up_dev_s *priv);
static const struct can_ops_s g_canops =
{
.co_reset = can_reset,
- .co_setup = can_setup,
+ .co_setup = can_setup,
.co_shutdown = can_shutdown,
.co_rxint = can_rxint,
.co_txint = can_txint,
diff --git a/drivers/can/can.c b/drivers/can/can.c
index 07b8c90..cca1ce8 100644
--- a/drivers/can/can.c
+++ b/drivers/can/can.c
@@ -392,7 +392,6 @@ static int can_open(FAR struct file *filep)
FAR struct inode *inode = filep->f_inode;
FAR struct can_dev_s *dev = inode->i_private;
irqstate_t flags;
- int tmp;
int ret;
/* If the port is the middle of closing, wait until the close is finished */
@@ -407,46 +406,48 @@ static int can_open(FAR struct file *filep)
* for this device, then perform hardware initialization.
*/
- if (list_is_empty(&dev->cd_readers))
+ caninfo("ocount: %u\n", dev->cd_crefs);
+
+ if (dev->cd_crefs >= 255)
{
- caninfo("ocount: %d\n", 0);
+ /* Limit to no more than 255 opens */
+ ret = -EMFILE;
+ goto errout;
+ }
+ else
+ {
flags = enter_critical_section();
- ret = dev_setup(dev);
- if (ret >= 0)
+
+ if (dev->cd_crefs == 0)
{
- /* Mark the FIFOs empty */
+ ret = dev_setup(dev);
+ if (ret == OK)
+ {
+ /* Mark the FIFOs empty */
- dev->cd_xmit.tx_head = 0;
- dev->cd_xmit.tx_queue = 0;
- dev->cd_xmit.tx_tail = 0;
+ dev->cd_xmit.tx_head = 0;
+ dev->cd_xmit.tx_queue = 0;
+ dev->cd_xmit.tx_tail = 0;
- /* Finally, Enable the CAN RX interrupt */
+ /* Finally, Enable the CAN RX interrupt */
- dev_rxint(dev, true);
+ dev_rxint(dev, true);
+ }
}
- list_add_head(&dev->cd_readers,
- (FAR struct list_node *)init_can_reader(filep));
-
- leave_critical_section(flags);
- }
- else
- {
- tmp = list_length(&dev->cd_readers);
- caninfo("ocount: %d\n", tmp);
-
- if (tmp >= 255)
+ if (ret == OK)
{
- /* Limit to no more than 255 opens */
+ dev->cd_crefs++;
- ret = -EMFILE;
- goto errout;
- }
+ /* Update the reader list only if driver was open for reading */
- flags = enter_critical_section();
- list_add_head(&dev->cd_readers,
- (FAR struct list_node *)init_can_reader(filep));
+ if ((filep->f_oflags & O_RDOK) != 0)
+ {
+ list_add_head(&dev->cd_readers,
+ (FAR struct list_node *)init_can_reader(filep));
+ }
+ }
leave_critical_section(flags);
}
@@ -475,7 +476,7 @@ static int can_close(FAR struct file *filep)
int ret;
#ifdef CONFIG_DEBUG_CAN_INFO
- caninfo("ocount: %d\n", list_length(&dev->cd_readers));
+ caninfo("ocount: %u\n", dev->cd_crefs);
#endif
ret = can_takesem(&dev->cd_closesem);
@@ -496,10 +497,11 @@ static int can_close(FAR struct file *filep)
}
filep->f_priv = NULL;
+ dev->cd_crefs--;
- /* Uninitialize the driver if there are no more readers */
+ /* De-initialize the driver if there are no more readers */
- if (!list_is_empty(&dev->cd_readers))
+ if (dev->cd_crefs > 0)
{
goto errout;
}
@@ -544,7 +546,7 @@ errout:
static ssize_t can_read(FAR struct file *filep, FAR char *buffer,
size_t buflen)
{
- FAR struct can_reader_s *reader = NULL;
+ FAR struct can_reader_s *reader;
FAR struct can_rxfifo_s *fifo;
size_t nread;
irqstate_t flags;
@@ -563,11 +565,25 @@ static ssize_t can_read(FAR struct file *filep, FAR char
*buffer,
if (buflen >= CAN_MSGLEN(0))
{
+ DEBUGASSERT(filep->f_priv != NULL);
+ reader = (FAR struct can_reader_s *)filep->f_priv;
+
+ fifo = &reader->fifo;
+
/* Interrupts must be disabled while accessing the cd_recv FIFO */
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)
@@ -604,12 +620,7 @@ static ssize_t can_read(FAR struct file *filep, FAR char
*buffer,
}
#endif /* CONFIG_CAN_ERRORS */
- DEBUGASSERT(filep->f_priv != NULL);
- reader = (FAR struct can_reader_s *)filep->f_priv;
-
- fifo = &reader->fifo;
-
- if (filep->f_oflags & O_NONBLOCK)
+ if ((filep->f_oflags & O_NONBLOCK) != 0)
{
ret = nxsem_trywait(&fifo->rx_sem);
}
@@ -1229,12 +1240,13 @@ int can_register(FAR const char *path, FAR struct
can_dev_s *dev)
/* Initialize the CAN device structure */
- list_initialize(&dev->cd_readers);
- dev->cd_ntxwaiters = 0;
+ 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 */
@@ -1427,7 +1439,7 @@ int can_receive(FAR struct can_dev_s *dev, FAR struct
can_hdr_s *hdr,
{
/* Report rx overflow error */
- dev->cd_error |= CAN_ERROR5_RXOVERFLOW;
+ fifo->rx_overflow = true;
}
#endif
}
diff --git a/include/nuttx/can/can.h b/include/nuttx/can/can.h
index 0f7db30..0b5d282 100644
--- a/include/nuttx/can/can.h
+++ b/include/nuttx/can/can.h
@@ -498,6 +498,9 @@ struct can_rxfifo_s
sem_t rx_sem;
+#ifdef CONFIG_CAN_ERRORS
+ bool rx_overflow; /* Indicates the RX FIFO overflow
event */
+#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 */
/* Circular buffer of CAN messages */
@@ -606,12 +609,13 @@ struct can_reader_s
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 */
- struct list_node cd_readers; /* List of readers */
#ifdef CONFIG_CAN_ERRORS
uint8_t cd_error; /* Flags to indicate internal device
errors */
#endif
+ struct list_node cd_readers; /* List of readers */
sem_t cd_closesem; /* Locks out new opens while close is
in progress */
sem_t cd_pollsem; /* Manages exclusive access to
cd_fds[] */
struct can_txfifo_s cd_xmit; /* Describes transmit FIFO */