driver/spi_slave: Simplify rx/tx buffer logic

1. send user data directly without memcpy
2. add qpoll check before enqueue

Signed-off-by: dongjiuzhu1 <dongjiuzhu1@xiaomi.com>
This commit is contained in:
dongjiuzhu1 2023-04-04 16:50:27 +08:00 committed by Petro Karashchenko
parent 9bf66ba3d5
commit 2221612512
1 changed files with 56 additions and 23 deletions

View File

@ -81,8 +81,10 @@ struct spi_slave_driver_s
/* Transmit buffer */
uint8_t tx_buffer[CONFIG_SPI_SLAVE_DRIVER_BUFFER_SIZE];
uint32_t tx_length; /* Location of next TX value */
#ifdef CONFIG_SPI_SLAVE_DRIVER_COLORIZE_TX_BUFFER
uint8_t tx_buffer[CONFIG_SPI_SLAVE_DRIVER_COLORIZE_NUM_BYTES];
#endif
mutex_t lock; /* Mutual exclusion */
int16_t crefs; /* Number of open references */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
@ -383,8 +385,8 @@ static ssize_t spi_slave_write(FAR struct file *filep,
{
FAR struct inode *inode;
FAR struct spi_slave_driver_s *priv;
size_t num_words;
size_t enqueued_bytes;
int ret;
spiinfo("filep=%p buffer=%p buflen=%zu\n", filep, buffer, buflen);
@ -393,16 +395,42 @@ static ssize_t spi_slave_write(FAR struct file *filep,
inode = filep->f_inode;
priv = (FAR struct spi_slave_driver_s *)inode->i_private;
memcpy(priv->tx_buffer, buffer, buflen);
priv->tx_length = buflen;
num_words = BYTES2WORDS(priv->tx_length);
ret = nxmutex_lock(&priv->lock);
if (ret < 0)
{
spierr("Failed to get exclusive access: %d\n", ret);
return ret;
}
if (SPIS_CTRLR_QFULL(priv->ctrlr))
{
nxmutex_unlock(&priv->lock);
if (filep->f_oflags & O_NONBLOCK)
{
return -EAGAIN;
}
ret = nxsem_wait(&priv->wait);
if (ret < 0)
{
return ret;
}
ret = nxmutex_lock(&priv->lock);
if (ret < 0)
{
spierr("Failed to get exclusive access: %d\n", ret);
return ret;
}
}
enqueued_bytes = WORDS2BYTES(SPIS_CTRLR_ENQUEUE(priv->ctrlr,
priv->tx_buffer,
num_words));
buffer,
BYTES2WORDS(buflen)));
spiinfo("%zu bytes enqueued\n", enqueued_bytes);
nxmutex_unlock(&priv->lock);
return (ssize_t)enqueued_bytes;
}
@ -446,12 +474,12 @@ static int spi_slave_poll(FAR struct file *filep, FAR struct pollfd *fds,
SPIS_CTRLR_QPOLL(priv->ctrlr);
if (priv->rx_length > 0)
{
eventset |= POLLOUT;
eventset |= POLLIN;
}
if (!SPIS_CTRLR_QFULL(priv->ctrlr))
{
eventset |= POLLIN;
eventset |= POLLOUT;
}
poll_notify(&priv->fds, 1, eventset);
@ -610,9 +638,13 @@ static size_t spi_slave_getdata(FAR struct spi_slave_dev_s *dev,
{
FAR struct spi_slave_driver_s *priv = (FAR struct spi_slave_driver_s *)dev;
#ifdef CONFIG_SPI_SLAVE_DRIVER_COLORIZE_TX_BUFFER
*data = priv->tx_buffer;
return BYTES2WORDS(priv->tx_length);
return BYTES2WORDS(CONFIG_SPI_SLAVE_DRIVER_COLORIZE_NUM_BYTES);
#else
*data = NULL;
return 0;
#endif
}
/****************************************************************************
@ -673,25 +705,24 @@ static void spi_slave_notify(FAR struct spi_slave_dev_s *dev,
spi_slave_state_t state)
{
FAR struct spi_slave_driver_s *priv = (FAR struct spi_slave_driver_s *)dev;
int semcnt;
if (state == SPISLAVE_TX_COMPLETE)
{
poll_notify(&priv->fds, 1, POLLIN);
poll_notify(&priv->fds, 1, POLLOUT);
}
else if (state == SPISLAVE_RX_COMPLETE)
{
int semcnt;
poll_notify(&priv->fds, 1, POLLOUT);
nxsem_get_value(&priv->wait, &semcnt);
if (semcnt < 1)
{
nxsem_post(&priv->wait);
}
poll_notify(&priv->fds, 1, POLLIN);
}
else
{
spiinfo("sdev: %p transfer failed\n", dev);
poll_notify(&priv->fds, 1, POLLERR);
}
while (nxsem_get_value(&priv->wait, &semcnt) == 0 && semcnt <= 0)
{
nxsem_post(&priv->wait);
}
}
@ -740,11 +771,12 @@ int spi_slave_register(FAR struct spi_slave_ctrlr_s *ctrlr, int bus)
priv->dev.ops = &g_spisdev_ops;
priv->ctrlr = ctrlr;
nxsem_init(&priv->wait, 0, 0);
#ifdef CONFIG_SPI_SLAVE_DRIVER_COLORIZE_TX_BUFFER
memset(priv->tx_buffer,
CONFIG_SPI_SLAVE_DRIVER_COLORIZE_PATTERN,
CONFIG_SPI_SLAVE_DRIVER_COLORIZE_NUM_BYTES);
priv->tx_length = CONFIG_SPI_SLAVE_DRIVER_COLORIZE_NUM_BYTES;
#endif
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
@ -761,6 +793,7 @@ int spi_slave_register(FAR struct spi_slave_ctrlr_s *ctrlr, int bus)
if (ret < 0)
{
spierr("ERROR: Failed to register driver: %d\n", ret);
nxsem_destroy(&priv->wait);
nxmutex_destroy(&priv->lock);
kmm_free(priv);
}