diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-12-26 18:52:31 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-12-26 18:52:31 +0000 |
commit | 3c09cbf50d9d97e31491675d8ddd33a6e45b7537 (patch) | |
tree | 71ae71ff913c68ccfda8551c2ab043cc275decb5 /nuttx/arch/mips/src/pic32mx | |
parent | 2f898df5ff183d891d185f75003c41e6c7867686 (diff) | |
download | px4-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/arch/mips/src/pic32mx')
-rw-r--r-- | nuttx/arch/mips/src/pic32mx/pic32mx-lowconsole.c | 12 | ||||
-rw-r--r-- | nuttx/arch/mips/src/pic32mx/pic32mx-serial.c | 56 |
2 files changed, 54 insertions, 14 deletions
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); + } } } |