summaryrefslogtreecommitdiff
path: root/nuttx
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-12-26 18:52:31 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-12-26 18:52:31 +0000
commit3c09cbf50d9d97e31491675d8ddd33a6e45b7537 (patch)
tree71ae71ff913c68ccfda8551c2ab043cc275decb5 /nuttx
parent2f898df5ff183d891d185f75003c41e6c7867686 (diff)
downloadpx4-nuttx-3c09cbf50d9d97e31491675d8ddd33a6e45b7537.tar.gz
px4-nuttx-3c09cbf50d9d97e31491675d8ddd33a6e45b7537.tar.bz2
px4-nuttx-3c09cbf50d9d97e31491675d8ddd33a6e45b7537.zip
Fix PIC32 serial driver lost interrupts
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4230 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx')
-rw-r--r--nuttx/arch/mips/src/mips32/up_sigdeliver.c8
-rw-r--r--nuttx/arch/mips/src/pic32mx/pic32mx-lowconsole.c12
-rw-r--r--nuttx/arch/mips/src/pic32mx/pic32mx-serial.c56
3 files changed, 61 insertions, 15 deletions
diff --git a/nuttx/arch/mips/src/mips32/up_sigdeliver.c b/nuttx/arch/mips/src/mips32/up_sigdeliver.c
index cf0ac944e..8009b369c 100644
--- a/nuttx/arch/mips/src/mips32/up_sigdeliver.c
+++ b/nuttx/arch/mips/src/mips32/up_sigdeliver.c
@@ -115,7 +115,7 @@ void up_sigdeliver(void)
/* Then restore the task interrupt state */
- irqrestore((uint16_t)regs[REG_STATUS]);
+ irqrestore((irqstate_t)regs[REG_STATUS]);
/* Deliver the signals */
@@ -137,6 +137,12 @@ void up_sigdeliver(void)
up_ledoff(LED_SIGNAL);
up_fullcontextrestore(regs);
+
+ /* up_fullcontextrestore() should not return but could if the software
+ * interrupts are disabled.
+ */
+
+ PANIC(OSERR_INTERNAL);
}
#endif /* !CONFIG_DISABLE_SIGNALS */
diff --git a/nuttx/arch/mips/src/pic32mx/pic32mx-lowconsole.c b/nuttx/arch/mips/src/pic32mx/pic32mx-lowconsole.c
index f8d318bf0..aaf765c32 100644
--- a/nuttx/arch/mips/src/pic32mx/pic32mx-lowconsole.c
+++ b/nuttx/arch/mips/src/pic32mx/pic32mx-lowconsole.c
@@ -247,16 +247,22 @@ void pic32mx_uartconfigure(uintptr_t uart_base, uint32_t baudrate,
/* Configure the FIFOs:
*
* 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.
+ *
+ * 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
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
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
/* Configure the FIFO interrupts */
diff --git a/nuttx/arch/mips/src/pic32mx/pic32mx-serial.c b/nuttx/arch/mips/src/pic32mx/pic32mx-serial.c
index 413eda9f8..9728717e6 100644
--- a/nuttx/arch/mips/src/pic32mx/pic32mx-serial.c
+++ b/nuttx/arch/mips/src/pic32mx/pic32mx-serial.c
@@ -491,37 +491,71 @@ static int up_interrupt(int irq, void *context)
up_clrpend_irq(priv->irqe);
lldbg("ERROR: interrrupt STA: %08x\n",
- up_serialin(priv, PIC32MX_UART_STA_OFFSET)
+ up_serialin(priv, PIC32MX_UART_STA_OFFSET));
handled = true;
}
#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))
{
- /* Clear the pending RX interrupt */
-
- up_clrpend_irq(priv->irqrx);
-
/* Process incoming bytes */
uart_recvchars(dev);
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))
{
- /* Clear the pending RX interrupt */
-
- up_clrpend_irq(priv->irqtx);
-
/* Process outgoing bytes */
uart_xmitchars(dev);
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);
+ }
}
}