diff options
Diffstat (limited to 'nuttx/arch/arm/src/kinetis/kinetis_serial.c')
-rw-r--r-- | nuttx/arch/arm/src/kinetis/kinetis_serial.c | 161 |
1 files changed, 123 insertions, 38 deletions
diff --git a/nuttx/arch/arm/src/kinetis/kinetis_serial.c b/nuttx/arch/arm/src/kinetis/kinetis_serial.c index 808ba6902..e4988e546 100644 --- a/nuttx/arch/arm/src/kinetis/kinetis_serial.c +++ b/nuttx/arch/arm/src/kinetis/kinetis_serial.c @@ -261,7 +261,9 @@ static bool up_rxavailable(struct uart_dev_s *dev); static void up_send(struct uart_dev_s *dev, int ch); static void up_txint(struct uart_dev_s *dev, bool enable); static bool up_txready(struct uart_dev_s *dev); +#ifdef CONFIG_KINETIS_UARTFIFOS static bool up_txempty(struct uart_dev_s *dev); +#endif /**************************************************************************** * Private Variables @@ -280,7 +282,11 @@ struct uart_ops_s g_uart_ops = .send = up_send, .txint = up_txint, .txready = up_txready, +#ifdef CONFIG_KINETIS_UARTFIFOS .txempty = up_txempty, +#else + .txempty = up_txready, +#endif }; /* I/O buffers */ @@ -731,6 +737,8 @@ static int up_interrupte(int irq, void *context) { struct uart_dev_s *dev = NULL; struct up_dev_s *priv; + uint8_t s1; + uint8_t regval; #ifdef CONFIG_KINETIS_UART0 if (g_uart0priv.irq == irqe) @@ -780,16 +788,22 @@ static int up_interrupte(int irq, void *context) priv = (struct up_dev_s*)dev->priv; DEBUGASSERT(priv); - /* Handle error interrupts. */ -#warning "Missing logic" - - /* Clear the pending error interrupt */ - - up_clrpend_irq(priv->irqe); // Necessary? + /* Handle error interrupts. This interrupt may be caused by: + * + * FE: Framing error. To clear FE, read S1 with FE set and then read the + * UART data register (D). + * NF: Noise flag. To clear NF, read S1 and then read the UART data + * register (D). + * PF: Parity error flag. To clear PF, read S1 and then read the UART data + * register (D). + */ + regval = up_serialin(priv, KINETIS_UART_S1_OFFSET + lldbg("S1: %02x\n", regval); + regval = up_serialin(priv, KINETIS_UART_D_OFFSET return OK; } -#endif +#endif /* CONFIG_DEBUG */ /**************************************************************************** * Name: up_interrupts @@ -809,11 +823,15 @@ static int up_interrupts(int irq, void *context) struct up_dev_s *priv; int passes; unsigned int size; +#ifdef CONFIG_KINETIS_UARTFIFOS unsigned int count; +#else + uint8_t s1; +#endif bool handled; #ifdef CONFIG_KINETIS_UART0 - if (g_uart0priv.irq == irqe) + if (g_uart0priv.irq == irqs) { dev = &g_uart0port; } @@ -869,35 +887,66 @@ static int up_interrupts(int irq, void *context) { handled = false; - /* Check for a pending status interrupt */ + /* Read status register 1 */ - if (up_pending_irq(priv->irqs)) - { - /* Clear the pending status interrupt */ +#ifndef CONFIG_KINETIS_UARTFIFOS + s1 = up_serialin(priv, KINETIS_UART_S1_OFFSET); +#endif - up_clrpend_irq(priv->irqs); // Necessary? + /* Handle incoming, receive bytes */ - /* Handle incoming, receive bytes */ +#ifdef CONFIG_KINETIS_UARTFIFOS + /* Check the count of bytes in the RX FIFO */ - count = up_serialin(priv, KINETIS_UART_RCFIFO_OFFSET); - if (count > 0) - { - /* Process incoming bytes */ + count = up_serialin(priv, KINETIS_UART_RCFIFO_OFFSET); + if (count > 0) +#else + /* Check if the receive data register is full (RDRF). NOTE: If + * FIFOS are enabled, this does not mean that the the FIFO is full, + * rather, it means that the the number of bytes in the RX FIFO has + * exceeded the watermark setting. There may actually be RX data + * available! + * + * The RDRF status indication is cleared when the data is read from + * the RX data register. + */ - uart_recvchars(dev); - handled = true; - } + if ((s1 & UART_S1_RDRF) != 0) +#endif + { + /* Process incoming bytes */ + + uart_recvchars(dev); + handled = true; + } - /* Handle outgoing, transmit bytes */ + /* Handle outgoing, transmit bytes */ - count = up_serialin(priv, KINETIS_UART_TCFIFO_OFFSET); - #warning "Missing logic" - { - /* Process outgoing bytes */ +#ifdef CONFIG_KINETIS_UARTFIFOS + /* Read the number of bytes currently in the FIFO and compare that to + * the size of the FIFO. If there are fewer bytes in the FIFO than + * the size of the FIFO, then we are able to transmit. + */ - uart_xmitchars(dev); - handled = true; - } +# error "Missing logic" +#else + /* Check if the transmit data register is "empty." NOTE: If FIFOS + * are enabled, this does not mean that the the FIFO is empty, rather, + * it means that the the number of bytes in the TX FIFO is below the + * watermark setting. There could actually be space for additional TX + * data. + * + * The TDRE status indication is cleared when the data is written to + * the TX data register. + */ + + if ((s1 & UART_S1_TDRE) != 0) +#endif + { + /* Process outgoing bytes */ + + uart_xmitchars(dev); + handled = true; } } @@ -956,15 +1005,30 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg) static int up_receive(struct uart_dev_s *dev, uint32_t *status) { struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + uint8_t s1; + + /* Get error status information: + * + * FE: Framing error. To clear FE, read S1 with FE set and then read + * read UART data register (D). + * NF: Noise flag. To clear NF, read S1 and then read the UART data + * register (D). + * PF: Parity error flag. To clear PF, read S1 and then read the UART + * data register (D). + */ + + s1 = up_serialin(priv, KINETIS_UART_S1_OFFSET); /* Return status information */ if (status) { - *status = 0; /* We are not yet tracking serial errors */ + *status = (uint32_t)s1; } - /* Then return the actual received byte */ + /* Then return the actual received byte. Reading S1 then D clears all + * RX errors. + */ return (int)up_serialin(priv, KINETIS_UART_D_OFFSET); } @@ -981,10 +1045,8 @@ static void up_rxint(struct uart_dev_s *dev, bool enable) { struct up_dev_s *priv = (struct up_dev_s*)dev->priv; irqstate_t flags; - uint8_t ie; flags = irqsave(); - ie = priv->ie; if (enable) { /* Receive an interrupt when their is anything in the Rx data register (or an Rx @@ -998,8 +1060,8 @@ static void up_rxint(struct uart_dev_s *dev, bool enable) } else { -#warning "Revisit: How are errors enabled? What is the IDLE receive interrupt. I think I need it" #ifdef CONFIG_DEBUG +# warning "Revisit: How are errors enabled?" priv->ie |= UART_C2_RIE; #else priv->ie |= UART_C2_RIE; @@ -1007,7 +1069,6 @@ static void up_rxint(struct uart_dev_s *dev, bool enable) up_setuartint(priv); } - priv->ie = ie; irqrestore(flags); } @@ -1022,12 +1083,23 @@ static void up_rxint(struct uart_dev_s *dev, bool enable) static bool up_rxavailable(struct uart_dev_s *dev) { struct up_dev_s *priv = (struct up_dev_s*)dev->priv; +#ifdef CONFIG_KINETIS_UARTFIFOS unsigned int count; /* Return true if there are any bytes in the RX FIFO */ count = up_serialin(priv, KINETIS_UART_RCFIFO_OFFSET); return count > 0; +#else + /* Return true if the receive data register is full (RDRF). NOTE: If + * FIFOS are enabled, this does not mean that the the FIFO is full, + * rather, it means that the the number of bytes in the RX FIFO has + * exceeded the watermark setting. There may actually be RX data + * available! + */ + + return (up_serialin(priv, KINETIS_UART_S1_OFFSET) & UART_S1_RDRF) != 0; +#endif } /**************************************************************************** @@ -1096,12 +1168,23 @@ static bool up_txready(struct uart_dev_s *dev) { struct up_dev_s *priv = (struct up_dev_s*)dev->priv; - /* Return true if the transmit data register is "empty." This state - * depends on the TX watermark setting and does not mean that the transmit - * buffer is really empty. +#ifdef CONFIG_KINETIS_UARTFIFOS + /* Read the number of bytes currently in the FIFO and compare that to the + * size of the FIFO. If there are fewer bytes in the FIFO than the size + * of the FIFO, then we are able to transmit. + */ + +# error "Missing logic" +#else + /* Return true if the transmit data register is "empty." NOTE: If + * FIFOS are enabled, this does not mean that the the FIFO is empty, + * rather, it means that the the number of bytes in the TX FIFO is + * below the watermark setting. There may actually be space for + * additional TX data. */ return (up_serialin(priv, KINETIS_UART_S1_OFFSET) & UART_S1_TDRE) != 0; +#endif } /**************************************************************************** @@ -1112,6 +1195,7 @@ static bool up_txready(struct uart_dev_s *dev) * ****************************************************************************/ +#ifdef CONFIG_KINETIS_UARTFIFOS static bool up_txempty(struct uart_dev_s *dev) { struct up_dev_s *priv = (struct up_dev_s*)dev->priv; @@ -1120,6 +1204,7 @@ static bool up_txempty(struct uart_dev_s *dev) return (up_serialin(priv, KINETIS_UART_SFIFO_OFFSET) & UART_SFIFO_TXEMPT) != 0; } +#endif /**************************************************************************** * Public Functions |