mirror of
https://github.com/apache/nuttx.git
synced 2026-05-10 07:18:49 +08:00
drivers/serial/16550: add polling mode support for serial drivers
Adds CONFIG_16550_POLLING options to enable polling mode for transmission. This avoids TX interrupts and reduces interrupt latency at the cost of blocking during TX. Implements sendbuf() method for efficient buffer transmission in polling mode. Signed-off-by: yinshengkai <yinshengkai@bytedance.com> Signed-off-by: chao an <anchao.archer@bytedance.com>
This commit is contained in:
committed by
Alan C. Assis
parent
8c035a2414
commit
45c38d8592
@@ -5,6 +5,14 @@
|
||||
|
||||
if 16550_UART
|
||||
|
||||
config 16550_POLLING
|
||||
bool "Force polling mode for TX"
|
||||
default n
|
||||
---help---
|
||||
Force using polling mode for transmission. This avoids using TX interrupts
|
||||
and potentially reduces interrupt latency, at the cost of blocking execution
|
||||
during transmission.
|
||||
|
||||
config 16550_SERIAL_DISABLE_REORDERING
|
||||
bool "Disable reordering of ttySx devices."
|
||||
default n
|
||||
|
||||
@@ -108,6 +108,8 @@ static void u16550_dmarxfree(FAR struct uart_dev_s *dev);
|
||||
static void u16550_dmarxconfig(FAR struct uart_dev_s *dev);
|
||||
#endif
|
||||
static void u16550_send(FAR struct uart_dev_s *dev, int ch);
|
||||
static ssize_t u16550_sendbuf(struct uart_dev_s *dev,
|
||||
const void *buffer, size_t size);
|
||||
static void u16550_txint(FAR struct uart_dev_s *dev, bool enable);
|
||||
static bool u16550_txready(FAR struct uart_dev_s *dev);
|
||||
static bool u16550_txempty(FAR struct uart_dev_s *dev);
|
||||
@@ -154,6 +156,7 @@ static const struct uart_ops_s g_uart_ops =
|
||||
.txint = u16550_txint,
|
||||
.txready = u16550_txready,
|
||||
.txempty = u16550_txempty,
|
||||
.sendbuf = u16550_sendbuf,
|
||||
};
|
||||
|
||||
/* I/O buffers */
|
||||
@@ -1568,6 +1571,26 @@ static void u16550_send(struct uart_dev_s *dev, int ch)
|
||||
u16550_serialout(priv, UART_THR_OFFSET, (uart_datawidth_t)ch);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: u16550_sendbuf
|
||||
*
|
||||
* Description:
|
||||
* This method will send a buffer of bytes on the UART
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t u16550_sendbuf(struct uart_dev_s *dev,
|
||||
const void *buffer, size_t size)
|
||||
{
|
||||
for (size_t i = 0; i < size; i++)
|
||||
{
|
||||
while (!u16550_txready(dev));
|
||||
u16550_send(dev, ((const unsigned char *)buffer)[i]);
|
||||
}
|
||||
|
||||
return (ssize_t)size;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: u16550_txint
|
||||
*
|
||||
@@ -1588,9 +1611,14 @@ static void u16550_txint(struct uart_dev_s *dev, bool enable)
|
||||
}
|
||||
#endif
|
||||
|
||||
flags = enter_critical_section();
|
||||
if (enable)
|
||||
{
|
||||
#ifdef CONFIG_16550_POLLING
|
||||
/* In polling mode, we loop until the buffer is empty */
|
||||
|
||||
uart_xmitchars(dev);
|
||||
#else
|
||||
flags = enter_critical_section();
|
||||
priv->ier |= UART_IER_ETBEI;
|
||||
u16550_serialout(priv, UART_IER_OFFSET, priv->ier);
|
||||
|
||||
@@ -1599,14 +1627,16 @@ static void u16550_txint(struct uart_dev_s *dev, bool enable)
|
||||
*/
|
||||
|
||||
uart_xmitchars(dev);
|
||||
leave_critical_section(flags);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
flags = enter_critical_section();
|
||||
priv->ier &= ~UART_IER_ETBEI;
|
||||
u16550_serialout(priv, UART_IER_OFFSET, priv->ier);
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
Reference in New Issue
Block a user