mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-28 00:13:34 +08:00
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:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user