mirror of
https://github.com/apache/nuttx.git
synced 2026-06-04 23:03:27 +08:00
Fix PIC32 serial driver lost interrupts
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4230 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
@@ -115,7 +115,7 @@ void up_sigdeliver(void)
|
|||||||
|
|
||||||
/* Then restore the task interrupt state */
|
/* Then restore the task interrupt state */
|
||||||
|
|
||||||
irqrestore((uint16_t)regs[REG_STATUS]);
|
irqrestore((irqstate_t)regs[REG_STATUS]);
|
||||||
|
|
||||||
/* Deliver the signals */
|
/* Deliver the signals */
|
||||||
|
|
||||||
@@ -137,6 +137,12 @@ void up_sigdeliver(void)
|
|||||||
|
|
||||||
up_ledoff(LED_SIGNAL);
|
up_ledoff(LED_SIGNAL);
|
||||||
up_fullcontextrestore(regs);
|
up_fullcontextrestore(regs);
|
||||||
|
|
||||||
|
/* up_fullcontextrestore() should not return but could if the software
|
||||||
|
* interrupts are disabled.
|
||||||
|
*/
|
||||||
|
|
||||||
|
PANIC(OSERR_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !CONFIG_DISABLE_SIGNALS */
|
#endif /* !CONFIG_DISABLE_SIGNALS */
|
||||||
|
|||||||
@@ -247,16 +247,22 @@ void pic32mx_uartconfigure(uintptr_t uart_base, uint32_t baudrate,
|
|||||||
/* Configure the FIFOs:
|
/* Configure the FIFOs:
|
||||||
*
|
*
|
||||||
* RX: Interrupt at 6 of 8 (for 8-deep FIFO) or 3 o 4 (4-deep FIFO)
|
* RX: Interrupt at 6 of 8 (for 8-deep FIFO) or 3 o 4 (4-deep FIFO)
|
||||||
* TX: Interrupt on FIFO not full
|
* TX: Interrupt on FIFO empty
|
||||||
* Invert transmit polarity.
|
* Invert transmit polarity.
|
||||||
|
*
|
||||||
|
* NOTE that there are not many options on trigger TX interrupts. The FIFO not
|
||||||
|
* full might generate better through-put but with a higher interrupt rate. FIFO
|
||||||
|
* empty should lower the interrupt rate but result in a burstier output. If
|
||||||
|
* you change this, please read the comment for acknowledging the interrupt in
|
||||||
|
* pic32mx-serial.c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef UART_STA_URXISEL_RXB6
|
#ifdef UART_STA_URXISEL_RXB6
|
||||||
pic32mx_putreg(uart_base, PIC32MX_UART_STACLR_OFFSET,
|
pic32mx_putreg(uart_base, PIC32MX_UART_STACLR_OFFSET,
|
||||||
UART_STA_UTXINV | UART_STA_UTXISEL_TXBNF | UART_STA_URXISEL_RXB6);
|
UART_STA_UTXINV | UART_STA_UTXISEL_TXBE | UART_STA_URXISEL_RXB6);
|
||||||
#else
|
#else
|
||||||
pic32mx_putreg(uart_base, PIC32MX_UART_STACLR_OFFSET,
|
pic32mx_putreg(uart_base, PIC32MX_UART_STACLR_OFFSET,
|
||||||
UART_STA_UTXINV | UART_STA_UTXISEL_TXBNF | UART_STA_URXISEL_RXB3);
|
UART_STA_UTXINV | UART_STA_UTXISEL_TXBE | UART_STA_URXISEL_RXB3);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Configure the FIFO interrupts */
|
/* Configure the FIFO interrupts */
|
||||||
|
|||||||
@@ -491,37 +491,71 @@ static int up_interrupt(int irq, void *context)
|
|||||||
|
|
||||||
up_clrpend_irq(priv->irqe);
|
up_clrpend_irq(priv->irqe);
|
||||||
lldbg("ERROR: interrrupt STA: %08x\n",
|
lldbg("ERROR: interrrupt STA: %08x\n",
|
||||||
up_serialin(priv, PIC32MX_UART_STA_OFFSET)
|
up_serialin(priv, PIC32MX_UART_STA_OFFSET));
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Handle incoming, receive bytes */
|
/* Handle incoming, received bytes. The RX FIFO is configured to
|
||||||
|
* interrupt when the RX FIFO is 75% full (that is 6 of 8 for 8-deep
|
||||||
|
* FIFOs or 3 of 4 for 4-deep FIFOS.
|
||||||
|
*/
|
||||||
|
|
||||||
if (up_pending_irq(priv->irqrx))
|
if (up_pending_irq(priv->irqrx))
|
||||||
{
|
{
|
||||||
/* Clear the pending RX interrupt */
|
|
||||||
|
|
||||||
up_clrpend_irq(priv->irqrx);
|
|
||||||
|
|
||||||
/* Process incoming bytes */
|
/* Process incoming bytes */
|
||||||
|
|
||||||
uart_recvchars(dev);
|
uart_recvchars(dev);
|
||||||
handled = true;
|
handled = true;
|
||||||
|
|
||||||
|
/* Clear the pending RX interrupt if the receive buffer is empty.
|
||||||
|
* Note that interrupts can be lost if the interrupt condition is
|
||||||
|
* still true when the interrupt is cleared. Keeping the RX
|
||||||
|
* interrupt pending too long is not a problem because the
|
||||||
|
* upper half driver will disable RX interrupts if it no
|
||||||
|
* longer has space to buffer the serial data.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((up_serialin(priv, PIC32MX_UART_STA_OFFSET) & UART_STA_URXDA) == 0)
|
||||||
|
{
|
||||||
|
up_clrpend_irq(priv->irqrx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle outgoing, transmit bytes */
|
/* Handle outgoing, transmit bytes The RT FIFO is configured to
|
||||||
|
* interrupt only when the TX FIFO is empty. There are not many
|
||||||
|
* options on trigger TX interrupts. The FIFO-not-full might generate
|
||||||
|
* better through-put but with a higher interrupt rate. FIFO-empty should
|
||||||
|
* lower the interrupt rate but result in a burstier output. If
|
||||||
|
* you change this, You will probably need to change the conditions for
|
||||||
|
* clearing the pending TX interrupt below.
|
||||||
|
*
|
||||||
|
* NOTE: When I tried using the FIFO-not-full interrupt trigger, I
|
||||||
|
* had either lost interrupts, or else a window where I might get
|
||||||
|
* infinite interrupts. The problem is that there is a race condition
|
||||||
|
* with trying to clearing the pending interrupt based on the FIFO
|
||||||
|
* full condition.
|
||||||
|
*/
|
||||||
|
|
||||||
if (up_pending_irq(priv->irqtx))
|
if (up_pending_irq(priv->irqtx))
|
||||||
{
|
{
|
||||||
/* Clear the pending RX interrupt */
|
|
||||||
|
|
||||||
up_clrpend_irq(priv->irqtx);
|
|
||||||
|
|
||||||
/* Process outgoing bytes */
|
/* Process outgoing bytes */
|
||||||
|
|
||||||
uart_xmitchars(dev);
|
uart_xmitchars(dev);
|
||||||
handled = true;
|
handled = true;
|
||||||
|
|
||||||
|
/* Clear the pending TX interrupt if the TX FIFO is empty.
|
||||||
|
* Note that interrupts can be lost if the interrupt condition is
|
||||||
|
* still true when the interrupt is cleared. Keeping the TX
|
||||||
|
* interrupt pending too long is not a problem: Upper level logic
|
||||||
|
* will disable the TX interrupt when there is no longer anything
|
||||||
|
* to be sent.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((up_serialin(priv, PIC32MX_UART_STA_OFFSET) & UART_STA_UTRMT) != 0)
|
||||||
|
{
|
||||||
|
up_clrpend_irq(priv->irqtx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user