mirror of
https://github.com/apache/nuttx.git
synced 2026-05-27 11:26:12 +08:00
Squashed commit of the following:
drivers/serial/uart_16550.c: Support 16550 auto hardware flow control
drivers/serial/uart_16550.c: Add configuration option CONFIG_16550_SUPRESS_INITIAL_CONFIG. This is identical to the standard configuration in arch/Kconfig CONFIG_SUPPRESS_UART_CONFIG, but with scope of only the 16550 driver.
This commit is contained in:
@@ -312,6 +312,11 @@ endchoice # 16550 Serial Console
|
|||||||
config 16550_SUPRESS_CONFIG
|
config 16550_SUPRESS_CONFIG
|
||||||
bool "Suppress 16550 configuration"
|
bool "Suppress 16550 configuration"
|
||||||
default n
|
default n
|
||||||
|
|
||||||
|
config 16550_SUPRESS_INITIAL_CONFIG
|
||||||
|
bool "Suppress initial 16550 configuration"
|
||||||
|
depends on !16550_SUPRESS_CONFIG
|
||||||
|
default n
|
||||||
---help---
|
---help---
|
||||||
This option is useful, for example, if you are using a bootloader
|
This option is useful, for example, if you are using a bootloader
|
||||||
that configures the 16550_UART. In that case, you may want to
|
that configures the 16550_UART. In that case, you may want to
|
||||||
|
|||||||
@@ -80,6 +80,9 @@ struct u16550_s
|
|||||||
uint8_t parity; /* 0=none, 1=odd, 2=even */
|
uint8_t parity; /* 0=none, 1=odd, 2=even */
|
||||||
uint8_t bits; /* Number of bits (7 or 8) */
|
uint8_t bits; /* Number of bits (7 or 8) */
|
||||||
bool stopbits2; /* true: Configure with 2 stop bits instead of 1 */
|
bool stopbits2; /* true: Configure with 2 stop bits instead of 1 */
|
||||||
|
#if defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL)
|
||||||
|
bool flow; /* flow control (RTS/CTS) enabled */
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -96,6 +99,10 @@ static int u16550_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
|
|||||||
static int u16550_receive(FAR struct uart_dev_s *dev, uint32_t *status);
|
static int u16550_receive(FAR struct uart_dev_s *dev, uint32_t *status);
|
||||||
static void u16550_rxint(FAR struct uart_dev_s *dev, bool enable);
|
static void u16550_rxint(FAR struct uart_dev_s *dev, bool enable);
|
||||||
static bool u16550_rxavailable(FAR struct uart_dev_s *dev);
|
static bool u16550_rxavailable(FAR struct uart_dev_s *dev);
|
||||||
|
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
||||||
|
static bool u16550_rxflowcontrol(struct uart_dev_s *dev, unsigned int nbuffered,
|
||||||
|
bool upper);
|
||||||
|
#endif
|
||||||
#ifdef CONFIG_SERIAL_DMA
|
#ifdef CONFIG_SERIAL_DMA
|
||||||
static void u16550_dmasend(FAR struct uart_dev_s *dev);
|
static void u16550_dmasend(FAR struct uart_dev_s *dev);
|
||||||
static void u16550_dmareceive(FAR struct uart_dev_s *dev);
|
static void u16550_dmareceive(FAR struct uart_dev_s *dev);
|
||||||
@@ -122,7 +129,7 @@ static const struct uart_ops_s g_uart_ops =
|
|||||||
.rxint = u16550_rxint,
|
.rxint = u16550_rxint,
|
||||||
.rxavailable = u16550_rxavailable,
|
.rxavailable = u16550_rxavailable,
|
||||||
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
||||||
.rxflowcontrol = NULL,
|
.rxflowcontrol = u16550_rxflowcontrol,
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_SERIAL_DMA
|
#ifdef CONFIG_SERIAL_DMA
|
||||||
.dmasend = u16550_dmasend,
|
.dmasend = u16550_dmasend,
|
||||||
@@ -170,6 +177,9 @@ static struct u16550_s g_uart0priv =
|
|||||||
.parity = CONFIG_16550_UART0_PARITY,
|
.parity = CONFIG_16550_UART0_PARITY,
|
||||||
.bits = CONFIG_16550_UART0_BITS,
|
.bits = CONFIG_16550_UART0_BITS,
|
||||||
.stopbits2 = CONFIG_16550_UART0_2STOP,
|
.stopbits2 = CONFIG_16550_UART0_2STOP,
|
||||||
|
#if defined(CONFIG_16550_UART0_IFLOWCONTROL) || defined(CONFIG_16550_UART0_OFLOWCONTROL)
|
||||||
|
.flow = true,
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -205,6 +215,9 @@ static struct u16550_s g_uart1priv =
|
|||||||
.parity = CONFIG_16550_UART1_PARITY,
|
.parity = CONFIG_16550_UART1_PARITY,
|
||||||
.bits = CONFIG_16550_UART1_BITS,
|
.bits = CONFIG_16550_UART1_BITS,
|
||||||
.stopbits2 = CONFIG_16550_UART1_2STOP,
|
.stopbits2 = CONFIG_16550_UART1_2STOP,
|
||||||
|
#if defined(CONFIG_16550_UART1_IFLOWCONTROL) || defined(CONFIG_16551_UART1_OFLOWCONTROL)
|
||||||
|
.flow = true,
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -240,6 +253,9 @@ static struct u16550_s g_uart2priv =
|
|||||||
.parity = CONFIG_16550_UART2_PARITY,
|
.parity = CONFIG_16550_UART2_PARITY,
|
||||||
.bits = CONFIG_16550_UART2_BITS,
|
.bits = CONFIG_16550_UART2_BITS,
|
||||||
.stopbits2 = CONFIG_16550_UART2_2STOP,
|
.stopbits2 = CONFIG_16550_UART2_2STOP,
|
||||||
|
#if defined(CONFIG_16550_UART2_IFLOWCONTROL) || defined(CONFIG_16550_UART2_OFLOWCONTROL)
|
||||||
|
.flow = true,
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -275,6 +291,9 @@ static struct u16550_s g_uart3priv =
|
|||||||
.parity = CONFIG_16550_UART3_PARITY,
|
.parity = CONFIG_16550_UART3_PARITY,
|
||||||
.bits = CONFIG_16550_UART3_BITS,
|
.bits = CONFIG_16550_UART3_BITS,
|
||||||
.stopbits2 = CONFIG_16550_UART3_2STOP,
|
.stopbits2 = CONFIG_16550_UART3_2STOP,
|
||||||
|
#if defined(CONFIG_16550_UART3_IFLOWCONTROL) || defined(CONFIG_16550_UART3_OFLOWCONTROL)
|
||||||
|
.flow = true,
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -606,6 +625,9 @@ static int u16550_setup(FAR struct uart_dev_s *dev)
|
|||||||
FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
|
FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
|
||||||
uint16_t div;
|
uint16_t div;
|
||||||
uint32_t lcr;
|
uint32_t lcr;
|
||||||
|
#if defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL)
|
||||||
|
uint32_t mcr;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Clear fifos */
|
/* Clear fifos */
|
||||||
|
|
||||||
@@ -677,6 +699,23 @@ static int u16550_setup(FAR struct uart_dev_s *dev)
|
|||||||
u16550_serialout(priv, UART_FCR_OFFSET,
|
u16550_serialout(priv, UART_FCR_OFFSET,
|
||||||
(UART_FCR_RXTRIGGER_8 | UART_FCR_TXRST | UART_FCR_RXRST |
|
(UART_FCR_RXTRIGGER_8 | UART_FCR_TXRST | UART_FCR_RXRST |
|
||||||
UART_FCR_FIFOEN));
|
UART_FCR_FIFOEN));
|
||||||
|
|
||||||
|
/* Set up the auto flow control */
|
||||||
|
|
||||||
|
#if defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL)
|
||||||
|
mcr = u16550_serialin(priv, UART_MCR_OFFSET);
|
||||||
|
if (priv->flow)
|
||||||
|
{
|
||||||
|
mcr |= UART_MCR_AFCE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mcr &= ~UART_MCR_AFCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
u16550_serialout(priv, UART_MCR_OFFSET, mcr);
|
||||||
|
#endif /* defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL) */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@@ -934,6 +973,9 @@ static int u16550_ioctl(struct file *filep, int cmd, unsigned long arg)
|
|||||||
termiosp->c_cflag = ((priv->parity != 0) ? PARENB : 0) |
|
termiosp->c_cflag = ((priv->parity != 0) ? PARENB : 0) |
|
||||||
((priv->parity == 1) ? PARODD : 0);
|
((priv->parity == 1) ? PARODD : 0);
|
||||||
termiosp->c_cflag |= (priv->stopbits2) ? CSTOPB : 0;
|
termiosp->c_cflag |= (priv->stopbits2) ? CSTOPB : 0;
|
||||||
|
#if defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL)
|
||||||
|
termiosp->c_cflag |= priv->flow ? CRTSCTS : 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (priv->bits)
|
switch (priv->bits)
|
||||||
{
|
{
|
||||||
@@ -1003,6 +1045,9 @@ static int u16550_ioctl(struct file *filep, int cmd, unsigned long arg)
|
|||||||
|
|
||||||
priv->baud = cfgetispeed(termiosp);
|
priv->baud = cfgetispeed(termiosp);
|
||||||
priv->stopbits2 = (termiosp->c_cflag & CSTOPB) != 0;
|
priv->stopbits2 = (termiosp->c_cflag & CSTOPB) != 0;
|
||||||
|
#if defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL)
|
||||||
|
priv->flow = (termiosp->c_cflag & CRTSCTS) != 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
u16550_setup(dev);
|
u16550_setup(dev);
|
||||||
leave_critical_section(flags);
|
leave_critical_section(flags);
|
||||||
@@ -1084,6 +1129,31 @@ static bool u16550_rxavailable(struct uart_dev_s *dev)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
||||||
|
static bool u16550_rxflowcontrol(struct uart_dev_s *dev, unsigned int nbuffered,
|
||||||
|
bool upper)
|
||||||
|
{
|
||||||
|
#ifndef CONFIG_16550_SUPRESS_CONFIG
|
||||||
|
FAR struct u16550_s *priv = (FAR struct u16550_s *)dev->priv;
|
||||||
|
|
||||||
|
if (priv->flow)
|
||||||
|
{
|
||||||
|
/* Disable Rx interrupt to prevent more data being from
|
||||||
|
* peripheral if the RX buffer is near full. When hardware
|
||||||
|
* RTS is enabled, this will prevent more data from coming
|
||||||
|
* in. Otherwise, enable Rx interrupt to make sure that more
|
||||||
|
* input is received.
|
||||||
|
*/
|
||||||
|
|
||||||
|
u16550_rxint(dev, !upper);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SERIAL_DMA
|
#ifdef CONFIG_SERIAL_DMA
|
||||||
static void u16550_dmasend(FAR struct uart_dev_s *dev)
|
static void u16550_dmasend(FAR struct uart_dev_s *dev)
|
||||||
{
|
{
|
||||||
@@ -1232,8 +1302,10 @@ void up_earlyserialinit(void)
|
|||||||
|
|
||||||
#ifdef CONSOLE_DEV
|
#ifdef CONSOLE_DEV
|
||||||
CONSOLE_DEV.isconsole = true;
|
CONSOLE_DEV.isconsole = true;
|
||||||
|
#ifndef CONFIG_16550_SUPRESS_INITIAL_CONFIG
|
||||||
u16550_setup(&CONSOLE_DEV);
|
u16550_setup(&CONSOLE_DEV);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
@@ -290,7 +290,8 @@
|
|||||||
#define UART_MCR_OUT1 (1 << 2) /* Bit 2: Auxiliary user-defined output 1 */
|
#define UART_MCR_OUT1 (1 << 2) /* Bit 2: Auxiliary user-defined output 1 */
|
||||||
#define UART_MCR_OUT2 (1 << 3) /* Bit 3: Auxiliary user-defined output 2 */
|
#define UART_MCR_OUT2 (1 << 3) /* Bit 3: Auxiliary user-defined output 2 */
|
||||||
#define UART_MCR_LPBK (1 << 4) /* Bit 4: Loopback Mode Select */
|
#define UART_MCR_LPBK (1 << 4) /* Bit 4: Loopback Mode Select */
|
||||||
/* Bit 5-7: Reserved */
|
#define UART_MCR_AFCE (1 << 5) /* Bit 5: Auto Flow Control Enable */
|
||||||
|
/* Bit 6-7: Reserved */
|
||||||
|
|
||||||
/* LSR Line Status Register */
|
/* LSR Line Status Register */
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user