drivers/usbdev: Correct input flow control logic when watermarks are not enabled. Problem not by and change based on suggestion by Juha Niskanen.

This commit is contained in:
Gregory Nutt 2017-10-18 06:49:11 -06:00
parent 477a8d1aa7
commit 85a1a3cc98
3 changed files with 42 additions and 23 deletions
drivers

@ -518,7 +518,7 @@ if SERIAL_IFLOWCONTROL_WATERMARKS
config SERIAL_IFLOWCONTROL_LOWER_WATERMARK config SERIAL_IFLOWCONTROL_LOWER_WATERMARK
int "RX lower Watermark (percent)" int "RX lower Watermark (percent)"
default 10 default 10
range 0 100 range 1 99
---help--- ---help---
Call the rxflowcontrol method then there are this amount (or or less) Call the rxflowcontrol method then there are this amount (or or less)
data buffered in the serial drivers RX buffer. This is expressed data buffered in the serial drivers RX buffer. This is expressed
@ -528,7 +528,7 @@ config SERIAL_IFLOWCONTROL_LOWER_WATERMARK
config SERIAL_IFLOWCONTROL_UPPER_WATERMARK config SERIAL_IFLOWCONTROL_UPPER_WATERMARK
int "RX upper Watermark (percent)" int "RX upper Watermark (percent)"
default 90 default 90
range 0 100 range 1 99
---help--- ---help---
Call the rxflowcontrol method then there are this amount (or more) Call the rxflowcontrol method then there are this amount (or more)
data buffered in the serial drivers RX buffer. This is expressed data buffered in the serial drivers RX buffer. This is expressed

@ -70,6 +70,24 @@
#define uart_putc(ch) up_putc(ch) #define uart_putc(ch) up_putc(ch)
/* Check watermark levels */
#if defined(CONFIG_SERIAL_IFLOWCONTROL) && \
defined(CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS)
# if CONFIG_SERIAL_IFLOWCONTROL_LOWER_WATERMARK < 1
# warning CONFIG_SERIAL_IFLOWCONTROL_LOWER_WATERMARK too small
# endif
# if CONFIG_SERIAL_IFLOWCONTROL_UPPER_WATERMARK > 99
# warning CONFIG_SERIAL_IFLOWCONTROL_UPPER_WATERMARK too large
# endif
# if CONFIG_SERIAL_IFLOWCONTROL_LOWER_WATERMARK >= CONFIG_SERIAL_IFLOWCONTROL_UPPER_WATERMARK
# warning CONFIG_SERIAL_IFLOWCONTROL_LOWER_WATERMARK too large
# warning Must be less than CONFIG_SERIAL_IFLOWCONTROL_UPPER_WATERMARK
# endif
#endif
/* Timing */
#define HALF_SECOND_MSEC 500 #define HALF_SECOND_MSEC 500
#define HALF_SECOND_USEC 500000L #define HALF_SECOND_USEC 500000L
@ -995,7 +1013,7 @@ static ssize_t uart_read(FAR struct file *filep, FAR char *buffer, size_t buflen
(void)uart_rxflowcontrol(dev, nbuffered, false); (void)uart_rxflowcontrol(dev, nbuffered, false);
} }
#else #else
/* If the RX buffer empty */ /* Is the RX buffer empty? */
if (rxbuf->head == rxbuf->tail) if (rxbuf->head == rxbuf->tail)
{ {

@ -515,7 +515,10 @@ static int cdcacm_recvpacket(FAR struct cdcacm_dev_s *priv,
} }
#ifdef CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS #ifdef CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS
/* Pre-calcuate the watermark level that we will need to test against. */ /* Pre-calcuate the watermark level that we will need to test against.
* Note that the range of the the upper watermark is from 1 to 99 percent
* and that the actual capacity of the RX biffer is (recv->size - 1).
*/
watermark = (CONFIG_SERIAL_IFLOWCONTROL_UPPER_WATERMARK * recv->size) / 100; watermark = (CONFIG_SERIAL_IFLOWCONTROL_UPPER_WATERMARK * recv->size) / 100;
#endif #endif
@ -535,8 +538,8 @@ static int cdcacm_recvpacket(FAR struct cdcacm_dev_s *priv,
while (nexthead != recv->tail && nbytes < reqlen) while (nexthead != recv->tail && nbytes < reqlen)
{ {
#ifdef CONFIG_SERIAL_IFLOWCONTROL #if defined(CONFIG_SERIAL_IFLOWCONTROL) && \
#ifdef CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS defined(CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS)
unsigned int nbuffered; unsigned int nbuffered;
/* How many bytes are buffered */ /* How many bytes are buffered */
@ -565,21 +568,6 @@ static int cdcacm_recvpacket(FAR struct cdcacm_dev_s *priv,
break; break;
} }
} }
#else
/* Check if RX buffer is full and allow serial low-level driver to pause
* processing. This allows proper utilization of hardware flow control.
*/
if (nexthead == rxbuf->tail)
{
if (cdcuart_rxflowcontrol(&priv->serdev, recv->size, true))
{
/* Low-level driver activated RX flow control, exit loop now. */
break;
}
}
#endif
#endif #endif
/* Copy one byte to the head of the circular RX buffer */ /* Copy one byte to the head of the circular RX buffer */
@ -604,10 +592,23 @@ static int cdcacm_recvpacket(FAR struct cdcacm_dev_s *priv,
recv->head = currhead; recv->head = currhead;
#if defined(CONFIG_SERIAL_IFLOWCONTROL) && \
!defined(CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS)
/* Check if RX buffer became full and allow serial low-level driver to
* pause processing. This allows proper utilization of hardware flow
* control when there are no watermarks.
*/
if (nexthead == recv->tail)
{
(void)cdcuart_rxflowcontrol(&priv->serdev, recv->size, true);
}
#endif
/* If data was added to the incoming serial buffer, then wake up any /* If data was added to the incoming serial buffer, then wake up any
* threads is waiting for incoming data. If we are running in an interrupt * threads is waiting for incoming data. If we are running in an interrupt
* handler, then the serial driver will not run until the interrupt handler * handler, then the serial driver will not run until the interrupt
* returns. * handler returns.
*/ */
if (nbytes > 0) if (nbytes > 0)