A couple of fixes to common and STM32 serial handling to fix some data overrun conditions

git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@4550 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
patacongo
2012-04-02 01:02:41 +00:00
parent 5800304777
commit 0036b9b3cd
2 changed files with 47 additions and 22 deletions
+41 -19
View File
@@ -799,8 +799,8 @@ static void up_detach(struct uart_dev_s *dev)
static int up_interrupt_common(struct up_dev_s *priv) static int up_interrupt_common(struct up_dev_s *priv)
{ {
int passes; int passes;
bool handled; bool handled;
/* Loop until there are no characters to be transferred or, /* Loop until there are no characters to be transferred or,
* until we have been looping for a long time. * until we have been looping for a long time.
@@ -811,7 +811,7 @@ static int up_interrupt_common(struct up_dev_s *priv)
{ {
handled = false; handled = false;
/* Get the masked USART status and clear the pending interrupts. */ /* Get the masked USART status word. */
priv->sr = up_serialin(priv, STM32_USART_SR_OFFSET); priv->sr = up_serialin(priv, STM32_USART_SR_OFFSET);
@@ -837,16 +837,35 @@ static int up_interrupt_common(struct up_dev_s *priv)
* being used. * being used.
*/ */
/* Handle incoming, receive bytes (with or without timeout) */ /* Handle incoming, receive bytes. */
if ((priv->sr & USART_SR_RXNE) != 0 && (priv->ie & USART_CR1_RXNEIE) != 0) if ((priv->sr & USART_SR_RXNE) != 0 && (priv->ie & USART_CR1_RXNEIE) != 0)
{ {
/* Received data ready... process incoming bytes */ /* Received data ready... process incoming bytes. NOTE the check for
* RXNEIE: We cannot call uart_recvchards of RX interrupts are disabled.
*/
uart_recvchars(&priv->dev); uart_recvchars(&priv->dev);
handled = true; handled = true;
} }
/* We may still have to read from the DR register to clear any pending
* error conditions.
*/
else if ((priv->sr & (USART_SR_ORE | USART_SR_NE | USART_SR_FE)) != 0)
{
/* If an error occurs, read from DR to clear the error (data has
* been lost). If ORE is set along with RXNE then it tells you
* that the byte *after* the one in the data register has been
* lost, but the data register value is correct. That case will
* be handled above if interrupts are enabled. Otherwise, that
* good byte will be lost.
*/
(void)up_serialin(priv, STM32_USART_DR_OFFSET);
}
/* Handle outgoing, transmit bytes */ /* Handle outgoing, transmit bytes */
if ((priv->sr & USART_SR_TXE) != 0 && (priv->ie & USART_CR1_TXEIE) != 0) if ((priv->sr & USART_SR_TXE) != 0 && (priv->ie & USART_CR1_TXEIE) != 0)
@@ -962,23 +981,25 @@ static int up_receive(struct uart_dev_s *dev, uint32_t *status)
static void up_rxint(struct uart_dev_s *dev, bool enable) static void up_rxint(struct uart_dev_s *dev, bool enable)
{ {
struct up_dev_s *priv = (struct up_dev_s*)dev->priv; struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
irqstate_t flags;
uint16_t ie; uint16_t ie;
/* USART receive interrupts: /* USART receive interrupts:
* *
* Enable Bit Status Meaning Usage * Enable Bit Status Meaning Usage
* ------------------ --- --------------- ------------------------------- ---------- * ------------------ --- --------------- ------------------------------- ----------
* USART_CR1_IDLEIE 4 USART_SR_IDLE Idle Line Detected (not used) * USART_CR1_IDLEIE 4 USART_SR_IDLE Idle Line Detected (not used)
* USART_CR1_RXNEIE 5 USART_SR_RXNE Received Data Ready to be Read * USART_CR1_RXNEIE 5 USART_SR_RXNE Received Data Ready to be Read
* " " USART_SR_ORE Overrun Error Detected * " " USART_SR_ORE Overrun Error Detected
* USART_CR1_PEIE 8 USART_SR_PE Parity Error * USART_CR1_PEIE 8 USART_SR_PE Parity Error
* *
* USART_CR2_LBDIE 6 USART_SR_LBD Break Flag (not used) * USART_CR2_LBDIE 6 USART_SR_LBD Break Flag (not used)
* USART_CR3_EIE 0 USART_SR_FE Framing Error * USART_CR3_EIE 0 USART_SR_FE Framing Error
* " " USART_SR_NE Noise Error * " " USART_SR_NE Noise Error
* " " USART_SR_ORE Overrun Error Detected * " " USART_SR_ORE Overrun Error Detected
*/ */
flags = irqsave();
ie = priv->ie; ie = priv->ie;
if (enable) if (enable)
{ {
@@ -1002,6 +1023,7 @@ static void up_rxint(struct uart_dev_s *dev, bool enable)
/* Then set the new interrupt state */ /* Then set the new interrupt state */
up_restoreusartint(priv, ie); up_restoreusartint(priv, ie);
irqrestore(flags);
} }
/**************************************************************************** /****************************************************************************
+6 -3
View File
@@ -321,11 +321,11 @@ static ssize_t uart_read(FAR struct file *filep, FAR char *buffer, size_t buflen
* data from the end of the buffer. * data from the end of the buffer.
*/ */
uart_disablerxint(dev);
while (recvd < buflen) while (recvd < buflen)
{ {
/* Check if there is more data to return in the circular buffer */ /* Check if there is more data to return in the circular buffer */
uart_disablerxint(dev);
if (dev->recv.head != dev->recv.tail) if (dev->recv.head != dev->recv.tail)
{ {
*buffer++ = dev->recv.buffer[dev->recv.tail]; *buffer++ = dev->recv.buffer[dev->recv.tail];
@@ -335,6 +335,7 @@ static ssize_t uart_read(FAR struct file *filep, FAR char *buffer, size_t buflen
{ {
dev->recv.tail = 0; dev->recv.tail = 0;
} }
uart_enablerxint(dev);
} }
#ifdef CONFIG_DEV_SERIAL_FULLBLOCKS #ifdef CONFIG_DEV_SERIAL_FULLBLOCKS
@@ -353,6 +354,8 @@ static ssize_t uart_read(FAR struct file *filep, FAR char *buffer, size_t buflen
{ {
recvd = -EAGAIN; recvd = -EAGAIN;
} }
uart_enablerxint(dev);
break; break;
} }
#else #else
@@ -366,6 +369,7 @@ static ssize_t uart_read(FAR struct file *filep, FAR char *buffer, size_t buflen
* received up to the wait condition. * received up to the wait condition.
*/ */
uart_enablerxint(dev);
break; break;
} }
@@ -379,6 +383,7 @@ static ssize_t uart_read(FAR struct file *filep, FAR char *buffer, size_t buflen
/* Break out of the loop returning -EAGAIN */ /* Break out of the loop returning -EAGAIN */
recvd = -EAGAIN; recvd = -EAGAIN;
uart_enablerxint(dev);
break; break;
} }
#endif #endif
@@ -395,12 +400,10 @@ static ssize_t uart_read(FAR struct file *filep, FAR char *buffer, size_t buflen
dev->recvwaiting = true; dev->recvwaiting = true;
uart_enablerxint(dev); uart_enablerxint(dev);
uart_takesem(&dev->recvsem); uart_takesem(&dev->recvsem);
uart_disablerxint(dev);
irqrestore(flags); irqrestore(flags);
} }
} }
uart_enablerxint(dev);
uart_givesem(&dev->recv.sem); uart_givesem(&dev->recv.sem);
return recvd; return recvd;
} }