drivers/can: optimize can driver reader side
Signed-off-by: Petro Karashchenko <petro.karashchenko@gmail.com>
This commit is contained in:
parent
e2114378b9
commit
c3bae60c57
@ -184,7 +184,7 @@ static int can_bittiming(struct up_dev_s *priv);
|
|||||||
static const struct can_ops_s g_canops =
|
static const struct can_ops_s g_canops =
|
||||||
{
|
{
|
||||||
.co_reset = can_reset,
|
.co_reset = can_reset,
|
||||||
.co_setup = can_setup,
|
.co_setup = can_setup,
|
||||||
.co_shutdown = can_shutdown,
|
.co_shutdown = can_shutdown,
|
||||||
.co_rxint = can_rxint,
|
.co_rxint = can_rxint,
|
||||||
.co_txint = can_txint,
|
.co_txint = can_txint,
|
||||||
|
@ -392,7 +392,6 @@ static int can_open(FAR struct file *filep)
|
|||||||
FAR struct inode *inode = filep->f_inode;
|
FAR struct inode *inode = filep->f_inode;
|
||||||
FAR struct can_dev_s *dev = inode->i_private;
|
FAR struct can_dev_s *dev = inode->i_private;
|
||||||
irqstate_t flags;
|
irqstate_t flags;
|
||||||
int tmp;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* If the port is the middle of closing, wait until the close is finished */
|
/* 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.
|
* 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 */
|
||||||
|
|
||||||
flags = enter_critical_section();
|
ret = -EMFILE;
|
||||||
ret = dev_setup(dev);
|
goto errout;
|
||||||
if (ret >= 0)
|
|
||||||
{
|
|
||||||
/* Mark the FIFOs empty */
|
|
||||||
|
|
||||||
dev->cd_xmit.tx_head = 0;
|
|
||||||
dev->cd_xmit.tx_queue = 0;
|
|
||||||
dev->cd_xmit.tx_tail = 0;
|
|
||||||
|
|
||||||
/* Finally, Enable the CAN RX interrupt */
|
|
||||||
|
|
||||||
dev_rxint(dev, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
list_add_head(&dev->cd_readers,
|
|
||||||
(FAR struct list_node *)init_can_reader(filep));
|
|
||||||
|
|
||||||
leave_critical_section(flags);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tmp = list_length(&dev->cd_readers);
|
flags = enter_critical_section();
|
||||||
caninfo("ocount: %d\n", tmp);
|
|
||||||
|
|
||||||
if (tmp >= 255)
|
if (dev->cd_crefs == 0)
|
||||||
{
|
{
|
||||||
/* Limit to no more than 255 opens */
|
ret = dev_setup(dev);
|
||||||
|
if (ret == OK)
|
||||||
|
{
|
||||||
|
/* Mark the FIFOs empty */
|
||||||
|
|
||||||
ret = -EMFILE;
|
dev->cd_xmit.tx_head = 0;
|
||||||
goto errout;
|
dev->cd_xmit.tx_queue = 0;
|
||||||
|
dev->cd_xmit.tx_tail = 0;
|
||||||
|
|
||||||
|
/* Finally, Enable the CAN RX interrupt */
|
||||||
|
|
||||||
|
dev_rxint(dev, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = enter_critical_section();
|
if (ret == OK)
|
||||||
list_add_head(&dev->cd_readers,
|
{
|
||||||
(FAR struct list_node *)init_can_reader(filep));
|
dev->cd_crefs++;
|
||||||
|
|
||||||
|
/* Update the reader list only if driver was open for reading */
|
||||||
|
|
||||||
|
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);
|
leave_critical_section(flags);
|
||||||
}
|
}
|
||||||
@ -475,7 +476,7 @@ static int can_close(FAR struct file *filep)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_CAN_INFO
|
#ifdef CONFIG_DEBUG_CAN_INFO
|
||||||
caninfo("ocount: %d\n", list_length(&dev->cd_readers));
|
caninfo("ocount: %u\n", dev->cd_crefs);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ret = can_takesem(&dev->cd_closesem);
|
ret = can_takesem(&dev->cd_closesem);
|
||||||
@ -496,10 +497,11 @@ static int can_close(FAR struct file *filep)
|
|||||||
}
|
}
|
||||||
|
|
||||||
filep->f_priv = NULL;
|
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;
|
goto errout;
|
||||||
}
|
}
|
||||||
@ -544,7 +546,7 @@ errout:
|
|||||||
static ssize_t can_read(FAR struct file *filep, FAR char *buffer,
|
static ssize_t can_read(FAR struct file *filep, FAR char *buffer,
|
||||||
size_t buflen)
|
size_t buflen)
|
||||||
{
|
{
|
||||||
FAR struct can_reader_s *reader = NULL;
|
FAR struct can_reader_s *reader;
|
||||||
FAR struct can_rxfifo_s *fifo;
|
FAR struct can_rxfifo_s *fifo;
|
||||||
size_t nread;
|
size_t nread;
|
||||||
irqstate_t flags;
|
irqstate_t flags;
|
||||||
@ -563,11 +565,25 @@ static ssize_t can_read(FAR struct file *filep, FAR char *buffer,
|
|||||||
|
|
||||||
if (buflen >= CAN_MSGLEN(0))
|
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 */
|
/* Interrupts must be disabled while accessing the cd_recv FIFO */
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = enter_critical_section();
|
||||||
|
|
||||||
#ifdef CONFIG_CAN_ERRORS
|
#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 */
|
/* Check for internal errors */
|
||||||
|
|
||||||
if (dev->cd_error != 0)
|
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 */
|
#endif /* CONFIG_CAN_ERRORS */
|
||||||
|
|
||||||
DEBUGASSERT(filep->f_priv != NULL);
|
if ((filep->f_oflags & O_NONBLOCK) != 0)
|
||||||
reader = (FAR struct can_reader_s *)filep->f_priv;
|
|
||||||
|
|
||||||
fifo = &reader->fifo;
|
|
||||||
|
|
||||||
if (filep->f_oflags & O_NONBLOCK)
|
|
||||||
{
|
{
|
||||||
ret = nxsem_trywait(&fifo->rx_sem);
|
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 */
|
/* Initialize the CAN device structure */
|
||||||
|
|
||||||
list_initialize(&dev->cd_readers);
|
dev->cd_crefs = 0;
|
||||||
dev->cd_ntxwaiters = 0;
|
|
||||||
dev->cd_npendrtr = 0;
|
dev->cd_npendrtr = 0;
|
||||||
|
dev->cd_ntxwaiters = 0;
|
||||||
#ifdef CONFIG_CAN_ERRORS
|
#ifdef CONFIG_CAN_ERRORS
|
||||||
dev->cd_error = 0;
|
dev->cd_error = 0;
|
||||||
#endif
|
#endif
|
||||||
|
list_initialize(&dev->cd_readers);
|
||||||
|
|
||||||
/* Initialize semaphores */
|
/* 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 */
|
/* Report rx overflow error */
|
||||||
|
|
||||||
dev->cd_error |= CAN_ERROR5_RXOVERFLOW;
|
fifo->rx_overflow = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -498,6 +498,9 @@ struct can_rxfifo_s
|
|||||||
|
|
||||||
sem_t rx_sem;
|
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_head; /* Index to the head [IN] in the circular buffer */
|
||||||
uint8_t rx_tail; /* Index to the tail [OUT] in the circular buffer */
|
uint8_t rx_tail; /* Index to the tail [OUT] in the circular buffer */
|
||||||
/* Circular buffer of CAN messages */
|
/* Circular buffer of CAN messages */
|
||||||
@ -606,12 +609,13 @@ struct can_reader_s
|
|||||||
|
|
||||||
struct can_dev_s
|
struct can_dev_s
|
||||||
{
|
{
|
||||||
|
uint8_t cd_crefs; /* References counts on number of opens */
|
||||||
uint8_t cd_npendrtr; /* Number of pending RTR messages */
|
uint8_t cd_npendrtr; /* Number of pending RTR messages */
|
||||||
volatile uint8_t cd_ntxwaiters; /* Number of threads waiting to enqueue a message */
|
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
|
#ifdef CONFIG_CAN_ERRORS
|
||||||
uint8_t cd_error; /* Flags to indicate internal device errors */
|
uint8_t cd_error; /* Flags to indicate internal device errors */
|
||||||
#endif
|
#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_closesem; /* Locks out new opens while close is in progress */
|
||||||
sem_t cd_pollsem; /* Manages exclusive access to cd_fds[] */
|
sem_t cd_pollsem; /* Manages exclusive access to cd_fds[] */
|
||||||
struct can_txfifo_s cd_xmit; /* Describes transmit FIFO */
|
struct can_txfifo_s cd_xmit; /* Describes transmit FIFO */
|
||||||
|
Loading…
Reference in New Issue
Block a user